diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-02-15 10:00:57 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-02-15 10:00:57 +0000 |
commit | 41e9e19bc6544563e8a5eca3d4d8a7c6df0944e1 (patch) | |
tree | 1da0967e3a430a50d07ddc0aa66fdba6bc2696f5 /array.c | |
parent | 9a9a4e874d2257fcdb6fba0be5fa6fb3c402076d (diff) | |
download | ruby-41e9e19bc6544563e8a5eca3d4d8a7c6df0944e1.tar.gz |
Array#values_at optimization
* array.c (rb_ary_values_at): optimization range argument case.
bulk concatenation than pushing for each element.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62413 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'array.c')
-rw-r--r-- | array.c | 36 |
1 files changed, 35 insertions, 1 deletions
@@ -2804,6 +2804,34 @@ rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func return result; } +static VALUE +append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx) +{ + long beg, len; + if (FIXNUM_P(idx)) { + beg = FIX2LONG(idx); + } + /* check if idx is Range */ + else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) { + if (len > 0) { + const VALUE *const src = RARRAY_CONST_PTR(ary); + const long end = beg + len; + const long prevlen = RARRAY_LEN(result); + if (beg < olen) { + rb_ary_cat(result, src + beg, end > olen ? olen-beg : len); + } + if (end > olen) { + rb_ary_store(result, prevlen + len - 1, Qnil); + } + } + return result; + } + else { + beg = NUM2LONG(idx); + } + return rb_ary_push(result, rb_ary_entry(ary, beg)); +} + /* * call-seq: * ary.values_at(selector, ...) -> new_ary @@ -2825,7 +2853,13 @@ rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func static VALUE rb_ary_values_at(int argc, VALUE *argv, VALUE ary) { - return rb_get_values_at(ary, RARRAY_LEN(ary), argc, argv, rb_ary_entry); + long i, olen = RARRAY_LEN(ary); + VALUE result = rb_ary_new_capa(argc); + for (i = 0; i < argc; ++i) { + append_values_at_single(result, ary, olen, argv[i]); + } + RB_GC_GUARD(ary); + return result; } |