List extraction fixed.
[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
24 #ifndef NDEBUG
25 #include "inspector.hxx"
26 #endif
27
28 extern "C"
29 {
30 #include "os_wcsdup.h"
31 }
32
33 namespace types
34 {
35 /**
36 ** Constructor & Destructor (public)
37 */
38 List::List() : Container()
39 {
40     m_plData = new std::vector<InternalType *>();
41 #ifndef NDEBUG
42     //Inspector::addItem(this);
43 #endif
44 }
45
46 List::~List()
47 {
48     if (isDeletable() == true)
49     {
50         std::vector<InternalType *>::iterator itValues;
51         for (itValues = m_plData->begin() ; itValues != m_plData->end() ; ++itValues)
52         {
53             (*itValues)->DecreaseRef();
54             (*itValues)->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     std::vector<InternalType *>::iterator itValues;
69     m_plData = new std::vector<InternalType *>;
70
71     for (int i = 0 ; i < (int)_oListCopyMe->getData()->size() ; i++)
72     {
73         append((*_oListCopyMe->getData())[i]);
74     }
75
76     m_iSize = static_cast<int>(m_plData->size());
77 #ifndef NDEBUG
78     //Inspector::addItem(this);
79 #endif
80 }
81
82 std::vector<InternalType *> *List::getData()
83 {
84     return m_plData;
85 }
86
87 /**
88 ** size_get
89 ** Return the number of elements in list
90 */
91 int List::getSize()
92 {
93     return static_cast<int>(m_plData->size());
94 }
95
96 /**
97 ** append(InternalType *_typedValue)
98 ** Append the given value to the end of the List
99 */
100 void List::append(InternalType *_typedValue)
101 {
102     m_plData->push_back(_typedValue->clone());
103     m_plData->back()->IncreaseRef();
104     m_iSize = static_cast<int>(m_plData->size());
105 }
106
107 /**
108 ** Clone
109 ** Create a new List and Copy all values.
110 */
111 InternalType *List::clone()
112 {
113     return new List(this);
114 }
115
116 /**
117 ** toString to display Lists
118 */
119 bool List::toString(std::wostringstream& ostr)
120 {
121     if (getSize() == 0)
122     {
123         ostr.str(L"");
124         ostr << L"     ()" << std::endl;
125         scilabWriteW(ostr.str().c_str());
126     }
127     else
128     {
129         wchar_t* wcsVarName = os_wcsdup(ostr.str().c_str());
130         int iPosition = 1;
131         std::vector<InternalType *>::iterator itValues;
132         for (itValues = m_plData->begin() ; itValues != m_plData->end() ; ++itValues, ++iPosition)
133         {
134             std::wostringstream nextVarName;
135             ostr.str(L"");
136             nextVarName << " " << wcsVarName << L"(" << iPosition << L")";
137             ostr << std::endl << nextVarName.str() << std::endl << std::endl;
138             scilabWriteW(ostr.str().c_str());
139             VariableToString(*itValues, nextVarName.str().c_str());
140         }
141
142         free(wcsVarName);
143     }
144
145     return true;
146 }
147
148 InternalType* List::extract(typed_list* _pArgs)
149 {
150     List* outList = new List();
151     //check input param
152     if (_pArgs->size() != 1)
153     {
154         return outList;
155     }
156
157     typed_list pArg;
158     int iDims           = (int)_pArgs->size();
159
160     int* piMaxDim       = new int[iDims];
161     int* piCountDim     = new int[iDims];
162
163     //evaluate each argument and replace by appropriate value and compute the count of combinations
164     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
165     if (iSeqCount == 0)
166     {
167         //outList.push_back(Double::Empty());
168     }
169
170     for (int i = 0 ; i < iSeqCount ; i++)
171     {
172         int idx = (int)pArg[0]->getAs<Double>()->get(i);
173         if (idx > getSize() || idx < 1)
174         {
175             delete outList;
176             outList = NULL;
177             break;
178         }
179         InternalType* pIT = (*m_plData)[idx - 1];
180         outList->set(i, pIT);
181     }
182
183     //free pArg content
184     for (int iArg = 0 ; iArg < (int)pArg.size() ; iArg++)
185     {
186         if (pArg[iArg] != (*_pArgs)[iArg])
187         {
188             pArg[iArg]->killMe();
189         }
190     }
191
192     return outList;
193 }
194
195 InternalType* List::insert(typed_list* _pArgs, InternalType* _pSource)
196 {
197     //check input param
198     if (_pArgs->size() != 1)
199     {
200         return NULL;
201     }
202
203     typed_list pArg;
204     int iDims           = (int)_pArgs->size();
205
206     int* piMaxDim       = new int[iDims];
207     int* piCountDim     = new int[iDims];
208
209     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
210     if (iSeqCount == 0)
211     {
212         //do nothing
213         return this;
214     }
215     else if (iSeqCount > 1)
216     {
217         std::wostringstream os;
218         os << _W("Unable to insert multiple item in a list.\n");
219         throw ast::ScilabError(os.str());
220     }
221     else if (iSeqCount < 0)
222     {
223         return NULL;
224     }
225
226     int idx = (int)pArg[0]->getAs<Double>()->get(0);
227     if (_pSource->isListDelete())
228     {
229         //delete item
230         if (idx == 0)
231         {
232             //do nothing
233             return this;
234         }
235         else if (idx <= (int)m_plData->size())
236         {
237             InternalType* pIT = (*m_plData)[idx - 1];
238             if (pIT)
239             {
240                 pIT->killMe();
241             }
242             m_plData->erase(m_plData->begin() + idx - 1);
243         }
244     }
245     else if (_pSource->isListInsert())
246     {
247         //insert item
248         if (idx == 0)
249         {
250             std::wostringstream os;
251             os << _W("Index out of bounds.\n");
252             throw ast::ScilabError(os.str());
253         }
254
255         InternalType* pInsert = _pSource->getAs<ListInsert>()->getInsert()->clone();
256         pInsert->IncreaseRef();
257         if (idx > (int)m_plData->size())
258         {
259             //try to insert after the last index, increase list size and assign value
260             while ((int)m_plData->size() < idx)
261             {
262                 //incease list size and fill with "Undefined"
263                 m_plData->push_back(new ListUndefined());
264             }
265             (*m_plData)[idx - 1] = pInsert;
266         }
267         else
268         {
269             m_plData->insert(m_plData->begin() + idx - 1, pInsert);
270         }
271     }
272     else if (idx == 0)
273     {
274         //special cazse to insert at the first position
275         InternalType* pInsert = NULL;
276         pInsert = _pSource->clone();
277         pInsert->IncreaseRef();
278         m_plData->insert(m_plData->begin(), pInsert);
279     }
280     else
281     {
282         while ((int)m_plData->size() < idx)
283         {
284             //incease list size and fill with "Undefined"
285             InternalType* pLU = new ListUndefined();
286             pLU->IncreaseRef();
287             m_plData->push_back(pLU);
288         }
289
290         InternalType* pIT = (*m_plData)[idx - 1];
291         pIT->DecreaseRef();
292         if (pIT)
293         {
294             pIT->killMe();
295         }
296
297         (*m_plData)[idx - 1] = _pSource->clone();
298         (*m_plData)[idx - 1]->IncreaseRef();
299     }
300
301     m_iSize = (int)m_plData->size();
302
303     //free pArg content
304     for (int iArg = 0 ; iArg < (int)pArg.size() ; iArg++)
305     {
306         if (pArg[iArg] != (*_pArgs)[iArg])
307         {
308             pArg[iArg]->killMe();
309         }
310     }
311
312     return this;
313 }
314
315 InternalType* List::get(const int _iIndex)
316 {
317     if (_iIndex >= 0 && _iIndex < (int)m_plData->size())
318     {
319         return (*m_plData)[_iIndex];
320     }
321     return NULL;
322 }
323
324 bool List::set(const int _iIndex, InternalType* _pIT)
325 {
326     if (_iIndex < 0)
327     {
328         return false;
329     }
330
331     while ((int)m_plData->size() < _iIndex)
332     {
333         //incease list size and fill with "Undefined"
334         m_plData->push_back(new ListUndefined());
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 }