[Bug #19349] Respect #to_int
of base
argument
This commit is contained in:
parent
24b2bb465f
commit
c45176dbca
Notes:
git
2023-08-31 09:42:27 +00:00
93
kernel.rb
93
kernel.rb
@ -216,4 +216,97 @@ module Kernel
|
|||||||
Primitive.rb_f_float(arg, exception)
|
Primitive.rb_f_float(arg, exception)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# call-seq:
|
||||||
|
# Integer(object, base = 0, exception: true) -> integer or nil
|
||||||
|
#
|
||||||
|
# Returns an integer converted from +object+.
|
||||||
|
#
|
||||||
|
# Tries to convert +object+ to an integer
|
||||||
|
# using +to_int+ first and +to_i+ second;
|
||||||
|
# see below for exceptions.
|
||||||
|
#
|
||||||
|
# With a non-zero +base+, +object+ must be a string or convertible
|
||||||
|
# to a string.
|
||||||
|
#
|
||||||
|
# ==== numeric objects
|
||||||
|
#
|
||||||
|
# With integer argument +object+ given, returns +object+:
|
||||||
|
#
|
||||||
|
# Integer(1) # => 1
|
||||||
|
# Integer(-1) # => -1
|
||||||
|
#
|
||||||
|
# With floating-point argument +object+ given,
|
||||||
|
# returns +object+ truncated to an integer:
|
||||||
|
#
|
||||||
|
# Integer(1.9) # => 1 # Rounds toward zero.
|
||||||
|
# Integer(-1.9) # => -1 # Rounds toward zero.
|
||||||
|
#
|
||||||
|
# ==== string objects
|
||||||
|
#
|
||||||
|
# With string argument +object+ and zero +base+ given,
|
||||||
|
# returns +object+ converted to an integer in base 10:
|
||||||
|
#
|
||||||
|
# Integer('100') # => 100
|
||||||
|
# Integer('-100') # => -100
|
||||||
|
#
|
||||||
|
# With +base+ zero, string +object+ may contain leading characters
|
||||||
|
# to specify the actual base (radix indicator):
|
||||||
|
#
|
||||||
|
# Integer('0100') # => 64 # Leading '0' specifies base 8.
|
||||||
|
# Integer('0b100') # => 4 # Leading '0b', specifies base 2.
|
||||||
|
# Integer('0x100') # => 256 # Leading '0x' specifies base 16.
|
||||||
|
#
|
||||||
|
# With a positive +base+ (in range 2..36) given, returns +object+
|
||||||
|
# converted to an integer in the given base:
|
||||||
|
#
|
||||||
|
# Integer('100', 2) # => 4
|
||||||
|
# Integer('100', 8) # => 64
|
||||||
|
# Integer('-100', 16) # => -256
|
||||||
|
#
|
||||||
|
# With a negative +base+ (in range -36..-2) given, returns +object+
|
||||||
|
# converted to an integer in the radix indicator if exists or
|
||||||
|
# +-base+:
|
||||||
|
#
|
||||||
|
# Integer('0x100', -2) # => 256
|
||||||
|
# Integer('100', -2) # => 4
|
||||||
|
# Integer('0b100', -8) # => 4
|
||||||
|
# Integer('100', -8) # => 64
|
||||||
|
# Integer('0o100', -10) # => 64
|
||||||
|
# Integer('100', -10) # => 100
|
||||||
|
#
|
||||||
|
# +base+ -1 is equal the -10 case.
|
||||||
|
#
|
||||||
|
# When converting strings, surrounding whitespace and embedded underscores
|
||||||
|
# are allowed and ignored:
|
||||||
|
#
|
||||||
|
# Integer(' 100 ') # => 100
|
||||||
|
# Integer('-1_0_0', 16) # => -256
|
||||||
|
#
|
||||||
|
# ==== other classes
|
||||||
|
#
|
||||||
|
# Examples with +object+ of various other classes:
|
||||||
|
#
|
||||||
|
# Integer(Rational(9, 10)) # => 0 # Rounds toward zero.
|
||||||
|
# Integer(Complex(2, 0)) # => 2 # Imaginary part must be zero.
|
||||||
|
# Integer(Time.now) # => 1650974042
|
||||||
|
#
|
||||||
|
# ==== keywords
|
||||||
|
#
|
||||||
|
# With optional keyword argument +exception+ given as +true+ (the default):
|
||||||
|
#
|
||||||
|
# - Raises TypeError if +object+ does not respond to +to_int+ or +to_i+.
|
||||||
|
# - Raises TypeError if +object+ is +nil+.
|
||||||
|
# - Raise ArgumentError if +object+ is an invalid string.
|
||||||
|
#
|
||||||
|
# With +exception+ given as +false+, an exception of any kind is suppressed
|
||||||
|
# and +nil+ is returned.
|
||||||
|
|
||||||
|
def Integer(arg, base = 0, exception: true)
|
||||||
|
if Primitive.mandatory_only?
|
||||||
|
Primitive.rb_f_integer1(arg)
|
||||||
|
else
|
||||||
|
Primitive.rb_f_integer(arg, base, exception);
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
122
object.c
122
object.c
@ -3312,121 +3312,17 @@ rb_opts_exception_p(VALUE opts, int default_value)
|
|||||||
return default_value;
|
return default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define opts_exception_p(opts) rb_opts_exception_p((opts), TRUE)
|
static VALUE
|
||||||
|
rb_f_integer1(rb_execution_context_t *ec, VALUE obj, VALUE arg)
|
||||||
/*
|
{
|
||||||
* call-seq:
|
return rb_convert_to_integer(arg, 0, TRUE);
|
||||||
* Integer(object, base = 0, exception: true) -> integer or nil
|
}
|
||||||
*
|
|
||||||
* Returns an integer converted from +object+.
|
|
||||||
*
|
|
||||||
* Tries to convert +object+ to an integer
|
|
||||||
* using +to_int+ first and +to_i+ second;
|
|
||||||
* see below for exceptions.
|
|
||||||
*
|
|
||||||
* With a non-zero +base+, +object+ must be a string or convertible
|
|
||||||
* to a string.
|
|
||||||
*
|
|
||||||
* ==== numeric objects
|
|
||||||
*
|
|
||||||
* With integer argument +object+ given, returns +object+:
|
|
||||||
*
|
|
||||||
* Integer(1) # => 1
|
|
||||||
* Integer(-1) # => -1
|
|
||||||
*
|
|
||||||
* With floating-point argument +object+ given,
|
|
||||||
* returns +object+ truncated to an integer:
|
|
||||||
*
|
|
||||||
* Integer(1.9) # => 1 # Rounds toward zero.
|
|
||||||
* Integer(-1.9) # => -1 # Rounds toward zero.
|
|
||||||
*
|
|
||||||
* ==== string objects
|
|
||||||
*
|
|
||||||
* With string argument +object+ and zero +base+ given,
|
|
||||||
* returns +object+ converted to an integer in base 10:
|
|
||||||
*
|
|
||||||
* Integer('100') # => 100
|
|
||||||
* Integer('-100') # => -100
|
|
||||||
*
|
|
||||||
* With +base+ zero, string +object+ may contain leading characters
|
|
||||||
* to specify the actual base (radix indicator):
|
|
||||||
*
|
|
||||||
* Integer('0100') # => 64 # Leading '0' specifies base 8.
|
|
||||||
* Integer('0b100') # => 4 # Leading '0b', specifies base 2.
|
|
||||||
* Integer('0x100') # => 256 # Leading '0x' specifies base 16.
|
|
||||||
*
|
|
||||||
* With a positive +base+ (in range 2..36) given, returns +object+
|
|
||||||
* converted to an integer in the given base:
|
|
||||||
*
|
|
||||||
* Integer('100', 2) # => 4
|
|
||||||
* Integer('100', 8) # => 64
|
|
||||||
* Integer('-100', 16) # => -256
|
|
||||||
*
|
|
||||||
* With a negative +base+ (in range -36..-2) given, returns +object+
|
|
||||||
* converted to an integer in the radix indicator if exists or
|
|
||||||
* +-base+:
|
|
||||||
*
|
|
||||||
* Integer('0x100', -2) # => 256
|
|
||||||
* Integer('100', -2) # => 4
|
|
||||||
* Integer('0b100', -8) # => 4
|
|
||||||
* Integer('100', -8) # => 64
|
|
||||||
* Integer('0o100', -10) # => 64
|
|
||||||
* Integer('100', -10) # => 100
|
|
||||||
*
|
|
||||||
* +base+ -1 is equal the -10 case.
|
|
||||||
*
|
|
||||||
* When converting strings, surrounding whitespace and embedded underscores
|
|
||||||
* are allowed and ignored:
|
|
||||||
*
|
|
||||||
* Integer(' 100 ') # => 100
|
|
||||||
* Integer('-1_0_0', 16) # => -256
|
|
||||||
*
|
|
||||||
* ==== other classes
|
|
||||||
*
|
|
||||||
* Examples with +object+ of various other classes:
|
|
||||||
*
|
|
||||||
* Integer(Rational(9, 10)) # => 0 # Rounds toward zero.
|
|
||||||
* Integer(Complex(2, 0)) # => 2 # Imaginary part must be zero.
|
|
||||||
* Integer(Time.now) # => 1650974042
|
|
||||||
*
|
|
||||||
* ==== keywords
|
|
||||||
*
|
|
||||||
* With optional keyword argument +exception+ given as +true+ (the default):
|
|
||||||
*
|
|
||||||
* - Raises TypeError if +object+ does not respond to +to_int+ or +to_i+.
|
|
||||||
* - Raises TypeError if +object+ is +nil+.
|
|
||||||
* - Raise ArgumentError if +object+ is an invalid string.
|
|
||||||
*
|
|
||||||
* With +exception+ given as +false+, an exception of any kind is suppressed
|
|
||||||
* and +nil+ is returned.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_f_integer(int argc, VALUE *argv, VALUE obj)
|
rb_f_integer(rb_execution_context_t *ec, VALUE obj, VALUE arg, VALUE base, VALUE exception)
|
||||||
{
|
{
|
||||||
VALUE arg = Qnil, opts = Qnil;
|
int exc = rb_bool_expected(exception, "exception", TRUE);
|
||||||
int base = 0;
|
return rb_convert_to_integer(arg, NUM2INT(base), exc);
|
||||||
|
|
||||||
if (argc > 1) {
|
|
||||||
int narg = 1;
|
|
||||||
VALUE vbase = rb_check_to_int(argv[1]);
|
|
||||||
if (!NIL_P(vbase)) {
|
|
||||||
base = NUM2INT(vbase);
|
|
||||||
narg = 2;
|
|
||||||
}
|
|
||||||
if (argc > narg) {
|
|
||||||
VALUE hash = rb_check_hash_type(argv[argc-1]);
|
|
||||||
if (!NIL_P(hash)) {
|
|
||||||
opts = rb_extract_keywords(&hash);
|
|
||||||
if (!hash) --argc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rb_check_arity(argc, 1, 2);
|
|
||||||
arg = argv[0];
|
|
||||||
|
|
||||||
return rb_convert_to_integer(arg, base, opts_exception_p(opts));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
@ -4475,8 +4371,6 @@ InitVM_Object(void)
|
|||||||
rb_define_global_function("sprintf", f_sprintf, -1);
|
rb_define_global_function("sprintf", f_sprintf, -1);
|
||||||
rb_define_global_function("format", f_sprintf, -1);
|
rb_define_global_function("format", f_sprintf, -1);
|
||||||
|
|
||||||
rb_define_global_function("Integer", rb_f_integer, -1);
|
|
||||||
|
|
||||||
rb_define_global_function("String", rb_f_string, 1);
|
rb_define_global_function("String", rb_f_string, 1);
|
||||||
rb_define_global_function("Array", rb_f_array, 1);
|
rb_define_global_function("Array", rb_f_array, 1);
|
||||||
rb_define_global_function("Hash", rb_f_hash, 1);
|
rb_define_global_function("Hash", rb_f_hash, 1);
|
||||||
|
@ -251,6 +251,17 @@ class TestInteger < Test::Unit::TestCase
|
|||||||
assert_raise(ArgumentError) { Integer(Object.new, 1) }
|
assert_raise(ArgumentError) { Integer(Object.new, 1) }
|
||||||
|
|
||||||
assert_raise(ArgumentError) { Integer(1, 1, 1) }
|
assert_raise(ArgumentError) { Integer(1, 1, 1) }
|
||||||
|
|
||||||
|
def (base = Object.new).to_int
|
||||||
|
8
|
||||||
|
end
|
||||||
|
assert_equal(8, Integer("10", base))
|
||||||
|
|
||||||
|
assert_raise(TypeError) { Integer("10", "8") }
|
||||||
|
def (base = Object.new).to_int
|
||||||
|
"8"
|
||||||
|
end
|
||||||
|
assert_raise(TypeError) { Integer("10", base) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_int_p
|
def test_int_p
|
||||||
|
Loading…
x
Reference in New Issue
Block a user