7f79b2da60a65f44f0e70c996c39a18157e0ac1c
[scilab.git] / scilab / modules / string / sci_gateway / c / sci_strtod.c
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) INRIA - 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.1-en.txt
10 *
11 */
12
13 /*----------------------------------------------------------------------------*/
14 #include <stdlib.h>
15 #include "gw_string.h"
16 #include "MALLOC.h"
17 #include "Scierror.h"
18 #include "localization.h"
19 #include "api_scilab.h"
20 #include "locale.h"
21 #include "freeArrayOfString.h"
22 #ifdef _MSC_VER
23 #include "strdup_windows.h"
24 #endif
25 /*----------------------------------------------------------------------------*/
26 int sci_strtod(char *fname, unsigned long fname_len)
27 {
28     SciErr sciErr;
29     int* piAddr = NULL;
30     int* piAddr2 = NULL;
31     int iRows = 0, iCols = 0;
32     int iRowsiCols = 0;
33     char **Input_StringMatrix_1 = NULL;
34     char *Input_SingleString_2 = NULL;
35     int first_nb = 0;
36     int x, y; //loop indexes
37     char keys[] = "1234567890";
38     char symbol1[] = "-+.";
39     char symbol2[] = "-+,";
40     unsigned long long raw = 0x7ff8000000000000;
41     double not_a_number = *( double* )&raw;
42     int iRhs = nbInputArgument(pvApiCtx);
43     int iLhs = nbOutputArgument(pvApiCtx);
44     int flag = 0;
45
46     //output values
47     double *OutputDoubles = NULL;
48     char **OutputStrings = NULL;
49
50     CheckInputArgument(pvApiCtx, 1, 2);
51     CheckOutputArgument(pvApiCtx, 1, 2);
52
53     if (iRhs == 2)
54     {
55         //get variable address
56         sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddr2);
57         if (sciErr.iErr)
58         {
59             printError(&sciErr, 0);
60             Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 2);
61             return 0;
62         }
63         if (isStringType(pvApiCtx, piAddr2) == 0 || isScalar(pvApiCtx, piAddr2) == 0)
64         {
65             Scierror(999, _("%s: Wrong type for input argument #%d: Single string expected.\n"), fname, 2);
66             return 0;
67         }
68         if (getAllocatedSingleString(pvApiCtx, piAddr2, &Input_SingleString_2))
69         {
70             Scierror(999, _("%s: Wrong type for input argument #%d: Single string expected.\n"), fname, 2);
71             return 0;
72         }
73         //Test on optional argument value
74         if (Input_SingleString_2[0] != '.' && Input_SingleString_2[0] != ',')
75         {
76             Scierror(999, _("%s: Wrong value for input argument #%d: '.' or ',' expected.\n"), fname, 2);
77         }
78     }
79     else
80     {
81         Input_SingleString_2 = strdup(".");
82     }
83
84     //get variable address
85     sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr);
86     if (sciErr.iErr)
87     {
88         FREE(Input_SingleString_2);
89         printError(&sciErr, 0);
90         Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 1);
91         return 0;
92     }
93
94     if (isEmptyMatrix(pvApiCtx, piAddr))
95     {
96         FREE(Input_SingleString_2);
97         if (createEmptyMatrix(pvApiCtx, iRhs + 1) != 0)
98         {
99             return 0;
100         }
101
102         AssignOutputVariable(pvApiCtx, 1) = iRhs + 1;
103
104         if (iLhs == 2)
105         {
106             if (createSingleString(pvApiCtx, iRhs + 2, ""))
107             {
108                 return 0;
109             }
110
111             AssignOutputVariable(pvApiCtx, 2) = iRhs + 2;
112         }
113
114         ReturnArguments(pvApiCtx);
115         return 0;
116     }
117
118     if (isStringType(pvApiCtx, piAddr) == 0) //Check type
119     {
120         FREE(Input_SingleString_2);
121         Scierror(999, _("%s: Wrong type for input argument #%d: Matrix of strings or empty matrix expected.\n"), fname, 1);
122         return 0;
123     }
124
125     if (getAllocatedMatrixOfString(pvApiCtx, piAddr, &iRows, &iCols, &Input_StringMatrix_1))
126     {
127         if (Input_StringMatrix_1)
128         {
129             freeAllocatedMatrixOfString(iRows, iCols, Input_StringMatrix_1);
130         }
131
132         FREE(Input_SingleString_2);
133         Scierror(999, _("%s: Wrong type for input argument #%d: Matrix of strings or empty matrix expected.\n"), fname, 1);
134         return 0;
135     }
136
137     iRowsiCols = iRows * iCols;
138
139     if (iLhs == 2)
140     {
141         OutputStrings = (char **)MALLOC(sizeof(char*) * iRowsiCols);
142         if (OutputStrings == NULL)
143         {
144             freeAllocatedMatrixOfString(iRows, iCols, Input_StringMatrix_1);
145             freeAllocatedSingleString(Input_SingleString_2);
146             Scierror(999, _("%s: No more memory.\n"), fname);
147             return 0;
148         }
149     }
150
151     sciErr = allocMatrixOfDouble(pvApiCtx, iRhs + 1, iRows, iCols, &OutputDoubles);
152     if (sciErr.iErr)
153     {
154         printError(&sciErr, 0);
155         Scierror(999, _("%s: Memory allocation error.\n"), fname);
156         return 0;
157     }
158
159     for (x = 0 ; x < iRowsiCols ; x++)
160     {
161         //Double part
162         char *stopstring = NULL;
163         int iSign = 0;
164
165         if (Input_SingleString_2[0] == ',')
166         {
167             iSign = (int)strcspn(Input_StringMatrix_1[x], symbol2);
168         }
169         else if (Input_SingleString_2[0] == '.')
170         {
171             iSign = (int)strcspn(Input_StringMatrix_1[x], symbol1);
172         }
173         first_nb = (int)strcspn(Input_StringMatrix_1[x], keys);
174
175         //symbol can be use only if it is before key
176         if (iSign == first_nb - 1)
177         {
178             //let strtod do with symbol
179             first_nb -= 1;
180         }
181
182         //special case for "-.3"
183         if (iSign == first_nb - 2 && (Input_StringMatrix_1[x][iSign + 1] == '.' || Input_StringMatrix_1[x][iSign + 1] == ','))
184         {
185
186             //let strtod do with symbol
187             first_nb -= 2;
188         }
189
190         //Check if there is a number in the string
191         if (first_nb != 0)
192         {
193             flag = 0;
194
195             for (y = 0 ; y < first_nb ; y++)
196             {
197                 if (Input_StringMatrix_1[x][y] != ' ') // spaces are accepted
198                 {
199                     OutputDoubles[x] = not_a_number;
200                     flag = 1;
201                     stopstring = Input_StringMatrix_1[x];
202                     break;
203                 }
204             }
205
206             //it is still a number
207             if (flag == 0)
208             {
209                 //only spaces ?
210                 if (strlen(Input_StringMatrix_1[x]) == first_nb) // strtod("  ")
211                 {
212                     OutputDoubles[x] = not_a_number;
213                     stopstring = Input_StringMatrix_1[x];
214                 }
215                 else // strtod("  000xxx")
216                 {
217                     if (Input_SingleString_2[0] == ',')
218                     {
219 #ifdef _MSC_VER
220                         setlocale(LC_NUMERIC, "French_France.1252");
221 #else
222                         setlocale(LC_NUMERIC, "fr_FR.UTF-8");
223 #endif
224                         OutputDoubles[x] = (double)strtod(Input_StringMatrix_1[x] + first_nb, &stopstring);
225                         setlocale(LC_NUMERIC, "C");
226                     }
227                     else
228                     {
229                         OutputDoubles[x] = (double)strtod(Input_StringMatrix_1[x] + first_nb, &stopstring);
230                     }
231                 }
232             }
233         }
234         else if (strlen(Input_StringMatrix_1[x]) == 0) //case strtod("")
235         {
236             OutputDoubles[x] = not_a_number;
237         }
238         else //all characters are digits
239         {
240             if (Input_SingleString_2[0] == ',')
241             {
242 #ifdef _MSC_VER
243                 setlocale(LC_NUMERIC, "French_France.1252");
244 #else
245                 setlocale(LC_NUMERIC, "fr_FR.UTF-8");
246 #endif
247                 OutputDoubles[x] = (double)strtod(Input_StringMatrix_1[x], &stopstring);
248                 setlocale(LC_NUMERIC, "C");
249             }
250             else
251             {
252                 OutputDoubles[x] = (double)strtod(Input_StringMatrix_1[x], &stopstring);
253             }
254         }
255
256         if (iLhs == 2)
257         {
258             //String part
259             if (stopstring)
260             {
261                 OutputStrings[x] = (char*)MALLOC(sizeof(char) * (strlen(stopstring) + 1));
262             }
263             else
264             {
265                 OutputStrings[x] = (char*)MALLOC(sizeof(char) * (strlen("") + 1));
266             }
267
268             if (OutputStrings[x] == NULL)
269             {
270                 freeAllocatedMatrixOfString(iRows, iCols, Input_StringMatrix_1);
271                 freeAllocatedSingleString(Input_SingleString_2);
272                 freeAllocatedMatrixOfString(iRows, iCols, OutputStrings);
273                 Scierror(999, _("%s: No more memory.\n"), fname);
274                 return 0;
275             }
276
277             if (stopstring)
278             {
279                 if (Input_SingleString_2[0] == ',')
280                 {
281                     strcpy(OutputStrings[x], stopstring);
282                 }
283                 else
284                 {
285                     strcpy(OutputStrings[x], stopstring);
286                 }
287             }
288             else
289             {
290                 strcpy(OutputStrings[x], "");
291             }
292         }
293     }
294
295     AssignOutputVariable(pvApiCtx, 1) = iRhs + 1;
296
297     if (iLhs == 2)
298     {
299         sciErr = createMatrixOfString(pvApiCtx, iRhs + 2, iRows, iCols, OutputStrings);
300         if (sciErr.iErr)
301         {
302             printError(&sciErr, 0);
303             Scierror(999, _("%s: Memory allocation error.\n"), fname);
304             return 0;
305         }
306
307         AssignOutputVariable(pvApiCtx, 2) = iRhs + 2;
308         freeArrayOfString(OutputStrings, iRows * iCols);
309     }
310
311     freeAllocatedMatrixOfString(iRows, iCols, Input_StringMatrix_1);
312     freeAllocatedSingleString(Input_SingleString_2);
313     ReturnArguments(pvApiCtx);
314     return 0;
315 }
316 /*--------------------------------------------------------------------------*/
317