diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-05-14 08:39:14 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-05-14 08:39:14 +0900 |
| commit | 364f275997a8deb2972b452f38b7155f21df4e92 (patch) | |
| tree | 5b2a42ef196c9dbc7644824908e42747ff74a04a /src | |
| parent | 99f0adc3f47d9994a0bc783d9249fb5cf9ac2bb4 (diff) | |
| download | mruby-364f275997a8deb2972b452f38b7155f21df4e92.tar.gz mruby-364f275997a8deb2972b452f38b7155f21df4e92.zip | |
range.c: implement (part of) `Range#to_a` in C.
Mostly for performance reason.
Diffstat (limited to 'src')
| -rw-r--r-- | src/range.c | 50 |
1 files changed, 50 insertions, 0 deletions
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<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()); } |
