allow underscores in integer literals; close #1960

This commit is contained in:
Yukihiro "Matz" Matsumoto
2014-03-27 12:33:32 +09:00
parent 5067e7b064
commit 9434506035
2 changed files with 27 additions and 8 deletions
+25 -8
View File
@@ -1952,10 +1952,10 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
mrb_value
mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
{
char *end;
const char *p;
char sign = 1;
int c;
unsigned long n;
int c, us;
unsigned long n = 0;
mrb_int val;
#undef ISDIGIT
@@ -2042,7 +2042,7 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
break;
} /* end of switch (base) { */
if (*str == '0') { /* squeeze preceeding 0s */
int us = 0;
us = 0;
while ((c = *++str) == '0' || c == '_') {
if (c == '_') {
if (++us >= 2)
@@ -2060,15 +2060,32 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
return mrb_fixnum_value(0);
}
n = strtoul((char*)str, &end, base);
us = 0;
for (p=str;*p;p++) {
if (*p == '_') {
if (us == 0) {
us++;
continue;
}
if (badcheck) goto bad;
break;
}
c = conv_digit(*p);
if (c < 0 || c >= base) {
if (badcheck) goto bad;
break;
}
n *= base;
n += c;
}
if (n > MRB_INT_MAX) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer", mrb_str_new_cstr(mrb, str));
}
val = n;
if (badcheck) {
if (end == str) goto bad; /* no number */
while (*end && ISSPACE(*end)) end++;
if (*end) goto bad; /* trailing garbage */
if (p == str) goto bad; /* no number */
while (*p && ISSPACE(*p)) p++;
if (*p) goto bad; /* trailing garbage */
}
return mrb_fixnum_value(sign ? val : -val);
+2
View File
@@ -433,11 +433,13 @@ assert('String#to_i', '15.2.10.5.39') do
b = '32143'.to_i
c = 'a'.to_i(16)
d = '100'.to_i(2)
e = '1_000'.to_i
assert_equal 0, a
assert_equal 32143, b
assert_equal 10, c
assert_equal 4, d
assert_equal 1_000, e
end
assert('String#to_s', '15.2.10.5.40') do