Check the file ID in mclose, meof, mseek and mtell to show an error if the file ID...
[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 #include "filemanager.hxx"
20
21 extern "C"
22 {
23 #include "localization.h"
24 #include "Scierror.h"
25 #include "sciprint.h"
26 #include "mgetl.h"
27 #include "do_xxprintf.h"
28 #include "do_xxscanf.h"
29 #include "scanf_functions.h"
30 }
31
32 types::Function::ReturnValue sci_mfscanf(types::typed_list &in, int _iRetCount, types::typed_list &out)
33 {
34     int iFile                   = -1; //default file : last opened file
35     int size                    = (int)in.size();
36     int iNiter                  = 1;
37     //int iLinesRead              = 0;
38     int iErr                    = 0;
39     wchar_t* wcsFormat          = 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>()->get(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>()->get(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     types::File* pFile = FileManager::getFile(iFile);
99     if(pFile == NULL)
100     {
101         ScierrorW(999, _W("%ls: Cannot read file %d.\n"), L"mfscanf", iFile);
102         return types::Function::Error;
103     }
104
105     FILE* fDesc = pFile->getFiledesc();
106     nrow = iNiter;
107     //nrow = iLinesRead;
108         while(++rowcount < iNiter)
109     {
110         if((iNiter >= 0) && (rowcount >= iNiter)) break;
111         // get data
112         int err = do_xxscanf(L"mfscanf", fDesc, wcsFormat, &args, NULL, &retval, buf, type);
113         if(err < 0)
114         {
115             return types::Function::Error;
116         }
117
118         err = Store_Scan(&nrow,&ncol,type_s,type,&retval,&retval_s,buf,&data,rowcount,args);
119         if(err < 0)
120         {
121             switch(err)
122             {
123                 case DO_XXPRINTF_MISMATCH:
124                     if(iNiter >= 0)
125                     {
126                         Free_Scan(rowcount,ncol,type_s,&data);
127                         ScierrorW(999,_W("%ls: Data mismatch.\n"),L"mfscanf");
128                         return types::Function::Error;
129                     }
130                 break;
131
132                 case DO_XXPRINTF_MEM_LACK:
133                     Free_Scan(rowcount,ncol,type_s,&data);
134                     ScierrorW(999,_W("%ls: No more memory.\n"),L"mfscanf");
135                     return types::Function::Error;
136                 break;
137             }
138             if(err==DO_XXPRINTF_MISMATCH) break;
139         }
140     }
141
142     unsigned int uiFormatUsed = 0;
143     for(int i = 0 ; i < ncol ; i++)
144     {
145         switch(type_s[i])
146         {
147             case SF_C:
148             case SF_S:
149             {
150                 types::String* ps = new types::String(iNiter,1);
151                 for(int j = 0 ; j < iNiter ; j++)
152                 {
153                     ps->set(j, data[i + ncol * j].s);
154                 }
155                 pIT->push_back(ps);
156                 uiFormatUsed |= (1 << 1);
157             }
158             break;
159                 case SF_LUI:
160             case SF_SUI:
161             case SF_UI:
162             case SF_LI:
163             case SF_SI:
164             case SF_I:
165             case SF_LF:
166             case SF_F:
167             {
168                 types::Double* p = new types::Double(iNiter,1);
169                 for(int j=0; j<iNiter; j++)
170                 {
171                     p->set(j, data[i+ncol*j].d);
172                 }
173                 pIT->push_back(p);
174                 uiFormatUsed |= (1 << 2);
175             }
176             break;
177         }
178     }
179
180     int sizeOfVector = (int)pIT->size();
181     if(_iRetCount > 1)
182     {
183         types::Double* pDouble = new types::Double(2,dimsArray);
184         pDouble->set(0,retval);
185         out.push_back(pDouble);
186
187         for(int i = 0; i < sizeOfVector; i++)
188         {
189             out.push_back((*pIT)[i]);
190         }
191         for(int i = sizeOfVector + 1; i < _iRetCount; i++)
192         {
193             out.push_back(types::Double::Empty());
194         }
195     }
196     else
197     {
198         if(sizeOfVector == 0)
199         {
200             out.push_back(types::Double::Empty());
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::RealString :
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
260                                 for(int k = 0; k < (*pIT)[i]->getAs<types::String>()->getSize() ; k++)
261                                 {
262                                     pType->set(iRows * iCols + k, (*pIT)[i]->getAs<types::String>()->get(k));
263                                 }
264                                 pITTemp->pop_back();
265                                 pITTemp->push_back(pType);
266                             }
267                             break;
268                             case types::InternalType::RealDouble :
269                             {
270                                 int iRows               = pITTemp->back()->getAs<types::Double>()->getRows();
271                                 int iCols               = pITTemp->back()->getAs<types::Double>()->getCols();
272                                 int arrayOfType[2]      = {iRows, iCols + 1};
273                                 types::Double* pType    = new types::Double(2, arrayOfType);
274
275                                 pType->set(pITTemp->back()->getAs<types::Double>()->get());
276                                 for(int k = 0; k < (*pIT)[i]->getAs<types::Double>()->getSize() ; k++)
277                                 {
278                                     pType->set(iRows * iCols + k, (*pIT)[i]->getAs<types::Double>()->get(k));
279                                 }
280                                 pITTemp->pop_back();
281                                 pITTemp->push_back(pType);
282                             }
283                             break;
284                             default :
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 < pITTemp->size() ; 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     return types::Function::OK;
306 }
307 /*--------------------------------------------------------------------------*/
308