Now items in list are cloned, add setfield and getfield functions, fix qmr function
[scilab.git] / scilab / modules / types / src / cpp / 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
21 #ifndef NDEBUG
22 #include "inspector.hxx"
23 #endif
24
25 extern "C"
26 {
27 #include "localization.h"
28 #include "charEncoding.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             if ((*itValues)->isDeletable())
53             {
54                 delete *itValues;
55             }
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 < _oListCopyMe->getData()->size() ; i++)
73     {
74         InternalType* pIT = (*_oListCopyMe->getData())[i];
75         append(pIT->clone());
76     }
77
78     m_iSize = static_cast<int>(m_plData->size());
79 #ifndef NDEBUG
80     Inspector::addItem(this);
81 #endif
82 }
83
84 std::vector<InternalType *> *List::getData()
85 {
86     return m_plData;
87 }
88
89 /**
90 ** size_get
91 ** Return the number of elements in list
92 */
93 int List::getSize()
94 {
95     return static_cast<int>(m_plData->size());
96 }
97
98 /**
99 ** append(InternalType *_typedValue)
100 ** Append the given value to the end of the List
101 */
102 void List::append(InternalType *_typedValue)
103 {
104     m_plData->push_back(_typedValue->clone());
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 GenericType* List::getColumnValues(int _iPos)
118 {
119     return NULL;
120 }
121
122 /**
123 ** toString to display Lists
124 ** FIXME : Find a better indentation process
125 */
126 bool List::toString(std::wostringstream& ostr)
127 {
128     if (getSize() == 0)
129     {
130         ostr << 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 << L"     (" << iPosition << L")" << std::endl;
139             //maange lines
140             bool bFinish = (*itValues)->toString(ostr);
141             ostr << std::endl;
142         }
143     }
144     return true;
145 }
146
147 std::vector<InternalType*>      List::extract(typed_list* _pArgs)
148 {
149     std::vector<InternalType*> outList;
150     //check input param
151     if (_pArgs->size() != 1)
152     {
153         return outList;
154     }
155
156     typed_list pArg;
157     int iDims           = (int)_pArgs->size();
158
159     int* piMaxDim       = new int[iDims];
160     int* piCountDim     = new int[iDims];
161
162     //evaluate each argument and replace by appropriate value and compute the count of combinations
163     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
164     if (iSeqCount == 0)
165     {
166         //outList.push_back(Double::Empty());
167     }
168
169     for (int i = 0 ; i < iSeqCount ; i++)
170     {
171         int idx = (int)pArg[0]->getAs<Double>()->get(i);
172         if (idx > getSize() || idx < 1)
173         {
174             outList.clear();
175             break;
176         }
177         InternalType* pIT = (*m_plData)[idx - 1];
178         outList.push_back(pIT->clone());
179     }
180
181     for (int iArg = 0 ; iArg < pArg.size() ; iArg++)
182     {
183         if (pArg[iArg] != (*_pArgs)[iArg] && pArg[iArg]->isDeletable())
184         {
185             delete pArg[iArg];
186         }
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         //do nothing
209         return this;
210     }
211     else if (iSeqCount > 1)
212     {
213         std::wostringstream os;
214         os << _W("Unable to insert multiple item in a list.\n");
215         throw ast::ScilabError(os.str());
216     }
217
218
219     int idx = (int)pArg[0]->getAs<Double>()->get(0);
220     if (_pSource->isListDelete())
221     {
222         //delete item
223         if (idx == 0)
224         {
225             //do nothing
226             return this;
227         }
228         else if (idx <= m_plData->size())
229         {
230             InternalType* pIT = (*m_plData)[idx - 1];
231             if (pIT && pIT->isDeletable())
232             {
233                 delete pIT;
234             }
235             m_plData->erase(m_plData->begin() + idx - 1);
236         }
237     }
238     else if (_pSource->isListInsert())
239     {
240         //insert item
241         if (idx == 0)
242         {
243             std::wostringstream os;
244             os << _W("Index out of bounds.\n");
245             throw ast::ScilabError(os.str());
246         }
247
248         InternalType* pInsert = _pSource->getAs<ListInsert>()->getInsert()->clone();
249         if (idx > m_plData->size())
250         {
251             //try to insert after the last index, increase list size and assign value
252             while (m_plData->size() < idx)
253             {
254                 //incease list size and fill with "Undefined"
255                 m_plData->push_back(new ListUndefined());
256             }
257             (*m_plData)[idx - 1] = pInsert;
258         }
259         else
260         {
261             m_plData->insert(m_plData->begin() + idx - 1, pInsert);
262         }
263     }
264     else if (idx == 0)
265     {
266         //special cazse to insert at the first position
267         InternalType* pInsert = NULL;
268         if (_pSource->isListInsert())
269         {
270             pInsert = _pSource->getAs<ListInsert>()->getInsert();
271         }
272         else
273         {
274             pInsert = _pSource;
275         }
276
277         m_plData->insert(m_plData->begin(), pInsert->clone());
278     }
279     else
280     {
281         while (m_plData->size() < idx)
282         {
283             //incease list size and fill with "Undefined"
284             m_plData->push_back(new ListUndefined());
285         }
286
287         InternalType* pIT = (*m_plData)[idx - 1];
288         if (pIT && pIT->isDeletable())
289         {
290             delete pIT;
291         }
292
293         (*m_plData)[idx - 1] = _pSource->clone();
294     }
295
296     m_iSize = (int)m_plData->size();
297     return this;
298 }
299
300 InternalType* List::get(const int _iIndex)
301 {
302     if (_iIndex >= 0 && _iIndex < m_plData->size())
303     {
304         return (*m_plData)[_iIndex];
305     }
306     return NULL;
307 }
308
309 bool List::operator==(const InternalType& it)
310 {
311     if (const_cast<InternalType &>(it).isList() == false)
312     {
313         return false;
314     }
315
316     List* plst = const_cast<InternalType &>(it).getAs<List>();
317
318     if (getSize() != plst->getSize())
319     {
320         return false;
321     }
322
323     for (int i = 0; i < getSize(); i++)
324     {
325         if (*(*m_plData)[i] != *plst->get(i))
326         {
327             return false;
328         }
329     }
330
331     return true;
332 }
333
334 }