bc6861efb6d535235adac0366be8b1e0e58125a7
[scilab.git] / scilab / modules / fileio / sci_gateway / cpp / sci_mfscanf.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 * This file must be used under the terms of the CeCILL.
9 * This source file is licensed as described in the file COPYING, which
10 * you should have received as part of this distribution.  The terms
11 * are also available at
12 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
13 *
14 */
15 /*--------------------------------------------------------------------------*/
16 #include "fileio_gw.hxx"
17 #include "string.hxx"
18 #include "cell.hxx"
19
20 extern "C"
21 {
22 #include "localization.h"
23 #include "Scierror.h"
24 #include "sciprint.h"
25 #include "mgetl.h"
26 #include "do_xxprintf.h"
27 #include "do_xxscanf.h"
28 #include "scanf_functions.h"
29 }
30
31 types::Function::ReturnValue sci_mfscanf(types::typed_list &in, int _iRetCount, types::typed_list &out)
32 {
33     int iFile                   = -1; //default file : last opened file
34     int size                    = (int)in.size();
35     int iNiter                  = 1;
36     int iLinesRead              = 0;
37     int iErr                    = 0;
38     wchar_t* wcsFormat          = NULL;
39     wchar_t** wcsRead           = NULL;
40     int dimsArray[2]            = {1,1};
41     std::vector<types::InternalType*>* pIT = new std::vector<types::InternalType*>();
42
43     int args        = 0;
44     int nrow        = 0;
45     int ncol        = 0;
46     int retval      = 0;
47     int retval_s    = 0;
48     int rowcount    = -1;
49     rec_entry buf[MAXSCAN];
50     entry *data;
51     sfdir type[MAXSCAN],type_s[MAXSCAN];
52
53     if(size < 2 || size >3)
54     {
55        ScierrorW(77, _W("%ls: Wrong number of input argument(s): %d to %d expected.\n"), L"mfscanf", 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             ScierrorW(999, _W("%ls: Wrong type for input argument #%d: A Real expected.\n"), L"mfscanf", 1);
64             return types::Function::Error;
65         }
66         iNiter = static_cast<int>(in[0]->getAs<types::Double>()->getReal()[0]);
67     }
68
69     if(in[size-2]->isDouble() == false || in[size-2]->getAs<types::Double>()->isScalar() == false || in[size-2]->getAs<types::Double>()->isComplex())
70     {
71         ScierrorW(999, _W("%ls: Wrong type for input argument #%d: A Real expected.\n"), L"mfscanf", 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         ScierrorW(999, _W("%ls: Wrong type for input argument #%d: A String expected.\n"), L"mfscanf", size);
78         return types::Function::Error;
79     }
80
81     iFile = static_cast<int>(in[size-2]->getAs<types::Double>()->getReal()[0]);
82         switch (iFile)
83         {
84     case 0:
85         // stderr
86         ScierrorW(999, _W("%ls: Wrong file descriptor: %d.\n"), L"mfscanf", iFile);
87         return types::Function::Error;
88     case 6:
89         // stdout
90         ScierrorW(999, _W("%ls: Wrong file descriptor: %d.\n"), L"mfscanf", iFile);
91         return types::Function::Error;
92     default :
93         break;
94     }
95
96     wcsFormat = in[size-1]->getAs<types::String>()->get(0);
97
98 // get data
99
100     wcsRead = mgetl(iFile, iNiter, &iLinesRead, &iErr);
101     switch(iErr)
102     {
103         case MGETL_NO_ERROR :
104         break;
105         case MGETL_EOF :
106             sciprintW(_W("Warning: Only %d line(s) read.\n"), iLinesRead);
107         break;
108         case MGETL_MEMORY_ALLOCATION_ERROR :
109             ScierrorW(999, _W("%ls: Memory allocation error in %ls function.\n"), L"mfscanf", L"mgetl");
110         return types::Function::Error;
111         case MGETL_ERROR :
112             ScierrorW(999, _W("%ls: Cannot read file %d.\n"), L"mfscanf", iFile);
113         return types::Function::Error;
114     }
115
116     nrow = iLinesRead;
117         while(++rowcount < iLinesRead)
118     {
119         if ((iLinesRead >= 0) && (rowcount >= iLinesRead)) break;
120         // get data
121         int err = do_xxscanf(L"sscanf",(FILE *)0,wcsFormat,&args,wcsRead[rowcount],&retval,buf,type);
122         if(err < 0) return types::Function::Error;
123         err=Store_Scan(&nrow,&ncol,type_s,type,&retval,&retval_s,buf,&data,rowcount,args);
124         if(err < 0)
125         {
126             switch (err)
127             {
128                 case DO_XXPRINTF_MISMATCH:
129                     if (iLinesRead >= 0)
130                     {
131                         Free_Scan(rowcount,ncol,type_s,&data);
132                         ScierrorW(999,_W("%ls: Data mismatch.\n"),L"mfscanf");
133                         return types::Function::Error;
134                     }
135                 break;
136
137                 case DO_XXPRINTF_MEM_LACK:
138                     Free_Scan(rowcount,ncol,type_s,&data);
139                     ScierrorW(999,_W("%ls: No more memory.\n"),L"mfscanf");
140                     return types::Function::Error;
141                 break;
142             }
143             if (err==DO_XXPRINTF_MISMATCH) break;
144         }
145         FREE(wcsRead[rowcount]);
146     }
147     FREE(wcsRead);
148     unsigned int uiFormatUsed = 0;
149     for(int i=0; i<ncol; i++)
150     {
151         switch ( type_s[i] )
152         {
153             case SF_C:
154             case SF_S:
155             {
156                 types::String* ps = new types::String(iLinesRead,1);
157                 for(int j=0; j<iLinesRead; j++)
158                 {
159                     ps->set(j, data[i+ncol*j].s);
160                 }
161                 pIT->push_back(ps);
162                 uiFormatUsed |= (1 << 1);
163             }
164             break;
165                 case SF_LUI:
166             case SF_SUI:
167             case SF_UI:
168             case SF_LI:
169             case SF_SI:
170             case SF_I:
171             case SF_LF:
172             case SF_F:
173             {
174                 types::Double* p = new types::Double(iLinesRead,1);
175                 for(int j=0; j<iLinesRead; j++)
176                 {
177                     p->set(j, data[i+ncol*j].d);
178                 }
179                 pIT->push_back(p);
180                 uiFormatUsed |= (1 << 2);
181             }
182             break;
183         }
184     }
185
186     int sizeOfVector = (int)pIT->size();
187     if(_iRetCount > 1)
188     {
189         types::Double* pDouble = new types::Double(2,dimsArray);
190         pDouble->set(0,retval);
191         out.push_back(pDouble);
192
193         for(int i = 0; i < sizeOfVector; i++)
194         {
195             out.push_back((*pIT)[i]);
196         }
197         for(int i = sizeOfVector + 1; i < _iRetCount; i++)
198         {
199             out.push_back(types::Double::Empty());
200         }
201     }
202     else
203     {
204         if(sizeOfVector == 0)
205         {
206             out.push_back(types::Double::Empty());
207             return types::Function::OK;
208         }
209
210         switch(uiFormatUsed)
211         {
212             case (1 << 1) :
213             {
214                 int sizeOfString = (*pIT)[0]->getAs<types::String>()->getRows();
215                 int dimsArrayOfRes[2] = {sizeOfString, sizeOfVector};
216                 types::String* pString = new types::String(2, dimsArrayOfRes);
217                 for(int i = 0; i < sizeOfVector; i++)
218                 {
219                     for(int j = 0; j < sizeOfString; j++)
220                     {
221                         pString->set(i*sizeOfString+j, (*pIT)[i]->getAs<types::String>()->get(j));
222                     }
223                 }
224                 out.push_back(pString);
225             }
226             break;
227             case (1 << 2) :
228             {
229                 int sizeOfDouble = (*pIT)[0]->getAs<types::Double>()->getRows();
230                 int dimsArrayOfRes[2] = {sizeOfDouble, sizeOfVector};
231                 types::Double* pDouble = new types::Double(2, dimsArrayOfRes);
232                 for(int i = 0; i < sizeOfVector; i++)
233                 {
234                     for(int j = 0; j < sizeOfDouble; j++)
235                     {
236                         pDouble->set(i*sizeOfDouble+j, (*pIT)[i]->getAs<types::Double>()->get(j));
237                     }
238                 }
239                 out.push_back(pDouble);
240             }
241             break;
242             default :
243             {
244                 std::vector<types::InternalType*>* pITTemp = new std::vector<types::InternalType*>();
245                 pITTemp->push_back((*pIT)[0]);
246
247                 // sizeOfVector always > 1
248                 for(int i = 1; i < sizeOfVector; i++) // concatenates the Cells. ex : [String 4x1] [String 4x1] = [String 4x2]
249                 {
250                     if(pITTemp->back()->getType() == (*pIT)[i]->getType())
251                     {
252                         switch(pITTemp->back()->getType())
253                         {
254                             case types::InternalType::RealString :
255                             {
256                                 int iRows               = pITTemp->back()->getAs<types::String>()->getRows();
257                                 int iCols               = pITTemp->back()->getAs<types::String>()->getCols();
258                                 int arrayOfType[2]      = {iRows, iCols + 1};
259                                 types::String* pType    = new types::String(2, arrayOfType);
260
261                                 for(int k=0; k<pITTemp->back()->getAs<types::String>()->getSize(); k++)
262                                 {
263                                     pType->set(k, pITTemp->back()->getAs<types::String>()->get(k));
264                                 }
265                                 for(int k=0; k<(*pIT)[i]->getAs<types::String>()->getSize(); k++)
266                                 {
267                                     pType->set(iRows * iCols + k, (*pIT)[i]->getAs<types::String>()->get(k));
268                                 }
269                                 pITTemp->pop_back();
270                                 pITTemp->push_back(pType);
271                             }
272                             break;
273                             case types::InternalType::RealDouble :
274                             {
275                                 int iRows               = pITTemp->back()->getAs<types::Double>()->getRows();
276                                 int iCols               = pITTemp->back()->getAs<types::Double>()->getCols();
277                                 int arrayOfType[2]      = {iRows, iCols + 1};
278                                 types::Double* pType    = new types::Double(2, arrayOfType);
279
280                                 pType->set(pITTemp->back()->getAs<types::Double>()->get());
281                                 for(int k=0; k<(*pIT)[i]->getAs<types::Double>()->getSize(); k++)
282                                 {
283                                     pType->set(iRows * iCols + k, (*pIT)[i]->getAs<types::Double>()->get(k));
284                                 }
285                                 pITTemp->pop_back();
286                                 pITTemp->push_back(pType);
287                             }
288                             break;
289                             default :
290                                 return types::Function::Error;
291                         }
292                     }
293                     else
294                     {
295                         pITTemp->push_back((*pIT)[i]);
296                     }
297                 }
298
299                 int dimsArrayOfCell[2] = {1, (int)pITTemp->size()};
300                 types::Cell* pCell = new types::Cell(2, dimsArrayOfCell);
301                 for(int i = 0; i < pITTemp->size(); i++)
302                 {
303                     pCell->set(i, (*pITTemp)[i]);
304                 }
305                 out.push_back(pCell);
306             }
307         }
308     }
309         Free_Scan(rowcount,ncol,type_s,&data);
310     return types::Function::OK;
311 }
312 /*--------------------------------------------------------------------------*/
313