mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Refactor mrb_cstr_to_dbl; ref #4920
This commit is contained in:
+3
-7
@@ -42,21 +42,17 @@ offset_crc_body(void)
|
||||
}
|
||||
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
double mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck);
|
||||
|
||||
static double
|
||||
str_to_double(mrb_state *mrb, const char *p, size_t len)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
/* `i`, `inf`, `infinity` */
|
||||
if (len > 0 && p[0] == 'i') return INFINITY;
|
||||
|
||||
/* `I`, `-inf`, `-infinity` */
|
||||
if (p[0] == 'I' || (len > 1 && p[0] == '-' && p[1] == 'i')) return -INFINITY;
|
||||
mrb_assert(len < sizeof(buf));
|
||||
strncpy(buf, p, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
return mrb_cstr_to_dbl(mrb, buf, TRUE);
|
||||
return mrb_str_len_to_dbl(mrb, p, len, TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+55
-37
@@ -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<pend && ISSPACE(*end)) end++;
|
||||
if (end<pend) goto bad;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
MRB_API double
|
||||
mrb_cstr_to_dbl(mrb_state *mrb, const char *s, mrb_bool badcheck)
|
||||
{
|
||||
return mrb_str_len_to_dbl(mrb, s, strlen(s), badcheck);
|
||||
}
|
||||
|
||||
MRB_API double
|
||||
mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck)
|
||||
{
|
||||
return mrb_cstr_to_dbl(mrb, RSTRING_CSTR(mrb, str), badcheck);
|
||||
return mrb_str_len_to_dbl(mrb, RSTRING_PTR(str), RSTRING_LEN(str), badcheck);
|
||||
}
|
||||
|
||||
/* 15.2.10.5.39 */
|
||||
|
||||
Reference in New Issue
Block a user