From df549c12e5852f640d37b2bd35e2d5dfc45a7283 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 10 Jun 2021 09:26:54 +0900 Subject: readflt.c: renamed from `strtod.c` The file provides `mrb_read_float()` renamed from `vim_strtod()`. --- src/readflt.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/readflt.c (limited to 'src/readflt.c') diff --git a/src/readflt.c b/src/readflt.c new file mode 100644 index 000000000..19a8e8dc6 --- /dev/null +++ b/src/readflt.c @@ -0,0 +1,120 @@ +#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_float_read` + * simplified the code + +My modifications in this file are also placed in the public domain. + +Matz (Yukihiro Matsumoto) +*/ + +#include +#include +#include +#include + +MRB_API double +mrb_float_read(const char *str, char **end) +{ + 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))) { + a = str; + goto done; + } + else if (*p == 0) + goto done; + d *= pow(10.0, (double) e); + a = p; + } + else if (p > str && !ISDIGIT(*(p-1))) { + a = str; + goto done; + } + +done: + if (end) + *end = (char*)a; + return d; +} +#endif -- cgit v1.2.3