range.c: implement (part of) `Range#to_a` in C.

Mostly for performance reason.
parent 99f0adc3
......@@ -79,8 +79,18 @@ class Range
h
end
##
# call-seq:
# rng.to_a -> array
# rng.entries -> array
#
# Returns an array containing the items in the range.
#
# (1..7).to_a #=> [1, 2, 3, 4, 5, 6, 7]
# (1..).to_a #=> RangeError: cannot convert endless range to an array
def to_a
raise RangeError, "cannot convert endless range to an array" if self.last.nil?
a = __num_to_a
return a if a
super
end
alias entries to_a
......
......@@ -342,6 +342,55 @@ range_initialize_copy(mrb_state *mrb, mrb_value copy)
return copy;
}
static mrb_value
range_num_to_a(mrb_state *mrb, mrb_value range)
{
struct RRange *r = mrb_range_ptr(mrb, range);
mrb_value beg = RANGE_BEG(r);
mrb_value end = RANGE_END(r);
mrb_value ary;
if (mrb_nil_p(end)) {
mrb_raise(mrb, E_RANGE_ERROR, "cannot convert endless range to an array");
}
if (mrb_integer_p(beg)) {
if (mrb_integer_p(end)) {
mrb_int a = mrb_integer(beg);
mrb_int b = mrb_integer(end);
mrb_int len = b - a;
if (!RANGE_EXCL(r)) len++;
ary = mrb_ary_new_capa(mrb, len);
for (mrb_int i=0; i<len; i++) {
mrb_ary_push(mrb, ary, mrb_int_value(mrb, a+i));
}
return ary;
}
#ifndef MRB_NO_FLOAT
if (mrb_float_p(end)) {
mrb_float a = (mrb_float)mrb_integer(beg);
mrb_float b = mrb_float(end);
ary = mrb_ary_new_capa(mrb, (mrb_int)(b - a) + 1);
if (RANGE_EXCL(r)) {
while (a < b) {
mrb_ary_push(mrb, ary, mrb_int_value(mrb, a));
a += 1.0;
}
}
else {
while (a <= b) {
mrb_ary_push(mrb, ary, mrb_int_value(mrb, a));
a += 1.0;
}
}
return ary;
}
#endif
}
return mrb_nil_value();
}
mrb_value
mrb_get_values_at(mrb_state *mrb, mrb_value obj, mrb_int olen, mrb_int argc, const mrb_value *argv, mrb_value (*func)(mrb_state*, mrb_value, mrb_int))
{
......@@ -456,4 +505,5 @@ mrb_init_range(mrb_state *mrb)
mrb_define_method(mrb, r, "inspect", range_inspect, MRB_ARGS_NONE()); /* 15.2.14.4.13(x) */
mrb_define_method(mrb, r, "eql?", range_eql, MRB_ARGS_REQ(1)); /* 15.2.14.4.14(x) */
mrb_define_method(mrb, r, "initialize_copy", range_initialize_copy, MRB_ARGS_REQ(1)); /* 15.2.14.4.15(x) */
mrb_define_method(mrb, r, "__num_to_a", range_num_to_a, MRB_ARGS_NONE());
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment