909ad57c8c71239c2ad0ab491a71f234686b9bba
[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     m_plData->push_back(_typedValue);
102     m_plData->back()->IncreaseRef();
103     m_iSize = static_cast<int>(m_plData->size());
104 }
105
106 /**
107 ** Clone
108 ** Create a new List and Copy all values.
109 */
110 InternalType *List::clone()
111 {
112     return new List(this);
113 }
114
115 /**
116 ** toString to display Lists
117 */
118 bool List::toString(std::wostringstream& ostr)
119 {
120     if (getSize() == 0)
121     {
122         ostr.str(L"");
123         ostr << L"     ()" << std::endl;
124     }
125     else
126     {
127         wchar_t* wcsVarName = os_wcsdup(ostr.str().c_str());
128         int iPosition = 1;
129         for (auto val : *m_plData)
130         {
131             std::wostringstream nextVarName;
132             ostr.str(L"");
133             nextVarName << " " << SPACES_LIST << wcsVarName << L"(" << iPosition++ << L")";
134             ostr << std::endl << nextVarName.str() << std::endl << std::endl;
135             scilabForcedWriteW(ostr.str().c_str());
136             if (VariableToString(val, nextVarName.str().c_str()) == types::Function::Error)
137             {
138                 free(wcsVarName);
139                 ostr.str(L"");
140                 return true;
141             }
142         }
143
144         ostr.str(L"");
145         free(wcsVarName);
146     }
147
148     return true;
149 }
150
151 InternalType* List::extract(typed_list* _pArgs)
152 {
153     List* outList = new List();
154     //check input param
155     if (_pArgs->size() != 1)
156     {
157         return outList;
158     }
159
160     typed_list pArg;
161     int iDims           = (int)_pArgs->size();
162
163     int* piMaxDim       = new int[iDims];
164     int* piCountDim     = new int[iDims];
165
166     //evaluate each argument and replace by appropriate value and compute the count of combinations
167     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
168     delete[] piMaxDim;
169     delete[] piCountDim;
170
171     for (int i = 0 ; i < iSeqCount ; i++)
172     {
173         int idx = (int)pArg[0]->getAs<Double>()->get(i);
174         if (idx > getSize() || idx < 1)
175         {
176             delete outList;
177             outList = NULL;
178             break;
179         }
180         InternalType* pIT = (*m_plData)[idx - 1];
181         outList->set(i, pIT);
182     }
183
184     //free pArg content
185     cleanIndexesArguments(_pArgs, &pArg);
186
187     return outList;
188 }
189
190 InternalType* List::insert(typed_list* _pArgs, InternalType* _pSource)
191 {
192     //check input param
193     if (_pArgs->size() != 1)
194     {
195         return NULL;
196     }
197
198     typed_list pArg;
199     int iDims           = (int)_pArgs->size();
200
201     int* piMaxDim       = new int[iDims];
202     int* piCountDim     = new int[iDims];
203
204     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
205     delete[] piMaxDim;
206     delete[] piCountDim;
207     if (iSeqCount == 0)
208     {
209         //free pArg content
210         cleanIndexesArguments(_pArgs, &pArg);
211         //do nothing
212         return this;
213     }
214     else if (iSeqCount > 1)
215     {
216         //free pArg content
217         cleanIndexesArguments(_pArgs, &pArg);
218         std::wostringstream os;
219         os << _W("Unable to insert multiple item in a list.\n");
220         throw ast::ScilabError(os.str());
221     }
222     else if (iSeqCount < 0)
223     {
224         //free pArg content
225         cleanIndexesArguments(_pArgs, &pArg);
226         return NULL;
227     }
228
229     int idx = (int)pArg[0]->getAs<Double>()->get(0);
230     if (_pSource->isListDelete())
231     {
232         //delete item
233         if (idx == 0)
234         {
235             //free pArg content
236             cleanIndexesArguments(_pArgs, &pArg);
237             //do nothing
238             return this;
239         }
240         else if (idx <= (int)m_plData->size())
241         {
242             InternalType* pIT = (*m_plData)[idx - 1];
243             if (pIT)
244             {
245                 pIT->DecreaseRef();
246                 pIT->killMe();
247             }
248             m_plData->erase(m_plData->begin() + idx - 1);
249         }
250     }
251     else if (_pSource->isListInsert())
252     {
253         //insert item
254         if (idx == 0)
255         {
256             //free pArg content
257             cleanIndexesArguments(_pArgs, &pArg);
258             std::wostringstream os;
259             os << _W("Index out of bounds.\n");
260             throw ast::ScilabError(os.str());
261         }
262
263         InternalType* pInsert = _pSource->getAs<ListInsert>()->getInsert()->clone();
264         pInsert->IncreaseRef();
265         if (idx > (int)m_plData->size())
266         {
267             //try to insert after the last index, increase list size and assign value
268             while ((int)m_plData->size() < idx)
269             {
270                 //incease list size and fill with "Undefined"
271                 m_plData->push_back(new ListUndefined());
272             }
273             (*m_plData)[idx - 1] = pInsert;
274         }
275         else
276         {
277             m_plData->insert(m_plData->begin() + idx - 1, pInsert);
278         }
279     }
280     else if (idx == 0)
281     {
282         //special cazse to insert at the first position
283         InternalType* pInsert = NULL;
284         pInsert = _pSource->clone();
285         pInsert->IncreaseRef();
286         m_plData->insert(m_plData->begin(), pInsert);
287     }
288     else
289     {
290         while ((int)m_plData->size() < idx)
291         {
292             //incease list size and fill with "Undefined"
293             InternalType* pLU = new ListUndefined();
294             pLU->IncreaseRef();
295             m_plData->push_back(pLU);
296         }
297
298         InternalType* pIT = (*m_plData)[idx - 1];
299         pIT->DecreaseRef();
300         pIT->killMe();
301
302         (*m_plData)[idx - 1] = _pSource->clone();
303         (*m_plData)[idx - 1]->IncreaseRef();
304     }
305
306     m_iSize = (int)m_plData->size();
307
308     //free pArg content
309     cleanIndexesArguments(_pArgs, &pArg);
310
311     return this;
312 }
313
314 InternalType* List::get(const int _iIndex)
315 {
316     if (_iIndex >= 0 && _iIndex < (int)m_plData->size())
317     {
318         return (*m_plData)[_iIndex];
319     }
320     return NULL;
321 }
322
323 bool List::set(const int _iIndex, InternalType* _pIT)
324 {
325     if (_iIndex < 0)
326     {
327         return false;
328     }
329
330     while ((int)m_plData->size() < _iIndex)
331     {
332         //incease list size and fill with "Undefined"
333         m_plData->push_back(new ListUndefined());
334         m_plData->back()->IncreaseRef();
335         m_iSize = getSize();
336     }
337
338     if ((int)m_plData->size() == _iIndex)
339     {
340         _pIT->IncreaseRef();
341         m_plData->push_back(_pIT);
342         m_iSize = getSize();
343     }
344     else
345     {
346         InternalType* pOld = (*m_plData)[_iIndex];
347
348         _pIT->IncreaseRef();
349         (*m_plData)[_iIndex] = _pIT;
350
351         //manage ref on the old value
352         if (pOld)
353         {
354             pOld->DecreaseRef();
355             pOld->killMe();
356         }
357     }
358
359     return true;
360 }
361
362 bool List::operator==(const InternalType& it)
363 {
364     if (const_cast<InternalType &>(it).isList() == false)
365     {
366         return false;
367     }
368
369     List* plst = const_cast<InternalType &>(it).getAs<List>();
370
371     if (getSize() != plst->getSize())
372     {
373         return false;
374     }
375
376     for (int i = 0; i < getSize(); i++)
377     {
378         if (*(*m_plData)[i] != *plst->get(i))
379         {
380             return false;
381         }
382     }
383
384     return true;
385 }
386
387 }