utf: ast 2
[scilab.git] / scilab / modules / ast / src / cpp / types / cell.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2010-2010 - DIGITEO - Bruno JOFRET
4 *  Copyright (C) 2011 - DIGITEO - Antoine ELIAS
5 *
6 *  This file must be used under the terms of the CeCILL.
7 *  This source file is licensed as described in the file COPYING, which
8 *  you should have received as part of this distribution.  The terms
9 *  are also available at
10 *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11 *
12 */
13
14 #include <algorithm>
15 #include <sstream>
16 #include <math.h>
17 #include "symbol.hxx"
18 #include "cell.hxx"
19 #include "double.hxx"
20 #include "list.hxx"
21 #include "colon.hxx"
22 #include "tostring_common.hxx"
23 #include "core_math.h"
24 #include "list.hxx"
25 #include "configvariable.hxx"
26
27 namespace types
28 {
29 /**
30 ** Constructor & Destructor (public)
31 */
32 Cell::Cell()
33 {
34     int piDims[2] = {0, 0};
35     createCell(2, piDims, nullptr);
36 }
37
38 Cell::Cell(int _iRows, int _iCols, InternalType** data)
39 {
40     int piDims[2] = {_iRows, _iCols};
41     createCell(2, piDims, data);
42 }
43
44 Cell::Cell(int _iDims, const int* _piDims, InternalType** data)
45 {
46     createCell(_iDims, _piDims, data);
47 }
48
49 void Cell::createCell(int _iDims, const int* _piDims, InternalType** data)
50 {
51     InternalType** pIT = NULL;
52     create(_piDims, _iDims, &pIT, NULL);
53     for (int i = 0; i < m_iSizeMax; i++)
54     {
55         if (data == nullptr)
56         {
57             m_pRealData[i] = Double::Empty();
58         }
59         else
60         {
61             m_pRealData[i] = data[i];
62         }
63
64         m_pRealData[i]->IncreaseRef();
65     }
66 #ifndef NDEBUG
67     Inspector::addItem(this);
68 #endif
69 }
70
71 Cell::~Cell()
72 {
73     if (isDeletable() == true)
74     {
75         for (int i = 0; i < m_iSizeMax; i++)
76         {
77             m_pRealData[i]->DecreaseRef();
78             m_pRealData[i]->killMe();
79         }
80     }
81
82     delete[] m_pRealData;
83 #ifndef NDEBUG
84     Inspector::removeItem(this);
85 #endif
86 }
87
88 /**
89 ** Private Copy Constructor and data Access
90 */
91 Cell::Cell(Cell *_oCellCopyMe)
92 {
93     InternalType** pIT = NULL;
94     create(_oCellCopyMe->getDimsArray(), _oCellCopyMe->getDims(), &pIT, NULL);
95     for (int i = 0 ; i < getSize() ; i++)
96     {
97         m_pRealData[i] = NULL;
98     }
99
100     for (int i = 0 ; i < getSize() ; i++)
101     {
102         set(i, _oCellCopyMe->get(i)->clone());
103     }
104 #ifndef NDEBUG
105     Inspector::addItem(this);
106 #endif
107 }
108
109 bool Cell::transpose(InternalType *& out)
110 {
111     if (isScalar())
112     {
113         out = clone();
114         return true;
115     }
116
117     if (m_iDims == 2)
118     {
119         Cell * pC = new Cell();
120         out = pC;
121         InternalType** pIT = NULL;
122         int piDims[2] = {getCols(), getRows()};
123         pC->create(piDims, 2, &pIT, NULL);
124
125         Transposition::transpose_clone(getRows(), getCols(), m_pRealData, pC->m_pRealData);
126
127         return true;
128     }
129
130     return false;
131 }
132
133 Cell* Cell::set(int _iRows, int _iCols, InternalType* _pIT)
134 {
135     if (_iRows < getRows() && _iCols < getCols())
136     {
137         return set(_iCols * getRows() + _iRows, _pIT);
138     }
139     return NULL;
140 }
141
142 Cell* Cell::set(int _iRows, int _iCols, const InternalType* _pIT)
143 {
144     if (_iRows < getRows() && _iCols < getCols())
145     {
146         return set(_iCols * getRows() + _iRows, _pIT);
147     }
148     return NULL;
149 }
150
151 Cell* Cell::set(int _iIndex, InternalType* _pIT)
152 {
153     if (_iIndex >= m_iSize)
154     {
155         return NULL;
156     }
157
158     // corner case when inserting twice
159     if (m_pRealData[_iIndex] == _pIT)
160     {
161         return this;
162     }
163
164     typedef Cell* (Cell::*set_t)(int, InternalType*);
165     Cell* pIT = checkRef(this, (set_t)&Cell::set, _iIndex, _pIT);
166     if (pIT != this)
167     {
168         return pIT;
169     }
170
171     if (m_pRealData[_iIndex] != NULL)
172     {
173         m_pRealData[_iIndex]->DecreaseRef();
174         m_pRealData[_iIndex]->killMe();
175     }
176
177     _pIT->IncreaseRef();
178     m_pRealData[_iIndex] = _pIT;
179     return this;
180 }
181
182 Cell* Cell::set(int _iIndex, const InternalType* _pIT)
183 {
184     if (_iIndex >= m_iSize)
185     {
186         return NULL;
187     }
188
189     typedef Cell* (Cell::*set_t)(int, const InternalType*);
190     Cell* pIT = checkRef(this, (set_t)&Cell::set, _iIndex, _pIT);
191     if (pIT != this)
192     {
193         return pIT;
194     }
195
196     if (m_pRealData[_iIndex] != NULL)
197     {
198         m_pRealData[_iIndex]->DecreaseRef();
199         m_pRealData[_iIndex]->killMe();
200     }
201
202     const_cast<InternalType*>(_pIT)->IncreaseRef();
203     m_pRealData[_iIndex] = const_cast<InternalType*>(_pIT);
204
205     return this;
206 }
207
208 Cell* Cell::set(InternalType** _pIT)
209 {
210     typedef Cell* (Cell::*set_t)(InternalType**);
211     Cell* pIT = checkRef(this, (set_t)&Cell::set, _pIT);
212     if (pIT != this)
213     {
214         return pIT;
215     }
216
217     for (int i = 0; i < m_iSize; i++)
218     {
219         if (i >= m_iSize)
220         {
221             return NULL;
222         }
223
224         if (m_pRealData[i] != NULL)
225         {
226             m_pRealData[i]->DecreaseRef();
227             m_pRealData[i]->killMe();
228         }
229
230         _pIT[i]->IncreaseRef();
231         m_pRealData[i] = _pIT[i];
232     }
233
234     return this;
235 }
236
237 /**
238 ** Clone
239 ** Create a new Struct and Copy all values.
240 */
241 Cell* Cell::clone()
242 {
243     return new Cell(this);
244 }
245
246 InternalType* Cell::getNullValue()
247 {
248     return Double::Empty();
249 }
250
251 Cell* Cell::createEmpty(int _iDims, int* _piDims, bool /*_bComplex*/)
252 {
253     return new Cell(_iDims, _piDims);
254 }
255
256 InternalType* Cell::copyValue(InternalType* _pData)
257 {
258     _pData->IncreaseRef();
259     return _pData;
260 }
261
262 void Cell::deleteAll()
263 {
264     for (int i = 0 ; i < getSize() ; i++)
265     {
266         m_pRealData[i]->DecreaseRef();
267         m_pRealData[i]->killMe();
268     }
269
270     delete[] m_pRealData;
271     m_pRealData = NULL;
272 }
273
274 void Cell::deleteImg()
275 {
276     return;
277 }
278
279 bool Cell::isEmpty()
280 {
281     if (getDims() == 2 && getRows() == 0 && getCols() == 0)
282     {
283         return true;
284     }
285     return false;
286 }
287
288 /**
289 ** toString to display Structs
290 ** FIXME : Find a better indentation process
291 */
292 bool Cell::subMatrixToString(std::ostringstream& ostr, int* _piDims, int /*_iDims*/)
293 {
294     int iPrecision = ConfigVariable::getFormatSize();
295
296     if (isEmpty())
297     {
298         ostr << "   {}";
299     }
300     else
301     {
302         //max len for each column
303         int *piTypeLen = new int[getCols()];
304         int *piSizeLen = new int[getCols()];
305
306         memset(piTypeLen, 0x00, getCols() * sizeof(int));
307         memset(piSizeLen, 0x00, getCols() * sizeof(int));
308
309         for (int j = 0 ; j < getCols() ; j++)
310         {
311             for (int i = 0 ; i < getRows() ; i++)
312             {
313                 _piDims[0] = i;
314                 _piDims[1] = j;
315
316                 int iPos = getIndex(_piDims);
317                 InternalType* pIT = get(iPos);
318
319                 if (pIT->isAssignable())
320                 {
321                     //compute number of digits to write dimensions
322                     int iTypeLen = 0;
323                     if (pIT->isGenericType())
324                     {
325                         GenericType* pGT = pIT->getAs<GenericType>();
326                         for (int k = 0 ; k < pGT->getDims() ; k++)
327                         {
328                             iTypeLen += static_cast<int>(log10(static_cast<double>(pGT->getDimsArray()[k])) + 1);
329                         }
330                         piSizeLen[j] = std::max(piSizeLen[j], iTypeLen + (pGT->getDims() - 1));//add number of "x"
331                     }
332                     else
333                     {
334                         //types non derived from ArrayOf.
335                         int iSize = static_cast<int>(log10(static_cast<double>(pIT->getAs<GenericType>()->getRows())) + 1);
336                         piSizeLen[j] = std::max(piSizeLen[j], iSize);
337                     }
338                 }
339                 else
340                 {
341                     //no size so let a white space, size == 1
342                     piSizeLen[j] = std::max(piSizeLen[j], 1);
343                 }
344
345                 piTypeLen[j] = std::max(piTypeLen[j], static_cast<int>(pIT->getTypeStr().size()));
346             }
347         }
348
349         for (int i = 0 ; i < getRows() ; i++)
350         {
351             for (int j = 0 ; j < getCols() ; j++)
352             {
353                 _piDims[0] = i;
354                 _piDims[1] = j;
355                 int iPos = getIndex(_piDims);
356                 InternalType* pIT = get(iPos);
357
358                 ostr << "  [";
359                 if (pIT->isAssignable())
360                 {
361                     if (pIT->isGenericType())
362                     {
363                         //"  ixjxkxl type   "
364                         GenericType* pGT = pIT->getAs<GenericType>();
365                         std::ostringstream ostemp;
366                         for (int k = 0 ; k < pGT->getDims() ; k++)
367                         {
368                             if (k != 0)
369                             {
370                                 ostemp << "x";
371                             }
372                             ostemp << pGT->getDimsArray()[k];
373                         }
374                         configureStream(&ostr, piSizeLen[j], iPrecision, ' ');
375                         ostr << std::right << ostemp.str();
376                     }
377                     else
378                     {
379                         //" i   "
380                         configureStream(&ostr, piSizeLen[j], iPrecision, ' ');
381                         if (pIT->isList())
382                         {
383                             ostr << std::right << pIT->getAs<List>()->getSize();
384                         }
385                         else
386                         {
387                             ostr << std::right << 1;
388                         }
389                     }
390                 }
391                 else
392                 {
393                     configureStream(&ostr, piSizeLen[j], iPrecision, ' ');
394                     ostr << "";//fill with space
395                 }
396                 ostr << " ";
397                 configureStream(&ostr, piTypeLen[j], iPrecision, ' ');
398                 ostr << std::left << pIT->getTypeStr();
399                 ostr << "]";
400             }
401             ostr << std::endl;
402         }
403
404         delete[] piSizeLen;
405         delete[] piTypeLen;
406     }
407     ostr << std::endl;
408     return true;
409 }
410
411 bool Cell::operator==(const InternalType& it)
412 {
413     if (const_cast<InternalType &>(it).isCell() == false)
414     {
415         return false;
416     }
417
418     Cell* pC = const_cast<InternalType &>(it).getAs<Cell>();
419
420     for (int i = 0 ; i < getDims() ; i++)
421     {
422         if (pC->getDimsArray()[i] != getDimsArray()[i])
423         {
424             return false;
425         }
426     }
427
428     for (int i = 0 ; i < getSize() ; i++)
429     {
430         if (get(i) != pC->get(i))
431         {
432             return false;
433         }
434     }
435     return true;
436 }
437
438 bool Cell::operator!=(const InternalType& it)
439 {
440     return !(*this == it);
441 }
442
443 List* Cell::extractCell(typed_list* _pArgs)
444 {
445     InternalType* pIT = extract(_pArgs);
446     if (pIT == NULL || pIT->isCell() == false)
447     {
448         return NULL;
449     }
450
451     List* pList = new List();
452
453     Cell* pCell = pIT->getAs<Cell>();
454     for (int i = 0 ; i < pCell->getSize() ; i++)
455     {
456         pList->append(pCell->get(i));
457     }
458     pCell->killMe();
459     return pList;
460 }
461
462 Cell* Cell::insertCell(typed_list* _pArgs, InternalType* _pSource)
463 {
464     Cell* pCell = new Cell(1, 1);
465     pCell->set(0, _pSource);
466     Cell* pOut = insert(_pArgs, pCell)->getAs<Cell>();
467     pCell->killMe();
468     return pOut;
469 }
470
471 Cell* Cell::insertNewCell(typed_list* _pArgs, InternalType* _pSource)
472 {
473     Cell* pCell = new Cell(1, 1);
474     pCell->set(0, _pSource);
475     Cell* pOut = pCell->insertNew(_pArgs)->getAs<Cell>();
476     return pOut;
477 }
478
479 InternalType** Cell::allocData(int _iSize)
480 {
481     InternalType** pData = new InternalType*[_iSize];
482     for (int i = 0 ; i < _iSize ; i++)
483     {
484         pData[i] = NULL;
485     }
486     return pData;
487 }
488
489 void Cell::deleteData(InternalType* _pData)
490 {
491     if (_pData)
492     {
493         _pData->DecreaseRef();
494         _pData->killMe();
495     }
496 }
497
498 Cell* Cell::createEmpty()
499 {
500     return new Cell();
501 }
502 }