macro print 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 #include "function.hxx"
24
25 #ifndef NDEBUG
26 #include "inspector.hxx"
27 #endif
28
29 extern "C"
30 {
31 #include "os_wcsdup.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         std::vector<InternalType *>::iterator itValues;
52         for (itValues = m_plData->begin() ; itValues != m_plData->end() ; ++itValues)
53         {
54             (*itValues)->DecreaseRef();
55             (*itValues)->killMe();
56         }
57         delete m_plData;
58     }
59 #ifndef NDEBUG
60     Inspector::removeItem(this);
61 #endif
62 }
63
64 /**
65 ** Private Copy Constructor and data Access
66 */
67 List::List(List *_oListCopyMe)
68 {
69     std::vector<InternalType *>::iterator itValues;
70     m_plData = new std::vector<InternalType *>;
71
72     for (int i = 0 ; i < (int)_oListCopyMe->getData()->size() ; i++)
73     {
74         append((*_oListCopyMe->getData())[i]);
75     }
76
77     m_iSize = static_cast<int>(m_plData->size());
78 #ifndef NDEBUG
79     Inspector::addItem(this);
80 #endif
81 }
82
83 std::vector<InternalType *> *List::getData()
84 {
85     return m_plData;
86 }
87
88 /**
89 ** size_get
90 ** Return the number of elements in list
91 */
92 int List::getSize()
93 {
94     return static_cast<int>(m_plData->size());
95 }
96
97 /**
98 ** append(InternalType *_typedValue)
99 ** Append the given value to the end of the List
100 */
101 void List::append(InternalType *_typedValue)
102 {
103     m_plData->push_back(_typedValue);
104     m_plData->back()->IncreaseRef();
105     m_iSize = static_cast<int>(m_plData->size());
106 }
107
108 /**
109 ** Clone
110 ** Create a new List and Copy all values.
111 */
112 InternalType *List::clone()
113 {
114     return new List(this);
115 }
116
117 /**
118 ** toString to display Lists
119 */
120 bool List::toString(std::wostringstream& ostr)
121 {
122     if (getSize() == 0)
123     {
124         ostr.str(L"");
125         ostr << L"     ()" << std::endl;
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 << " " << SPACES_LIST << wcsVarName << L"(" << iPosition << L")";
137             ostr << std::endl << nextVarName.str() << std::endl << std::endl;
138             scilabWriteW(ostr.str().c_str());
139             if (VariableToString(*itValues, nextVarName.str().c_str()) == types::Function::Error)
140             {
141                 free(wcsVarName);
142                 ostr.str(L"");
143                 return true;
144             }
145         }
146
147         ostr.str(L"");
148         free(wcsVarName);
149     }
150
151     return true;
152 }
153
154 InternalType* List::extract(typed_list* _pArgs)
155 {
156     List* outList = new List();
157     //check input param
158     if (_pArgs->size() != 1)
159     {
160         return outList;
161     }
162
163     typed_list pArg;
164     int iDims           = (int)_pArgs->size();
165
166     int* piMaxDim       = new int[iDims];
167     int* piCountDim     = new int[iDims];
168
169     //evaluate each argument and replace by appropriate value and compute the count of combinations
170     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
171
172     for (int i = 0 ; i < iSeqCount ; i++)
173     {
174         int idx = (int)pArg[0]->getAs<Double>()->get(i);
175         if (idx > getSize() || idx < 1)
176         {
177             delete outList;
178             outList = NULL;
179             break;
180         }
181         InternalType* pIT = (*m_plData)[idx - 1];
182         outList->set(i, pIT);
183     }
184
185     //free pArg content
186     cleanIndexesArguments(_pArgs, &pArg);
187
188     return outList;
189 }
190
191 InternalType* List::insert(typed_list* _pArgs, InternalType* _pSource)
192 {
193     //check input param
194     if (_pArgs->size() != 1)
195     {
196         return NULL;
197     }
198
199     typed_list pArg;
200     int iDims           = (int)_pArgs->size();
201
202     int* piMaxDim       = new int[iDims];
203     int* piCountDim     = new int[iDims];
204
205     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
206     if (iSeqCount == 0)
207     {
208         //free pArg content
209         cleanIndexesArguments(_pArgs, &pArg);
210         //do nothing
211         return this;
212     }
213     else if (iSeqCount > 1)
214     {
215         //free pArg content
216         cleanIndexesArguments(_pArgs, &pArg);
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         //free pArg content
224         cleanIndexesArguments(_pArgs, &pArg);
225         return NULL;
226     }
227
228     int idx = (int)pArg[0]->getAs<Double>()->get(0);
229     if (_pSource->isListDelete())
230     {
231         //delete item
232         if (idx == 0)
233         {
234             //free pArg content
235             cleanIndexesArguments(_pArgs, &pArg);
236             //do nothing
237             return this;
238         }
239         else if (idx <= (int)m_plData->size())
240         {
241             InternalType* pIT = (*m_plData)[idx - 1];
242             if (pIT)
243             {
244                 pIT->killMe();
245             }
246             m_plData->erase(m_plData->begin() + idx - 1);
247         }
248     }
249     else if (_pSource->isListInsert())
250     {
251         //insert item
252         if (idx == 0)
253         {
254             //free pArg content
255             cleanIndexesArguments(_pArgs, &pArg);
256             std::wostringstream os;
257             os << _W("Index out of bounds.\n");
258             throw ast::ScilabError(os.str());
259         }
260
261         InternalType* pInsert = _pSource->getAs<ListInsert>()->getInsert()->clone();
262         pInsert->IncreaseRef();
263         if (idx > (int)m_plData->size())
264         {
265             //try to insert after the last index, increase list size and assign value
266             while ((int)m_plData->size() < idx)
267             {
268                 //incease list size and fill with "Undefined"
269                 m_plData->push_back(new ListUndefined());
270             }
271             (*m_plData)[idx - 1] = pInsert;
272         }
273         else
274         {
275             m_plData->insert(m_plData->begin() + idx - 1, pInsert);
276         }
277     }
278     else if (idx == 0)
279     {
280         //special cazse to insert at the first position
281         InternalType* pInsert = NULL;
282         pInsert = _pSource->clone();
283         pInsert->IncreaseRef();
284         m_plData->insert(m_plData->begin(), pInsert);
285     }
286     else
287     {
288         while ((int)m_plData->size() < idx)
289         {
290             //incease list size and fill with "Undefined"
291             InternalType* pLU = new ListUndefined();
292             pLU->IncreaseRef();
293             m_plData->push_back(pLU);
294         }
295
296         InternalType* pIT = (*m_plData)[idx - 1];
297         pIT->DecreaseRef();
298         if (pIT)
299         {
300             pIT->killMe();
301         }
302
303         (*m_plData)[idx - 1] = _pSource->clone();
304         (*m_plData)[idx - 1]->IncreaseRef();
305     }
306
307     m_iSize = (int)m_plData->size();
308
309     //free pArg content
310     cleanIndexesArguments(_pArgs, &pArg);
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 }