Project

General

Profile

Feature #14473 » 0001-range.c-add-subset-superset-methods.patch

owst (Owen Stephens), 02/22/2018 06:10 PM

View differences:

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] }
(1-1/6)