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