Merge pull request #6288 from dearblue/closing
[mruby.git] / src / readfloat.c
blob1c4cf7bc28a74537ef71aa3e3ad332e98b3faa4c
1 #include <mruby.h>
3 #ifndef MRB_NO_FLOAT
4 /*
5 * strtod implementation.
6 * author: Yasuhiro Matsumoto (@mattn)
7 * license: public domain
8 */
11 The original code can be found in https://github.com/mattn/strtod
13 I modified the routine for mruby:
15 * renamed the function `vim_strtod` -> `mrb_read_float`
16 * simplified the code
17 * changed the API
19 My modifications in this file are also placed in the public domain.
21 Matz (Yukihiro Matsumoto)
24 #include <string.h>
25 #include <math.h>
27 MRB_API mrb_bool
28 mrb_read_float(const char *str, char **endp, double *fp)
30 double d = 0.0;
31 int sign;
32 const char *p, *a;
34 a = p = str;
35 while (ISSPACE(*p))
36 p++;
38 /* decimal part */
39 sign = 1;
40 if (*p == '-') {
41 sign = -1;
42 p++;
44 else if (*p == '+')
45 p++;
46 if (ISDIGIT(*p)) {
47 d = (double)(*p++ - '0');
48 while (*p && ISDIGIT(*p)) {
49 d = d * 10.0 + (double)(*p - '0');
50 p++;
52 a = p;
54 else if (*p != '.')
55 goto done;
56 d *= sign;
58 /* fraction part */
59 if (*p == '.') {
60 double f = 0.0;
61 double base = 0.1;
62 p++;
64 if (ISDIGIT(*p)) {
65 while (*p && ISDIGIT(*p)) {
66 f += base * (*p - '0');
67 base /= 10.0;
68 p++;
71 d += f * sign;
72 a = p;
75 /* exponential part */
76 if ((*p == 'E') || (*p == 'e')) {
77 int e = 0;
79 p++;
80 sign = 1;
81 if (*p == '-') {
82 sign = -1;
83 p++;
85 else if (*p == '+')
86 p++;
88 if (ISDIGIT(*p)) {
89 while (*p == '0')
90 p++;
91 if (*p == '\0') --p;
92 e = (int)(*p++ - '0');
93 for (; *p && ISDIGIT(*p); p++) {
94 if (e < 10000)
95 e = e * 10 + (*p - '0');
97 e *= sign;
99 else if (!ISDIGIT(*(a-1))) {
100 return FALSE;
102 else if (*p == 0)
103 goto done;
104 d *= pow(10.0, (double)e);
105 a = p;
107 else if (p > str && !ISDIGIT(*(p-1))) {
108 goto done;
111 done:
112 *fp = d;
113 if (endp) *endp = (char*)a;
114 if (str == a) return FALSE;
115 return TRUE;
117 #endif