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
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
12 * This code is also published under the GPL v3 license.
18 #include "gw_spreadsheet.h"
19 #include "api_scilab.h"
21 #include "localization.h"
22 #include "freeArrayOfString.h"
26 #include "strdup_windows.h"
28 #include "stringToComplex.h"
29 #include "csvDefault.h"
30 #include "complex_array.h"
31 #include "gw_csv_helpers.h"
34 static void freeVar(char** filename, char** separator, char** decimal, char** conversion, int** iRange, char*** toreplace, int sizeReplace, char** regexp);
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, unsigned long fname_len)
46 char *filename = NULL;
47 char *separator = NULL;
49 char *conversion = NULL;
54 char **toreplace = NULL;
55 int nbElementsToReplace = 0;
60 csvResult *result = NULL;
62 double *dRealValues = NULL;
71 header = (int) csv_getArgumentAsScalarDouble(pvApiCtx, 8, fname, &iErr);
74 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, 0, ®exp);
83 iRange = csv_getArgumentAsMatrixofIntFromDouble(pvApiCtx, 7, fname, &m7, &n7, &iErr);
86 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, 0, ®exp);
90 if ((m7 * n7 != SIZE_RANGE_SUPPORTED) )
92 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, 0, ®exp);
93 Scierror(999, _("%s: Wrong size for input argument #%d: Four entries expected.\n"), fname, 7);
97 if ((m7 != 1) && (n7 != 1))
99 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, 0, ®exp);
100 Scierror(999, _("%s: Wrong size for input argument #%d: A column or row vector expected.\n"), fname, 7);
104 if (isValidRange(iRange, m7 * n7))
110 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, 0, ®exp);
111 Scierror(999, _("%s: Wrong value for input argument #%d: Inconsistent range.\n"), fname, 7);
119 regexp = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 6, fname, getCsvDefaultCommentsRegExp(), &iErr);
122 if (strcmp(regexp, "") == 0)
135 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, 0, ®exp);
141 regexp = strdup(getCsvDefaultCommentsRegExp());
144 if (strcmp(regexp, "") == 0)
154 if (csv_isEmpty(pvApiCtx, 5))
157 nbElementsToReplace = 0;
162 toreplace = csv_getArgumentAsMatrixOfString(pvApiCtx, 5, fname, &m5, &n5, &iErr);
165 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, m5 * n5, ®exp);
171 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, m5 * n5, ®exp);
172 Scierror(999, _("%s: Wrong size for input argument #%d.\n"), fname, 5);
175 nbElementsToReplace = m5;
181 nbElementsToReplace = 0;
187 conversion = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 4, fname, getCsvDefaultConversion(), &iErr);
190 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
194 if (!((strcmp(conversion, CONVTOSTR) == 0) || (strcmp(conversion, CONVTODOUBLE) == 0)))
196 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
197 Scierror(999, _("%s: Wrong value for input argument #%d: '%s' or '%s' string expected.\n"), fname, 4, "double", "string");
203 /* read_csv is using a 'string' conversion while csvRead is doing
204 a 'double' conversion */
205 if (strcmp(fname, "read_csv") == 0)
207 conversion = (char*)MALLOC((strlen("string") + 1) * sizeof(char));
208 strcpy(conversion, "string");
212 conversion = strdup(getCsvDefaultConversion());
219 decimal = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 3, fname, getCsvDefaultDecimal(), &iErr);
222 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
228 decimal = strdup(getCsvDefaultDecimal());
234 separator = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 2, fname, getCsvDefaultSeparator(), &iErr);
237 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
243 separator = strdup(getCsvDefaultSeparator());
246 if (strcmp(separator, "\\t") == 0)
248 /* In Scilab, if the user is providing \t as separator, transform it to a real
249 tab. Example: read_csv(filename,"\t");
251 strcpy(separator, "\t");
255 filename = csv_getArgumentAsString(pvApiCtx, 1, fname, &iErr);
258 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
262 result = csvRead(filename, separator, decimal, (const char**)toreplace, nbElementsToReplace * 2, regexp, header);
263 freeVar(NULL, &separator, &decimal, NULL, NULL, &toreplace, nbElementsToReplace, ®exp);
269 case CSV_READ_REGEXP_ERROR:
271 Scierror(999, _("%s: Wrong value for input argument #%d.\n"), fname, 6);
275 case CSV_READ_SEPARATOR_DECIMAL_EQUAL:
277 Scierror(999, _("%s: separator and decimal must have different values.\n"), fname);
281 case CSV_READ_NO_ERROR:
283 if (strcmp(conversion, CONVTOSTR) == 0)
290 char **pStrRange = getRangeAsString((const char**)result->pstrValues, result->m, result->n, iRange, &newM, &newN);
293 sciErr = createMatrixOfString(pvApiCtx, Rhs + 1, newM, newN, pStrRange);
294 freeArrayOfString(pStrRange, newM * newN);
298 if ((newM == 0) || (newN == 0))
300 Scierror(999, _("%s: Range row or/and column left indice(s) out of bounds.\n"), fname);
304 Scierror(999, _("%s: Memory allocation error.\n"), fname);
307 freeCsvResult(result);
308 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
314 sciErr = createMatrixOfString(pvApiCtx, Rhs + 1, result->m, result->n, result->pstrValues);
319 stringToComplexError ierr = STRINGTOCOMPLEX_ERROR;
320 complexArray *ptrComplexArray = stringsToComplexArray((const char**)result->pstrValues, result->m * result->n, decimal, TRUE, &ierr);
322 if (ptrComplexArray == NULL)
324 freeCsvResult(result);
325 if (ierr == STRINGTOCOMPLEX_ERROR)
327 Scierror(999, _("%s: can not convert data.\n"), fname);
331 Scierror(999, _("%s: Memory allocation error.\n"), fname);
334 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
340 case STRINGTOCOMPLEX_NOT_A_NUMBER:
341 case STRINGTOCOMPLEX_NO_ERROR:
347 complexArray *complexRange = getRangeAsComplexArray(ptrComplexArray, result->m, result->n, iRange, &newM, &newN);
350 if (complexRange->isComplex)
352 sciErr = createComplexMatrixOfDouble(pvApiCtx, Rhs + 1, newM, newN, ptrComplexArray->realPart, ptrComplexArray->imagPart);
356 sciErr = createMatrixOfDouble(pvApiCtx, Rhs + 1, newM, newN, complexRange->realPart);
358 freeComplexArray(complexRange);
363 if ((newM == 0) || (newN == 0))
365 Scierror(999, _("%s: Range row or/and column left indice(s) out of bounds.\n"), fname);
369 Scierror(999, _("%s: Memory allocation error.\n"), fname);
372 freeCsvResult(result);
373 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
379 if (ptrComplexArray->isComplex)
381 sciErr = createComplexMatrixOfDouble(pvApiCtx, Rhs + 1, result->m, result->n, ptrComplexArray->realPart, ptrComplexArray->imagPart);
385 sciErr = createMatrixOfDouble(pvApiCtx, Rhs + 1, result->m, result->n, ptrComplexArray->realPart);
387 freeComplexArray(ptrComplexArray);
388 ptrComplexArray = NULL;
393 case STRINGTOCOMPLEX_MEMORY_ALLOCATION:
395 Scierror(999, _("%s: Memory allocation error.\n"), fname);
396 freeCsvResult(result);
397 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
401 case STRINGTOCOMPLEX_ERROR:
403 Scierror(999, _("%s: can not convert data.\n"), fname);
404 freeCsvResult(result);
405 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
413 Scierror(999, _("%s: Memory allocation error.\n"), fname);
414 freeCsvResult(result);
415 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
426 char **emptyStringMatrix = NULL;
427 emptyStringMatrix = (char**) malloc(sizeof(char*));
428 emptyStringMatrix[0] = "";
429 sciErr = createMatrixOfString(pvApiCtx, Rhs + 2, 1, 1, emptyStringMatrix);
430 free(emptyStringMatrix);
434 sciErr = createMatrixOfString(pvApiCtx, Rhs + 2, result->nbComments, 1, result->pstrComments);
438 Scierror(999, _("%s: Memory allocation error.\n"), fname);
439 freeCsvResult(result);
440 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
450 case CSV_READ_FILE_NOT_EXIST:
452 Scierror(999, _("%s: %s does not exist.\n"), fname, filename);
456 case CSV_READ_MOPEN_ERROR:
458 Scierror(999, _("%s: can not open file %s.\n"), fname, filename);
462 case CSV_READ_MEMORY_ALLOCATION:
464 Scierror(999, _("%s: Memory allocation error.\n"), fname);
468 case CSV_READ_COLUMNS_ERROR:
470 Scierror(999, _("%s: can not read file %s: Error in the column structure\n"), fname, filename);
474 case CSV_READ_READLINES_ERROR:
477 Scierror(999, _("%s: can not read file %s.\n"), fname, filename);
484 Scierror(999, _("%s: Memory allocation error.\n"), fname);
487 freeCsvResult(result);
489 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
493 /* ==================================================================== */
494 static void freeVar(char** filename, char** separator, char** decimal, char** conversion, int** iRange, char*** toreplace, int sizeReplace, char** regexp)
496 if (filename && *filename)
502 if (separator && *separator)
508 if (decimal && *decimal)
514 if (conversion && *conversion)
520 if (iRange && *iRange)
526 if (toreplace && *toreplace)
528 freeArrayOfString(*toreplace, sizeReplace);
532 if (regexp && *regexp)