Feature #14473 » v2-0001-range.c-add-subset-superset-methods.patch
range.c | ||
---|---|---|
#include <math.h>
|
||
VALUE rb_cRange;
|
||
static ID id_beg, id_end, id_excl, id_integer_p, id_div;
|
||
static ID id_beg, id_end, id_excl, id_integer_p, id_div, id_min, id_max;
|
||
#define id_cmp idCmp
|
||
#define id_succ idSucc
|
||
... | ... | |
return Qfalse;
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* rng.subset?(obj) -> true or false
|
||
* rng <= obj -> true or false
|
||
*
|
||
* Returns <code>true</code> if +obj+ is a Range and it includes the first and
|
||
* last elements of the range, <code>false</code> otherwise.
|
||
* Raises +TypeError+ if +obj+ is not a Range.
|
||
*
|
||
* ("b".."d").subset?("b".."e") #=> true
|
||
* ("b".."e").subset?("b".."e") #=> true
|
||
* ("a".."e").subset?("b".."e") #=> false
|
||
*/
|
||
static VALUE
|
||
range_subset(VALUE range, VALUE obj)
|
||
{
|
||
if (!rb_obj_is_kind_of(obj, rb_cRange))
|
||
rb_raise(rb_eTypeError, "not a range object");
|
||
VALUE min = rb_funcall(range, id_min, 0);
|
||
if (min == Qnil)
|
||
return Qtrue;
|
||
if (range_cover(obj, min) &&
|
||
range_cover(obj, rb_funcall(range, id_max, 0))) {
|
||
return Qtrue;
|
||
}
|
||
return Qfalse;
|
||
}
|
||
static VALUE
|
||
r_differ_at(VALUE range, VALUE obj, ID id)
|
||
{
|
||
return !rb_equal(rb_funcall(range, id, 0), rb_funcall(obj, id, 0));
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* rng.strict_subset?(obj) -> true or false
|
||
* rng < obj -> true or false
|
||
*
|
||
* Returns <code>true</code> if +obj+ is a Range and it includes the first and
|
||
* last elements of the range, but is not equal to the range,
|
||
* <code>false</code> otherwise.
|
||
* Raises +TypeError+ if +obj+ is not a Range.
|
||
*
|
||
* ("b".."d").strict_subset?("b".."e") #=> true
|
||
* ("b".."e").strict_subset?("b".."e") #=> false
|
||
* ("a".."e").strict_subset?("b".."e") #=> false
|
||
*/
|
||
static VALUE
|
||
range_strict_subset(VALUE range, VALUE obj)
|
||
{
|
||
if (range_subset(range, obj) &&
|
||
(r_differ_at(range, obj, id_min) || r_differ_at(range, obj, id_max))) {
|
||
return Qtrue;
|
||
}
|
||
return Qfalse;
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* rng.superset?(obj) -> true or false
|
||
* rng >= obj -> true or false
|
||
*
|
||
* Returns <code>true</code> if +obj+ is a Range, and its first and last
|
||
* elements are included in the range, <code>false</code> otherwise.
|
||
* Raises +TypeError+ if +obj+ is not a Range.
|
||
*
|
||
* ("b".."e").superset?("b".."d") #=> true
|
||
* ("b".."e").superset?("b".."e") #=> true
|
||
* ("b".."e").superset?("a".."e") #=> false
|
||
*/
|
||
static VALUE
|
||
range_superset(VALUE range, VALUE obj)
|
||
{
|
||
if (!rb_obj_is_kind_of(obj, rb_cRange))
|
||
rb_raise(rb_eTypeError, "not a range object");
|
||
return range_subset(obj, range);
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* rng.strict_superset?(obj) -> true or false
|
||
* rng > obj -> true or false
|
||
*
|
||
* Returns <code>true</code> if +obj+ is a Range, and its first and last
|
||
* elements are included in the range, but it is not equal to the range,
|
||
* <code>false</code> otherwise.
|
||
* Raises +TypeError+ if +obj+ is not a Range.
|
||
*
|
||
* ("b".."e").strict_superset?("b".."d") #=> true
|
||
* ("b".."e").strict_superset?("b".."e") #=> false
|
||
* ("b".."e").strict_superset?("a".."e") #=> false
|
||
*/
|
||
static VALUE
|
||
range_strict_superset(VALUE range, VALUE obj)
|
||
{
|
||
if (!rb_obj_is_kind_of(obj, rb_cRange))
|
||
rb_raise(rb_eTypeError, "not a range object");
|
||
return range_strict_subset(obj, range);
|
||
}
|
||
static VALUE
|
||
range_dumper(VALUE range)
|
||
{
|
||
... | ... | |
id_excl = rb_intern("excl");
|
||
id_integer_p = rb_intern("integer?");
|
||
id_div = rb_intern("div");
|
||
id_min = rb_intern("min");
|
||
id_max = rb_intern("max");
|
||
rb_cRange = rb_struct_define_without_accessor(
|
||
"Range", rb_cObject, range_alloc,
|
||
... | ... | |
rb_define_method(rb_cRange, "member?", range_include, 1);
|
||
rb_define_method(rb_cRange, "include?", range_include, 1);
|
||
rb_define_method(rb_cRange, "cover?", range_cover, 1);
|
||
rb_define_method(rb_cRange, "subset?", range_subset, 1);
|
||
rb_define_method(rb_cRange, "<=", range_subset, 1);
|
||
rb_define_method(rb_cRange, "strict_subset?", range_strict_subset, 1);
|
||
rb_define_method(rb_cRange, "<", range_strict_subset, 1);
|
||
rb_define_method(rb_cRange, "superset?", range_superset, 1);
|
||
rb_define_method(rb_cRange, ">=", range_superset, 1);
|
||
rb_define_method(rb_cRange, "strict_superset?", range_strict_superset, 1);
|
||
rb_define_method(rb_cRange, ">", range_strict_superset, 1);
|
||
}
|
test/ruby/test_range.rb | ||
---|---|---|
assert_operator("a".."z", :cover?, "cc")
|
||
end
|
||
def test_subset
|
||
[:subset?, :<=].each do |op|
|
||
assert_operator("b".."e", op, "b".."e")
|
||
assert_operator("b".."e", op, "b"..."f")
|
||
assert_operator("b"..."f", op, "b".."e")
|
||
assert_operator("b".."d", op, "b".."e")
|
||
assert_operator("c".."e", op, "b".."e")
|
||
assert_operator("c".."d", op, "b".."e")
|
||
assert_operator("g".."f", op, "b".."e")
|
||
assert_operator("c".."b", op, "d".."a")
|
||
assert_not_operator("a".."e", op, "b".."e")
|
||
assert_not_operator("a".."e", op, "b"..."f")
|
||
assert_not_operator("a"..."f", op, "b".."e")
|
||
assert_not_operator("b".."f", op, "b".."e")
|
||
assert_not_operator("a".."f", op, "b".."e")
|
||
assert_raise(TypeError) { ("a".."c").send(op, "x") }
|
||
end
|
||
end
|
||
def test_strict_subset
|
||
[:strict_subset?, :<].each do |op|
|
||
assert_operator("b".."d", op, "b".."e")
|
||
assert_operator("b".."d", op, "b"..."f")
|
||
assert_operator("b"..."e", op, "b".."e")
|
||
assert_operator("c".."e", op, "b".."e")
|
||
assert_operator("c".."d", op, "b".."e")
|
||
assert_operator("g".."f", op, "b".."e")
|
||
assert_not_operator("b".."e", op, "b".."e")
|
||
assert_not_operator("b".."e", op, "b"..."f")
|
||
assert_not_operator("b"..."f", op, "b".."e")
|
||
assert_not_operator("a".."e", op, "b".."e")
|
||
assert_not_operator("b".."f", op, "b".."e")
|
||
assert_not_operator("a".."f", op, "b".."e")
|
||
assert_not_operator("c".."b", op, "d".."a")
|
||
assert_raise(TypeError) { ("a".."c").send(op, "x") }
|
||
end
|
||
end
|
||
def test_superset
|
||
[:superset?, :>=].each do |op|
|
||
assert_operator("b".."e", op, "b".."e")
|
||
assert_operator("b".."e", op, "b"..."f")
|
||
assert_operator("b"..."f", op, "b".."e")
|
||
assert_operator("b".."e", op, "b".."d")
|
||
assert_operator("b".."e", op, "c".."e")
|
||
assert_operator("b".."e", op, "c".."d")
|
||
assert_operator("b".."e", op, "g".."f")
|
||
assert_operator("d".."a", op, "c".."b")
|
||
assert_not_operator("b".."e", op, "a".."e")
|
||
assert_not_operator("b".."e", op, "a"..."f")
|
||
assert_not_operator("b"..."f", op, "a".."e")
|
||
assert_not_operator("b".."e", op, "b".."f")
|
||
assert_not_operator("b".."e", op, "a".."f")
|
||
assert_not_operator("b".."e", op, "b".."f")
|
||
assert_not_operator("b".."e", op, "a".."f")
|
||
assert_raise(TypeError) { ("a".."c").send(op, "x") }
|
||
end
|
||
end
|
||
def test_strict_superset
|
||
[:strict_superset?, :>].each do |op|
|
||
assert_operator("b".."e", op, "b".."d")
|
||
assert_operator("b".."e", op, "b"..."e")
|
||
assert_operator("b"..."f", op, "b".."d")
|
||
assert_operator("b".."e", op, "c".."e")
|
||
assert_operator("b".."e", op, "c".."d")
|
||
assert_operator("b".."e", op, "g".."f")
|
||
assert_not_operator("b".."e", op, "b".."e")
|
||
assert_not_operator("b".."e", op, "b"..."f")
|
||
assert_not_operator("b"..."f", op, "b".."e")
|
||
assert_not_operator("b".."e", op, "a".."e")
|
||
assert_not_operator("b".."e", op, "b".."f")
|
||
assert_not_operator("b".."e", op, "a".."f")
|
||
assert_not_operator("d".."a", op, "c".."b")
|
||
assert_raise(TypeError) { ("a".."c").send(op, "x") }
|
||
end
|
||
end
|
||
def test_beg_len
|
||
o = Object.new
|
||
assert_raise(TypeError) { [][o] }
|