Coverity #1350439 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  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13 *
14 */
15
16 #include <sstream>
17 #include "double.hxx"
18 #include "list.hxx"
19 #include "listundefined.hxx"
20 #include "listinsert.hxx"
21 #include "types_tools.hxx"
22 #include "localization.hxx"
23 #include "scilabWrite.hxx"
24 #include "types_tools.hxx"
25 #include "function.hxx"
26
27 #ifndef NDEBUG
28 #include "inspector.hxx"
29 #endif
30
31 extern "C"
32 {
33 #include "os_string.h"
34 }
35
36 namespace types
37 {
38 /**
39 ** Constructor & Destructor (public)
40 */
41 List::List() : Container()
42 {
43     m_plData = new std::vector<InternalType *>();
44 #ifndef NDEBUG
45     Inspector::addItem(this);
46 #endif
47 }
48
49 List::~List()
50 {
51     if (isDeletable() == true)
52     {
53         for (auto data : *m_plData)
54         {
55             data->DecreaseRef();
56             data->killMe();
57         }
58         delete m_plData;
59     }
60 #ifndef NDEBUG
61     Inspector::removeItem(this);
62 #endif
63 }
64
65 /**
66 ** Private Copy Constructor and data Access
67 */
68 List::List(List *_oListCopyMe)
69 {
70     m_plData = new std::vector<InternalType *>;
71     std::vector<InternalType *>* lData = _oListCopyMe->getData();
72     int size = lData->size();
73     for (int i = 0 ; i < size ; i++)
74     {
75         append((*lData)[i]);
76     }
77
78     m_iSize = static_cast<int>(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 List* List::append(InternalType *_typedValue)
103 {
104     List* pIT = checkRef(this, &List::append, _typedValue);
105     if (pIT != this)
106     {
107         return pIT;
108     }
109
110     _typedValue->IncreaseRef();
111     m_plData->push_back(_typedValue);
112     m_iSize = static_cast<int>(m_plData->size());
113     return this;
114 }
115
116 /**
117 ** Clone
118 ** Create a new List and Copy all values.
119 */
120 List *List::clone()
121 {
122     return new List(this);
123 }
124
125 /**
126 ** toString to display Lists
127 */
128 bool List::toString(std::wostringstream& ostr)
129 {
130     if (getSize() == 0)
131     {
132         ostr.str(L"");
133         ostr << L"     ()" << std::endl;
134     }
135     else
136     {
137         wchar_t* wcsVarName = os_wcsdup(ostr.str().c_str());
138         int iPosition = 1;
139         for (auto val : *m_plData)
140         {
141             std::wostringstream nextVarName;
142             ostr.str(L"");
143             nextVarName << " " << SPACES_LIST << wcsVarName << L"(" << iPosition++ << L")";
144             ostr << std::endl << nextVarName.str() << std::endl << std::endl;
145             scilabForcedWriteW(ostr.str().c_str());
146             if (VariableToString(val, nextVarName.str().c_str()) == types::Function::Error)
147             {
148                 free(wcsVarName);
149                 ostr.str(L"");
150                 return true;
151             }
152         }
153
154         ostr.str(L"");
155         free(wcsVarName);
156     }
157
158     return true;
159 }
160
161 InternalType* List::extract(typed_list* _pArgs)
162 {
163     List* outList = new List();
164     //check input param
165     if (_pArgs->size() != 1)
166     {
167         return outList;
168     }
169
170     typed_list pArg;
171     int iDims           = (int)_pArgs->size();
172
173     int* piMaxDim       = new int[iDims];
174     int* piCountDim     = new int[iDims];
175
176     //evaluate each argument and replace by appropriate value and compute the count of combinations
177     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
178     delete[] piMaxDim;
179     delete[] piCountDim;
180
181     for (int i = 0 ; i < iSeqCount ; i++)
182     {
183         int idx = (int)pArg[0]->getAs<Double>()->get(i);
184         if (idx > getSize() || idx < 1)
185         {
186             delete outList;
187             outList = NULL;
188             break;
189         }
190         InternalType* pIT = (*m_plData)[idx - 1];
191         outList->set(i, pIT);
192     }
193
194     //free pArg content
195     cleanIndexesArguments(_pArgs, &pArg);
196
197     return outList;
198 }
199
200 List* List::insert(typed_list* _pArgs, InternalType* _pSource)
201 {
202     //check input param
203     if (_pArgs->size() != 1)
204     {
205         return NULL;
206     }
207
208     List* pIT = checkRef(this, &List::insert, _pArgs, _pSource);
209     if (pIT != this)
210     {
211         return pIT;
212     }
213
214     typed_list pArg;
215     int iDims           = (int)_pArgs->size();
216
217     int* piMaxDim       = new int[iDims];
218     int* piCountDim     = new int[iDims];
219
220     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
221     delete[] piMaxDim;
222     delete[] piCountDim;
223     if (iSeqCount == 0)
224     {
225         //free pArg content
226         cleanIndexesArguments(_pArgs, &pArg);
227         //do nothing
228         return this;
229     }
230     else if (iSeqCount > 1)
231     {
232         //free pArg content
233         cleanIndexesArguments(_pArgs, &pArg);
234         std::wostringstream os;
235         os << _W("Unable to insert multiple item in a list.\n");
236         throw ast::InternalError(os.str());
237     }
238     else if (iSeqCount < 0)
239     {
240         //free pArg content
241         cleanIndexesArguments(_pArgs, &pArg);
242         return NULL;
243     }
244
245     int idx = (int)pArg[0]->getAs<Double>()->get(0);
246     if (_pSource->isListDelete())
247     {
248         //delete item
249         if (idx == 0)
250         {
251             //free pArg content
252             cleanIndexesArguments(_pArgs, &pArg);
253             //do nothing
254             return this;
255         }
256         else if (idx <= (int)m_plData->size())
257         {
258             InternalType* pIT = (*m_plData)[idx - 1];
259             if (pIT)
260             {
261                 pIT->DecreaseRef();
262                 pIT->killMe();
263             }
264             m_plData->erase(m_plData->begin() + idx - 1);
265         }
266     }
267     else if (_pSource->isListInsert())
268     {
269         //insert item
270         if (idx == 0)
271         {
272             //free pArg content
273             cleanIndexesArguments(_pArgs, &pArg);
274             std::wostringstream os;
275             os << _W("Index out of bounds.\n");
276             throw ast::InternalError(os.str());
277         }
278
279         InternalType* pInsert = _pSource->getAs<ListInsert>()->getInsert();
280         pInsert->IncreaseRef();
281         if (idx > (int)m_plData->size())
282         {
283             //try to insert after the last index, increase list size and assign value
284             while ((int)m_plData->size() < idx)
285             {
286                 //incease list size and fill with "Undefined"
287                 m_plData->push_back(new ListUndefined());
288             }
289             (*m_plData)[idx - 1] = pInsert;
290         }
291         else
292         {
293             m_plData->insert(m_plData->begin() + idx - 1, pInsert);
294         }
295     }
296     else if (idx == 0)
297     {
298         //special case to insert at the first position
299         _pSource->IncreaseRef();
300         m_plData->insert(m_plData->begin(), _pSource);
301     }
302     else
303     {
304         while ((int)m_plData->size() < idx)
305         {
306             //incease list size and fill with "Undefined"
307             InternalType* pLU = new ListUndefined();
308             pLU->IncreaseRef();
309             m_plData->push_back(pLU);
310         }
311
312         InternalType* pIT = (*m_plData)[idx - 1];
313
314         (*m_plData)[idx - 1] = _pSource;
315         (*m_plData)[idx - 1]->IncreaseRef();
316
317         pIT->DecreaseRef();
318         pIT->killMe();
319     }
320
321     m_iSize = (int)m_plData->size();
322
323     //free pArg content
324     cleanIndexesArguments(_pArgs, &pArg);
325
326     return this;
327 }
328
329 InternalType* List::get(const int _iIndex)
330 {
331     if (_iIndex >= 0 && _iIndex < (int)m_plData->size())
332     {
333         return (*m_plData)[_iIndex];
334     }
335     return NULL;
336 }
337
338 List* List::set(const int _iIndex, InternalType* _pIT)
339 {
340     if (_iIndex < 0)
341     {
342         return NULL;
343     }
344
345     List* pIT = checkRef(this, &List::set, _iIndex, _pIT);
346     if (pIT != this)
347     {
348         return pIT;
349     }
350
351     while ((int)m_plData->size() < _iIndex)
352     {
353         //incease list size and fill with "Undefined"
354         m_plData->push_back(new ListUndefined());
355         m_plData->back()->IncreaseRef();
356         m_iSize = getSize();
357     }
358
359     if ((int)m_plData->size() == _iIndex)
360     {
361         _pIT->IncreaseRef();
362         m_plData->push_back(_pIT);
363         m_iSize = getSize();
364     }
365     else
366     {
367         InternalType* pOld = (*m_plData)[_iIndex];
368
369         _pIT->IncreaseRef();
370         (*m_plData)[_iIndex] = _pIT;
371
372         //manage ref on the old value
373         if (pOld)
374         {
375             pOld->DecreaseRef();
376             pOld->killMe();
377         }
378     }
379
380     return this;
381 }
382
383 bool List::operator==(const InternalType& it)
384 {
385     if (const_cast<InternalType &>(it).isList() == false)
386     {
387         return false;
388     }
389
390     List* plst = const_cast<InternalType &>(it).getAs<List>();
391
392     if (getSize() != plst->getSize())
393     {
394         return false;
395     }
396
397     for (int i = 0; i < getSize(); i++)
398     {
399         if (*(*m_plData)[i] != *plst->get(i))
400         {
401             return false;
402         }
403     }
404
405     return true;
406 }
407
408 }