summaryrefslogtreecommitdiffhomepage
path: root/mrbgems
diff options
context:
space:
mode:
authorJun Hiroe <[email protected]>2014-05-19 16:02:44 +0900
committerJun Hiroe <[email protected]>2014-05-19 16:17:10 +0900
commit4b3ff090ab393d5cbe027d05039667751a07bca6 (patch)
tree6d47410c59b4fff1bdeedc8c9e499c7e2948df6a /mrbgems
parent67c5d554a359ad602910c2062b37e109db032d3d (diff)
downloadmruby-4b3ff090ab393d5cbe027d05039667751a07bca6.tar.gz
mruby-4b3ff090ab393d5cbe027d05039667751a07bca6.zip
Add Range#size
Diffstat (limited to 'mrbgems')
-rw-r--r--mrbgems/mruby-range-ext/src/range.c40
-rw-r--r--mrbgems/mruby-range-ext/test/range.rb9
2 files changed, 49 insertions, 0 deletions
diff --git a/mrbgems/mruby-range-ext/src/range.c b/mrbgems/mruby-range-ext/src/range.c
index 9fbfd431f..93393e487 100644
--- a/mrbgems/mruby-range-ext/src/range.c
+++ b/mrbgems/mruby-range-ext/src/range.c
@@ -121,6 +121,45 @@ mrb_range_last(mrb_state *mrb, mrb_value range)
return mrb_funcall(mrb, array, "last", 1, mrb_to_int(mrb, num));
}
+/*
+ * call-seq:
+ * rng.size -> num
+ *
+ * Returns the number of elements in the range. Both the begin and the end of
+ * the Range must be Numeric, otherwise nil is returned.
+ *
+ * (10..20).size #=> 11
+ * ('a'..'z').size #=> nil
+ */
+
+static mrb_value
+mrb_range_size(mrb_state *mrb, mrb_value range)
+{
+ struct RRange *r = mrb_range_ptr(range);
+ mrb_value beg, end, end_f;
+ mrb_bool dec = TRUE;
+
+ beg = r->edges->beg;
+ end = r->edges->end;
+ if (mrb_obj_is_kind_of(mrb, beg, mrb->float_class)) {
+ beg = mrb_funcall(mrb, beg, "to_i", 0);
+ }
+ if (mrb_obj_is_kind_of(mrb, end, mrb->float_class)) {
+ end_f = end;
+ end = mrb_funcall(mrb, end, "to_i", 0);
+ if (r->excl && mrb_obj_eq(mrb, mrb_funcall(mrb, end_f, "==", 1, end), mrb_false_value())) {
+ dec = FALSE;
+ }
+ }
+ if (mrb_obj_is_kind_of(mrb, beg, mrb->fixnum_class) &&
+ mrb_obj_is_kind_of(mrb, end, mrb->fixnum_class)) {
+ mrb_int end_i = mrb_fixnum(end);
+ if (r->excl && dec) end_i--;
+ return mrb_fixnum_value(end_i - mrb_fixnum(beg) + 1);
+ }
+ return mrb_nil_value();
+}
+
void
mrb_mruby_range_ext_gem_init(mrb_state* mrb)
{
@@ -129,6 +168,7 @@ mrb_mruby_range_ext_gem_init(mrb_state* mrb)
mrb_define_method(mrb, s, "cover?", mrb_range_cover, MRB_ARGS_REQ(1));
mrb_define_method(mrb, s, "first", mrb_range_first, MRB_ARGS_OPT(1));
mrb_define_method(mrb, s, "last", mrb_range_last, MRB_ARGS_OPT(1));
+ mrb_define_method(mrb, s, "size", mrb_range_size, MRB_ARGS_NONE());
}
void
diff --git a/mrbgems/mruby-range-ext/test/range.rb b/mrbgems/mruby-range-ext/test/range.rb
index 2a170a66a..18e7dafe4 100644
--- a/mrbgems/mruby-range-ext/test/range.rb
+++ b/mrbgems/mruby-range-ext/test/range.rb
@@ -18,3 +18,12 @@ assert('Range#last') do
assert_equal [18, 19, 20], (10..20).last(3)
assert_equal [17, 18, 19], (10...20).last(3)
end
+
+assert('Range#size') do
+ assert_equal 42, (1..42).size
+ assert_equal 41, (1...42).size
+ assert_equal 6, (1...6.3).size
+ assert_equal 5, (1...6.0).size
+ assert_equal 5, (1.1...6).size
+ assert_nil ('a'..'z').size
+end