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