Fileio gateways: allocate vector on stack instead of heap
[scilab.git] / scilab / modules / fileio / sci_gateway / cpp / sci_mscanf.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 "scilabWrite.hxx"
22 #include "cell.hxx"
23 #include "function.hxx"
24 #include "double.hxx"
25 #include "configvariable.hxx"
26 #include "threadmanagement.hxx"
27
28 extern "C"
29 {
30 #include "sci_malloc.h"
31 #include "localization.h"
32 #include "Scierror.h"
33 #include "do_xxscanf.h"
34 #include "scanf_functions.h"
35 #include "scilabRead.h"
36 }
37
38 types::Function::ReturnValue sci_mscanf(types::typed_list &in, int _iRetCount, types::typed_list &out)
39 {
40     int size                    = (int)in.size();
41     int iNiter                  = 1;
42     wchar_t* wcsFormat          = NULL;
43     wchar_t* wcsRead            = NULL;
44     int dimsArray[2]            = {1, 1};
45     std::vector<types::InternalType*> pIT;
46
47     int args        = 0;
48     int nrow        = 0;
49     int ncol        = 0;
50     int retval      = 0;
51     int retval_s    = 0;
52     int rowcount    = -1;
53     rec_entry buf[MAXSCAN];
54     entry *data = NULL;
55     sfdir type[MAXSCAN] = {NONE};
56     sfdir type_s[MAXSCAN] = {NONE};
57
58     if (size < 1 || size > 2)
59     {
60         Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "mscanf", 1, 2);
61         return types::Function::Error;
62     }
63
64     if (size == 2)
65     {
66         if (in[0]->isDouble() == false || in[0]->getAs<types::Double>()->isScalar() == false || in[0]->getAs<types::Double>()->isComplex())
67         {
68             Scierror(999, _("%s: Wrong type for input argument #%d: A Real expected.\n"), "mscanf", 1);
69             return types::Function::Error;
70         }
71         iNiter = static_cast<int>(in[0]->getAs<types::Double>()->get(0));
72         if (iNiter < 0)
73         {
74             iNiter = 1;
75         }
76     }
77
78     if (in[size - 1]->isString() == false || in[size - 1]->getAs<types::String>()->isScalar() == false)
79     {
80         Scierror(999, _("%s: Wrong type for input argument #%d: A String expected.\n"), "mscanf", size);
81         return types::Function::Error;
82     }
83
84     wcsFormat = in[size - 1]->getAs<types::String>()->get(0);
85     nrow = iNiter;
86     while (++rowcount < iNiter)
87     {
88         if ((iNiter >= 0) && (rowcount >= iNiter))
89         {
90             break;
91         }
92
93         // get data
94         // The console thread must not parse the next console input.
95         ConfigVariable::setScilabCommand(0);
96
97         // Get the console input filled by the console thread.
98         char* pcConsoleReadStr = ConfigVariable::getConsoleReadStr();
99         ThreadManagement::SendConsoleExecDoneSignal();
100         while (pcConsoleReadStr == NULL)
101         {
102             pcConsoleReadStr = ConfigVariable::getConsoleReadStr();
103             ThreadManagement::SendConsoleExecDoneSignal();
104         }
105
106         // reset flag to default value
107         ConfigVariable::setScilabCommand(1);
108
109         wcsRead = to_wide_string(pcConsoleReadStr);
110         FREE(pcConsoleReadStr);
111         int err = do_xxscanf(L"sscanf", (FILE *)0, wcsFormat, &args, wcsRead, &retval, buf, type);
112         FREE(wcsRead);
113         if (err < 0)
114         {
115             return types::Function::Error;
116         }
117         err = Store_Scan(&nrow, &ncol, type_s, type, &retval, &retval_s, buf, &data, rowcount, args);
118         if (err < 0)
119         {
120             switch (err)
121             {
122                 case DO_XXPRINTF_MISMATCH:
123                     Free_Scan(rowcount, ncol, type_s, &data);
124                     Scierror(999, _("%s: Data mismatch.\n"), "mscanf");
125                     return types::Function::Error;
126
127                 case DO_XXPRINTF_MEM_LACK:
128                     Free_Scan(rowcount, ncol, type_s, &data);
129                     Scierror(999, _("%s: No more memory.\n"), "mscanf");
130                     return types::Function::Error;
131             }
132         }
133     }
134
135     unsigned int uiFormatUsed = 0;
136     for (int i = 0; i < ncol; i++)
137     {
138         switch ( type_s[i] )
139         {
140             case SF_C:
141             case SF_S:
142             {
143                 types::String* ps = new types::String(iNiter, 1);
144                 for (int j = 0; j < iNiter; j++)
145                 {
146                     ps->set(j, data[i + ncol * j].s);
147                 }
148                 pIT.push_back(ps);
149                 uiFormatUsed |= (1 << 1);
150             }
151             break;
152             case SF_LUI:
153             case SF_SUI:
154             case SF_UI:
155             case SF_LI:
156             case SF_SI:
157             case SF_I:
158             case SF_LF:
159             case SF_F:
160             {
161                 types::Double* p = new types::Double(iNiter, 1);
162                 for (int j = 0; j < iNiter; j++)
163                 {
164                     p->set(j, data[i + ncol * j].d);
165                 }
166                 pIT.push_back(p);
167                 uiFormatUsed |= (1 << 2);
168             }
169             break;
170             case NONE:
171                 break;
172         }
173     }
174
175     int sizeOfVector = (int)pIT.size();
176     if (_iRetCount > 1)
177     {
178         types::Double* pDouble = new types::Double(2, dimsArray);
179         pDouble->set(0, retval);
180         out.push_back(pDouble);
181
182         for (int i = 0; i < sizeOfVector; i++)
183         {
184             out.push_back(pIT[i]);
185         }
186         for (int i = sizeOfVector + 1; i < _iRetCount; i++)
187         {
188             out.push_back(types::Double::Empty());
189         }
190     }
191     else
192     {
193         if (sizeOfVector == 0)
194         {
195             out.push_back(new types::String(L""));
196             return types::Function::OK;
197         }
198
199         switch (uiFormatUsed)
200         {
201             case (1 << 1) :
202             {
203                 int sizeOfString = pIT[0]->getAs<types::String>()->getRows();
204                 int dimsArrayOfRes[2] = {sizeOfString, sizeOfVector};
205                 types::String* pString = new types::String(2, dimsArrayOfRes);
206                 for (int i = 0; i < sizeOfVector; i++)
207                 {
208                     for (int j = 0; j < sizeOfString; j++)
209                     {
210                         pString->set(i * sizeOfString + j, pIT[i]->getAs<types::String>()->get(j));
211                     }
212                 }
213                 out.push_back(pString);
214             }
215             break;
216             case (1 << 2) :
217             {
218                 int sizeOfDouble = pIT[0]->getAs<types::Double>()->getRows();
219                 int dimsArrayOfRes[2] = {sizeOfDouble, sizeOfVector};
220                 types::Double* pDouble = new types::Double(2, dimsArrayOfRes);
221                 for (int i = 0; i < sizeOfVector; i++)
222                 {
223                     for (int j = 0; j < sizeOfDouble; j++)
224                     {
225                         pDouble->set(i * sizeOfDouble + j, pIT[i]->getAs<types::Double>()->get(j));
226                     }
227                 }
228                 out.push_back(pDouble);
229             }
230             break;
231             default :
232             {
233                 std::vector<types::InternalType*> pITTemp = std::vector<types::InternalType*>();
234                 pITTemp.push_back(pIT[0]);
235
236                 // sizeOfVector always > 1
237                 for (int i = 1; i < sizeOfVector; i++) // concatenates the Cells. ex : [String 4x1] [String 4x1] = [String 4x2]
238                 {
239                     if (pITTemp.back()->getType() == pIT[i]->getType())
240                     {
241                         switch (pITTemp.back()->getType())
242                         {
243                             case types::InternalType::ScilabString :
244                             {
245                                 int iRows               = pITTemp.back()->getAs<types::String>()->getRows();
246                                 int iCols               = pITTemp.back()->getAs<types::String>()->getCols();
247                                 int arrayOfType[2]      = {iRows, iCols + 1};
248                                 types::String* pType    = new types::String(2, arrayOfType);
249
250                                 for (int k = 0; k < pITTemp.back()->getAs<types::String>()->getSize(); k++)
251                                 {
252                                     pType->set(k, pITTemp.back()->getAs<types::String>()->get(k));
253                                 }
254                                 for (int k = 0; k < pIT[i]->getAs<types::String>()->getSize(); k++)
255                                 {
256                                     pType->set(iRows * iCols + k, pIT[i]->getAs<types::String>()->get(k));
257                                 }
258                                 pITTemp.pop_back();
259                                 pITTemp.push_back(pType);
260                             }
261                             break;
262                             case types::InternalType::ScilabDouble :
263                             {
264                                 int iRows               = pITTemp.back()->getAs<types::Double>()->getRows();
265                                 int iCols               = pITTemp.back()->getAs<types::Double>()->getCols();
266                                 int arrayOfType[2]      = {iRows, iCols + 1};
267                                 types::Double* pType    = new types::Double(2, arrayOfType);
268
269                                 pType->set(pITTemp.back()->getAs<types::Double>()->get());
270                                 for (int k = 0; k < pIT[i]->getAs<types::Double>()->getSize(); k++)
271                                 {
272                                     pType->set(iRows * iCols + k, pIT[i]->getAs<types::Double>()->get(k));
273                                 }
274                                 pITTemp.back();
275                                 pITTemp.push_back(pType);
276                             }
277                             break;
278                             default :
279                                 return types::Function::Error;
280                         }
281                     }
282                     else
283                     {
284                         pITTemp.push_back(pIT[i]);
285                     }
286                 }
287
288                 int dimsArrayOfCell[2] = {1, (int)pITTemp.size()};
289                 types::Cell* pCell = new types::Cell(2, dimsArrayOfCell);
290                 for (int i = 0; i < dimsArrayOfCell[1]; i++)
291                 {
292                     pCell->set(i, pITTemp[i]);
293                 }
294                 out.push_back(pCell);
295             }
296         }
297     }
298     Free_Scan(rowcount, ncol, type_s, &data);
299     return types::Function::OK;
300 }
301 /*--------------------------------------------------------------------------*/