Coverity: fileio module memory errors fixed.
[scilab.git] / scilab / modules / fileio / sci_gateway / cpp / sci_msscanf.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2006 - INRIA - Allan CORNET
4 * Copyright (C) 2009 - DIGITEO - Allan CORNET
5 * Copyright (C) 2010 - DIGITEO - Antoine ELIAS
6 * Copyright (C) 2011 - DIGITEO - Cedric DELAMARRE
7 *
8  * Copyright (C) 2012 - 2016 - Scilab Enterprises
9  *
10  * This file is hereby licensed under the terms of the GNU GPL v2.0,
11  * pursuant to article 5.3.4 of the CeCILL v.2.1.
12  * This file was originally licensed under the terms of the CeCILL v2.1,
13  * and continues to be available under such terms.
14  * For more information, see the COPYING file which you should have received
15  * along with this program.
16 *
17 */
18 /*--------------------------------------------------------------------------*/
19 #include "fileio_gw.hxx"
20 #include "string.hxx"
21 #include "mlist.hxx"
22 #include "function.hxx"
23 #include "double.hxx"
24
25 extern "C"
26 {
27 #include "localization.h"
28 #include "Scierror.h"
29 #include "do_xxscanf.h"
30 #include "scanf_functions.h"
31 }
32
33 types::Function::ReturnValue sci_msscanf(types::typed_list &in, int _iRetCount, types::typed_list &out)
34 {
35     int size                    = (int)in.size();
36     int iNiter                  = 1;
37     wchar_t* wcsFormat          = NULL;
38     types::String* pStrRead     = NULL;
39     int dimsArray[2]            = {1, 1};
40     std::vector<types::InternalType*> IT;
41
42     int args        = 0;
43     int nrow        = 0;
44     int ncol        = 0;
45     int retval      = 0;
46     int retval_s    = 0;
47     int rowcount    = -1;
48     rec_entry buf[MAXSCAN];
49     entry *data = NULL;
50     sfdir type[MAXSCAN]   = {NONE};
51     sfdir type_s[MAXSCAN] = {NONE};
52
53     if (size < 2 || size > 3)
54     {
55         Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "msscanf", 2, 3);
56         return types::Function::Error;
57     }
58
59     if (size == 3)
60     {
61         if (in[0]->isDouble() == false || in[0]->getAs<types::Double>()->isScalar() == false || in[0]->getAs<types::Double>()->isComplex())
62         {
63             Scierror(999, _("%s: Wrong type for input argument #%d: A Real expected.\n"), "msscanf", 1);
64             return types::Function::Error;
65         }
66         iNiter = static_cast<int>(in[0]->getAs<types::Double>()->get(0));
67     }
68
69     if (in[size - 2]->isString() == false)
70     {
71         Scierror(999, _("%s: Wrong type for input argument #%d: A Strings expected.\n"), "msscanf", size - 1);
72         return types::Function::Error;
73     }
74
75     if (in[size - 1]->isString() == false || in[size - 1]->getAs<types::String>()->isScalar() == false)
76     {
77         Scierror(999, _("%s: Wrong type for input argument #%d: A String expected.\n"), "msscanf", size);
78         return types::Function::Error;
79     }
80
81     pStrRead  = in[size - 2]->getAs<types::String>();
82     if (iNiter == -1)
83     {
84         iNiter = pStrRead->getRows();
85     }
86     wcsFormat = in[size - 1]->getAs<types::String>()->get(0);
87     nrow = iNiter;
88     while (++rowcount < iNiter)
89     {
90         if ((iNiter >= 0) && (rowcount >= iNiter))
91         {
92             break;
93         }
94         int err = do_xxscanf(L"sscanf", (FILE *)0, wcsFormat, &args, pStrRead->get(rowcount), &retval, buf, type);
95         if (err == DO_XXPRINTF_MISMATCH)
96         {
97             break;
98         }
99         if (err < 0)
100         {
101             return types::Function::Error;
102         }
103         err = Store_Scan(&nrow, &ncol, type_s, type, &retval, &retval_s, buf, &data, rowcount, args);
104         if (err < 0)
105         {
106             switch (err)
107             {
108                 case DO_XXPRINTF_MISMATCH:
109                     Free_Scan(rowcount, ncol, type_s, &data);
110                     Scierror(999, _("%s: Data mismatch.\n"), "msscanf");
111                     return types::Function::Error;
112
113                 case DO_XXPRINTF_MEM_LACK:
114                     Free_Scan(rowcount, ncol, type_s, &data);
115                     Scierror(999, _("%s: No more memory.\n"), "msscanf");
116                     return types::Function::Error;
117             }
118         }
119     }
120
121     unsigned int uiFormatUsed = 0;
122     for (int i = 0; i < ncol; i++)
123     {
124         switch ( type_s[i] )
125         {
126             case SF_C:
127             case SF_S:
128             {
129                 types::String* ps = new types::String(iNiter, 1);
130                 for (int j = 0; j < iNiter; j++)
131                 {
132                     ps->set(j, data[i + ncol * j].s);
133                 }
134
135                 IT.push_back(ps);
136                 uiFormatUsed |= (1 << 1);
137             }
138             break;
139             case SF_LUI:
140             case SF_SUI:
141             case SF_UI:
142             case SF_LI:
143             case SF_SI:
144             case SF_I:
145             case SF_LF:
146             case SF_F:
147             {
148                 types::Double* p = new types::Double(iNiter, 1);
149                 for (int j = 0; j < iNiter; j++)
150                 {
151                     p->set(j, data[i + ncol * j].d);
152                 }
153
154                 IT.push_back(p);
155                 uiFormatUsed |= (1 << 2);
156             }
157             break;
158             case NONE:
159                 break;
160         }
161     }
162
163     int sizeOfVector = (int)IT.size();
164     if (_iRetCount > 1)
165     {
166         out.push_back(new types::Double((double)retval));
167
168         for (int i = 0; i < sizeOfVector; i++)
169         {
170             out.push_back(IT[i]);
171         }
172         for (int i = sizeOfVector + 1; i < _iRetCount; i++)
173         {
174             out.push_back(types::Double::Empty());
175         }
176     }
177     else
178     {
179         if (sizeOfVector == 0)
180         {
181             out.push_back(types::Double::Empty());
182             return types::Function::OK;
183         }
184
185         switch (uiFormatUsed)
186         {
187             case (1 << 1) :
188             {
189                 int sizeOfString = IT[0]->getAs<types::String>()->getRows();
190                 int dimsArrayOfRes[2] = {sizeOfString, sizeOfVector};
191                 types::String* pString = new types::String(2, dimsArrayOfRes);
192                 for (int i = 0; i < sizeOfVector; i++)
193                 {
194                     for (int j = 0; j < sizeOfString; j++)
195                     {
196                         pString->set(i * sizeOfString + j, IT[i]->getAs<types::String>()->get(j));
197                     }
198                 }
199                 out.push_back(pString);
200             }
201             break;
202             case (1 << 2) :
203             {
204                 int sizeOfDouble = IT[0]->getAs<types::Double>()->getRows();
205                 int dimsArrayOfRes[2] = {sizeOfDouble, sizeOfVector};
206                 types::Double* pDouble = new types::Double(2, dimsArrayOfRes);
207                 for (int i = 0; i < sizeOfVector; i++)
208                 {
209                     types::Double* pdbl = IT[i]->getAs<types::Double>();
210                     double* dbl = pdbl->get();
211                     for (int j = 0; j < sizeOfDouble; j++)
212                     {
213                         pDouble->set(i * sizeOfDouble + j, dbl[j]);
214                     }
215
216                     pdbl->killMe();
217                 }
218                 out.push_back(pDouble);
219             }
220             break;
221             default :
222             {
223                 std::vector<types::InternalType*>* pITTemp = new std::vector<types::InternalType*>();
224                 pITTemp->push_back(IT[0]);
225
226                 // sizeOfVector always > 1
227                 for (int i = 1; i < sizeOfVector; i++) // concatenates the Cells. ex : [String 4x1] [String 4x1] = [String 4x2]
228                 {
229                     if (pITTemp->back()->getType() == IT[i]->getType())
230                     {
231                         switch (pITTemp->back()->getType())
232                         {
233                             case types::InternalType::ScilabString :
234                             {
235                                 int iRows               = pITTemp->back()->getAs<types::String>()->getRows();
236                                 int iCols               = pITTemp->back()->getAs<types::String>()->getCols();
237                                 int arrayOfType[2]      = {iRows, iCols + 1};
238                                 types::String* pType    = new types::String(2, arrayOfType);
239
240                                 for (int k = 0; k < pITTemp->back()->getAs<types::String>()->getSize(); k++)
241                                 {
242                                     pType->set(k, pITTemp->back()->getAs<types::String>()->get(k));
243                                 }
244                                 for (int k = 0; k < IT[i]->getAs<types::String>()->getSize(); k++)
245                                 {
246                                     pType->set(iRows * iCols + k, IT[i]->getAs<types::String>()->get(k));
247                                 }
248                                 pITTemp->pop_back();
249                                 pITTemp->push_back(pType);
250                             }
251                             break;
252                             case types::InternalType::ScilabDouble :
253                             {
254                                 int iRows               = pITTemp->back()->getAs<types::Double>()->getRows();
255                                 int iCols               = pITTemp->back()->getAs<types::Double>()->getCols();
256                                 int arrayOfType[2]      = {iRows, iCols + 1};
257                                 types::Double* pType    = new types::Double(2, arrayOfType);
258
259                                 pType->set(pITTemp->back()->getAs<types::Double>()->get());
260                                 for (int k = 0; k < IT[i]->getAs<types::Double>()->getSize(); k++)
261                                 {
262                                     pType->set(iRows * iCols + k, IT[i]->getAs<types::Double>()->get(k));
263                                 }
264                                 pITTemp->pop_back();
265                                 pITTemp->push_back(pType);
266                             }
267                             break;
268                             default :
269                                 delete pITTemp;
270                                 return types::Function::Error;
271                         }
272                     }
273                     else
274                     {
275                         pITTemp->push_back(IT[i]);
276                     }
277                 }
278
279                 types::MList* pMList = new types::MList();
280                 pMList->append(new types::String(L"cblock"));
281                 for (int i = 0 ; i < pITTemp->size() ; i++)
282                 {
283                     pMList->append((*pITTemp)[i]);
284                 }
285                 out.push_back(pMList);
286
287                 //                int dimsArrayOfCell[2] = {1, (int)pITTemp->size()};
288                 //                types::Cell* pCell = new types::Cell(2, dimsArrayOfCell);
289                 //                for (int i = 0; i < pITTemp->size(); i++)
290                 //                {
291                 //                    pCell->set(i, (*pITTemp)[i]);
292                 //                }
293                 //                out.push_back(pCell);
294             }
295         }
296     }
297     Free_Scan(rowcount, ncol, type_s, &data);
298     return types::Function::OK;
299 }
300 /*--------------------------------------------------------------------------*/