utf: module string 2
[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 double stringToDouble(const char *pSTR, BOOL bConvertByNAN, stringToDoubleError *ierr)
69 {
70     double dValue = 0.0;
71     *ierr = STRINGTODOUBLE_ERROR;
72     if (pSTR)
73     {
74         if ((stricmp(pSTR, NanString) == 0) || (stricmp(pSTR, NegNanString) == 0) ||
75                 (stricmp(pSTR, PosNanString) == 0) || (stricmp(pSTR, ScilabPosNanString) == 0) ||
76                 (stricmp(pSTR, ScilabNanString) == 0) || (stricmp(pSTR, ScilabNegNanString) == 0))
77         {
78             dValue = returnNAN();
79         }
80         else if ((stricmp(pSTR, InfString) == 0) || (stricmp(pSTR, PosInfString) == 0) ||
81                  (stricmp(pSTR, ScilabInfString) == 0) || (stricmp(pSTR, ScilabPosInfString) == 0))
82         {
83             dValue = returnINF(TRUE);
84         }
85         else if ((stricmp(pSTR, NegInfString) == 0) || (stricmp(pSTR, ScilabNegInfString) == 0))
86         {
87             dValue = returnINF(FALSE);
88         }
89         else if ((stricmp(pSTR, ScilabPiString) == 0) || (stricmp(pSTR, ScilabPosPiString) == 0))
90         {
91             dValue = M_PI;
92         }
93         else if (stricmp(pSTR, ScilabNegPiString) == 0)
94         {
95             dValue = -M_PI;
96         }
97         else if ((stricmp(pSTR, ScilabEpsString) == 0) || (stricmp(pSTR, ScilabPosEpsString) == 0))
98         {
99             dValue = EPSILON;
100         }
101         else if (stricmp(pSTR, ScilabNegEpsString) == 0)
102         {
103             dValue = -EPSILON;
104         }
105         else if ((stricmp(pSTR, ScilabEString) == 0) || (stricmp(pSTR, ScilabPosEString) == 0))
106         {
107             dValue = exp(1);
108         }
109         else if (stricmp(pSTR, ScilabNegEString) == 0)
110         {
111             dValue = -exp(1);
112         }
113         else
114         {
115             char* pstReplaced = replace_D_By_E(pSTR);
116             char *pEnd = NULL;
117             double v = strtod(pstReplaced, &pEnd);
118             if ((v == 0) && (pEnd == pstReplaced))
119             {
120                 if (bConvertByNAN)
121                 {
122                     dValue = returnNAN();
123                 }
124                 else
125                 {
126                     *ierr = STRINGTODOUBLE_NOT_A_NUMBER;
127                     FREE(pstReplaced);
128                     return (dValue = 0.0);
129                 }
130             }
131             else
132             {
133                 if (strcmp(pEnd, "") == 0)
134                 {
135                     dValue = v;
136                 }
137                 else
138                 {
139                     if (bConvertByNAN)
140                     {
141                         dValue = returnNAN();
142                     }
143                     else
144                     {
145                         *ierr = STRINGTODOUBLE_NOT_A_NUMBER;
146                         FREE(pstReplaced);
147                         return (dValue = 0.0);
148                     }
149                 }
150             }
151
152             FREE(pstReplaced);
153         }
154         *ierr = STRINGTODOUBLE_NO_ERROR;
155     }
156     else
157     {
158         *ierr = STRINGTODOUBLE_MEMORY_ALLOCATION;
159     }
160     return dValue;
161 }
162 // =============================================================================
163 static double returnINF(BOOL bPositive)
164 {
165     double dbl1 = 1.0;
166     double dbl0 = dbl1 - dbl1;
167     int iSign = bPositive == 1 ? 1 : -1;
168
169     return iSign * dbl1 / dbl0;
170 }
171 // =============================================================================
172 static double returnNAN(void)
173 {
174     static int first = 1;
175     static double nan = 1.0;
176
177     if ( first )
178     {
179         nan = (nan - (double) first) / (nan - (double) first);
180         first = 0;
181     }
182     return (nan);
183 }
184 // =============================================================================