5ba5d49c33ef22db6954921f4c0dfa35b43bc495
[scilab.git] / scilab / modules / spreadsheet / src / cpp / csvWrite.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010-2011 - DIGITEO - Allan CORNET
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12 #if defined(__linux__)
13 #define _GNU_SOURCE /* Bug 5673 fix: avoid dependency on GLIBC_2.7 */
14 #endif
15 // =============================================================================
16 #include <stdio.h>
17 #include <string.h>
18 #include "stringToDouble.h"
19 #include "csvWrite.h"
20 #include "mopen.h"
21 #include "mgetl.h"
22 #include "expandPathVariable.h"
23 #include "FileExist.h"
24 #include "mclose.h"
25 #include "MALLOC.h"
26 #include "core_math.h"
27 #ifdef _MSC_VER
28 #include "strdup_windows.h"
29 #endif
30 #include "csv_strsubst.h"
31 #include "csvDefault.h"
32 #include "utftolatin.h"
33 // =============================================================================
34 #define DEFAULT_CSV_WRITE_STRING_FORMAT "%s"
35 #define DEFAULT_CSV_WRITE_DOUBLE_FORMAT "%.lg"
36 #define PlusStr "+"
37 #define LessStr "-"
38 #define ComplexStr "i"
39 #define EMPTY_STRING ""
40 #if _MSC_VER
41 #define MODEWFD "wt"
42 #else
43 #define MODEWFD "w"
44 #endif
45 // =============================================================================
46 #ifndef signbit
47 static int signbit(double x)
48 {
49     union
50     {
51         double d;
52         short s[4];
53         int i[2];
54     } u;
55
56     u.d = x;
57 #if SIZEOF_INT == 4
58     return u.i[1] < 0;
59 #else
60     return u.s[3] < 0;
61 #endif
62 }
63 #endif /* signbit */
64 // =============================================================================
65 static int doConvertToLatin(void)
66 {
67     const char *encoding = getCsvDefaultEncoding();
68     if (encoding)
69     {
70         return (strcmp(encoding, "iso-latin") == 0) ? 1 : 0;
71     }
72     return 0;
73 }
74 // =============================================================================
75 csvWriteError csvWrite_double(const char *filename,
76                               const double *pdValues, int m, int n,
77                               const char *separator,
78                               const char *decimal,
79                               const char *precisionFormat,
80                               const char **headersLines,
81                               int nbHeadersLines)
82 {
83     FILE  *fd = NULL;
84     int i = 0, j = 0;
85     char *expandedFilename = NULL;
86     int isIsoLatin = 0;
87
88     if (filename == NULL) return CSV_WRITE_ERROR;
89     if (pdValues == NULL) return CSV_WRITE_ERROR;
90     if (m < 0 || n < 0) return CSV_WRITE_ERROR;
91     if (separator == NULL) return CSV_WRITE_ERROR;
92     if (decimal == NULL) return CSV_WRITE_ERROR;
93     if (precisionFormat == NULL) return CSV_WRITE_ERROR;
94
95     if (strcmp(separator, decimal) == 0) return CSV_WRITE_SEPARATOR_DECIMAL_EQUAL;
96
97     expandedFilename = expandPathVariable((char*)filename);
98     wcfopen(fd , filename, MODEWFD);
99     if (expandedFilename)
100     {
101         FREE(expandedFilename);
102         expandedFilename = NULL;
103     }
104     if ( fd == (FILE *)NULL ) return CSV_WRITE_FOPEN_ERROR;
105
106     isIsoLatin = doConvertToLatin();
107
108     if ((headersLines) && (nbHeadersLines > 0))
109     {
110         for (i = 0; i < nbHeadersLines; i++)
111         {
112             if (isIsoLatin)
113             {
114                 char *converted = utftolatin((char*)headersLines[i]);
115                 if (converted)
116                 {
117                     fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, converted);
118                     FREE(converted);
119                 }
120                 else
121                 {
122                     fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, headersLines[i]);
123                 }
124             }
125             else
126             {
127                 fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, headersLines[i]);
128             }
129             fprintf(fd, "%s", getCsvDefaultEOL());
130         }
131     }
132
133     for (i = 0; i < m; i++)
134     {
135         for (j = 0; j < n; j++)
136         {
137             if (ISNAN(pdValues[i + m * j]))
138             {
139                 fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, NanString);
140             }
141             else if (finite(pdValues[i + m * j]))
142             {
143                 char buffer[65535];
144                 char *result = NULL;
145                 sprintf(buffer, precisionFormat, pdValues[i + m * j]);
146                 result = csv_strsubst(buffer, getCsvDefaultDecimal(), decimal);
147                 if (result)
148                 {
149                     fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, result);
150                     FREE(result);
151                     result = NULL;
152                 }
153                 else
154                 {
155                     fprintf(fd, DEFAULT_CSV_WRITE_DOUBLE_FORMAT, pdValues[i + m * j]);
156                 }
157             }
158             else
159             {
160                 if ( signbit(pdValues[i + m * j]) )
161                 {
162                     fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, NegInfString);
163                 }
164                 else
165                 {
166                     fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, InfString);
167                 }
168             }
169             if (j + 1 < n) fprintf(fd, "%s", separator);
170         }
171         fprintf(fd, "%s", getCsvDefaultEOL());
172     }
173
174     fclose(fd);
175     return CSV_WRITE_NO_ERROR;
176 }
177 // =============================================================================
178 csvWriteError csvWrite_complex(const char *filename,
179                                const double *pdValuesReal,
180                                const double *pdValuesImag,
181                                int m, int n,
182                                const char *separator,
183                                const char *decimal,
184                                const char *precisionFormat,
185                                const char **headersLines,
186                                int nbHeadersLines)
187 {
188     FILE  *fd = NULL;
189     int i = 0, j = 0;
190     char *expandedFilename = NULL;
191     int isIsoLatin = 0;
192
193     if (filename == NULL) return CSV_WRITE_ERROR;
194     if (pdValuesReal == NULL) return CSV_WRITE_ERROR;
195     if (pdValuesImag == NULL) return CSV_WRITE_ERROR;
196     if (m < 0 || n < 0) return CSV_WRITE_ERROR;
197     if (separator == NULL) return CSV_WRITE_ERROR;
198     if (decimal == NULL) return CSV_WRITE_ERROR;
199     if (precisionFormat == NULL) return CSV_WRITE_ERROR;
200
201     if (strcmp(separator, decimal) == 0) return CSV_WRITE_SEPARATOR_DECIMAL_EQUAL;
202
203     expandedFilename = expandPathVariable((char*)filename);
204     wcfopen(fd , filename, MODEWFD);
205     if (expandedFilename)
206     {
207         FREE(expandedFilename);
208         expandedFilename = NULL;
209     }
210     if ( fd == (FILE *)NULL ) return CSV_WRITE_FOPEN_ERROR;
211
212     isIsoLatin = doConvertToLatin();
213
214     if ((headersLines) && (nbHeadersLines > 0))
215     {
216         for (i = 0; i < nbHeadersLines; i++)
217         {
218             if (isIsoLatin)
219             {
220                 const char *converted = utftolatin((char*)headersLines[i]);
221                 if (converted)
222                 {
223                     fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, converted);
224                     FREE((char*)converted);
225                     converted = NULL;
226                 }
227                 else
228                 {
229                     fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, headersLines[i]);
230                 }
231             }
232             else
233             {
234                 fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, headersLines[i]);
235             }
236             fprintf(fd, "%s", getCsvDefaultEOL());
237         }
238     }
239
240     for (i = 0; i < m; i++)
241     {
242         for (j = 0; j < n; j++)
243         {
244             char StringValue[65535];
245             if (ISNAN(pdValuesReal[i + m * j]))
246             {
247                 strcpy(StringValue, NanString);
248             }
249             else if (finite(pdValuesReal[i + m * j]))
250             {
251                 char buffer[65535];
252                 char *result = NULL;
253                 sprintf(buffer, precisionFormat, pdValuesReal[i + m * j]);
254                 result = csv_strsubst(buffer, getCsvDefaultDecimal(), decimal);
255                 if (result)
256                 {
257                     strcpy(StringValue, result);
258                     FREE(result);
259                     result = NULL;
260                 }
261                 else
262                 {
263                     sprintf(StringValue, DEFAULT_CSV_WRITE_DOUBLE_FORMAT, pdValuesReal[i + m * j]);
264                 }
265             }
266             else
267             {
268                 if ( signbit(pdValuesReal[i + m * j]) )
269                 {
270                     // NegInfString
271                     strcpy(StringValue, NegInfString);
272                 }
273                 else
274                 {
275                     // InfString
276                     strcpy(StringValue, InfString);
277                 }
278             }
279
280             if (ISNAN(pdValuesImag[i + m * j]))
281             {
282                 strcat(StringValue, PlusStr);
283                 strcat(StringValue, NanString);
284                 strcat(StringValue, ComplexStr);
285             }
286             else if (finite(pdValuesImag[i + m * j]))
287             {
288                 char buffer[65535];
289                 char *result = NULL;
290
291                 if (pdValuesImag[i + m * j] >= 0)
292                 {
293                     strcat(StringValue, PlusStr);
294                 }
295                 else
296                 {
297                     strcat(StringValue, LessStr);
298                 }
299
300                 sprintf(buffer, precisionFormat, fabs(pdValuesImag[i + m * j]));
301                 result = csv_strsubst(buffer, getCsvDefaultDecimal(), decimal);
302
303                 if (result)
304                 {
305                     strcat(StringValue, result);
306                     FREE(result);
307                     result = NULL;
308                 }
309                 else
310                 {
311                     sprintf(buffer, DEFAULT_CSV_WRITE_DOUBLE_FORMAT, fabs(pdValuesImag[i + m * j]));
312                     strcat(StringValue, buffer);
313                 }
314                 strcat(StringValue, ComplexStr);
315             }
316             else
317             {
318                 if ( signbit(pdValuesImag[i + m * j]) )
319                 {
320                     // NegInfString
321                     strcat(StringValue, LessStr);
322                 }
323                 else
324                 {
325                     // InfString
326                     strcat(StringValue, PlusStr);
327                 }
328                 strcat(StringValue, InfString);
329                 strcat(StringValue, ComplexStr);
330             }
331             fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, StringValue);
332             if (j + 1 < n) fprintf(fd, "%s", separator);
333         }
334         fprintf(fd, "%s", getCsvDefaultEOL());
335     }
336
337     fclose(fd);
338     return CSV_WRITE_NO_ERROR;
339 }
340 // =============================================================================
341 csvWriteError csvWrite_string(const char *filename,
342                               const char **pStrValues, int m, int n,
343                               const char *separator,
344                               const char *decimal,
345                               const char **headersLines,
346                               int nbHeadersLines)
347 {
348     FILE  *fd = NULL;
349     int i = 0, j = 0;
350     char *expandedFilename = NULL;
351     int isIsoLatin = 0;
352
353     if (filename == NULL) return CSV_WRITE_ERROR;
354     if (pStrValues == NULL) return CSV_WRITE_ERROR;
355     if (m < 0 || n < 0) return CSV_WRITE_ERROR;
356     if (separator == NULL) return CSV_WRITE_ERROR;
357
358     if (strcmp(separator, decimal) == 0) return CSV_WRITE_SEPARATOR_DECIMAL_EQUAL;
359
360     expandedFilename = expandPathVariable((char*)filename);
361     wcfopen(fd , filename, MODEWFD);
362     if (expandedFilename)
363     {
364         FREE(expandedFilename);
365         expandedFilename = NULL;
366     }
367     if ( fd == (FILE *)NULL ) return CSV_WRITE_FOPEN_ERROR;
368
369     isIsoLatin = doConvertToLatin();
370
371     if ((headersLines) && (nbHeadersLines > 0))
372     {
373         for (i = 0; i < nbHeadersLines; i++)
374         {
375             if (isIsoLatin)
376             {
377                 const char *converted = utftolatin((char*)headersLines[i]);
378                 if (converted)
379                 {
380                     fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, converted);
381                     FREE((char*)converted);
382                     converted = NULL;
383                 }
384                 else
385                 {
386                     fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, headersLines[i]);
387                 }
388             }
389             else
390             {
391                 fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, headersLines[i]);
392             }
393             fprintf(fd, "%s", getCsvDefaultEOL());
394         }
395     }
396
397     for (i = 0 ; i < m ; i++ )
398     {
399         for ( j = 0 ; j < n ; j++)
400         {
401             if (decimal == NULL)
402             {
403                 if (isIsoLatin)
404                 {
405                     const char *converted = utftolatin((char*)pStrValues[i + m * j]);
406                     if (converted)
407                     {
408                         fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, converted);
409                         FREE((char*)converted);
410                         converted = NULL;
411                     }
412                     else
413                     {
414                         fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, pStrValues[i + m * j]);
415                     }
416                 }
417                 else
418                 {
419                     fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, pStrValues[i + m * j]);
420                 }
421             }
422             else
423             {
424                 char *result = NULL;
425                 result = csv_strsubst((char*)(pStrValues[i + m * j]), getCsvDefaultDecimal(), decimal);
426                 if (result)
427                 {
428                     if (isIsoLatin)
429                     {
430                         char *converted = utftolatin(result);
431                         if (converted)
432                         {
433                             fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, converted);
434                             FREE(converted);
435                             converted = NULL;
436                         }
437                         else
438                         {
439                             fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, result);
440                         }
441                     }
442                     else
443                     {
444                         fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, result);
445                     }
446                     FREE(result);
447                     result = NULL;
448                 }
449                 else
450                 {
451                     fprintf(fd, DEFAULT_CSV_WRITE_STRING_FORMAT, pStrValues[i + m * j]);
452                 }
453             }
454             if (j + 1 < n) fprintf(fd, "%s", separator);
455         }
456         fprintf(fd, "%s", getCsvDefaultEOL());
457     }
458
459     fclose(fd);
460     return CSV_WRITE_NO_ERROR;
461 }
462 // =============================================================================
463