43329e42bfa97019e534c1de55e9af61f054cb79
[scilab.git] / scilab / modules / string / src / c / stringToDouble.c
1 /*
2 *  Copyright (C) 2010-2011 - DIGITEO - Allan CORNET
3 *
4 *  This file must be used under the terms of the CeCILL.
5 *  This source file is licensed as described in the file COPYING, which
6 *  you should have received as part of this distribution.  The terms
7 *  are also available at
8 *  http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
9 *
10 */
11
12 /* ========================================================================== */
13 #if defined(__linux__)
14 #define _GNU_SOURCE             /* avoid dependency on GLIBC_2.7 */
15 #endif
16 /* ========================================================================== */
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <math.h>
21 #include "stringToDouble.h"
22 #include "core_math.h"
23 #include "sci_malloc.h"
24 #include "os_string.h"
25 #ifndef _MSC_VER
26 #ifndef stricmp
27 #define stricmp strcasecmp
28 #endif
29 #else
30 #define stricmp _stricmp
31 #endif
32 /* ========================================================================== */
33 #define DEFAULT_DOUBLE_MAX_DIGIT_FORMAT "%lg"
34 /* ========================================================================== */
35 static double returnINF(BOOL bPositive);
36 static double returnNAN(void);
37 /* ========================================================================== */
38
39 static char* replace_D_By_E(const char* _pst)
40 {
41     //find and replace d and D by E for compatibility with strtod Linux/Mac
42     char* pstReturn = os_strdup(_pst);
43     char* pstFind = pstReturn;
44     do
45     {
46         pstFind = strchr(pstFind, 'D');
47         if (pstFind)
48         {
49             pstFind[0] = 'E';
50         }
51     }
52     while (pstFind);
53
54     pstFind = pstReturn;
55     do
56     {
57         pstFind = strchr(pstFind, 'd');
58         if (pstFind)
59         {
60             pstFind[0] = 'e';
61         }
62     }
63     while (pstFind);
64
65     return pstReturn;
66 }
67
68 static wchar_t* replace_D_By_EW(const wchar_t* _pst)
69 {
70     //find and replace d and D by E for compatibility with strtod Linux/Mac
71     wchar_t* pstReturn = os_wcsdup(_pst);
72     wchar_t* pstFind = pstReturn;
73     do
74     {
75         pstFind = wcschr(pstFind, L'D');
76         if (pstFind)
77         {
78             pstFind[0] = L'E';
79         }
80     }
81     while (pstFind);
82
83     pstFind = pstReturn;
84     do
85     {
86         pstFind = wcschr(pstFind, L'd');
87         if (pstFind)
88         {
89             pstFind[0] = L'e';
90         }
91     }
92     while (pstFind);
93
94     return pstReturn;
95 }
96
97 double stringToDouble(const char *pSTR, BOOL bConvertByNAN, stringToDoubleError *ierr)
98 {
99     double dValue = 0.0;
100     *ierr = STRINGTODOUBLE_ERROR;
101     if (pSTR)
102     {
103         if ((stricmp(pSTR, NanString) == 0) || (stricmp(pSTR, NegNanString) == 0) ||
104                 (stricmp(pSTR, PosNanString) == 0) || (stricmp(pSTR, ScilabPosNanString) == 0) ||
105                 (stricmp(pSTR, ScilabNanString) == 0) || (stricmp(pSTR, ScilabNegNanString) == 0))
106         {
107             dValue = returnNAN();
108         }
109         else if ((stricmp(pSTR, InfString) == 0) || (stricmp(pSTR, PosInfString) == 0) ||
110                  (stricmp(pSTR, ScilabInfString) == 0) || (stricmp(pSTR, ScilabPosInfString) == 0))
111         {
112             dValue = returnINF(TRUE);
113         }
114         else if ((stricmp(pSTR, NegInfString) == 0) || (stricmp(pSTR, ScilabNegInfString) == 0))
115         {
116             dValue = returnINF(FALSE);
117         }
118         else if ((stricmp(pSTR, ScilabPiString) == 0) || (stricmp(pSTR, ScilabPosPiString) == 0))
119         {
120             dValue = M_PI;
121         }
122         else if (stricmp(pSTR, ScilabNegPiString) == 0)
123         {
124             dValue = -M_PI;
125         }
126         else if ((stricmp(pSTR, ScilabEpsString) == 0) || (stricmp(pSTR, ScilabPosEpsString) == 0))
127         {
128             dValue = EPSILON;
129         }
130         else if (stricmp(pSTR, ScilabNegEpsString) == 0)
131         {
132             dValue = -EPSILON;
133         }
134         else if ((stricmp(pSTR, ScilabEString) == 0) || (stricmp(pSTR, ScilabPosEString) == 0))
135         {
136             dValue = exp(1);
137         }
138         else if (stricmp(pSTR, ScilabNegEString) == 0)
139         {
140             dValue = -exp(1);
141         }
142         else
143         {
144             char* pstReplaced = replace_D_By_E(pSTR);
145             char *pEnd = NULL;
146             double v = strtod(pstReplaced, &pEnd);
147             if ((v == 0) && (pEnd == pstReplaced))
148             {
149                 if (bConvertByNAN)
150                 {
151                     dValue = returnNAN();
152                 }
153                 else
154                 {
155                     *ierr = STRINGTODOUBLE_NOT_A_NUMBER;
156                     FREE(pstReplaced);
157                     return (dValue = 0.0);
158                 }
159             }
160             else
161             {
162                 if (strcmp(pEnd, "") == 0)
163                 {
164                     dValue = v;
165                 }
166                 else
167                 {
168                     if (bConvertByNAN)
169                     {
170                         dValue = returnNAN();
171                     }
172                     else
173                     {
174                         *ierr = STRINGTODOUBLE_NOT_A_NUMBER;
175                         FREE(pstReplaced);
176                         return (dValue = 0.0);
177                     }
178                 }
179             }
180
181             FREE(pstReplaced);
182         }
183         *ierr = STRINGTODOUBLE_NO_ERROR;
184     }
185     else
186     {
187         *ierr = STRINGTODOUBLE_MEMORY_ALLOCATION;
188     }
189     return dValue;
190 }
191 // =============================================================================
192 double stringToDoubleW(const wchar_t *pSTR, BOOL bConvertByNAN, stringToDoubleError *ierr)
193 {
194     double dValue = 0.0;
195     *ierr = STRINGTODOUBLE_ERROR;
196     if (pSTR)
197     {
198         if ((wcsicmp(pSTR, NanStringW) == 0) || (wcsicmp(pSTR, NegNanStringW) == 0) ||
199                 (wcsicmp(pSTR, PosNanStringW) == 0) || (wcsicmp(pSTR, ScilabPosNanStringW) == 0) ||
200                 (wcsicmp(pSTR, ScilabNanStringW) == 0) || (wcsicmp(pSTR, ScilabNegNanStringW) == 0))
201         {
202             dValue = returnNAN();
203         }
204         else if ((wcsicmp(pSTR, InfStringW) == 0) || (wcsicmp(pSTR, PosInfStringW) == 0) ||
205                  (wcsicmp(pSTR, ScilabInfStringW) == 0) || (wcsicmp(pSTR, ScilabPosInfStringW) == 0))
206         {
207             dValue = returnINF(TRUE);
208         }
209         else if ((wcsicmp(pSTR, NegInfStringW) == 0) || (wcsicmp(pSTR, ScilabNegInfStringW) == 0))
210         {
211             dValue = returnINF(FALSE);
212         }
213         else if ((wcsicmp(pSTR, ScilabPiStringW) == 0) || (wcsicmp(pSTR, ScilabPosPiStringW) == 0))
214         {
215             dValue = M_PI;
216         }
217         else if (wcsicmp(pSTR, ScilabNegPiStringW) == 0)
218         {
219             dValue = -M_PI;
220         }
221         else if ((wcsicmp(pSTR, ScilabPosEStringW) == 0) || (wcsicmp(pSTR, ScilabEStringW) == 0))
222         {
223             dValue = exp(1);
224         }
225         else if (wcsicmp(pSTR, ScilabNegEStringW) == 0)
226         {
227             dValue = -exp(1);
228         }
229         else if ((wcsicmp(pSTR, ScilabEpsStringW) == 0) || (wcsicmp(pSTR, ScilabPosEpsStringW) == 0))
230         {
231             dValue = EPSILON;
232         }
233         else if (wcsicmp(pSTR, ScilabNegEpsStringW) == 0)
234         {
235             dValue = -EPSILON;
236         }
237         else
238         {
239             wchar_t* pstReplaced = replace_D_By_EW(pSTR);
240             wchar_t *pEnd = NULL;
241             double v = wcstod(pstReplaced, &pEnd);
242             if ((v == 0) && (pEnd == pstReplaced))
243             {
244                 if (bConvertByNAN)
245                 {
246                     dValue = returnNAN();
247                 }
248                 else
249                 {
250                     *ierr = STRINGTODOUBLE_NOT_A_NUMBER;
251                     FREE(pstReplaced);
252                     return (dValue = 0.0);
253                 }
254             }
255             else
256             {
257                 if (wcscmp(pEnd, L"") == 0)
258                 {
259                     dValue = v;
260                 }
261                 else
262                 {
263                     if (bConvertByNAN)
264                     {
265                         dValue = returnNAN();
266                     }
267                     else
268                     {
269                         *ierr = STRINGTODOUBLE_NOT_A_NUMBER;
270                         FREE(pstReplaced);
271                         return (dValue = 0.0);
272                     }
273                 }
274             }
275
276             FREE(pstReplaced);
277         }
278         *ierr = STRINGTODOUBLE_NO_ERROR;
279     }
280     else
281     {
282         *ierr = STRINGTODOUBLE_MEMORY_ALLOCATION;
283     }
284     return dValue;
285 }
286 // =============================================================================
287 static double returnINF(BOOL bPositive)
288 {
289     double dbl1 = 1.0;
290     double dbl0 = dbl1 - dbl1;
291     int iSign = bPositive == 1 ? 1 : -1;
292
293     return iSign * dbl1 / dbl0;
294 }
295 // =============================================================================
296 static double returnNAN(void)
297 {
298     static int first = 1;
299     static double nan = 1.0;
300
301     if ( first )
302     {
303         nan = (nan - (double) first) / (nan - (double) first);
304         first = 0;
305     }
306     return (nan);
307 }
308 // =============================================================================