From 2532e625edc2457447369e36e2ecf7882d872ef9 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 6 Jan 2020 15:40:03 +0900 Subject: Refactor `mrb_cstr_to_dbl`; ref #4920 --- src/string.c | 92 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 37 deletions(-) (limited to 'src/string.c') diff --git a/src/string.c b/src/string.c index 08c14d8e8..15e52fb3c 100644 --- a/src/string.c +++ b/src/string.c @@ -2488,20 +2488,58 @@ mrb_str_to_i(mrb_state *mrb, mrb_value self) } #ifndef MRB_WITHOUT_FLOAT -MRB_API double -mrb_cstr_to_dbl(mrb_state *mrb, const char *s, mrb_bool badcheck) +double +mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck) { - const char *p = s; - char *end; char buf[DBL_DIG * 4 + 10]; + const char *p; + const char *pend = s + len; + char *end; + char *n; + char prev = 0; double d; - if (!p) return 0.0; - while (ISSPACE(*p)) p++; + if (!s) return 0.0; + while (ISSPACE(*s)) s++; + p = s; if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { return 0.0; } + while (p < pend) { + if (!*p) { + if (badcheck && p < pend) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "string for Float contains null byte"); + /* not reached */ + } + pend = p; + p = s; + goto nocopy; + } + if (*p == '_') break; + p++; + } + p = s; + n = buf; + while (p < pend) { + char c = *p++; + if (c == '_') { + /* remove an underscore between digits */ + if (n == buf || !ISDIGIT(prev) || p == pend) { + if (badcheck) goto bad; + break; + } + } + else if (badcheck && prev == '_' && !ISDIGIT(c)) goto bad; + else { + *n++ = c; + } + prev = c; + } + *n = '\0'; + p = buf; + pend = n; +nocopy: d = mrb_float_read(p, &end); if (p == end) { if (badcheck) { @@ -2511,44 +2549,24 @@ bad: } return d; } - if (*end) { - char *n = buf; - char *e = buf + sizeof(buf) - 1; - char prev = 0; - - while (p < end && n < e) prev = *n++ = *p++; - while (*p) { - if (*p == '_') { - /* remove an underscore between digits */ - if (n == buf || !ISDIGIT(prev) || (++p, !ISDIGIT(*p))) { - if (badcheck) goto bad; - break; - } - } - prev = *p++; - if (n < e) *n++ = prev; - } - *n = '\0'; - p = buf; - - if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { - return 0.0; - } - - d = mrb_float_read(p, &end); - if (badcheck) { - if (!end || p == end) goto bad; - while (*end && ISSPACE(*end)) end++; - if (*end) goto bad; - } + if (badcheck) { + if (!end || p == end) goto bad; + while (end