From: naruse@... Date: 2017-12-01T16:26:29+00:00 Subject: [ruby-core:84033] [Ruby trunk Feature#12753][Assigned] Useful operator to check bit-flag is true or false Issue #12753 has been updated by naruse (Yui NARUSE). Status changed from Open to Assigned Assignee set to matz (Yukihiro Matsumoto) Target version set to 2.5 A patch is as follows: ```diff diff --git a/numeric.c b/numeric.c index 1858113c09..511155a3ac 100644 --- a/numeric.c +++ b/numeric.c @@ -3209,6 +3209,45 @@ int_even_p(VALUE num) return Qfalse; } +/* + * call-seq: + * int.allbits?(mask) -> true or false + * + * Returns +true+ if all bits of +int+ & +mask+ is 1. + */ + +static VALUE +int_allbits_p(VALUE num, VALUE mask) +{ + return rb_int_equal(rb_int_and(num, mask), mask); +} + +/* + * call-seq: + * int.anybits?(mask) -> true or false + * + * Returns +true+ if any bits of +int+ & +mask+ is 1. + */ + +static VALUE +int_anybits_p(VALUE num, VALUE mask) +{ + return num_zero_p(rb_int_and(num, mask)) ? Qfalse : Qtrue; +} + +/* + * call-seq: + * int.nobits?(mask) -> true or false + * + * Returns +true+ if no bits of +int+ & +mask+ is 1. + */ + +static VALUE +int_nobits_p(VALUE num, VALUE mask) +{ + return num_zero_p(rb_int_and(num, mask)); +} + /* * Document-method: Integer#succ * Document-method: Integer#next @@ -5396,6 +5435,9 @@ Init_Numeric(void) rb_define_method(rb_cInteger, "integer?", int_int_p, 0); rb_define_method(rb_cInteger, "odd?", int_odd_p, 0); rb_define_method(rb_cInteger, "even?", int_even_p, 0); + rb_define_method(rb_cInteger, "allbits?", int_allbits_p, 1); + rb_define_method(rb_cInteger, "anybits?", int_anybits_p, 1); + rb_define_method(rb_cInteger, "nobits?", int_nobits_p, 1); rb_define_method(rb_cInteger, "upto", int_upto, 1); rb_define_method(rb_cInteger, "downto", int_downto, 1); rb_define_method(rb_cInteger, "times", int_dotimes, 0); diff --git a/test/ruby/test_integer_comb.rb b/test/ruby/test_integer_comb.rb index 80d08cac04..1ad13dd31b 100644 --- a/test/ruby/test_integer_comb.rb +++ b/test/ruby/test_integer_comb.rb @@ -457,6 +457,30 @@ def test_even_odd } end + def test_allbits_p + VS.each {|a| + VS.each {|b| + assert_equal((a & b) == b, a.allbits?(b), "(#{a}).allbits?(#{b}") + } + } + end + + def test_anybits_p + VS.each {|a| + VS.each {|b| + assert_equal((a & b) != 0, a.anybits?(b), "(#{a}).anybits?(#{b}") + } + } + end + + def test_nobits_p + VS.each {|a| + VS.each {|b| + assert_equal((a & b) == 0, a.nobits?(b), "(#{a}).nobits?(#{b}") + } + } + end + def test_to_s 2.upto(36) {|radix| VS.each {|a| ``` ---------------------------------------- Feature #12753: Useful operator to check bit-flag is true or false https://bugs.ruby-lang.org/issues/12753#change-68117 * Author: tagomoris (Satoshi TAGOMORI) * Status: Assigned * Priority: Normal * Assignee: matz (Yukihiro Matsumoto) * Target version: 2.5 ---------------------------------------- Ruby's 0 is truthy value. It's useful for many cases, but it's confusing and I made many bugs when I'm writing code to handle binary data, because my thought is almost same with one to write C code in such situation. ```ruby n = get_integer_value if n & 0b10100000 # code for the case when flag is true else # never comes here :( end ``` IMO it's very useful to have methods for such use-cases, like `#and?` and `#xor?` (`#or?` looks not so useful... I can't imagine the use case of this operator, but it's better to have for consistency). ```ruby n = get_integer_value case when n.and?(0b10000000) # negative signed char when n.and?(0b01110000) # large positive else # small positive end ``` -- https://bugs.ruby-lang.org/ Unsubscribe: