diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-10-03 10:18:14 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-10-03 10:18:14 +0000 |
commit | 74926fefb7de9ade12ef1dbc4994efe981aaa55a (patch) | |
tree | 82836b85012684734d6edaa678c30e26be5297e7 | |
parent | 51b89eeb03414636ed144841626f358ba6788303 (diff) |
* object.c (rb_f_integer): now Integer() takes optional base
argument. base will be ignored for non string values.
suggested by Sam Carr at RubyFoo Lounge at London.
* test/ruby/test_integer.rb (TestInteger#test_Integer): test
updated.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25205 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | object.c | 57 | ||||
-rw-r--r-- | test/ruby/test_integer.rb | 13 |
3 files changed, 67 insertions, 12 deletions
@@ -1,3 +1,12 @@ +Sat Oct 3 18:51:11 2009 Yukihiro Matsumoto <matz@ruby-lang.org> + + * object.c (rb_f_integer): now Integer() takes optional base + argument. base will be ignored for non string values. + suggested by Sam Carr at RubyFoo Lounge at London. + + * test/ruby/test_integer.rb (TestInteger#test_Integer): test + updated. + Sat Oct 3 04:34:25 2009 Nobuyoshi Nakada <nobu@ruby-lang.org> * parse.y (assignable_gen): parser_yyerror takes two arguments. @@ -2087,13 +2087,14 @@ rb_to_int(VALUE val) return rb_to_integer(val, "to_int"); } -VALUE -rb_Integer(VALUE val) +static VALUE +rb_convert_to_integer(VALUE val, int base) { VALUE tmp; switch (TYPE(val)) { case T_FLOAT: + if (base != 0) goto arg_error; if (RFLOAT_VALUE(val) <= (double)FIXNUM_MAX && RFLOAT_VALUE(val) >= (double)FIXNUM_MIN) { break; @@ -2102,36 +2103,55 @@ rb_Integer(VALUE val) case T_FIXNUM: case T_BIGNUM: + if (base != 0) goto arg_error; return val; case T_STRING: - return rb_str_to_inum(val, 0, TRUE); + string_conv: + return rb_str_to_inum(val, base, TRUE); case T_NIL: + if (base != 0) goto arg_error; rb_raise(rb_eTypeError, "can't convert nil into Integer"); break; default: break; } + if (base != 0) { + tmp = rb_check_string_type(val); + if (!NIL_P(tmp)) goto string_conv; + arg_error: + rb_raise(rb_eArgError, "base specified for non string value"); + } tmp = convert_type(val, "Integer", "to_int", FALSE); if (NIL_P(tmp)) { return rb_to_integer(val, "to_i"); } return tmp; + +} + +VALUE +rb_Integer(VALUE val) +{ + return rb_convert_to_integer(val, 0); } /* * call-seq: - * Integer(arg) => integer + * Integer(arg,base=0) => integer * * Converts <i>arg</i> to a <code>Fixnum</code> or <code>Bignum</code>. * Numeric types are converted directly (with floating point numbers - * being truncated). If <i>arg</i> is a <code>String</code>, leading - * radix indicators (<code>0</code>, <code>0b</code>, and - * <code>0x</code>) are honored. Others are converted using - * <code>to_int</code> and <code>to_i</code>. This behavior is - * different from that of <code>String#to_i</code>. + * being truncated). <i>base</i> (0, or between 2 and 36) is a base for + * integer string representation. If <i>arg</i> is a <code>String</code>, + * when <i>base</i> is omitted or equals to zero, radix indicators + * (<code>0</code>, <code>0b</code>, and <code>0x</code>) are honored. + * In any case, strings should be strictly conformed to numeric + * representation. This behavior is different from that of + * <code>String#to_i</code>. Non string valueswill be converted using + * <code>to_int</code>, and <code>to_i</code>. * * Integer(123.999) #=> 123 * Integer("0x1a") #=> 26 @@ -2139,9 +2159,22 @@ rb_Integer(VALUE val) */ static VALUE -rb_f_integer(VALUE obj, VALUE arg) +rb_f_integer(int argc, VALUE *argv, VALUE obj) { - return rb_Integer(arg); + VALUE arg = Qnil; + int base = 0; + + switch (argc) { + case 2: + base = NUM2INT(argv[1]); + case 1: + arg = argv[0]; + break; + default: + /* should cause ArgumentError */ + rb_scan_args(argc, argv, "11", NULL, NULL); + } + return rb_convert_to_integer(arg, base); } double @@ -2556,7 +2589,7 @@ Init_Object(void) rb_define_global_function("sprintf", rb_f_sprintf, -1); /* in sprintf.c */ rb_define_global_function("format", rb_f_sprintf, -1); /* in sprintf.c */ - rb_define_global_function("Integer", rb_f_integer, 1); + rb_define_global_function("Integer", rb_f_integer, -1); rb_define_global_function("Float", rb_f_float, 1); rb_define_global_function("String", rb_f_string, 1); diff --git a/test/ruby/test_integer.rb b/test/ruby/test_integer.rb index 232a7fae30..b3dd11d55a 100644 --- a/test/ruby/test_integer.rb +++ b/test/ruby/test_integer.rb @@ -71,6 +71,19 @@ class TestInteger < Test::Unit::TestCase assert_equal(0377, Integer("0_3_7_7")) } assert_raise(ArgumentError, "[ruby-core:14139]") {Integer("0__3_7_7")} + assert_equal(1234, Integer(1234)) + assert_equal(1, Integer(1.234)) + + # base argument + assert_equal(1234, Integer("1234", 10)) + assert_equal(668, Integer("1234", 8)) + assert_equal(4660, Integer("1234", 16)) + assert_equal(49360, Integer("1234", 36)) + # decimal, not octal + assert_equal(1234, Integer("01234", 10)) + assert_raise(ArgumentError) { Integer("0x123", 10) } + assert_raise(ArgumentError) { Integer(1234, 10) } + assert_raise(ArgumentError) { Integer(12.34, 10) } end def test_int_p |