74be4207ab1cfa60ba9fafc1c965801381096a6f
[scilab.git] / scilab / modules / spreadsheet / sci_gateway / cpp / sci_csvWrite.cpp
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 #include <string.h>
16 #include <stdio.h>
17 #include "gw_csv_tools.h"
18 #include "api_scilab.h"
19 #include "Scierror.h"
20 #include "MALLOC.h"
21 #include "csvWrite.h"
22 #include "localization.h"
23 extern "C" {
24 #include "freeArrayOfString.h"
25 };
26 #ifdef _MSC_VER
27 #include "strdup_windows.h"
28 #endif
29 #include "csvDefault.h"
30 #include "checkCsvWriteFormat.h"
31 #include "gw_csv_helpers.h"
32 // =============================================================================
33 // csvWrite(M, filename[, separator, decimal, precision]) */
34 // with M string or double (not complex)
35 // =============================================================================
36 int sci_csvWrite(char *fname)
37 {
38     SciErr sciErr;
39     int iErr = 0;
40     csvWriteError csvError = CSV_WRITE_ERROR;
41
42     char *separator = NULL;
43     char *decimal = NULL;
44     char *filename = NULL;
45     char *precisionFormat = NULL;
46     char **pHeadersLines = NULL;
47     int nbHeadersLines = 0;
48
49     char **pStringValues = NULL;
50     double *pDoubleValuesReal = NULL;
51     double *pDoubleValuesImag = NULL;
52     int bIsComplex = 0;
53     int mValues = 0;
54     int nValues = 0;
55
56     int *piAddressVarTwo = NULL;
57     int m2 = 0, n2 = 0;
58     int iType2 = 0;
59
60     int *piAddressVarOne = NULL;
61     int m1 = 0, n1 = 0;
62     int iType1 = 0;
63
64     CheckRhs(2, 6);
65     CheckLhs(1, 1);
66
67     if (Rhs > 5)
68     {
69         int isOnlyRowOrCol = 0;
70         int m6 = 0;
71         int n6 = 0;
72         pHeadersLines = csv_getArgumentAsMatrixOfString(pvApiCtx, 6, fname, &m6, &n6, &iErr);
73         if (iErr) return 0;
74         isOnlyRowOrCol = ((m6 > 1) && (n6 == 1)) || ((m6 == 1) && (n6 > 1)) || ((m6 == 1) && (n6 == 1));
75         if (!isOnlyRowOrCol)
76         {
77             if (pHeadersLines)
78             {
79                 freeArrayOfString(pHeadersLines, nbHeadersLines);
80                 pHeadersLines = NULL;
81             }
82             Scierror(999, _("%s: Wrong size for input argument #%d: A 1-by-n or m-by-1 array of strings expected.\n"), fname, 6);
83             return 0;
84         }
85         nbHeadersLines = m6 * n6;
86     }
87
88     if (Rhs > 4)
89     {
90         if (csv_isDoubleScalar(pvApiCtx, 5))
91         {
92 #define FORMAT_FIELDVALUESTR "%%.%dlg"
93             int iFormatValue = (int) csv_getArgumentAsScalarDouble(pvApiCtx, 5, fname, &iErr);
94             if (iErr)
95             {
96                 if (pHeadersLines)
97                 {
98                     freeArrayOfString(pHeadersLines, nbHeadersLines);
99                     pHeadersLines = NULL;
100                 }
101                 return 0;
102             }
103
104             if ((iFormatValue < 1) || (iFormatValue > 17))
105             {
106                 Scierror(999, _("%s: Wrong value for input argument #%d: A double (value 1 to 17) expected.\n"), fname, 5);
107                 if (pHeadersLines)
108                 {
109                     freeArrayOfString(pHeadersLines, nbHeadersLines);
110                     pHeadersLines = NULL;
111                 }
112                 return 0;
113             }
114
115             precisionFormat = (char*)MALLOC(sizeof(char) * ((int)strlen(FORMAT_FIELDVALUESTR) + 1));
116             if (precisionFormat == NULL)
117             {
118                 Scierror(999, _("%s: Memory allocation error.\n"), fname);
119                 if (pHeadersLines)
120                 {
121                     freeArrayOfString(pHeadersLines, nbHeadersLines);
122                     pHeadersLines = NULL;
123                 }
124                 return 0;
125             }
126             sprintf(precisionFormat, FORMAT_FIELDVALUESTR, iFormatValue);
127         }
128         else
129         {
130             precisionFormat = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 5, fname, getCsvDefaultPrecision(), &iErr);
131             if (iErr) return 0;
132             if (checkCsvWriteFormat(precisionFormat))
133             {
134                 Scierror(999, _("%s: Not supported format %s.\n"), fname, precisionFormat);
135                 if (precisionFormat)
136                 {
137                     FREE(precisionFormat);
138                     precisionFormat = NULL;
139                 }
140                 if (pHeadersLines)
141                 {
142                     freeArrayOfString(pHeadersLines, nbHeadersLines);
143                     pHeadersLines = NULL;
144                 }
145                 return 0;
146             }
147         }
148     }
149     else
150     {
151         precisionFormat = strdup(getCsvDefaultPrecision());
152     }
153
154     if (Rhs > 3)
155     {
156         decimal = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 4, fname, getCsvDefaultDecimal(), &iErr);
157         if (iErr)
158         {
159             if (precisionFormat)
160             {
161                 FREE(precisionFormat);
162                 precisionFormat = NULL;
163             }
164             if (pHeadersLines)
165             {
166                 freeArrayOfString(pHeadersLines, nbHeadersLines);
167                 pHeadersLines = NULL;
168             }
169             return 0;
170         }
171
172         if (strcmp(decimal, ".") && strcmp(decimal, ","))
173         {
174             //invalid value
175             Scierror(999, _("%s: Wrong value for input argument #%d: '%s' or '%s' expected.\n"), "write_csv", 4, ".", ",");
176             FREE(precisionFormat);
177             return 1;
178         }
179     }
180     else
181     {
182         decimal = strdup(getCsvDefaultDecimal());
183     }
184
185     if (Rhs > 2)
186     {
187         separator = csv_getArgumentAsStringWithEmptyManagement(pvApiCtx, 3, fname, getCsvDefaultSeparator(), &iErr);
188         if (iErr)
189         {
190             if (pHeadersLines)
191             {
192                 freeArrayOfString(pHeadersLines, nbHeadersLines);
193                 pHeadersLines = NULL;
194             }
195             if (precisionFormat)
196             {
197                 FREE(precisionFormat);
198                 precisionFormat = NULL;
199             }
200             if (decimal)
201             {
202                 FREE(decimal);
203                 decimal = NULL;
204             }
205             return 0;
206         }
207     }
208     else
209     {
210         separator = strdup(getCsvDefaultSeparator());
211     }
212
213     filename = csv_getArgumentAsString(pvApiCtx, 2, fname, &iErr);
214     if (iErr)
215     {
216         if (pHeadersLines)
217         {
218             freeArrayOfString(pHeadersLines, nbHeadersLines);
219             pHeadersLines = NULL;
220         }
221         if (separator)
222         {
223             FREE(separator);
224             separator = NULL;
225         }
226         if (precisionFormat)
227         {
228             FREE(precisionFormat);
229             precisionFormat = NULL;
230         }
231         if (decimal)
232         {
233             FREE(decimal);
234             decimal = NULL;
235         }
236         return 0;
237     }
238
239     sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddressVarOne);
240     if (sciErr.iErr)
241     {
242         if (pHeadersLines)
243         {
244             freeArrayOfString(pHeadersLines, nbHeadersLines);
245             pHeadersLines = NULL;
246         }
247         if (filename)
248         {
249             FREE(filename);
250             filename = NULL;
251         }
252         if (precisionFormat)
253         {
254             FREE(precisionFormat);
255             precisionFormat = NULL;
256         }
257         if (decimal)
258         {
259             FREE(decimal);
260             decimal = NULL;
261         }
262         if (separator)
263         {
264             FREE(separator);
265             separator = NULL;
266         }
267         printError(&sciErr, 0);
268         return 0;
269     }
270
271     sciErr = getVarType(pvApiCtx, piAddressVarOne, &iType1);
272     if (sciErr.iErr)
273     {
274         if (pHeadersLines)
275         {
276             freeArrayOfString(pHeadersLines, nbHeadersLines);
277             pHeadersLines = NULL;
278         }
279         if (filename)
280         {
281             FREE(filename);
282             filename = NULL;
283         }
284         if (precisionFormat)
285         {
286             FREE(precisionFormat);
287             precisionFormat = NULL;
288         }
289         if (decimal)
290         {
291             FREE(decimal);
292             decimal = NULL;
293         }
294         if (separator)
295         {
296             FREE(separator);
297             separator = NULL;
298         }
299         printError(&sciErr, 0);
300         return 0;
301     }
302
303     if (iType1 == sci_strings)
304     {
305         pStringValues = csv_getArgumentAsMatrixOfString(pvApiCtx, 1, fname, &m1, &n1, &iErr);
306         if (iErr)
307         {
308             if (pHeadersLines)
309             {
310                 freeArrayOfString(pHeadersLines, nbHeadersLines);
311                 pHeadersLines = NULL;
312             }
313             if (filename)
314             {
315                 FREE(filename);
316                 filename = NULL;
317             }
318             if (precisionFormat)
319             {
320                 FREE(precisionFormat);
321                 precisionFormat = NULL;
322             }
323             if (decimal)
324             {
325                 FREE(decimal);
326                 decimal = NULL;
327             }
328             if (separator)
329             {
330                 FREE(separator);
331                 separator = NULL;
332             }
333             return 0;
334         }
335     }
336     else if (iType1 == sci_matrix)
337     {
338         if (isVarComplex(pvApiCtx, piAddressVarOne))
339         {
340             bIsComplex = 1;
341             sciErr = getComplexMatrixOfDouble(pvApiCtx, piAddressVarOne, &m1, &n1, &pDoubleValuesReal, &pDoubleValuesImag);
342         }
343         else
344         {
345             sciErr = getMatrixOfDouble(pvApiCtx, piAddressVarOne, &m1, &n1, &pDoubleValuesReal);
346         }
347
348         if (sciErr.iErr)
349         {
350             if (pHeadersLines)
351             {
352                 freeArrayOfString(pHeadersLines, nbHeadersLines);
353                 pHeadersLines = NULL;
354             }
355             if (precisionFormat)
356             {
357                 FREE(precisionFormat);
358                 precisionFormat = NULL;
359             }
360             if (filename)
361             {
362                 FREE(filename);
363                 filename = NULL;
364             }
365             if (decimal)
366             {
367                 FREE(decimal);
368                 decimal = NULL;
369             }
370             if (separator)
371             {
372                 FREE(separator);
373                 separator = NULL;
374             }
375             printError(&sciErr, 0);
376             return 0;
377         }
378     }
379     else
380     {
381         if (pHeadersLines)
382         {
383             freeArrayOfString(pHeadersLines, nbHeadersLines);
384             pHeadersLines = NULL;
385         }
386         if (precisionFormat)
387         {
388             FREE(precisionFormat);
389             precisionFormat = NULL;
390         }
391         if (filename)
392         {
393             FREE(filename);
394             filename = NULL;
395         }
396         if (decimal)
397         {
398             FREE(decimal);
399             decimal = NULL;
400         }
401         if (separator)
402         {
403             FREE(separator);
404             separator = NULL;
405         }
406
407         Scierror(999, _("%s: Wrong type for input argument #%d: A matrix of string or a matrix of real expected.\n"), fname, 1);
408         return 0;
409     }
410
411     if (pStringValues)
412     {
413         csvError = csvWrite_string(filename,
414                                    (const char**)pStringValues, m1, n1,
415                                    separator,
416                                    decimal,
417                                    (const char**)pHeadersLines, nbHeadersLines);
418     }
419     else
420     {
421         if (bIsComplex)
422         {
423             csvError = csvWrite_complex(filename,
424                                         pDoubleValuesReal,
425                                         pDoubleValuesImag,
426                                         m1, n1,
427                                         separator,
428                                         decimal,
429                                         precisionFormat,
430                                         (const char**)pHeadersLines, nbHeadersLines);
431         }
432         else
433         {
434             csvError = csvWrite_double(filename,
435                                        pDoubleValuesReal, m1, n1,
436                                        separator,
437                                        decimal,
438                                        precisionFormat,
439                                        (const char**)pHeadersLines, nbHeadersLines);
440         }
441     }
442
443     if (pHeadersLines)
444     {
445         freeArrayOfString(pHeadersLines, nbHeadersLines);
446         pHeadersLines = NULL;
447     }
448     if (pStringValues)
449     {
450         freeArrayOfString(pStringValues, m1 * n1);
451         pStringValues = NULL;
452     }
453     if (decimal)
454     {
455         FREE(decimal);
456         decimal = NULL;
457     }
458     if (separator)
459     {
460         FREE(separator);
461         separator = NULL;
462     }
463     if (precisionFormat)
464     {
465         FREE(precisionFormat);
466         precisionFormat = NULL;
467     }
468
469     switch (csvError)
470     {
471         case CSV_WRITE_SEPARATOR_DECIMAL_EQUAL:
472         {
473             Scierror(999, _("%s: separator and decimal must have different values.\n"), fname);
474         }
475         break;
476         case CSV_WRITE_NO_ERROR:
477         {
478             LhsVar(1) = 0;
479             PutLhsVar();
480         }
481         break;
482
483         case CSV_WRITE_FOPEN_ERROR:
484         {
485             Scierror(999, _("%s: can not open file %s.\n"), fname, filename);
486         }
487         break;
488         default:
489         case CSV_WRITE_ERROR:
490         {
491             Scierror(999, _("%s: error.\n"), fname);
492         }
493         break;
494     }
495
496     if (filename)
497     {
498         FREE(filename);
499         filename = NULL;
500     }
501
502     return 0;
503 }
504 // =============================================================================
505