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)
47 char *filename = NULL;
48 char *separator = NULL;
50 char *conversion = NULL;
55 char **toreplace = NULL;
56 int nbElementsToReplace = 0;
61 csvResult *result = NULL;
63 double *dRealValues = NULL;
72 header = (int) csv_getArgumentAsScalarDouble(pvApiCtx, 8, fname, &iErr);
75 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, 0, ®exp);
84 iRange = csv_getArgumentAsMatrixofIntFromDouble(pvApiCtx, 7, fname, &m7, &n7, &iErr);
87 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, 0, ®exp);
91 if ((m7 * n7 != SIZE_RANGE_SUPPORTED) )
93 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, 0, ®exp);
94 Scierror(999, _("%s: Wrong size for input argument #%d: Four entries expected.\n"), fname, 7);
98 if ((m7 != 1) && (n7 != 1))
100 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, 0, ®exp);
101 Scierror(999, _("%s: Wrong size for input argument #%d: A column or row vector expected.\n"), fname, 7);
105 if (isValidRange(iRange, m7 * n7))
111 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, 0, ®exp);
112 Scierror(999, _("%s: Wrong value for input argument #%d: Inconsistent range.\n"), fname, 7);
120 regexp = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 6, fname, getCsvDefaultCommentsRegExp(), &iErr);
123 if (strcmp(regexp, "") == 0)
136 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, 0, ®exp);
142 regexp = strdup(getCsvDefaultCommentsRegExp());
145 if (strcmp(regexp, "") == 0)
155 if (csv_isEmpty(pvApiCtx, 5))
158 nbElementsToReplace = 0;
163 toreplace = csv_getArgumentAsMatrixOfString(pvApiCtx, 5, fname, &m5, &n5, &iErr);
166 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, m5 * n5, ®exp);
172 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, m5 * n5, ®exp);
173 Scierror(999, _("%s: Wrong size for input argument #%d.\n"), fname, 5);
176 nbElementsToReplace = m5;
182 nbElementsToReplace = 0;
188 conversion = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 4, fname, getCsvDefaultConversion(), &iErr);
191 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
195 if (!((strcmp(conversion, CONVTOSTR) == 0) || (strcmp(conversion, CONVTODOUBLE) == 0)))
197 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
198 Scierror(999, _("%s: Wrong value for input argument #%d: '%s' or '%s' string expected.\n"), fname, 4, "double", "string");
204 /* read_csv is using a 'string' conversion while csvRead is doing
205 a 'double' conversion */
206 if (strcmp(fname, "read_csv") == 0)
208 conversion = (char*)MALLOC((strlen("string") + 1) * sizeof(char));
209 strcpy(conversion, "string");
213 conversion = strdup(getCsvDefaultConversion());
220 decimal = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 3, fname, getCsvDefaultDecimal(), &iErr);
223 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
229 decimal = strdup(getCsvDefaultDecimal());
235 separator = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 2, fname, getCsvDefaultSeparator(), &iErr);
238 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
244 separator = strdup(getCsvDefaultSeparator());
247 if (strcmp(separator, "\\t") == 0)
249 /* In Scilab, if the user is providing \t as separator, transform it to a real
250 tab. Example: read_csv(filename,"\t");
252 strcpy(separator, "\t");
256 filename = csv_getArgumentAsString(pvApiCtx, 1, fname, &iErr);
259 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
263 result = csvRead(filename, separator, decimal, (const char**)toreplace, nbElementsToReplace * 2, regexp, header);
264 freeVar(NULL, &separator, &decimal, NULL, NULL, &toreplace, nbElementsToReplace, ®exp);
270 case CSV_READ_REGEXP_ERROR:
272 Scierror(999, _("%s: Wrong value for input argument #%d.\n"), fname, 6);
276 case CSV_READ_SEPARATOR_DECIMAL_EQUAL:
278 Scierror(999, _("%s: separator and decimal must have different values.\n"), fname);
282 case CSV_READ_NO_ERROR:
284 if (strcmp(conversion, CONVTOSTR) == 0)
291 char **pStrRange = getRangeAsString((const char**)result->pstrValues, result->m, result->n, iRange, &newM, &newN);
294 sciErr = createMatrixOfString(pvApiCtx, Rhs + 1, newM, newN, pStrRange);
295 freeArrayOfString(pStrRange, newM * newN);
299 if ((newM == 0) || (newN == 0))
301 Scierror(999, _("%s: Range row or/and column left indice(s) out of bounds.\n"), fname);
305 Scierror(999, _("%s: Memory allocation error.\n"), fname);
308 freeCsvResult(result);
309 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
315 sciErr = createMatrixOfString(pvApiCtx, Rhs + 1, result->m, result->n, result->pstrValues);
320 stringToComplexError ierr = STRINGTOCOMPLEX_ERROR;
321 complexArray *ptrComplexArray = stringsToComplexArray((const char**)result->pstrValues, result->m * result->n, decimal, TRUE, &ierr);
323 if (ptrComplexArray == NULL)
325 freeCsvResult(result);
326 if (ierr == STRINGTOCOMPLEX_ERROR)
328 Scierror(999, _("%s: can not convert data.\n"), fname);
332 Scierror(999, _("%s: Memory allocation error.\n"), fname);
335 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
341 case STRINGTOCOMPLEX_NOT_A_NUMBER:
342 case STRINGTOCOMPLEX_NO_ERROR:
348 complexArray *complexRange = getRangeAsComplexArray(ptrComplexArray, result->m, result->n, iRange, &newM, &newN);
351 if (complexRange->isComplex)
353 sciErr = createComplexMatrixOfDouble(pvApiCtx, Rhs + 1, newM, newN, ptrComplexArray->realPart, ptrComplexArray->imagPart);
357 sciErr = createMatrixOfDouble(pvApiCtx, Rhs + 1, newM, newN, complexRange->realPart);
359 freeComplexArray(complexRange);
364 if ((newM == 0) || (newN == 0))
366 Scierror(999, _("%s: Range row or/and column left indice(s) out of bounds.\n"), fname);
370 Scierror(999, _("%s: Memory allocation error.\n"), fname);
373 freeCsvResult(result);
374 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
380 if (ptrComplexArray->isComplex)
382 sciErr = createComplexMatrixOfDouble(pvApiCtx, Rhs + 1, result->m, result->n, ptrComplexArray->realPart, ptrComplexArray->imagPart);
386 sciErr = createMatrixOfDouble(pvApiCtx, Rhs + 1, result->m, result->n, ptrComplexArray->realPart);
388 freeComplexArray(ptrComplexArray);
389 ptrComplexArray = NULL;
394 case STRINGTOCOMPLEX_MEMORY_ALLOCATION:
396 Scierror(999, _("%s: Memory allocation error.\n"), fname);
397 freeCsvResult(result);
398 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
402 case STRINGTOCOMPLEX_ERROR:
404 Scierror(999, _("%s: can not convert data.\n"), fname);
405 freeCsvResult(result);
406 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
414 Scierror(999, _("%s: Memory allocation error.\n"), fname);
415 freeCsvResult(result);
416 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
427 char **emptyStringMatrix = NULL;
428 emptyStringMatrix = (char**) malloc(sizeof(char*));
429 emptyStringMatrix[0] = "";
430 sciErr = createMatrixOfString(pvApiCtx, Rhs + 2, 1, 1, emptyStringMatrix);
431 free(emptyStringMatrix);
435 if (result->nbComments > 0)
437 sciErr = createMatrixOfString(pvApiCtx, Rhs + 2, result->nbComments, 1, result->pstrComments);
441 iErrEmpty = createEmptyMatrix(pvApiCtx, Rhs+2);
442 sciErr.iErr = iErrEmpty;
447 Scierror(999, _("%s: Memory allocation error.\n"), fname);
448 freeCsvResult(result);
449 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
459 case CSV_READ_FILE_NOT_EXIST:
461 Scierror(999, _("%s: %s does not exist.\n"), fname, filename);
465 case CSV_READ_MOPEN_ERROR:
467 Scierror(999, _("%s: can not open file %s.\n"), fname, filename);
471 case CSV_READ_MEMORY_ALLOCATION:
473 Scierror(999, _("%s: Memory allocation error.\n"), fname);
477 case CSV_READ_COLUMNS_ERROR:
479 Scierror(999, _("%s: can not read file %s: Error in the column structure\n"), fname, filename);
483 case CSV_READ_READLINES_ERROR:
486 Scierror(999, _("%s: can not read file %s.\n"), fname, filename);
493 Scierror(999, _("%s: Memory allocation error.\n"), fname);
496 freeCsvResult(result);
498 freeVar(&filename, &separator, &decimal, &conversion, &iRange, &toreplace, nbElementsToReplace, ®exp);
502 /* ==================================================================== */
503 static void freeVar(char** filename, char** separator, char** decimal, char** conversion, int** iRange, char*** toreplace, int sizeReplace, char** regexp)
505 if (filename && *filename)
511 if (separator && *separator)
517 if (decimal && *decimal)
523 if (conversion && *conversion)
529 if (iRange && *iRange)
535 if (toreplace && *toreplace)
537 freeArrayOfString(*toreplace, sizeReplace);
541 if (regexp && *regexp)