commit 5e3c474aaff56e8adb53fe0674a9a2f5081cdfb9 Author: Prodis Date: Sat Dec 19 13:16:40 2015 -0200 New #to_b method for String, Symbol, Numeric, NilClass, TrueClass and FalseClass. diff --git a/numeric.c b/numeric.c index 5e70caf..eb8e9ea 100644 --- a/numeric.c +++ b/numeric.c @@ -650,6 +650,22 @@ num_to_int(VALUE num) } /* + * call-seq: + * num.to_b -> true or false + * + * Returns +false+ if +num+ is zero, +true+ otherwise. + */ + +static VALUE +num_to_b(VALUE num) +{ + if (rb_funcallv(num, rb_intern("zero?"), 0, 0)) { + return Qfalse; + } + return Qtrue; +} + +/* * call-seq: * num.positive? -> true or false * @@ -4182,6 +4198,7 @@ Init_Numeric(void) rb_define_method(rb_cNumeric, "abs", num_abs, 0); rb_define_method(rb_cNumeric, "magnitude", num_abs, 0); rb_define_method(rb_cNumeric, "to_int", num_to_int, 0); + rb_define_method(rb_cNumeric, "to_b", num_to_b, 0); rb_define_method(rb_cNumeric, "real?", num_real_p, 0); rb_define_method(rb_cNumeric, "integer?", num_int_p, 0); diff --git a/object.c b/object.c index 99f58a8..e623edc 100644 --- a/object.c +++ b/object.c @@ -1191,6 +1191,22 @@ nil_inspect(VALUE obj) return rb_usascii_str_new2("nil"); } +/* + * call-seq: + * nil.to_b -> false + * + * Always returns false. + * + * nil.to_b #=> false + */ + +static VALUE +nil_to_b(VALUE obj) +{ + return Qfalse; +} + + /*********************************************************************** * Document-class: TrueClass * @@ -1269,6 +1285,20 @@ true_xor(VALUE obj, VALUE obj2) /* + * call-seq: + * true.to_b -> true + * + * Returns true. + */ + +static VALUE +true_to_b(VALUE obj) +{ + return Qtrue; +} + + +/* * Document-class: FalseClass * * The global value false is the only instance of class @@ -1342,6 +1372,21 @@ false_xor(VALUE obj, VALUE obj2) return RTEST(obj2)?Qtrue:Qfalse; } + +/* + * call-seq: + * false.to_b -> false + * + * Returns false. + */ + +static VALUE +false_to_b(VALUE obj) +{ + return Qfalse; +} + + /* * call-seq: * nil.nil? -> true @@ -3477,6 +3522,7 @@ InitVM_Object(void) rb_define_method(rb_cNilClass, "to_s", nil_to_s, 0); rb_define_method(rb_cNilClass, "to_a", nil_to_a, 0); rb_define_method(rb_cNilClass, "to_h", nil_to_h, 0); + rb_define_method(rb_cNilClass, "to_b", nil_to_b, 0); rb_define_method(rb_cNilClass, "inspect", nil_inspect, 0); rb_define_method(rb_cNilClass, "&", false_and, 1); rb_define_method(rb_cNilClass, "|", false_or, 1); @@ -3562,6 +3608,7 @@ InitVM_Object(void) rb_undef_alloc_func(rb_cData); rb_cTrueClass = rb_define_class("TrueClass", rb_cObject); + rb_define_method(rb_cTrueClass, "to_b", true_to_b, 0); rb_define_method(rb_cTrueClass, "to_s", true_to_s, 0); rb_define_alias(rb_cTrueClass, "inspect", "to_s"); rb_define_method(rb_cTrueClass, "&", true_and, 1); @@ -3576,6 +3623,7 @@ InitVM_Object(void) rb_define_global_const("TRUE", Qtrue); rb_cFalseClass = rb_define_class("FalseClass", rb_cObject); + rb_define_method(rb_cFalseClass, "to_b", false_to_b, 0); rb_define_method(rb_cFalseClass, "to_s", false_to_s, 0); rb_define_alias(rb_cFalseClass, "inspect", "to_s"); rb_define_method(rb_cFalseClass, "&", false_and, 1); diff --git a/string.c b/string.c index 4ab89a8..31b5744 100644 --- a/string.c +++ b/string.c @@ -8945,6 +8945,37 @@ str_scrub_bang(int argc, VALUE *argv, VALUE str) return str; } + +/* "trues" array contains the valid values to convert String to TrueClass. */ +#define STRING_TRUES_SIZE 6 +static const char* trues[STRING_TRUES_SIZE] = {"t", "true", "on", "y", "yes", "1"}; + +/* + * call-seq: + * str.to_b -> true or false + * + * Returns true if str is one of "t", "true", "on", "y", "yes" or "1" values. + * Returns false otherwise. + * to_b method ignores trailing spaces and letter cases. + */ + +static VALUE +rb_str_to_b(VALUE str) +{ + int i; + for (i = 0; i < STRING_TRUES_SIZE; i++) { + str = rb_str_downcase(rb_str_strip(str)); + + if (strcmp(RSTRING_PTR(str), trues[i]) == 0) { + return Qtrue; + } + } + + return Qfalse; +} + + + /********************************************************************** * Document-class: Symbol * @@ -9088,6 +9119,20 @@ sym_inspect(VALUE sym) /* + * call-seq: + * sym.to_b -> true or false + * + * Same as sym.to_s.to_b. + */ + +static VALUE +rb_sym_to_b(VALUE sym) +{ + return rb_str_to_b(rb_sym2str(sym)); +} + + +/* * call-seq: * sym.id2name -> string * sym.to_s -> string @@ -9423,6 +9468,7 @@ Init_String(void) rb_define_method(rb_cString, "to_i", rb_str_to_i, -1); rb_define_method(rb_cString, "to_f", rb_str_to_f, 0); + rb_define_method(rb_cString, "to_b", rb_str_to_b, 0); rb_define_method(rb_cString, "to_s", rb_str_to_s, 0); rb_define_method(rb_cString, "to_str", rb_str_to_s, 0); rb_define_method(rb_cString, "inspect", rb_str_inspect, 0); @@ -9524,6 +9570,7 @@ Init_String(void) rb_define_method(rb_cSymbol, "==", sym_equal, 1); rb_define_method(rb_cSymbol, "===", sym_equal, 1); rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0); + rb_define_method(rb_cSymbol, "to_b", rb_sym_to_b, 0); rb_define_method(rb_cSymbol, "to_s", rb_sym_to_s, 0); rb_define_method(rb_cSymbol, "id2name", rb_sym_to_s, 0); rb_define_method(rb_cSymbol, "intern", sym_to_sym, 0); diff --git a/test/ruby/test_bignum.rb b/test/ruby/test_bignum.rb index 93afbe4..54c6318 100644 --- a/test/ruby/test_bignum.rb +++ b/test/ruby/test_bignum.rb @@ -723,4 +723,9 @@ def obj.coerce(other) end assert_equal(T1024 ^ 10, T1024 ^ obj) end + + def test_to_b + assert_predicate(1111_1111_1111_1111_1111_1111_1111_1111, :to_b) + assert_predicate(-1111_1111_1111_1111_1111_1111_1111_1111, :to_b) + end end diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb index 3afd26d..a8b8406 100644 --- a/test/ruby/test_float.rb +++ b/test/ruby/test_float.rb @@ -705,4 +705,12 @@ def test_hash_0 h = {0.0 => bug10979} assert_equal(bug10979, h[-0.0]) end + + def test_to_b + assert_not_predicate(0.0, :to_b) + assert_predicate(1.0, :to_b) + assert_predicate(2.0, :to_b) + assert_predicate(-1.0, :to_b) + assert_predicate(-2.0, :to_b) + end end diff --git a/test/ruby/test_integer.rb b/test/ruby/test_integer.rb index 64b8e1e..e0dfcf6 100644 --- a/test/ruby/test_integer.rb +++ b/test/ruby/test_integer.rb @@ -278,4 +278,12 @@ def test_bit_length assert_equal(i+1, (n+1).bit_length, "#{n+1}.bit_length") } end + + def test_to_b + assert_not_predicate(0, :to_b) + assert_predicate(1, :to_b) + assert_predicate(2, :to_b) + assert_predicate(-1, :to_b) + assert_predicate(-2, :to_b) + end end diff --git a/test/ruby/test_integer_comb.rb b/test/ruby/test_integer_comb.rb index c96b34a..cfb9b6d 100644 --- a/test/ruby/test_integer_comb.rb +++ b/test/ruby/test_integer_comb.rb @@ -629,4 +629,14 @@ def test_pack_utf8 end } end + + def test_to_b + VS.each do |a| + if a == 0 + assert_equal(false, a.to_b, "(#{a}).to_b") + else + assert_equal(true, a.to_b, "(#{a}).to_b") + end + end + end end diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb index 0ab1341..2f2a39b 100644 --- a/test/ruby/test_object.rb +++ b/test/ruby/test_object.rb @@ -889,4 +889,15 @@ def (a = Object.new).set; @v = nil; end num.times {a.clone.set} end; end + + def test_nil_to_b + assert_not_predicate(nil, :to_b) + end + + def test_true_to_b + assert_predicate(true, :to_b) + end + def test_false_to_b + assert_not_predicate(false, :to_b) + end end diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 47bd0d5..616c3d9 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -2298,6 +2298,39 @@ def test_uplus_minus assert_not_equal(str.object_id, (+str).object_id) assert_equal(str.object_id, (-str).object_id) end + + def test_to_b + [ '1', '1 ', ' 1', ' 1 ', + 't', 't ', ' t', ' t ', + 'T', 'T ', ' T', ' T ', + 'true', 'true ', ' true', ' true ', + 'TRUE', 'TRUE ', ' TRUE', ' TRUE ', + 'on', 'on ', ' on', ' on ', + 'ON', 'ON ', ' ON ', ' ON ', + 'y', 'y ', ' y', ' y ', + 'Y', 'Y ', ' Y', ' Y ', + 'yes', 'yes ', ' yes', ' yes ', + 'YES', 'YES ', ' YES', ' YES ' + ].each do |value| + assert_predicate(value, :to_b) + end + + [ '', + '0', + '2', '2 ', ' 2', ' 2 ', + '-1', '-1 ', ' -1', ' -1 ', + '-2', '-2 ', ' -2', ' -2 ', + 'f', 'F', + 'false', 'FALSE', + 'off', 'OFF', + 'n', 'N', + 'no', 'NO', + 'not', 'NOT', + 'wherever' + ].each do |value| + assert_not_predicate(value, :to_b) + end + end end class TestString2 < TestString diff --git a/test/ruby/test_symbol.rb b/test/ruby/test_symbol.rb index 8960bec..8e5e442 100644 --- a/test/ruby/test_symbol.rb +++ b/test/ruby/test_symbol.rb @@ -364,4 +364,29 @@ def test_not_freeze assert_equal str, str.to_sym.to_s assert_not_predicate(str, :frozen?, bug11721) end + + def test_to_b + [ :'1', + :t, :T, + :true, :TRUE, + :on, :ON, + :y, :Y, + :yes, :YES, + ].each do |value| + assert_predicate(value, :to_b) + end + + [ :'', + :'0', :'2', :'-1', :'-2', + :f, :F, + :false, :FALSE, + :off, :OFF, + :n, :N, + :no, :NO, + :not, :NOT, + :wherever + ].each do |value| + assert_not_predicate(value, :to_b) + end + end end