summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-range-ext/src/range.c
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/mruby-range-ext/src/range.c')
-rw-r--r--mrbgems/mruby-range-ext/src/range.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/mrbgems/mruby-range-ext/src/range.c b/mrbgems/mruby-range-ext/src/range.c
index 9fbfd431f..35632ad20 100644
--- a/mrbgems/mruby-range-ext/src/range.c
+++ b/mrbgems/mruby-range-ext/src/range.c
@@ -1,5 +1,6 @@
#include "mruby.h"
#include "mruby/range.h"
+#include <math.h>
static mrb_bool
r_le(mrb_state *mrb, mrb_value a, mrb_value b)
@@ -121,6 +122,58 @@ 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;
+ double beg_f, end_f;
+ mrb_bool num_p = TRUE;
+
+ beg = r->edges->beg;
+ end = r->edges->end;
+ if (mrb_fixnum_p(beg)) {
+ beg_f = (double)mrb_fixnum(beg);
+ }
+ else if (mrb_float_p(beg)) {
+ beg_f = mrb_float(beg);
+ }
+ else {
+ num_p = FALSE;
+ }
+ if (mrb_fixnum_p(end)) {
+ end_f = (double)mrb_fixnum(end);
+ }
+ else if (mrb_float_p(end)) {
+ end_f = mrb_float(end);
+ }
+ else {
+ num_p = FALSE;
+ }
+ if (num_p) {
+ double f;
+
+ if (beg_f > end_f) return mrb_fixnum_value(0);
+ f = end_f - beg_f;
+ if (!r->excl) {
+ return mrb_fixnum_value((mrb_int)ceil(f + 1));
+ }
+ return mrb_fixnum_value((mrb_int)ceil(f));
+ }
+ return mrb_nil_value();
+}
+
void
mrb_mruby_range_ext_gem_init(mrb_state* mrb)
{
@@ -129,6 +182,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