* read_csv has the same behavior as in the version 5.3.3
[scilab.git] / scilab / modules / spreadsheet / sci_gateway / cpp / sci_csvTextScan.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010 - 2012 - INRIA - Allan CORNET
4  * Copyright (C) 2011 - INRIA - Michael Baudin
5  *
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  *
12  * This code is also published under the GPL v3 license.
13  *
14  */
15 #include <string.h>
16 #include "gw_csv_tools.h"
17 #include "api_scilab.h"
18 #include "Scierror.h"
19 #include "MALLOC.h"
20 #include "Scierror.h"
21 #include "localization.h"
22 extern "C" {
23 #include "freeArrayOfString.h"
24 };
25 #ifdef _MSC_VER
26 #include "strdup_windows.h"
27 #endif
28 #include "stringToComplex.h"
29 #include "csvDefault.h"
30 #include "csvRead.h"
31 #include "getRange.h"
32 #include "gw_csv_helpers.h"
33 // =============================================================================
34 #define CONVTOSTR "string"
35 #define CONVTODOUBLE "double"
36 // =============================================================================
37 int sci_csvTextScan(char *fname)
38 {
39     SciErr sciErr;
40     int iErr = 0;
41     int i = 0;
42
43     int *piAddressVarOne = NULL;
44     int m1 = 0, n1 = 0;
45     int iType1 = 0;
46
47     char **text = NULL;
48     int *lengthText = NULL;
49     int nbLines = 0;
50
51     char *separator = NULL;
52     char *decimal = NULL;
53     char *conversion = NULL;
54
55     double * dRealValues = NULL;
56
57     int *iRange = NULL;
58     int haveRange = 0;
59
60     csvResult *result = NULL;
61
62     CheckRhs(1, 5);
63     CheckLhs(1, 1);
64
65     if (Rhs == 5)
66     {
67         int m5 = 0, n5 = 0;
68
69         iRange = csv_getArgumentAsMatrixofIntFromDouble(pvApiCtx, 5, fname, &m5, &n5, &iErr);
70         if (iErr) return 0;
71
72         if ((m5 * n5 != SIZE_RANGE_SUPPORTED) )
73         {
74             if (iRange)
75             {
76                 FREE(iRange);
77                 iRange = NULL;
78             }
79             Scierror(999, _("%s: Wrong size for input argument #%d: Four entries expected.\n"), fname, 5);
80             return 0;
81         }
82
83         if ((m5 != 1) && (n5 != 1))
84         {
85             if (iRange)
86             {
87                 FREE(iRange);
88                 iRange = NULL;
89             }
90             Scierror(999, _("%s: Wrong size for input argument #%d: A column or row vector expected.\n"), fname, 5);
91             return 0;
92         }
93
94         if (isValidRange(iRange, m5 * n5))
95         {
96             haveRange = 1;
97         }
98         else
99         {
100             if (iRange)
101             {
102                 FREE(iRange);
103                 iRange = NULL;
104             }
105             Scierror(999, _("%s: Wrong value for input argument #%d: Unconsistent range.\n"), fname, 5);
106             return 0;
107         }
108     }
109
110     if (Rhs >= 4)
111     {
112         conversion = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 4, fname, getCsvDefaultConversion(), &iErr);
113         if (iErr)
114         {
115             if (iRange)
116             {
117                 FREE(iRange);
118                 iRange = NULL;
119             }
120             return 0;
121         }
122
123         if (!((strcmp(conversion, CONVTOSTR) == 0) || (strcmp(conversion, CONVTODOUBLE) == 0)))
124         {
125             if (iRange)
126             {
127                 FREE(iRange);
128                 iRange = NULL;
129             }
130             if (conversion)
131             {
132                 FREE(conversion);
133                 conversion = NULL;
134             }
135
136             Scierror(999, _("%s: Wrong value for input argument #%d: '%s' or '%s' string expected.\n"), fname, 4, "double", "string");
137             return 0;
138         }
139     }
140     else
141     {
142         conversion = strdup(getCsvDefaultConversion());
143     }
144
145     if (Rhs >= 3)
146     {
147         decimal = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 3, fname, getCsvDefaultDecimal(), &iErr);
148         if (iErr)
149         {
150             if (iRange)
151             {
152                 FREE(iRange);
153                 iRange = NULL;
154             }
155             if (conversion)
156             {
157                 FREE(conversion);
158                 conversion = NULL;
159             }
160             return 0;
161         }
162     }
163     else
164     {
165         decimal = strdup(getCsvDefaultDecimal());
166     }
167
168     if (Rhs >= 2)
169     {
170         separator = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 2, fname, getCsvDefaultSeparator(), &iErr);
171         if (iErr)
172         {
173             if (iRange)
174             {
175                 FREE(iRange);
176                 iRange = NULL;
177             }
178             if (decimal)
179             {
180                 FREE(decimal);
181                 decimal = NULL;
182             }
183             if (conversion)
184             {
185                 FREE(conversion);
186                 conversion = NULL;
187             }
188             return 0;
189         }
190     }
191     else
192     {
193         separator = strdup(getCsvDefaultSeparator());
194     }
195
196     if (!csv_isRowVector(pvApiCtx, 1) &&
197             !csv_isColumnVector(pvApiCtx, 1) &&
198             !csv_isScalar(pvApiCtx, 1))
199     {
200         if (iRange)
201         {
202             FREE(iRange);
203             iRange = NULL;
204         }
205         if (separator)
206         {
207             FREE(separator);
208             separator = NULL;
209         }
210         if (decimal)
211         {
212             FREE(decimal);
213             decimal = NULL;
214         }
215         if (conversion)
216         {
217             FREE(conversion);
218             conversion = NULL;
219         }
220         Scierror(999, _("%s: Wrong size for input argument #%d: string expected.\n"), fname, 1);
221         return 0;
222     }
223
224     text = csv_getArgumentAsMatrixOfString(pvApiCtx, 1, fname, &m1, &n1, &iErr);
225     if (iErr)
226     {
227         if (iRange)
228         {
229             FREE(iRange);
230             iRange = NULL;
231         }
232         if (separator)
233         {
234             FREE(separator);
235             separator = NULL;
236         }
237         if (decimal)
238         {
239             FREE(decimal);
240             decimal = NULL;
241         }
242         if (conversion)
243         {
244             FREE(conversion);
245             conversion = NULL;
246         }
247         return 0;
248     }
249
250     nbLines = m1 * n1;
251     result = csvTextScan((const char**)text, nbLines, separator, decimal);
252
253     if (text)
254     {
255         if (separator)
256         {
257             FREE(separator);
258             separator = NULL;
259         }
260         freeArrayOfString(text, nbLines);
261         text = NULL;
262     }
263
264     if (separator)
265     {
266         FREE(separator);
267         separator = NULL;
268     }
269
270     if (result)
271     {
272         switch (result->err)
273         {
274             case CSV_READ_SEPARATOR_DECIMAL_EQUAL:
275             {
276                 Scierror(999, _("%s: separator and decimal must have different values.\n"), fname);
277             }
278             break;
279
280             case CSV_READ_NO_ERROR:
281             {
282                 if (strcmp(conversion, CONVTOSTR) == 0)
283                 {
284                     if (haveRange)
285                     {
286                         int newM = 0;
287                         int newN = 0;
288
289                         char **pStrRange = getRangeAsString((const char**)result->pstrValues, result->m, result->n, iRange, &newM, &newN);
290                         if (pStrRange)
291                         {
292                             sciErr = createMatrixOfString(pvApiCtx, Rhs + 1, newM, newN, pStrRange);
293                             freeArrayOfString(pStrRange, newM * newN);
294                         }
295                         else
296                         {
297                             Scierror(999, _("%s: Memory allocation error.\n"), fname);
298                         }
299
300                     }
301                     else
302                     {
303                         sciErr = createMatrixOfString(pvApiCtx, Rhs + 1, result->m, result->n, result->pstrValues);
304                     }
305                 }
306                 else /* to double */
307                 {
308                     stringToComplexError ierr = STRINGTOCOMPLEX_ERROR;
309                     csv_complexArray *ptrCsvComplexArray = stringsToCsvComplexArray((const char**)result->pstrValues, result->m * result->n, decimal, TRUE, &ierr);
310                     if (ptrCsvComplexArray == NULL)
311                     {
312                         freeCsvResult(result);
313                         if (decimal)
314                         {
315                             FREE(decimal);
316                             decimal = NULL;
317                         }
318                         if (conversion)
319                         {
320                             FREE(conversion);
321                             conversion = NULL;
322                         }
323                         if (iRange)
324                         {
325                             FREE(iRange);
326                             iRange = NULL;
327                         }
328                         if (ierr == STRINGTOCOMPLEX_ERROR)
329                         {
330                             Scierror(999, _("%s: can not convert data.\n"), fname);
331                         }
332                         else
333                         {
334                             Scierror(999, _("%s: Memory allocation error.\n"), fname);
335                         }
336                         return 0;
337                     }
338
339                     switch (ierr)
340                     {
341                         case STRINGTOCOMPLEX_NOT_A_NUMBER:
342                         case STRINGTOCOMPLEX_NO_ERROR:
343                         {
344                             if (haveRange)
345                             {
346                                 int newM = 0;
347                                 int newN = 0;
348                                 csv_complexArray *csvComplexRange = getRangeAsCsvComplexArray(ptrCsvComplexArray, result->m, result->n, iRange, &newM, &newN);
349                                 if (csvComplexRange)
350                                 {
351                                     if (csvComplexRange->isComplex)
352                                     {
353                                         sciErr = createComplexMatrixOfDouble(pvApiCtx, Rhs + 1, newM, newN, ptrCsvComplexArray->realPart, ptrCsvComplexArray->imagPart);
354                                     }
355                                     else
356                                     {
357                                         sciErr = createMatrixOfDouble(pvApiCtx, Rhs + 1, newM, newN, csvComplexRange->realPart);
358                                     }
359                                     freeCsvComplexArray(csvComplexRange);
360                                     csvComplexRange = NULL;
361                                 }
362                                 else
363                                 {
364                                     Scierror(999, _("%s: Memory allocation error.\n"), fname);
365                                 }
366                             }
367                             else
368                             {
369                                 if (ptrCsvComplexArray->isComplex)
370                                 {
371                                     sciErr = createComplexMatrixOfDouble(pvApiCtx, Rhs + 1, result->m, result->n, ptrCsvComplexArray->realPart, ptrCsvComplexArray->imagPart);
372                                 }
373                                 else
374                                 {
375                                     sciErr = createMatrixOfDouble(pvApiCtx, Rhs + 1, result->m, result->n, ptrCsvComplexArray->realPart);
376                                 }
377                             }
378                             freeCsvComplexArray(ptrCsvComplexArray);
379                             ptrCsvComplexArray = NULL;
380                         }
381                         break;
382
383                         case STRINGTOCOMPLEX_MEMORY_ALLOCATION:
384                         {
385                             Scierror(999, _("%s: Memory allocation error.\n"), fname);
386                         }
387                         default:
388                         case STRINGTOCOMPLEX_ERROR:
389                         {
390                             Scierror(999, _("%s: can not convert data.\n"), fname);
391                         }
392                     }
393                 }
394
395                 if (sciErr.iErr)
396                 {
397                     freeCsvResult(result);
398                     if (decimal)
399                     {
400                         FREE(decimal);
401                         decimal = NULL;
402                     }
403                     if (conversion)
404                     {
405                         FREE(conversion);
406                         conversion = NULL;
407                     }
408                     if (iRange)
409                     {
410                         FREE(iRange);
411                         iRange = NULL;
412                     }
413                     printError(&sciErr, 0);
414                     Scierror(17, _("%s: Memory allocation error.\n"), fname);
415                     return 0;
416                 }
417                 else
418                 {
419                     LhsVar(1) = Rhs + 1;
420                     PutLhsVar();
421                 }
422             }
423             break;
424
425             case CSV_READ_MEMORY_ALLOCATION:
426             {
427                 Scierror(999, _("%s: Memory allocation error.\n"), fname);
428             }
429             break;
430
431             case CSV_READ_READLINES_ERROR:
432             case CSV_READ_COLUMNS_ERROR:
433             case CSV_READ_ERROR:
434             {
435                 Scierror(999, _("%s: can not read text.\n"), fname);
436             }
437             break;
438         }
439     }
440     else
441     {
442         Scierror(999, _("%s: Memory allocation error.\n"), fname);
443     }
444     freeCsvResult(result);
445     if (decimal)
446     {
447         FREE(decimal);
448         decimal = NULL;
449     }
450     if (conversion)
451     {
452         FREE(conversion);
453         conversion = NULL;
454     }
455     if (iRange)
456     {
457         FREE(iRange);
458         iRange = NULL;
459     }
460
461     return 0;
462 }
463 // =============================================================================