insert in struct corrected.
[scilab.git] / scilab / modules / ast / src / cpp / types / struct.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2011 - DIGITEO - Antoine ELIAS
4 *
5 *  This file must be used under the terms of the CeCILL.
6 *  This source file is licensed as described in the file COPYING, which
7 *  you should have received as part of this distribution.  The terms
8 *  are also available at
9 *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10 *
11 */
12 #include "struct.hxx"
13 #include "string.hxx"
14 #include "double.hxx"
15 #include "list.hxx"
16 #include "int.hxx"
17 #include "localization.hxx"
18
19 namespace types
20 {
21 Struct::Struct()
22 {
23     m_bDisableCloneInCopyValue = false;
24     SingleStruct** pIT  = NULL;
25     int piDims[2] = {0, 0};
26     create(piDims, 2, &pIT, NULL);
27 #ifndef NDEBUG
28     //Inspector::addItem(this);
29 #endif
30 }
31
32 Struct::Struct(int _iRows, int _iCols)
33 {
34     m_bDisableCloneInCopyValue = false;
35     SingleStruct** pIT  = NULL;
36     SingleStruct *p = new SingleStruct();
37     int piDims[2] = {_iRows, _iCols};
38     create(piDims, 2, &pIT, NULL);
39     for (int i = 0 ; i < getSize() ; i++)
40     {
41         set(i, p);
42     }
43     delete p;
44 #ifndef NDEBUG
45     //Inspector::addItem(this);
46 #endif
47 }
48
49 Struct::Struct(int _iDims, int* _piDims)
50 {
51     m_bDisableCloneInCopyValue = false;
52     SingleStruct** pIT  = NULL;
53     create(_piDims, _iDims, &pIT, NULL);
54     for (int i = 0 ; i < getSize() ; i++)
55     {
56         SingleStruct *p = new SingleStruct();
57         set(i, p);
58         delete p;
59     }
60 #ifndef NDEBUG
61     //Inspector::addItem(this);
62 #endif
63 }
64
65 Struct::~Struct()
66 {
67     if (isDeletable() == true)
68     {
69         for (int i = 0 ; i < getSize() ; i++)
70         {
71             SingleStruct *pStr = m_pRealData[i];
72             if (pStr)
73             {
74                 pStr->DecreaseRef();
75                 if (pStr->isDeletable())
76                 {
77                     //std::wcout << L"delete sub struct(" << i << L") : " << pStr << std::endl;
78                     delete pStr;
79                 }
80                 else
81                 {
82                     //std::wcout << L"!!!!!!!!!!!!!!! pas touche sub struct(" << i << L") : " << pStr->getRef() << L" @" << pStr << std::endl;
83                 }
84             }
85         }
86     }
87 #ifndef NDEBUG
88     //Inspector::removeItem(this);
89 #endif
90 }
91
92 Struct::Struct(Struct *_oStructCopyMe)
93 {
94     m_bDisableCloneInCopyValue = false;
95     SingleStruct** pIT = NULL;
96     create(_oStructCopyMe->getDimsArray(), _oStructCopyMe->getDims(), &pIT, NULL);
97     for (int i = 0 ; i < getSize() ; i++)
98     {
99         m_pRealData[i] = NULL;
100     }
101
102     for (int i = 0 ; i < getSize() ; i++)
103     {
104         pIT[i] = _oStructCopyMe->get(i)->clone();
105     }
106 #ifndef NDEBUG
107     //Inspector::addItem(this);
108 #endif
109 }
110
111 InternalType* Struct::clone()
112 {
113     return new Struct(this);
114 }
115
116 bool Struct::transpose(InternalType *& out)
117 {
118     if (isScalar())
119     {
120         out = clone();
121         return true;
122     }
123
124     if (m_iDims == 2)
125     {
126         Struct * pSt = new Struct();
127         out = pSt;
128         SingleStruct** pSSt = NULL;
129         int piDims[2] = {getCols(), getRows()};
130         pSt->create(piDims, 2, &pSSt, NULL);
131
132         Transposition::transpose_clone(getRows(), getCols(), m_pRealData, pSt->m_pRealData);
133
134         return true;
135     }
136
137     return false;
138 }
139
140 bool Struct::extract(const std::wstring & name, InternalType *& out)
141 {
142     if (exists(name))
143     {
144         out = extractField(name);
145     }
146     else
147     {
148         wchar_t szError[bsiz];
149         os_swprintf(szError, bsiz, _W("Unknown field : %ls.\n").c_str(), name.c_str());
150         throw std::wstring(szError);
151     }
152
153     return true;
154 }
155
156 bool Struct::invoke(typed_list & in, optional_list & opt, int _iRetCount, typed_list & out, ast::ConstVisitor & execFunc, const ast::CallExp & e)
157 {
158     if (in.size() == 0)
159     {
160         out.push_back(this);
161         return true;
162     }
163     else if (in.size() == 1)
164     {
165         InternalType * arg = in[0];
166         std::vector<InternalType *> _out;
167         if (arg->isString())
168         {
169             std::vector<std::wstring> wstFields;
170             String * pString = arg->getAs<types::String>();
171             for (int i = 0; i < pString->getSize(); ++i)
172             {
173                 std::wstring wstField(pString->get(i));
174                 if (this->exists(wstField))
175                 {
176                     wstFields.push_back(wstField);
177                 }
178                 else
179                 {
180                     wchar_t szError[bsiz];
181                     os_swprintf(szError, bsiz, _W("Field \"%ls\" does not exists\n").c_str(), wstField.c_str());
182                     throw ast::ScilabError(szError, 999, (*e.args_get().begin())->location_get());
183                 }
184             }
185
186             _out = extractFields(wstFields);
187             if (_out.size() == 1)
188             {
189                 InternalType * pIT = _out[0];
190                 if (pIT->isList() && pIT->getAs<List>()->getSize() == 1)
191                 {
192                     out.push_back(pIT->getAs<List>()->get(0));
193                     return true;
194                 }
195             }
196
197             out.swap(_out);
198             return true;
199         }
200     }
201
202     return ArrayOf<SingleStruct*>::invoke(in, opt, _iRetCount, out, execFunc, e);
203 }
204
205 bool Struct::set(int _iRows, int _iCols, SingleStruct* _pIT)
206 {
207     if (_iRows < getRows() && _iCols < getCols())
208     {
209         return set(_iCols * getRows() + _iRows, _pIT);
210     }
211     return false;
212 }
213
214 bool Struct::set(int _iRows, int _iCols, const SingleStruct* _pIT)
215 {
216     if (_iRows < getRows() && _iCols < getCols())
217     {
218         return set(_iCols * getRows() + _iRows, _pIT);
219     }
220     return false;
221 }
222
223 bool Struct::set(int _iIndex, SingleStruct* _pIT)
224 {
225     if (_iIndex < getSize())
226     {
227         if (m_bDisableCloneInCopyValue && m_pRealData[_iIndex] == _pIT)
228         {
229             return true;
230         }
231
232         InternalType* pOld = m_pRealData[_iIndex];
233
234         m_pRealData[_iIndex] = copyValue(_pIT);
235         m_pRealData[_iIndex]->IncreaseRef();
236
237         if (pOld != NULL)
238         {
239             pOld->DecreaseRef();
240             if (pOld->isDeletable())
241             {
242                 delete pOld;
243             }
244         }
245
246         return true;
247     }
248     return false;
249 }
250
251 bool Struct::set(int _iIndex, const SingleStruct* _pIT)
252 {
253     if (_iIndex < getSize())
254     {
255         InternalType* pOld = m_pRealData[_iIndex];
256
257         m_pRealData[_iIndex] = const_cast<SingleStruct*>(_pIT)->clone();
258
259         if (pOld != NULL)
260         {
261             pOld->DecreaseRef();
262             if (pOld->isDeletable())
263             {
264                 delete pOld;
265             }
266         }
267
268         return true;
269     }
270     return false;
271 }
272
273 bool Struct::set(SingleStruct** _pIT)
274 {
275     for (int i = 0 ; i < getSize() ; i++)
276     {
277         if (set(i, _pIT[i]) == false)
278         {
279             return false;
280         }
281     }
282     return true;
283 }
284
285 String* Struct::getFieldNames()
286 {
287     if (getSize() != 0)
288     {
289         return get(0)->getFieldNames();
290     }
291     else
292     {
293         return NULL;
294     }
295 }
296
297 bool Struct::exists(const std::wstring& _sKey)
298 {
299     if (getSize() != 0)
300     {
301         return get(0)->exists(_sKey);
302     }
303     else
304     {
305         return false;
306     }
307 }
308
309 bool Struct::operator==(const InternalType& it)
310 {
311     if (const_cast<InternalType &>(it).isStruct() == false)
312     {
313         return false;
314     }
315
316     Struct* pStr = const_cast<InternalType &>(it).getAs<Struct>();
317
318     for (int i = 0 ; i < getDims() ; i++)
319     {
320         if (pStr->getDimsArray()[i] != getDimsArray()[i])
321         {
322             return false;
323         }
324     }
325
326     for (int i = 0 ; i < getSize() ; i++)
327     {
328         if (*get(i) != *pStr->get(i))
329         {
330             return false;
331         }
332     }
333     return true;
334 }
335
336 bool Struct::operator!=(const InternalType& it)
337 {
338     return !(*this == it);
339 }
340
341 SingleStruct* Struct::getNullValue()
342 {
343     return new SingleStruct();
344 }
345
346 Struct* Struct::createEmpty(int _iDims, int* _piDims, bool _bComplex)
347 {
348     Struct* pStr = new Struct(_iDims, _piDims);
349     pStr->setCloneInCopyValue(!m_bDisableCloneInCopyValue);
350     return pStr;
351 }
352
353 SingleStruct* Struct::copyValue(SingleStruct* _pData)
354 {
355     SingleStruct* pStr = NULL;
356     if (m_bDisableCloneInCopyValue)
357     {
358         pStr = _pData;
359         //pStr->IncreaseRef();
360         //std::wcout << L"copyValueWithoutClone -> " << pStr << L" : " << pStr->getRef() << std::endl;
361     }
362     else
363     {
364         pStr = _pData->clone();
365     }
366
367     return pStr;
368 }
369
370 void Struct::deleteAll()
371 {
372     for (int i = 0 ; i < getSize() ; i++)
373     {
374         m_pRealData[i]->DecreaseRef();
375         if (m_pRealData[i]->isDeletable())
376         {
377             delete m_pRealData[i];
378         }
379     }
380     delete[] m_pRealData;
381     m_pRealData = NULL;
382 }
383
384 void Struct::deleteImg()
385 {
386     return;
387 }
388
389 SingleStruct** Struct::allocData(int _iSize)
390 {
391     SingleStruct** pData = new SingleStruct*[_iSize];
392     for (int i = 0 ; i < _iSize ; i++)
393     {
394         pData[i] = NULL;
395     }
396     return pData;
397 }
398
399 bool Struct::subMatrixToString(std::wostringstream& ostr, int* _piDims, int _iDims)
400 {
401     return true;
402 }
403
404 bool Struct::addField(const std::wstring& _sKey)
405 {
406     if (getSize() == 0)
407     {
408         //change dimension to 1x1 and add field
409         resize(1, 1);
410     }
411
412     for (int i = 0 ; i < getSize() ; i++)
413     {
414         /*
415                     if(get(i)->isRef(1))
416                     {//assign more than once
417                         //clone it before add field
418                         set(i, get(i)->clone());
419                     }
420         */
421         get(i)->addField(_sKey);
422     }
423     return true;
424 }
425
426 bool Struct::addFieldFront(const std::wstring& _sKey)
427 {
428     if (getSize() == 0)
429     {
430         //change dimension to 1x1 and add field
431         resize(1, 1);
432     }
433
434     for (int i = 0 ; i < getSize() ; i++)
435     {
436         get(i)->addFieldFront(_sKey);
437     }
438
439     return true;
440 }
441
442 bool Struct::removeField(const std::wstring& _sKey)
443 {
444     for (int j = 0; j < getSize(); j++)
445     {
446         get(j)->removeField(_sKey);
447     }
448
449     return true;
450 }
451
452 bool Struct::toString(std::wostringstream& ostr)
453 {
454     if (getSize() == 0)
455     {
456         ostr << L"0x0 struct array with no field.";
457     }
458     else if (getSize() == 1)
459     {
460         SingleStruct* pSS =  get(0);
461         String* pwstFields =  pSS->getFieldNames();
462         if (pwstFields->getSize() == 0)
463         {
464             ostr << L"1x1 struct array with no field.";
465         }
466
467         for (int i = 0 ; i < pwstFields->getSize() ; i++)
468         {
469             std::wstring wstField(pwstFields->get(i));
470             InternalType* pIT = pSS->get(wstField);
471
472             //                ostr << L"  " << wstField << ": ";
473             ostr << L"  " << wstField << L": ";
474             ostr << pIT->toStringInLine();
475             ostr << std::endl;
476         }
477         delete pwstFields;
478     }
479     else
480     {
481         ostr << L"  ";
482         for (int i = 0 ; i < m_iDims ; i++)
483         {
484             if (i > 0)
485             {
486                 ostr << L"x";
487             }
488             ostr << m_piDims[i];
489         }
490         ostr << L" struct array with ";
491
492         String* pwstFields = getFieldNames();
493         ostr <<  L"fields:" << std::endl;
494         for (int i = 0 ; i < pwstFields->getSize() ; i++)
495         {
496             ostr << L"    " << pwstFields->get(i) << std::endl;
497         }
498         delete pwstFields;
499     }
500
501     return true;
502 }
503
504 List* Struct::extractFieldWithoutClone(std::wstring _wstField)
505 {
506     List* pL = new List();
507     for (int j = 0 ; j < getSize() ; j++)
508     {
509         pL->set(j, get(j)->get(_wstField));
510     }
511
512     return pL;
513 }
514
515 std::vector<InternalType*> Struct::extractFields(std::vector<std::wstring> _wstFields)
516 {
517     std::vector<InternalType*> ResultList;
518
519     for (int i = 0 ; i < _wstFields.size() ; i++)
520     {
521         ResultList.push_back(extractField(_wstFields[i]));
522     }
523
524     return ResultList;
525 }
526
527 InternalType * Struct::extractField(const std::wstring & wstField)
528 {
529     if (wstField == L"dims")
530     {
531         Int32 * pDims = new Int32(1, getDims());
532         for (int j = 0 ; j < getDims() ; j++)
533         {
534             pDims->set(j, getDimsArray()[j]);
535         }
536
537         return pDims;
538     }
539     else
540     {
541         if (getSize() == 1)
542         {
543             return get(0)->get(wstField)->clone();
544         }
545         else
546         {
547             List * pL = new List();
548             for (int j = 0 ; j < getSize() ; j++)
549             {
550                 pL->append(get(j)->get(wstField)->clone());
551             }
552
553             return pL;
554         }
555     }
556 }
557
558 std::vector<InternalType*> Struct::extractFields(typed_list* _pArgs)
559 {
560     std::vector<InternalType*> ResultList;
561
562     int iDims           = (int)_pArgs->size();
563     typed_list pArg;
564
565     int* piMaxDim       = new int[iDims];
566     int* piCountDim     = new int[iDims];
567
568     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
569     if (iSeqCount == 0)
570     {
571         ResultList.push_back(createEmptyDouble());
572         return ResultList;
573     }
574
575     Double* pIndex = pArg[0]->getAs<Double>();
576
577     for (int i = 0 ; i < iSeqCount ; i++)
578     {
579         int iIndex = (int)pIndex->get(i);
580
581         if (iIndex == 1)
582         {
583             //struct fields name
584             String* pS = getFieldNames();
585
586             String* pFields = new String(1, pS->getSize() + 2);
587
588             pFields->set(0, L"st");
589             pFields->set(1, L"dims");
590
591             for (int j = 0 ; j < pS->getSize() ; j++)
592             {
593                 pFields->set(2 + j, pS->get(j));
594             }
595
596             delete pS;
597             ResultList.push_back(pFields);
598         }
599         else if (iIndex == 2)
600         {
601             //struct dims
602             Int32* pDims = new Int32(1, getDims());
603             for (int j = 0 ; j < getDims() ; j++)
604             {
605                 pDims->set(j, getDimsArray()[j]);
606             }
607
608             ResultList.push_back(pDims);
609         }
610         else if (getSize() == 0)
611         {
612             break;
613         }
614         else if (iIndex > get(0)->getData().size() + 2)
615         {
616             break;
617         }
618         else if (getSize() == 1)
619         {
620             //return elements
621             std::list<InternalType*> pData = get(0)->getData();
622             std::list<InternalType*>::iterator it = pData.begin();
623             std::advance(it, iIndex - 3);
624             ResultList.push_back((*it)->clone());
625         }
626         else
627         {
628             //return each elements for sub structs in a list
629             List* pL = new List();
630
631             for (int j = 0 ; j < getSize() ; j++)
632             {
633                 //-2 for fieldlist and dims, -1 for indexed at 0
634                 std::list<InternalType*> pData = get(j)->getData();
635                 std::list<InternalType*>::iterator it = pData.begin();
636                 std::advance(it, iIndex - 3);
637                 pL->append((*it)->clone());
638             }
639
640             ResultList.push_back(pL);
641         }
642     }
643
644     //free pArg content
645     for (int iArg = 0 ; iArg < pArg.size() ; iArg++)
646     {
647         if (pArg[iArg] != (*_pArgs)[iArg] && pArg[iArg]->isDeletable())
648         {
649             delete pArg[iArg];
650         }
651     }
652
653     return ResultList;
654 }
655
656 bool Struct::resize(int _iNewRows, int _iNewCols)
657 {
658     int piDims[2] = {_iNewRows, _iNewCols};
659     return resize(piDims, 2);
660 }
661
662 bool Struct::resize(int* _piDims, int _iDims)
663 {
664     bool bRes = ArrayOf<SingleStruct*>::resize(_piDims, _iDims);
665     if (bRes)
666     {
667         // insert field(s) only in new element(s) of current struct
668         String* pFields = getFieldNames();
669         for (int iterField = 0; iterField < pFields->getSize(); iterField++)
670         {
671             for (int iterStruct = 0; iterStruct < getSize(); iterStruct++)
672             {
673                 get(iterStruct)->addField(pFields->get(iterField));
674             }
675         }
676     }
677
678     return bRes;
679 }
680
681 InternalType* Struct::insertWithoutClone(typed_list* _pArgs, InternalType* _pSource)
682 {
683     //std::wcout << L"insertWithoutClone start" << std::endl;
684     m_bDisableCloneInCopyValue = true;
685     InternalType* pIT = insert(_pArgs, _pSource);
686     _pSource->IncreaseRef();
687     //std::wcout << L"insertWithoutClone -> " << _pSource << L" : " << _pSource->getRef() << std::endl;
688     m_bDisableCloneInCopyValue = false;
689     //std::wcout << L"insertWithoutClone end" << std::endl;
690     return pIT;
691 }
692
693 InternalType* Struct::extractWithoutClone(typed_list* _pArgs)
694 {
695     //std::wcout << L"extractWithoutClone start" << std::endl;
696     m_bDisableCloneInCopyValue = true;
697     InternalType* pIT = extract(_pArgs);
698     m_bDisableCloneInCopyValue = false;
699     //std::wcout << L"extractWithoutClone end" << std::endl;
700     return pIT;
701 }
702
703 void Struct::setCloneInCopyValue(bool _val)
704 {
705     m_bDisableCloneInCopyValue = !_val;
706 }
707
708 }