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 * Copyright (C) 2012 - 2016 - Scilab Enterprises
7 *
8 * This file is hereby licensed under the terms of the GNU GPL v2.0,
9 * pursuant to article 5.3.4 of the CeCILL v.2.1.
10 * This file was originally licensed under the terms of the CeCILL v2.1,
11 * and continues to be available under such terms.
12 * For more information, see the COPYING file which you should have received
13 * along with this program.
14 *
15 * This code is also published under the GPL v3 license.
16 *
17 */
18 #include <string.h>
19 #include <stdio.h>
20
21 #include "gw_spreadsheet.h"
22 #include "api_scilab.h"
23 #include "Scierror.h"
24 #include "sci_malloc.h"
25 #include "csvWrite.h"
26 #include "localization.h"
27 #include "freeArrayOfString.h"
28 #include "csvDefault.h"
29 #include "checkCsvWriteFormat.h"
30 #include "gw_csv_helpers.h"
31 #include "os_string.h"
32
33
34 static void freeVar(char** separator, char** decimal, char** filename, char** precisionFormat, char*** pHeadersLines, int sizeHeader);
35 // =============================================================================
36 // csvWrite(M, filename[, separator, decimal, precision]) */
37 // with M string or double (not complex)
38 // =============================================================================
sci_csvWrite(char * fname,void * pvApiCtx)39 int sci_csvWrite(char *fname, void* pvApiCtx)
40 {
41 SciErr sciErr;
42 int iErr = 0;
43 csvWriteError csvError = CSV_WRITE_ERROR;
44
45 char *separator = NULL;
46 char *decimal = NULL;
47 char *filename = NULL;
48 char *precisionFormat = NULL;
49 char **pHeadersLines = NULL;
50 int nbHeadersLines = 0;
51
52 char **pStringValues = NULL;
53 double *pDoubleValuesReal = NULL;
54 double *pDoubleValuesImag = NULL;
55 int bIsComplex = 0;
56 int mValues = 0;
57 int nValues = 0;
58
59 int *piAddressVarTwo = NULL;
60 int m2 = 0, n2 = 0;
61 int iType2 = 0;
62
63 int *piAddressVarOne = NULL;
64 int m1 = 0, n1 = 0;
65 int iType1 = 0;
66
67 CheckRhs(2, 6);
68 CheckLhs(0, 1);
69
70 if (Rhs > 5)
71 {
72 int isOnlyRowOrCol = 0;
73 int m6 = 0;
74 int n6 = 0;
75 pHeadersLines = csv_getArgumentAsMatrixOfString(pvApiCtx, 6, fname, &m6, &n6, &iErr);
76 if (iErr)
77 {
78 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
79 return 0;
80 }
81 isOnlyRowOrCol = ((m6 > 1) && (n6 == 1)) || ((m6 == 1) && (n6 > 1)) || ((m6 == 1) && (n6 == 1));
82 if (!isOnlyRowOrCol)
83 {
84 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
85 Scierror(999, _("%s: Wrong size for input argument #%d: A 1-by-n or m-by-1 array of strings expected.\n"), fname, 6);
86 return 0;
87 }
88 nbHeadersLines = m6 * n6;
89 }
90
91 if (Rhs > 4)
92 {
93 if (csv_isDoubleScalar(pvApiCtx, 5))
94 {
95 #define FORMAT_FIELDVALUESTR "%%.%dlg"
96 int iFormatValue = (int) csv_getArgumentAsScalarDouble(pvApiCtx, 5, fname, &iErr);
97 if (iErr)
98 {
99 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
100 return 0;
101 }
102
103 if ((iFormatValue < 1) || (iFormatValue > 17))
104 {
105 Scierror(999, _("%s: Wrong value for input argument #%d: A double (value 1 to 17) expected.\n"), fname, 5);
106 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
107 return 0;
108 }
109
110 precisionFormat = (char*)MALLOC(sizeof(char) * ((int)strlen(FORMAT_FIELDVALUESTR) + 1));
111 if (precisionFormat == NULL)
112 {
113 Scierror(999, _("%s: Memory allocation error.\n"), fname);
114 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
115 return 0;
116 }
117 sprintf(precisionFormat, FORMAT_FIELDVALUESTR, iFormatValue);
118 }
119 else
120 {
121 precisionFormat = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 5, fname, getCsvDefaultPrecision(), &iErr);
122 if (iErr)
123 {
124 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
125 return 0;
126 }
127
128 if (checkCsvWriteFormat(precisionFormat))
129 {
130 Scierror(999, _("%s: Not supported format %s.\n"), fname, precisionFormat);
131 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
132 return 0;
133 }
134 }
135 }
136 else
137 {
138 precisionFormat = os_strdup(getCsvDefaultPrecision());
139 }
140
141 if (Rhs > 3)
142 {
143 decimal = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 4, fname, getCsvDefaultDecimal(), &iErr);
144 if (iErr)
145 {
146 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
147 return 0;
148 }
149
150 if (strcmp(decimal, ".") && strcmp(decimal, ","))
151 {
152 //invalid value
153 Scierror(999, _("%s: Wrong value for input argument #%d: '%s' or '%s' expected.\n"), "write_csv", 4, ".", ",");
154 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
155 return 1;
156 }
157 }
158 else
159 {
160 decimal = os_strdup(getCsvDefaultDecimal());
161 }
162
163 if (Rhs > 2)
164 {
165 separator = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 3, fname, getCsvDefaultSeparator(), &iErr);
166 if (iErr)
167 {
168 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
169 return 0;
170 }
171 }
172 else
173 {
174 separator = os_strdup(getCsvDefaultSeparator());
175 }
176
177 filename = csv_getArgumentAsString(pvApiCtx, 2, fname, &iErr);
178 if (iErr)
179 {
180 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
181 return 0;
182 }
183
184 sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddressVarOne);
185 if (sciErr.iErr)
186 {
187 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
188 printError(&sciErr, 0);
189 return 0;
190 }
191
192 sciErr = getVarType(pvApiCtx, piAddressVarOne, &iType1);
193 if (sciErr.iErr)
194 {
195 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
196 printError(&sciErr, 0);
197 return 0;
198 }
199
200 if (iType1 == sci_strings)
201 {
202 pStringValues = csv_getArgumentAsMatrixOfString(pvApiCtx, 1, fname, &m1, &n1, &iErr);
203 if (iErr)
204 {
205 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
206 return 0;
207 }
208 }
209 else if (iType1 == sci_matrix)
210 {
211 if (isVarComplex(pvApiCtx, piAddressVarOne))
212 {
213 bIsComplex = 1;
214 sciErr = getComplexMatrixOfDouble(pvApiCtx, piAddressVarOne, &m1, &n1, &pDoubleValuesReal, &pDoubleValuesImag);
215 }
216 else
217 {
218 sciErr = getMatrixOfDouble(pvApiCtx, piAddressVarOne, &m1, &n1, &pDoubleValuesReal);
219 }
220
221 if (sciErr.iErr)
222 {
223 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
224 printError(&sciErr, 0);
225 return 0;
226 }
227 }
228 else
229 {
230 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
231 Scierror(999, _("%s: Wrong type for input argument #%d: A matrix of string or a matrix of real expected.\n"), fname, 1);
232 return 0;
233 }
234
235 if (pStringValues)
236 {
237 csvError = csvWrite_string(filename,
238 (const char**)pStringValues, m1, n1,
239 separator,
240 decimal,
241 (const char**)pHeadersLines, nbHeadersLines);
242 freeAllocatedMatrixOfString(m1, n1, pStringValues);
243 }
244 else
245 {
246 if (bIsComplex)
247 {
248 csvError = csvWrite_complex(filename,
249 pDoubleValuesReal,
250 pDoubleValuesImag,
251 m1, n1,
252 separator,
253 decimal,
254 precisionFormat,
255 (const char**)pHeadersLines, nbHeadersLines);
256 }
257 else
258 {
259 csvError = csvWrite_double(filename,
260 pDoubleValuesReal, m1, n1,
261 separator,
262 decimal,
263 precisionFormat,
264 (const char**)pHeadersLines, nbHeadersLines);
265 }
266 }
267
268 switch (csvError)
269 {
270 case CSV_WRITE_SEPARATOR_DECIMAL_EQUAL:
271 {
272 Scierror(999, _("%s: separator and decimal must have different values.\n"), fname);
273 }
274 break;
275 case CSV_WRITE_NO_ERROR:
276 {
277 LhsVar(1) = 0;
278 PutLhsVar();
279 }
280 break;
281
282 case CSV_WRITE_FOPEN_ERROR:
283 {
284 Scierror(999, _("%s: can not open file %s.\n"), fname, filename);
285 }
286 break;
287 default:
288 case CSV_WRITE_ERROR:
289 {
290 Scierror(999, _("%s: error.\n"), fname);
291 }
292 break;
293 }
294
295 freeVar(&separator, &decimal, &filename, &precisionFormat, &pHeadersLines, nbHeadersLines);
296 return 0;
297 }
298 // =============================================================================
freeVar(char ** separator,char ** decimal,char ** filename,char ** precisionFormat,char *** pHeadersLines,int sizeHeader)299 static void freeVar(char** separator, char** decimal, char** filename, char** precisionFormat, char*** pHeadersLines, int sizeHeader)
300 {
301 if (separator && *separator)
302 {
303 FREE(*separator);
304 *separator = NULL;
305 }
306
307 if (decimal && *decimal)
308 {
309 FREE(*decimal);
310 *decimal = NULL;
311 }
312
313 if (filename && *filename)
314 {
315 FREE(*filename);
316 *filename = NULL;
317 }
318
319 if (precisionFormat && *precisionFormat)
320 {
321 FREE(*precisionFormat);
322 *precisionFormat = NULL;
323 }
324
325 if (pHeadersLines && *pHeadersLines)
326 {
327 freeArrayOfString(*pHeadersLines, sizeHeader);
328 *pHeadersLines = NULL;
329 }
330
331 }
332
333