mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
range.c: implement (part of) Range#to_a in C.
Mostly for performance reason.
This commit is contained in:
+11
-1
@@ -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
|
||||
|
||||
+50
@@ -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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user