* read_csv has the same behavior as in the version 5.3.3
[scilab.git] / scilab / modules / spreadsheet / sci_gateway / cpp / sci_csvRead.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 <stdio.h>
17
18 #include "gw_csv_tools.h"
19 #include "api_scilab.h"
20 #include "Scierror.h"
21 #include "localization.h"
22 extern "C" {
23 #include "freeArrayOfString.h"
24 };
25 #include "MALLOC.h"
26 #include "csvRead.h"
27 #ifdef _MSC_VER
28 #include "strdup_windows.h"
29 #endif
30 #include "stringToComplex.h"
31 #include "csvDefault.h"
32 #include "csv_complex.h"
33 #include "gw_csv_helpers.h"
34 #include "getRange.h"
35 /* ==================================================================== */
36 #define CONVTOSTR "string"
37 #define CONVTODOUBLE "double"
38 /* ==================================================================== */
39 /* csvRead(filename, separator, decimal, conversion, substitute, range)*/
40 /* ==================================================================== */
41 int sci_csvRead(char *fname)
42 {
43     SciErr sciErr;
44     int iErr = 0;
45
46     char *filename = NULL;
47     char *separator = NULL;
48     char *decimal = NULL;
49     char *conversion = NULL;
50     int *iRange = NULL;
51     int haveRange = 0;
52
53     char **toreplace = NULL;
54     int nbElementsToReplace = 0;
55
56     char *regexp = NULL;
57
58     csvResult *result = NULL;
59
60     double *dRealValues = NULL;
61
62     CheckRhs(1, 7);
63     CheckLhs(1, 2);
64
65     if (Rhs == 7)
66     {
67         int m7 = 0, n7 = 0;
68
69         iRange = csv_getArgumentAsMatrixofIntFromDouble(pvApiCtx, 7, fname, &m7, &n7, &iErr);
70         if (iErr) return 0;
71
72         if ((m7 * n7 != 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, 7);
80             return 0;
81         }
82
83         if ((m7 != 1) && (n7 != 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, 7);
91             return 0;
92         }
93
94         if (isValidRange(iRange, m7 * n7))
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, 7);
106             return 0;
107         }
108     }
109
110
111     if (Rhs >= 6)
112     {
113         regexp = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 6, fname, getCsvDefaultCommentsRegExp(), &iErr);
114         if (regexp)
115         {
116             if (strcmp(regexp, "") == 0)
117             {
118                 FREE(regexp);
119                 regexp = NULL;
120             }
121         }
122         if (iErr) return 0;
123     }
124     else
125     {
126         regexp = strdup(getCsvDefaultCommentsRegExp());
127         if (regexp)
128         {
129             if (strcmp(regexp, "") == 0)
130             {
131                 FREE(regexp);
132                 regexp = NULL;
133             }
134         }
135     }
136
137     if (Rhs >= 5)
138     {
139         if (csv_isEmpty(pvApiCtx, 5))
140         {
141             toreplace = NULL;
142             nbElementsToReplace = 0;
143         }
144         else
145         {
146             int m5 = 0, n5 = 0;
147             toreplace = csv_getArgumentAsMatrixOfString(pvApiCtx, 5, fname, &m5, &n5, &iErr);
148             if (iErr)
149             {
150                 if (regexp)
151                 {
152                     FREE(regexp);
153                     regexp = NULL;
154                 }
155                 return 0;
156             }
157
158             if (n5 != 2)
159             {
160                 if (regexp)
161                 {
162                     FREE(regexp);
163                     regexp = NULL;
164                 }
165                 freeArrayOfString(toreplace, m5 * n5);
166                 toreplace = NULL;
167                 Scierror(999, _("%s: Wrong size for input argument #%d.\n"), fname, 5);
168                 return 0;
169             }
170             nbElementsToReplace = m5;
171         }
172     }
173     else
174     {
175         toreplace = NULL;
176         nbElementsToReplace = 0;
177     }
178
179     if (Rhs >= 4)
180     {
181         int iErr = 0;
182         conversion = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 4, fname, getCsvDefaultConversion(), &iErr);
183         if (iErr) return 0;
184         if (!((strcmp(conversion, CONVTOSTR) == 0) || (strcmp(conversion, CONVTODOUBLE) == 0)))
185         {
186             if (regexp)
187             {
188                 FREE(regexp);
189                 regexp = NULL;
190             }
191             if (toreplace)
192             {
193                 freeArrayOfString(toreplace, nbElementsToReplace * 2);
194                 toreplace = NULL;
195             }
196             if (conversion)
197             {
198                 FREE(conversion);
199                 conversion = NULL;
200             }
201             Scierror(999, _("%s: Wrong value for input argument #%d: '%s' or '%s' string expected.\n"), fname, 4, "double", "string");
202             return 0;
203         }
204     }
205     else
206     {
207         /* read_csv is using a 'string' conversion while csvRead is doing
208            a 'double' conversion */
209         if (strcmp(fname, "read_csv") == 0)
210         {
211             conversion = (char*)MALLOC((strlen("string") + 1) * sizeof(char));
212             strcpy(conversion, "string");
213         }
214         else
215         {
216             conversion = strdup(getCsvDefaultConversion());
217         }
218     }
219
220     if (Rhs >= 3)
221     {
222         int iErr = 0;
223         decimal = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 3, fname, getCsvDefaultDecimal(), &iErr);
224         if (iErr)
225         {
226             if (regexp)
227             {
228                 FREE(regexp);
229                 regexp = NULL;
230             }
231             if (conversion)
232             {
233                 FREE(conversion);
234                 conversion = NULL;
235             }
236             if (toreplace)
237             {
238                 freeArrayOfString(toreplace, nbElementsToReplace * 2);
239                 toreplace = NULL;
240             }
241             return 0;
242         }
243     }
244     else
245     {
246         decimal = strdup(getCsvDefaultDecimal());
247     }
248
249     if (Rhs >= 2)
250     {
251         int iErr = 0;
252         separator = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 2, fname, getCsvDefaultSeparator(), &iErr);
253         if (iErr)
254         {
255             if (regexp)
256             {
257                 FREE(regexp);
258                 regexp = NULL;
259             }
260             if (toreplace)
261             {
262                 freeArrayOfString(toreplace, nbElementsToReplace * 2);
263                 toreplace = NULL;
264             }
265             if (conversion)
266             {
267                 FREE(conversion);
268                 conversion = NULL;
269             }
270             if (decimal)
271             {
272                 FREE(decimal);
273                 decimal = NULL;
274             }
275             return 0;
276         }
277     }
278     else
279     {
280         separator = strdup(getCsvDefaultSeparator());
281     }
282
283     if (strcmp(separator, "\\t") == 0)
284     {
285         /* In Scilab, if the user is providing \t as separator, transform it to a real
286            tab. Example: read_csv(filename,"\t");
287         */
288         strcpy(separator, "\t");
289     }
290
291
292     filename = csv_getArgumentAsString(pvApiCtx, 1, fname, &iErr);
293     if (iErr)
294     {
295         if (regexp)
296         {
297             FREE(regexp);
298             regexp = NULL;
299         }
300         if (toreplace)
301         {
302             freeArrayOfString(toreplace, nbElementsToReplace * 2);
303             toreplace = NULL;
304         }
305         if (separator)
306         {
307             FREE(separator);
308             separator = NULL;
309         }
310         if (conversion)
311         {
312             FREE(conversion);
313             conversion = NULL;
314         }
315         if (decimal)
316         {
317             FREE(decimal);
318             decimal = NULL;
319         }
320         return 0;
321     }
322
323     result = csvRead(filename, separator, decimal, (const char**)toreplace, nbElementsToReplace * 2, regexp);
324     if (regexp)
325     {
326         FREE(regexp);
327         regexp = NULL;
328     }
329     if (toreplace)
330     {
331         freeArrayOfString(toreplace, nbElementsToReplace * 2);
332         toreplace = NULL;
333     }
334     if (separator)
335     {
336         FREE(separator);
337         separator = NULL;
338     }
339     if (decimal)
340     {
341         FREE(decimal);
342         decimal = NULL;
343     }
344
345     if (result)
346     {
347         switch (result->err)
348         {
349             case CSV_READ_REGEXP_ERROR:
350             {
351                 Scierror(999, _("%s: Wrong value for input argument #%d.\n"), fname, 6);
352             }
353             break;
354
355             case CSV_READ_SEPARATOR_DECIMAL_EQUAL:
356             {
357                 Scierror(999, _("%s: separator and decimal must have different values.\n"), fname);
358             }
359             break;
360
361             case CSV_READ_NO_ERROR:
362             {
363                 if (strcmp(conversion, CONVTOSTR) == 0)
364                 {
365                     if (haveRange)
366                     {
367                         int newM = 0;
368                         int newN = 0;
369
370                         char **pStrRange = getRangeAsString((const char**)result->pstrValues, result->m, result->n, iRange, &newM, &newN);
371                         if (pStrRange)
372                         {
373                             sciErr = createMatrixOfString(pvApiCtx, Rhs + 1, newM, newN, pStrRange);
374                             freeArrayOfString(pStrRange, newM * newN);
375                         }
376                         else
377                         {
378                             Scierror(999, _("%s: Memory allocation error.\n"), fname);
379                         }
380                     }
381                     else
382                     {
383                         sciErr = createMatrixOfString(pvApiCtx, Rhs + 1, result->m, result->n, result->pstrValues);
384                     }
385                 }
386                 else /* to double */
387                 {
388                     stringToComplexError ierr = STRINGTOCOMPLEX_ERROR;
389                     csv_complexArray *ptrCsvComplexArray = stringsToCsvComplexArray((const char**)result->pstrValues, result->m * result->n, decimal, TRUE, &ierr);
390
391                     if (ptrCsvComplexArray == NULL)
392                     {
393                         freeCsvResult(result);
394                         if (filename)
395                         {
396                             FREE(filename);
397                             filename = NULL;
398                         }
399                         if (conversion)
400                         {
401                             FREE(conversion);
402                             conversion = NULL;
403                         }
404                         if (ierr == STRINGTOCOMPLEX_ERROR)
405                         {
406                             Scierror(999, _("%s: can not convert data.\n"), fname);
407                         }
408                         else
409                         {
410                             Scierror(999, _("%s: Memory allocation error.\n"), fname);
411                         }
412                         return 0;
413                     }
414
415                     switch (ierr)
416                     {
417                         case STRINGTOCOMPLEX_NOT_A_NUMBER:
418                         case STRINGTOCOMPLEX_NO_ERROR:
419                         {
420                             if (haveRange)
421                             {
422                                 int newM = 0;
423                                 int newN = 0;
424                                 csv_complexArray *csvComplexRange = getRangeAsCsvComplexArray(ptrCsvComplexArray, result->m, result->n, iRange, &newM, &newN);
425                                 if (csvComplexRange)
426                                 {
427                                     if (csvComplexRange->isComplex)
428                                     {
429                                         sciErr = createComplexMatrixOfDouble(pvApiCtx, Rhs + 1, newM, newN, ptrCsvComplexArray->realPart, ptrCsvComplexArray->imagPart);
430                                     }
431                                     else
432                                     {
433                                         sciErr = createMatrixOfDouble(pvApiCtx, Rhs + 1, newM, newN, csvComplexRange->realPart);
434                                     }
435                                     freeCsvComplexArray(csvComplexRange);
436                                     csvComplexRange = NULL;
437                                 }
438                                 else
439                                 {
440                                     Scierror(999, _("%s: Memory allocation error.\n"), fname);
441                                 }
442                             }
443                             else
444                             {
445                                 if (ptrCsvComplexArray->isComplex)
446                                 {
447                                     sciErr = createComplexMatrixOfDouble(pvApiCtx, Rhs + 1, result->m, result->n, ptrCsvComplexArray->realPart, ptrCsvComplexArray->imagPart);
448                                 }
449                                 else
450                                 {
451                                     sciErr = createMatrixOfDouble(pvApiCtx, Rhs + 1, result->m, result->n, ptrCsvComplexArray->realPart);
452                                 }
453                                 freeCsvComplexArray(ptrCsvComplexArray);
454                                 ptrCsvComplexArray = NULL;
455                             }
456                         }
457                         break;
458
459                         case STRINGTOCOMPLEX_MEMORY_ALLOCATION:
460                         {
461                             Scierror(999, _("%s: Memory allocation error.\n"), fname);
462                         }
463                         default:
464                         case STRINGTOCOMPLEX_ERROR:
465                         {
466                             Scierror(999, _("%s: can not convert data.\n"), fname);
467                         }
468                     }
469                 }
470
471                 if (sciErr.iErr)
472                 {
473                     freeCsvResult(result);
474                     if (filename)
475                     {
476                         FREE(filename);
477                         filename = NULL;
478                     }
479                     if (conversion)
480                     {
481                         FREE(conversion);
482                         conversion = NULL;
483                     }
484                     printError(&sciErr, 0);
485                     Scierror(17, _("%s: Memory allocation error.\n"), fname);
486                     return 0;
487                 }
488                 else
489                 {
490                     LhsVar(1) = Rhs + 1;
491
492                     if (Lhs == 2)
493                     {
494                         sciErr = createMatrixOfString(pvApiCtx, Rhs + 2, result->nbComments, 1, result->pstrComments);
495                         if (sciErr.iErr)
496                         {
497                             freeCsvResult(result);
498                             if (filename)
499                             {
500                                 FREE(filename);
501                                 filename = NULL;
502                             }
503                             if (conversion)
504                             {
505                                 FREE(conversion);
506                                 conversion = NULL;
507                             }
508                             printError(&sciErr, 0);
509                             Scierror(17, _("%s: Memory allocation error.\n"), fname);
510                             return 0;
511                         }
512                         LhsVar(2) = Rhs + 2;
513                     }
514                     PutLhsVar();
515                 }
516             }
517             break;
518
519             case CSV_READ_FILE_NOT_EXIST:
520             {
521                 Scierror(999, _("%s: %s does not exist.\n"), fname, filename);
522             }
523             break;
524
525             case CSV_READ_MOPEN_ERROR:
526             {
527                 Scierror(999, _("%s: can not open file %s.\n"), fname, filename);
528             }
529             break;
530
531             case CSV_READ_MEMORY_ALLOCATION:
532             {
533                 Scierror(999, _("%s: Memory allocation error.\n"), fname);
534             }
535             break;
536
537             case CSV_READ_READLINES_ERROR:
538             case CSV_READ_COLUMNS_ERROR:
539             case CSV_READ_ERROR:
540             {
541                 Scierror(999, _("%s: can not read file %s.\n"), fname, filename);
542             }
543             break;
544         }
545     }
546     else
547     {
548         Scierror(999, _("%s: Memory allocation error.\n"), fname);
549     }
550     freeCsvResult(result);
551     if (filename)
552     {
553         FREE(filename);
554         filename = NULL;
555     }
556     if (conversion)
557     {
558         FREE(conversion);
559         conversion = NULL;
560     }
561
562     return 0;
563 }
564 /* ==================================================================== */