From 364f275997a8deb2972b452f38b7155f21df4e92 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 14 May 2021 08:39:14 +0900 Subject: range.c: implement (part of) `Range#to_a` in C. Mostly for performance reason. --- mrblib/range.rb | 12 +++++++++++- src/range.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/mrblib/range.rb b/mrblib/range.rb index fb217f771..f808053ca 100644 --- a/mrblib/range.rb +++ b/mrblib/range.rb @@ -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 diff --git a/src/range.c b/src/range.c index 3ef4b14f5..1615f03b2 100644 --- a/src/range.c +++ b/src/range.c @@ -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