summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2014-03-27 12:33:32 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2014-03-27 12:33:32 +0900
commit9434506035c3fc01de55ac0bc8b75497f8b5df5f (patch)
tree3920ca6a5080c60d79d5d79da165aa6eb340b73b
parent5067e7b0640507b1b953609b53a00a1bf14042c1 (diff)
downloadmruby-9434506035c3fc01de55ac0bc8b75497f8b5df5f.tar.gz
mruby-9434506035c3fc01de55ac0bc8b75497f8b5df5f.zip
allow underscores in integer literals; close #1960
-rw-r--r--src/string.c33
-rw-r--r--test/t/string.rb2
2 files changed, 27 insertions, 8 deletions
diff --git a/src/string.c b/src/string.c
index 266db4989..0bee35d0e 100644
--- a/src/string.c
+++ b/src/string.c
@@ -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);
diff --git a/test/t/string.rb b/test/t/string.rb
index 445cf7439..04f90fb45 100644
--- a/test/t/string.rb
+++ b/test/t/string.rb
@@ -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