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