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