#include #ifndef MRB_NO_FLOAT /* * strtod implementation. * author: Yasuhiro Matsumoto (@mattn) * license: public domain */ /* The original code can be found in https://github.com/mattn/strtod I modified the routine for mruby: * renamed the function `vim_strtod` -> `mrb_read_float` * simplified the code * changed the API My modifications in this file are also placed in the public domain. Matz (Yukihiro Matsumoto) */ #include #include MRB_API mrb_bool mrb_read_float(const char *str, char **endp, double *fp) { double d = 0.0; int sign; int n = 0; const char *p, *a; a = p = str; while (ISSPACE(*p)) p++; /* decimal part */ sign = 1; if (*p == '-') { sign = -1; p++; } else if (*p == '+') p++; if (ISDIGIT(*p)) { d = (double)(*p++ - '0'); while (*p && ISDIGIT(*p)) { d = d * 10.0 + (double)(*p - '0'); p++; n++; } a = p; } else if (*p != '.') goto done; d *= sign; /* fraction part */ if (*p == '.') { double f = 0.0; double base = 0.1; p++; if (ISDIGIT(*p)) { while (*p && ISDIGIT(*p)) { f += base * (*p - '0'); base /= 10.0; p++; n++; } } d += f * sign; a = p; } /* exponential part */ if ((*p == 'E') || (*p == 'e')) { int e = 0; p++; sign = 1; if (*p == '-') { sign = -1; p++; } else if (*p == '+') p++; if (ISDIGIT(*p)) { while (*p == '0') p++; if (*p == '\0') --p; e = (int)(*p++ - '0'); for (; *p && ISDIGIT(*p); p++) { if (e < 10000) e = e * 10 + (*p - '0'); } e *= sign; } else if (!ISDIGIT(*(a-1))) { return FALSE; } else if (*p == 0) goto done; d *= pow(10.0, (double)e); a = p; } else if (p > str && !ISDIGIT(*(p-1))) { goto done; } done: *fp = d; if (endp) *endp = (char*)a; if (str == a) return FALSE; return TRUE; } #endif