* Bug 4401 fixed - String: fix for isnum
[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 "MALLOC.h"
24 #ifdef  _MSC_VER
25 #include "strdup_windows.h"
26 #endif
27 #ifndef _MSC_VER
28 #ifndef stricmp
29 #define stricmp strcasecmp
30 #endif
31 #else
32 #define stricmp _stricmp
33 #endif
34 /* ========================================================================== */
35 #define DEFAULT_DOUBLE_MAX_DIGIT_FORMAT "%lg"
36 /* ========================================================================== */
37 static double returnINF(BOOL bPositive);
38 static double returnNAN(void);
39 /* ========================================================================== */
40
41 static char* replace_D_By_E(const char* _pst)
42 {
43     //find and replace d and D by E for compatibility with strtod Linux/Mac
44     char* pstReturn = strdup(_pst);
45     char* pstFind = pstReturn;
46     do
47     {
48         pstFind = strchr(pstFind, 'D');
49         if (pstFind)
50         {
51             pstFind[0] = 'E';
52         }
53     }
54     while (pstFind);
55
56     pstFind = pstReturn;
57     do
58     {
59         pstFind = strchr(pstFind, 'd');
60         if (pstFind)
61         {
62             pstFind[0] = 'e';
63         }
64     }
65     while (pstFind);
66
67     return pstReturn;
68 }
69
70 double stringToDouble(const char *pSTR, BOOL bConvertByNAN, stringToDoubleError *ierr)
71 {
72     double dValue = 0.0;
73     *ierr = STRINGTODOUBLE_ERROR;
74     if (pSTR)
75     {
76         if ((stricmp(pSTR, NanString) == 0) || (stricmp(pSTR, NegNanString) == 0) ||
77                 (stricmp(pSTR, PosNanString) == 0) || (stricmp(pSTR, ScilabPosNanString) == 0) ||
78                 (stricmp(pSTR, ScilabNanString) == 0) || (stricmp(pSTR, ScilabNegNanString) == 0))
79         {
80             dValue = returnNAN();
81         }
82         else if ((stricmp(pSTR, InfString) == 0) || (stricmp(pSTR, PosInfString) == 0) ||
83                  (stricmp(pSTR, ScilabInfString) == 0) || (stricmp(pSTR, ScilabPosInfString) == 0))
84         {
85             dValue = returnINF(TRUE);
86         }
87         else if ((stricmp(pSTR, NegInfString) == 0) || (stricmp(pSTR, ScilabNegInfString) == 0))
88         {
89             dValue = returnINF(FALSE);
90         }
91         else if ((stricmp(pSTR, ScilabPiString) == 0) || (stricmp(pSTR, ScilabPosPiString) == 0))
92         {
93             dValue = M_PI;
94         }
95         else if (stricmp(pSTR, ScilabNegPiString) == 0)
96         {
97             dValue = -M_PI;
98         }
99         else if ((stricmp(pSTR, ScilabEString) == 0) || (stricmp(pSTR, ScilabPosEString) == 0))
100         {
101             dValue = exp(1);
102         }
103         else if (stricmp(pSTR, ScilabNegEString) == 0)
104         {
105             dValue = -exp(1);
106         }
107         else if ((stricmp(pSTR, ScilabEpsString) == 0) || (stricmp(pSTR, ScilabPosEpsString) == 0))
108         {
109             dValue = EPSILON;
110         }
111         else if (stricmp(pSTR, ScilabNegEpsString) == 0)
112         {
113             dValue = -EPSILON;
114         }
115         else
116         {
117             char* pstReplaced = replace_D_By_E(pSTR);
118             char *pEnd = NULL;
119             double v = strtod(pstReplaced, &pEnd);
120             if ((v == 0) && (pEnd == pstReplaced))
121             {
122                 if (bConvertByNAN)
123                 {
124                     dValue = returnNAN();
125                 }
126                 else
127                 {
128                     *ierr = STRINGTODOUBLE_NOT_A_NUMBER;
129                     FREE(pstReplaced);
130                     return (dValue = 0.0);
131                 }
132             }
133             else
134             {
135                 if (strcmp(pEnd, "") == 0)
136                 {
137                     dValue = v;
138                 }
139                 else
140                 {
141                     if (bConvertByNAN)
142                     {
143                         dValue = returnNAN();
144                     }
145                     else
146                     {
147                         *ierr = STRINGTODOUBLE_NOT_A_NUMBER;
148                         FREE(pstReplaced);
149                         return (dValue = 0.0);
150                     }
151                 }
152             }
153
154             FREE(pstReplaced);
155         }
156         *ierr = STRINGTODOUBLE_NO_ERROR;
157     }
158     else
159     {
160         *ierr = STRINGTODOUBLE_MEMORY_ALLOCATION;
161     }
162     return dValue;
163 }
164 // =============================================================================
165 static double returnINF(BOOL bPositive)
166 {
167     double dbl1 = 1.0;
168     double dbl0 = dbl1 - dbl1;
169     int iSign = bPositive == 1 ? 1 : -1;
170
171     return iSign * dbl1 / dbl0;
172 }
173 // =============================================================================
174 static double returnNAN(void)
175 {
176     static int first = 1;
177     static double nan = 1.0;
178
179     if ( first )
180     {
181         nan = (nan - (double) first) / (nan - (double) first);
182         first = 0;
183     }
184     return (nan);
185 }
186 // =============================================================================