21db7996009cd6e126245eb8074fc2127931a7fe
[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: Inconsistent 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)
184         {
185             FREE(regexp);
186             return 0;
187         }
188         if (!((strcmp(conversion, CONVTOSTR) == 0) || (strcmp(conversion, CONVTODOUBLE) == 0)))
189         {
190             if (regexp)
191             {
192                 FREE(regexp);
193                 regexp = NULL;
194             }
195             if (toreplace)
196             {
197                 freeArrayOfString(toreplace, nbElementsToReplace * 2);
198                 toreplace = NULL;
199             }
200             if (conversion)
201             {
202                 FREE(conversion);
203                 conversion = NULL;
204             }
205             Scierror(999, _("%s: Wrong value for input argument #%d: '%s' or '%s' string expected.\n"), fname, 4, "double", "string");
206             return 0;
207         }
208     }
209     else
210     {
211         /* read_csv is using a 'string' conversion while csvRead is doing
212            a 'double' conversion */
213         if (strcmp(fname, "read_csv") == 0)
214         {
215             conversion = (char*)MALLOC((strlen("string") + 1) * sizeof(char));
216             strcpy(conversion, "string");
217         }
218         else
219         {
220             conversion = strdup(getCsvDefaultConversion());
221         }
222     }
223
224     if (Rhs >= 3)
225     {
226         int iErr = 0;
227         decimal = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 3, fname, getCsvDefaultDecimal(), &iErr);
228         if (iErr)
229         {
230             if (regexp)
231             {
232                 FREE(regexp);
233                 regexp = NULL;
234             }
235             if (conversion)
236             {
237                 FREE(conversion);
238                 conversion = NULL;
239             }
240             if (toreplace)
241             {
242                 freeArrayOfString(toreplace, nbElementsToReplace * 2);
243                 toreplace = NULL;
244             }
245             return 0;
246         }
247     }
248     else
249     {
250         decimal = strdup(getCsvDefaultDecimal());
251     }
252
253     if (Rhs >= 2)
254     {
255         int iErr = 0;
256         separator = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 2, fname, getCsvDefaultSeparator(), &iErr);
257         if (iErr)
258         {
259             if (regexp)
260             {
261                 FREE(regexp);
262                 regexp = NULL;
263             }
264             if (toreplace)
265             {
266                 freeArrayOfString(toreplace, nbElementsToReplace * 2);
267                 toreplace = NULL;
268             }
269             if (conversion)
270             {
271                 FREE(conversion);
272                 conversion = NULL;
273             }
274             if (decimal)
275             {
276                 FREE(decimal);
277                 decimal = NULL;
278             }
279             return 0;
280         }
281     }
282     else
283     {
284         separator = strdup(getCsvDefaultSeparator());
285     }
286
287     if (strcmp(separator, "\\t") == 0)
288     {
289         /* In Scilab, if the user is providing \t as separator, transform it to a real
290            tab. Example: read_csv(filename,"\t");
291         */
292         strcpy(separator, "\t");
293     }
294
295
296     filename = csv_getArgumentAsString(pvApiCtx, 1, fname, &iErr);
297     if (iErr)
298     {
299         if (regexp)
300         {
301             FREE(regexp);
302             regexp = NULL;
303         }
304         if (toreplace)
305         {
306             freeArrayOfString(toreplace, nbElementsToReplace * 2);
307             toreplace = NULL;
308         }
309         if (separator)
310         {
311             FREE(separator);
312             separator = NULL;
313         }
314         if (conversion)
315         {
316             FREE(conversion);
317             conversion = NULL;
318         }
319         if (decimal)
320         {
321             FREE(decimal);
322             decimal = NULL;
323         }
324         return 0;
325     }
326
327     result = csvRead(filename, separator, decimal, (const char**)toreplace, nbElementsToReplace * 2, regexp);
328     if (regexp)
329     {
330         FREE(regexp);
331         regexp = NULL;
332     }
333     if (toreplace)
334     {
335         freeArrayOfString(toreplace, nbElementsToReplace * 2);
336         toreplace = NULL;
337     }
338     if (separator)
339     {
340         FREE(separator);
341         separator = NULL;
342     }
343     if (decimal)
344     {
345         FREE(decimal);
346         decimal = NULL;
347     }
348
349     if (result)
350     {
351         switch (result->err)
352         {
353             case CSV_READ_REGEXP_ERROR:
354             {
355                 Scierror(999, _("%s: Wrong value for input argument #%d.\n"), fname, 6);
356             }
357             break;
358
359             case CSV_READ_SEPARATOR_DECIMAL_EQUAL:
360             {
361                 Scierror(999, _("%s: separator and decimal must have different values.\n"), fname);
362             }
363             break;
364
365             case CSV_READ_NO_ERROR:
366             {
367                 if (strcmp(conversion, CONVTOSTR) == 0)
368                 {
369                     if (haveRange)
370                     {
371                         int newM = 0;
372                         int newN = 0;
373
374                         char **pStrRange = getRangeAsString((const char**)result->pstrValues, result->m, result->n, iRange, &newM, &newN);
375                         if (pStrRange)
376                         {
377                             sciErr = createMatrixOfString(pvApiCtx, Rhs + 1, newM, newN, pStrRange);
378                             freeArrayOfString(pStrRange, newM * newN);
379                         }
380                         else
381                         {
382                             Scierror(999, _("%s: Memory allocation error.\n"), fname);
383                         }
384                     }
385                     else
386                     {
387                         sciErr = createMatrixOfString(pvApiCtx, Rhs + 1, result->m, result->n, result->pstrValues);
388                     }
389                 }
390                 else /* to double */
391                 {
392                     stringToComplexError ierr = STRINGTOCOMPLEX_ERROR;
393                     csv_complexArray *ptrCsvComplexArray = stringsToCsvComplexArray((const char**)result->pstrValues, result->m * result->n, decimal, TRUE, &ierr);
394
395                     if (ptrCsvComplexArray == NULL)
396                     {
397                         freeCsvResult(result);
398                         if (filename)
399                         {
400                             FREE(filename);
401                             filename = NULL;
402                         }
403                         if (conversion)
404                         {
405                             FREE(conversion);
406                             conversion = NULL;
407                         }
408                         if (ierr == STRINGTOCOMPLEX_ERROR)
409                         {
410                             Scierror(999, _("%s: can not convert data.\n"), fname);
411                         }
412                         else
413                         {
414                             Scierror(999, _("%s: Memory allocation error.\n"), fname);
415                         }
416                         return 0;
417                     }
418
419                     switch (ierr)
420                     {
421                         case STRINGTOCOMPLEX_NOT_A_NUMBER:
422                         case STRINGTOCOMPLEX_NO_ERROR:
423                         {
424                             if (haveRange)
425                             {
426                                 int newM = 0;
427                                 int newN = 0;
428                                 csv_complexArray *csvComplexRange = getRangeAsCsvComplexArray(ptrCsvComplexArray, result->m, result->n, iRange, &newM, &newN);
429                                 if (csvComplexRange)
430                                 {
431                                     if (csvComplexRange->isComplex)
432                                     {
433                                         sciErr = createComplexMatrixOfDouble(pvApiCtx, Rhs + 1, newM, newN, ptrCsvComplexArray->realPart, ptrCsvComplexArray->imagPart);
434                                     }
435                                     else
436                                     {
437                                         sciErr = createMatrixOfDouble(pvApiCtx, Rhs + 1, newM, newN, csvComplexRange->realPart);
438                                     }
439                                     freeCsvComplexArray(csvComplexRange);
440                                     csvComplexRange = NULL;
441                                 }
442                                 else
443                                 {
444                                     Scierror(999, _("%s: Memory allocation error.\n"), fname);
445                                 }
446                             }
447                             else
448                             {
449                                 if (ptrCsvComplexArray->isComplex)
450                                 {
451                                     sciErr = createComplexMatrixOfDouble(pvApiCtx, Rhs + 1, result->m, result->n, ptrCsvComplexArray->realPart, ptrCsvComplexArray->imagPart);
452                                 }
453                                 else
454                                 {
455                                     sciErr = createMatrixOfDouble(pvApiCtx, Rhs + 1, result->m, result->n, ptrCsvComplexArray->realPart);
456                                 }
457                                 freeCsvComplexArray(ptrCsvComplexArray);
458                                 ptrCsvComplexArray = NULL;
459                             }
460                         }
461                         break;
462
463                         case STRINGTOCOMPLEX_MEMORY_ALLOCATION:
464                         {
465                             Scierror(999, _("%s: Memory allocation error.\n"), fname);
466                         }
467                         default:
468                         case STRINGTOCOMPLEX_ERROR:
469                         {
470                             Scierror(999, _("%s: can not convert data.\n"), fname);
471                         }
472                     }
473                 }
474
475                 if (sciErr.iErr)
476                 {
477                     freeCsvResult(result);
478                     if (filename)
479                     {
480                         FREE(filename);
481                         filename = NULL;
482                     }
483                     if (conversion)
484                     {
485                         FREE(conversion);
486                         conversion = NULL;
487                     }
488                     printError(&sciErr, 0);
489                     Scierror(17, _("%s: Memory allocation error.\n"), fname);
490                     return 0;
491                 }
492                 else
493                 {
494                     LhsVar(1) = Rhs + 1;
495
496                     if (Lhs == 2)
497                     {
498                         sciErr = createMatrixOfString(pvApiCtx, Rhs + 2, result->nbComments, 1, result->pstrComments);
499                         if (sciErr.iErr)
500                         {
501                             freeCsvResult(result);
502                             if (filename)
503                             {
504                                 FREE(filename);
505                                 filename = NULL;
506                             }
507                             if (conversion)
508                             {
509                                 FREE(conversion);
510                                 conversion = NULL;
511                             }
512                             printError(&sciErr, 0);
513                             Scierror(17, _("%s: Memory allocation error.\n"), fname);
514                             return 0;
515                         }
516                         LhsVar(2) = Rhs + 2;
517                     }
518                     PutLhsVar();
519                 }
520             }
521             break;
522
523             case CSV_READ_FILE_NOT_EXIST:
524             {
525                 Scierror(999, _("%s: %s does not exist.\n"), fname, filename);
526             }
527             break;
528
529             case CSV_READ_MOPEN_ERROR:
530             {
531                 Scierror(999, _("%s: can not open file %s.\n"), fname, filename);
532             }
533             break;
534
535             case CSV_READ_MEMORY_ALLOCATION:
536             {
537                 Scierror(999, _("%s: Memory allocation error.\n"), fname);
538             }
539             break;
540
541             case CSV_READ_COLUMNS_ERROR:
542             {
543                 Scierror(999, _("%s: can not read file %s: Error in the column structure\n"), fname, filename);
544             }
545             break;
546
547             case CSV_READ_READLINES_ERROR:
548             case CSV_READ_ERROR:
549             {
550                 Scierror(999, _("%s: can not read file %s.\n"), fname, filename);
551             }
552             break;
553         }
554     }
555     else
556     {
557         Scierror(999, _("%s: Memory allocation error.\n"), fname);
558     }
559     freeCsvResult(result);
560     if (filename)
561     {
562         FREE(filename);
563         filename = NULL;
564     }
565     if (conversion)
566     {
567         FREE(conversion);
568         conversion = NULL;
569     }
570
571     return 0;
572 }
573 /* ==================================================================== */