summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-range-ext
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/mruby-range-ext')
-rw-r--r--mrbgems/mruby-range-ext/mrblib/range.rb16
-rw-r--r--mrbgems/mruby-range-ext/src/range.c16
-rw-r--r--mrbgems/mruby-range-ext/test/range.rb29
3 files changed, 53 insertions, 8 deletions
diff --git a/mrbgems/mruby-range-ext/mrblib/range.rb b/mrbgems/mruby-range-ext/mrblib/range.rb
index a213beb57..8b0969003 100644
--- a/mrbgems/mruby-range-ext/mrblib/range.rb
+++ b/mrbgems/mruby-range-ext/mrblib/range.rb
@@ -27,10 +27,12 @@ class Range
end
def max(&block)
- val = self.first
- last = self.last
+ val = self.begin
+ last = self.end
return super if block
+ raise RangeError, "cannot get the maximum of endless range" if last.nil?
+
# fast path for numerics
if val.kind_of?(Numeric) && last.kind_of?(Numeric)
raise TypeError if exclude_end? && !last.kind_of?(Fixnum)
@@ -47,9 +49,13 @@ class Range
end
def min(&block)
- val = self.first
- last = self.last
- return super if block
+ val = self.begin
+ last = self.end
+ if block
+ raise RangeError, "cannot get the minimum of endless range with custom comparison method" if last.nil?
+ return super
+ end
+ return val if last.nil?
# fast path for numerics
if val.kind_of?(Numeric) && last.kind_of?(Numeric)
diff --git a/mrbgems/mruby-range-ext/src/range.c b/mrbgems/mruby-range-ext/src/range.c
index 2a0b4e97d..c263b484b 100644
--- a/mrbgems/mruby-range-ext/src/range.c
+++ b/mrbgems/mruby-range-ext/src/range.c
@@ -42,6 +42,9 @@ range_cover(mrb_state *mrb, mrb_value range)
end = RANGE_END(r);
if (r_le(mrb, beg, val)) {
+ if (mrb_nil_p(end)) {
+ return mrb_true_value();
+ }
if (RANGE_EXCL(r)) {
if (r_lt(mrb, val, end))
return mrb_true_value();
@@ -76,6 +79,11 @@ range_last(mrb_state *mrb, mrb_value range)
{
mrb_value num;
mrb_value array;
+ struct RRange *r = mrb_range_ptr(mrb, range);
+
+ if (mrb_nil_p(RANGE_END(r))) {
+ mrb_raise(mrb, E_RANGE_ERROR, "cannot get the last element of endless range");
+ }
if (mrb_get_args(mrb, "|o", &num) == 0) {
return mrb_range_end(mrb, range);
@@ -108,6 +116,10 @@ range_size(mrb_state *mrb, mrb_value range)
beg = RANGE_BEG(r);
end = RANGE_END(r);
+ if ((mrb_fixnum_p(beg) || mrb_float_p(beg)) && mrb_nil_p(end)) {
+ return mrb_float_value(mrb, INFINITY);
+ }
+
excl = RANGE_EXCL(r);
if (mrb_fixnum_p(beg)) {
beg_f = (mrb_float)mrb_fixnum(beg);
@@ -159,6 +171,10 @@ range_size(mrb_state *mrb, mrb_value range)
beg = RANGE_BEG(r);
end = RANGE_END(r);
+ if (mrb_fixnum_p(beg) && mrb_nil_p(end)) {
+ return mrb_nil_value();
+ }
+
excl = RANGE_EXCL(r) ? 0 : 1;
if (mrb_fixnum_p(beg) && mrb_fixnum_p(end)) {
diff --git a/mrbgems/mruby-range-ext/test/range.rb b/mrbgems/mruby-range-ext/test/range.rb
index 865e46d02..169ba7169 100644
--- a/mrbgems/mruby-range-ext/test/range.rb
+++ b/mrbgems/mruby-range-ext/test/range.rb
@@ -5,11 +5,16 @@ assert('Range#cover?') do
assert_true ("a".."z").cover?("c")
assert_true !("a".."z").cover?("5")
assert_true ("a".."z").cover?("cc")
+ assert_true ("a"..).cover?("c")
+ assert_false ("a"..).cover?("5")
+ assert_true ("a"..).cover?("cc")
end
assert('Range#first') do
assert_equal 10, (10..20).first
assert_equal [10, 11, 12], (10..20).first(3)
+ assert_equal 10, (10..).first
+ assert_equal [10, 11, 12], (10..).first(3)
skip unless Object.const_defined?(:Float)
assert_equal [0, 1, 2], (0..Float::INFINITY).first(3)
@@ -18,6 +23,8 @@ end
assert('Range#last') do
assert_equal 20, (10..20).last
assert_equal 20, (10...20).last
+ assert_raise(RangeError) { (10..).last }
+ assert_raise(RangeError) { (10...).last }
assert_equal [18, 19, 20], (10..20).last(3)
assert_equal [17, 18, 19], (10...20).last(3)
end
@@ -26,6 +33,9 @@ assert('Range#size') do
assert_equal 42, (1..42).size
assert_equal 41, (1...42).size
assert_nil ('a'..'z').size
+ assert_nil ('a'..).size
+
+ assert_nil (1..).size unless Object.const_defined?(:Float)
skip unless Object.const_defined?(:Float)
assert_equal 6, (1...6.3).size
@@ -33,6 +43,10 @@ assert('Range#size') do
assert_equal 5, (1.1...6).size
assert_equal 15, (1.0..15.9).size
assert_equal Float::INFINITY, (0..Float::INFINITY).size
+
+ assert_equal Float::INFINITY, (1..).size
+ assert_equal Float::INFINITY, (1...).size
+ assert_equal Float::INFINITY, (1.0..).size
end
assert('Range#max') do
@@ -50,6 +64,10 @@ assert('Range#max') do
# returns the endpoint when the endpoint equals the start point and the range is inclusive
assert_equal 5, (5..5).max
+ # raises RangeError when called on an endless range
+ assert_raise(RangeError) { (10..).max }
+ assert_raise(RangeError) { (10...).max }
+
skip unless Object.const_defined?(:Float)
# returns the maximum value in the Float range when called with no arguments
@@ -94,26 +112,31 @@ assert('Range#min') do
# returns the minimum value in the range when called with no arguments
assert_equal 1, (1..10).min
assert_equal 1, (1...10).min
+ assert_equal 1, (1..).min
# returns nil when the start point is greater than the endpoint
assert_equal nil, (100..10).min
# returns nil when the endpoint equals the start point and the range is exclusive
- assert_equal nil, (5...5).max
+ assert_equal nil, (5...5).min
# returns the endpoint when the endpoint equals the start point and the range is inclusive
- assert_equal 5, (5..5).max
+ assert_equal 5, (5..5).min
skip unless Object.const_defined?(:Float)
# returns the minimum value in the Float range when called with no arguments
assert_equal 303.20, (303.20..908.1111).min
+ assert_equal 1, (1.0..).min
# returns nil when the start point is greater than the endpoint in a Float range
- assert_equal nil, (3003.20..908.1111).max
+ assert_equal nil, (3003.20..908.1111).min
end
assert('Range#min given a block') do
+ # raise when called with a block in endless range
+ assert_raise(RangeError) { (1..).min{} }
+
# passes each pair of values in the range to the block
acc = []
(1..10).min do |a, b|