Xlist integrated in another Xlist need to be copied to perform an affectation
[scilab.git] / scilab / modules / ast / src / cpp / types / list.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2010-2010 - DIGITEO - Bruno JOFRET
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
13 #include <sstream>
14 #include "double.hxx"
15 #include "list.hxx"
16 #include "listundefined.hxx"
17 #include "listinsert.hxx"
18 #include "types_tools.hxx"
19 #include "scilabexception.hxx"
20 #include "localization.hxx"
21 #include "scilabWrite.hxx"
22 #include "types_tools.hxx"
23 #include "function.hxx"
24
25 #ifndef NDEBUG
26 #include "inspector.hxx"
27 #endif
28
29 extern "C"
30 {
31 #include "os_string.h"
32 }
33
34 namespace types
35 {
36 /**
37 ** Constructor & Destructor (public)
38 */
39 List::List() : Container()
40 {
41     m_plData = new std::vector<InternalType *>();
42 #ifndef NDEBUG
43     Inspector::addItem(this);
44 #endif
45 }
46
47 List::~List()
48 {
49     if (isDeletable() == true)
50     {
51         for (auto data : *m_plData)
52         {
53             data->DecreaseRef();
54             data->killMe();
55         }
56         delete m_plData;
57     }
58 #ifndef NDEBUG
59     Inspector::removeItem(this);
60 #endif
61 }
62
63 /**
64 ** Private Copy Constructor and data Access
65 */
66 List::List(List *_oListCopyMe)
67 {
68     m_plData = new std::vector<InternalType *>;
69
70     for (int i = 0 ; i < (int)_oListCopyMe->getData()->size() ; i++)
71     {
72         append((*_oListCopyMe->getData())[i]);
73     }
74
75     m_iSize = static_cast<int>(m_plData->size());
76 #ifndef NDEBUG
77     Inspector::addItem(this);
78 #endif
79 }
80
81 std::vector<InternalType *> *List::getData()
82 {
83     return m_plData;
84 }
85
86 /**
87 ** size_get
88 ** Return the number of elements in list
89 */
90 int List::getSize()
91 {
92     return static_cast<int>(m_plData->size());
93 }
94
95 /**
96 ** append(InternalType *_typedValue)
97 ** Append the given value to the end of the List
98 */
99 void List::append(InternalType *_typedValue)
100 {
101     if (_typedValue->isList())
102     {
103         m_plData->push_back(_typedValue->clone());
104     }
105     else
106     {
107         m_plData->push_back(_typedValue);
108     }
109     m_plData->back()->IncreaseRef();
110     m_iSize = static_cast<int>(m_plData->size());
111 }
112
113 /**
114 ** Clone
115 ** Create a new List and Copy all values.
116 */
117 InternalType *List::clone()
118 {
119     return new List(this);
120 }
121
122 /**
123 ** toString to display Lists
124 */
125 bool List::toString(std::wostringstream& ostr)
126 {
127     if (getSize() == 0)
128     {
129         ostr.str(L"");
130         ostr << L"     ()" << std::endl;
131     }
132     else
133     {
134         wchar_t* wcsVarName = os_wcsdup(ostr.str().c_str());
135         int iPosition = 1;
136         for (auto val : *m_plData)
137         {
138             std::wostringstream nextVarName;
139             ostr.str(L"");
140             nextVarName << " " << SPACES_LIST << wcsVarName << L"(" << iPosition++ << L")";
141             ostr << std::endl << nextVarName.str() << std::endl << std::endl;
142             scilabForcedWriteW(ostr.str().c_str());
143             if (VariableToString(val, nextVarName.str().c_str()) == types::Function::Error)
144             {
145                 free(wcsVarName);
146                 ostr.str(L"");
147                 return true;
148             }
149         }
150
151         ostr.str(L"");
152         free(wcsVarName);
153     }
154
155     return true;
156 }
157
158 InternalType* List::extract(typed_list* _pArgs)
159 {
160     List* outList = new List();
161     //check input param
162     if (_pArgs->size() != 1)
163     {
164         return outList;
165     }
166
167     typed_list pArg;
168     int iDims           = (int)_pArgs->size();
169
170     int* piMaxDim       = new int[iDims];
171     int* piCountDim     = new int[iDims];
172
173     //evaluate each argument and replace by appropriate value and compute the count of combinations
174     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
175     delete[] piMaxDim;
176     delete[] piCountDim;
177
178     for (int i = 0 ; i < iSeqCount ; i++)
179     {
180         int idx = (int)pArg[0]->getAs<Double>()->get(i);
181         if (idx > getSize() || idx < 1)
182         {
183             delete outList;
184             outList = NULL;
185             break;
186         }
187         InternalType* pIT = (*m_plData)[idx - 1];
188         outList->set(i, pIT);
189     }
190
191     //free pArg content
192     cleanIndexesArguments(_pArgs, &pArg);
193
194     return outList;
195 }
196
197 InternalType* List::insert(typed_list* _pArgs, InternalType* _pSource)
198 {
199     //check input param
200     if (_pArgs->size() != 1)
201     {
202         return NULL;
203     }
204
205     typed_list pArg;
206     int iDims           = (int)_pArgs->size();
207
208     int* piMaxDim       = new int[iDims];
209     int* piCountDim     = new int[iDims];
210
211     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
212     delete[] piMaxDim;
213     delete[] piCountDim;
214     if (iSeqCount == 0)
215     {
216         //free pArg content
217         cleanIndexesArguments(_pArgs, &pArg);
218         //do nothing
219         return this;
220     }
221     else if (iSeqCount > 1)
222     {
223         //free pArg content
224         cleanIndexesArguments(_pArgs, &pArg);
225         std::wostringstream os;
226         os << _W("Unable to insert multiple item in a list.\n");
227         throw ast::ScilabError(os.str());
228     }
229     else if (iSeqCount < 0)
230     {
231         //free pArg content
232         cleanIndexesArguments(_pArgs, &pArg);
233         return NULL;
234     }
235
236     int idx = (int)pArg[0]->getAs<Double>()->get(0);
237     if (_pSource->isListDelete())
238     {
239         //delete item
240         if (idx == 0)
241         {
242             //free pArg content
243             cleanIndexesArguments(_pArgs, &pArg);
244             //do nothing
245             return this;
246         }
247         else if (idx <= (int)m_plData->size())
248         {
249             InternalType* pIT = (*m_plData)[idx - 1];
250             if (pIT)
251             {
252                 pIT->DecreaseRef();
253                 pIT->killMe();
254             }
255             m_plData->erase(m_plData->begin() + idx - 1);
256         }
257     }
258     else if (_pSource->isListInsert())
259     {
260         //insert item
261         if (idx == 0)
262         {
263             //free pArg content
264             cleanIndexesArguments(_pArgs, &pArg);
265             std::wostringstream os;
266             os << _W("Index out of bounds.\n");
267             throw ast::ScilabError(os.str());
268         }
269
270         InternalType* pInsert = _pSource->getAs<ListInsert>()->getInsert()->clone();
271         pInsert->IncreaseRef();
272         if (idx > (int)m_plData->size())
273         {
274             //try to insert after the last index, increase list size and assign value
275             while ((int)m_plData->size() < idx)
276             {
277                 //incease list size and fill with "Undefined"
278                 m_plData->push_back(new ListUndefined());
279             }
280             (*m_plData)[idx - 1] = pInsert;
281         }
282         else
283         {
284             m_plData->insert(m_plData->begin() + idx - 1, pInsert);
285         }
286     }
287     else if (idx == 0)
288     {
289         //special cazse to insert at the first position
290         InternalType* pInsert = NULL;
291         pInsert = _pSource->clone();
292         pInsert->IncreaseRef();
293         m_plData->insert(m_plData->begin(), pInsert);
294     }
295     else
296     {
297         while ((int)m_plData->size() < idx)
298         {
299             //incease list size and fill with "Undefined"
300             InternalType* pLU = new ListUndefined();
301             pLU->IncreaseRef();
302             m_plData->push_back(pLU);
303         }
304
305         InternalType* pIT = (*m_plData)[idx - 1];
306         pIT->DecreaseRef();
307         pIT->killMe();
308
309         (*m_plData)[idx - 1] = _pSource->clone();
310         (*m_plData)[idx - 1]->IncreaseRef();
311     }
312
313     m_iSize = (int)m_plData->size();
314
315     //free pArg content
316     cleanIndexesArguments(_pArgs, &pArg);
317
318     return this;
319 }
320
321 InternalType* List::get(const int _iIndex)
322 {
323     if (_iIndex >= 0 && _iIndex < (int)m_plData->size())
324     {
325         return (*m_plData)[_iIndex];
326     }
327     return NULL;
328 }
329
330 bool List::set(const int _iIndex, InternalType* _pIT)
331 {
332     if (_iIndex < 0)
333     {
334         return false;
335     }
336
337     while ((int)m_plData->size() < _iIndex)
338     {
339         //incease list size and fill with "Undefined"
340         m_plData->push_back(new ListUndefined());
341         m_plData->back()->IncreaseRef();
342         m_iSize = getSize();
343     }
344
345     if ((int)m_plData->size() == _iIndex)
346     {
347         _pIT->IncreaseRef();
348         m_plData->push_back(_pIT);
349         m_iSize = getSize();
350     }
351     else
352     {
353         InternalType* pOld = (*m_plData)[_iIndex];
354
355         _pIT->IncreaseRef();
356         (*m_plData)[_iIndex] = _pIT;
357
358         //manage ref on the old value
359         if (pOld)
360         {
361             pOld->DecreaseRef();
362             pOld->killMe();
363         }
364     }
365
366     return true;
367 }
368
369 bool List::operator==(const InternalType& it)
370 {
371     if (const_cast<InternalType &>(it).isList() == false)
372     {
373         return false;
374     }
375
376     List* plst = const_cast<InternalType &>(it).getAs<List>();
377
378     if (getSize() != plst->getSize())
379     {
380         return false;
381     }
382
383     for (int i = 0; i < getSize(); i++)
384     {
385         if (*(*m_plData)[i] != *plst->get(i))
386         {
387             return false;
388         }
389     }
390
391     return true;
392 }
393
394 }