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