delete of opt arguments corrected.
[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
22 #ifndef NDEBUG
23 #include "inspector.hxx"
24 #endif
25
26 extern "C"
27 {
28 #include "os_wcsdup.h"
29 }
30
31 namespace types
32 {
33 /**
34 ** Constructor & Destructor (public)
35 */
36 List::List() : Container()
37 {
38     m_plData = new std::vector<InternalType *>();
39 #ifndef NDEBUG
40     //Inspector::addItem(this);
41 #endif
42 }
43
44 List::~List()
45 {
46     if (isDeletable() == true)
47     {
48         std::vector<InternalType *>::iterator itValues;
49         for (itValues = m_plData->begin() ; itValues != m_plData->end() ; ++itValues)
50         {
51             (*itValues)->DecreaseRef();
52             (*itValues)->killMe();
53         }
54         delete m_plData;
55     }
56 #ifndef NDEBUG
57     //Inspector::removeItem(this);
58 #endif
59 }
60
61 /**
62 ** Private Copy Constructor and data Access
63 */
64 List::List(List *_oListCopyMe)
65 {
66     std::vector<InternalType *>::iterator itValues;
67     m_plData = new std::vector<InternalType *>;
68
69     for (int i = 0 ; i < _oListCopyMe->getData()->size() ; i++)
70     {
71         append((*_oListCopyMe->getData())[i]);
72     }
73
74     m_iSize = static_cast<int>(m_plData->size());
75 #ifndef NDEBUG
76     //Inspector::addItem(this);
77 #endif
78 }
79
80 std::vector<InternalType *> *List::getData()
81 {
82     return m_plData;
83 }
84
85 /**
86 ** size_get
87 ** Return the number of elements in list
88 */
89 int List::getSize()
90 {
91     return static_cast<int>(m_plData->size());
92 }
93
94 /**
95 ** append(InternalType *_typedValue)
96 ** Append the given value to the end of the List
97 */
98 void List::append(InternalType *_typedValue)
99 {
100     m_plData->push_back(_typedValue->clone());
101     m_plData->back()->IncreaseRef();
102     m_iSize = static_cast<int>(m_plData->size());
103 }
104
105 /**
106 ** Clone
107 ** Create a new List and Copy all values.
108 */
109 InternalType *List::clone()
110 {
111     return new List(this);
112 }
113
114 GenericType* List::getColumnValues(int _iPos)
115 {
116     return NULL;
117 }
118
119 /**
120 ** toString to display Lists
121 ** FIXME : Find a better indentation process
122 */
123 bool List::toString(std::wostringstream& ostr)
124 {
125     wchar_t* wcsVarName = os_wcsdup(ostr.str().c_str());
126     ostr.str(L"");
127
128     if (getSize() == 0)
129     {
130         ostr << wcsVarName << L"()" << std::endl;
131     }
132     else
133     {
134         int iPosition = 1;
135         std::vector<InternalType *>::iterator itValues;
136         for (itValues = m_plData->begin() ; itValues != m_plData->end() ; ++itValues, ++iPosition)
137         {
138             ostr << "     " << wcsVarName << L"(" << iPosition << L")" << std::endl;
139             //maange lines
140             bool bFinish = (*itValues)->toString(ostr);
141             ostr << std::endl;
142         }
143     }
144
145     free(wcsVarName);
146     return true;
147 }
148
149 std::vector<InternalType*>      List::extract(typed_list* _pArgs)
150 {
151     std::vector<InternalType*> outList;
152     //check input param
153     if (_pArgs->size() != 1)
154     {
155         return outList;
156     }
157
158     typed_list pArg;
159     int iDims           = (int)_pArgs->size();
160
161     int* piMaxDim       = new int[iDims];
162     int* piCountDim     = new int[iDims];
163
164     //evaluate each argument and replace by appropriate value and compute the count of combinations
165     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
166     if (iSeqCount == 0)
167     {
168         //outList.push_back(Double::Empty());
169     }
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             outList.clear();
177             break;
178         }
179         InternalType* pIT = (*m_plData)[idx - 1];
180         outList.push_back(pIT);
181     }
182
183     //free pArg content
184     for (int iArg = 0 ; iArg < 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 <= 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 > m_plData->size())
258         {
259             //try to insert after the last index, increase list size and assign value
260             while (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 (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 < 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 < 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 (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     InternalType* pOld = (*m_plData)[_iIndex];
339
340     _pIT->IncreaseRef();
341     (*m_plData)[_iIndex] = _pIT;
342
343     //manage ref on the old value
344     if (pOld)
345     {
346         pOld->DecreaseRef();
347         pOld->killMe();
348     }
349
350     return true;
351 }
352
353 bool List::operator==(const InternalType& it)
354 {
355     if (const_cast<InternalType &>(it).isList() == false)
356     {
357         return false;
358     }
359
360     List* plst = const_cast<InternalType &>(it).getAs<List>();
361
362     if (getSize() != plst->getSize())
363     {
364         return false;
365     }
366
367     for (int i = 0; i < getSize(); i++)
368     {
369         if (*(*m_plData)[i] != *plst->get(i))
370         {
371             return false;
372         }
373     }
374
375     return true;
376 }
377
378 }