diff options
author | 卜部昌平 <shyouhei@ruby-lang.org> | 2020-06-11 11:45:03 +0900 |
---|---|---|
committer | 卜部昌平 <shyouhei@ruby-lang.org> | 2020-06-29 11:05:41 +0900 |
commit | 4f2425549a870d8c42ff26812aa53ab93bba5bc8 (patch) | |
tree | 52066939a9904d85b31d72ad58963d2e54271b3e /array.c | |
parent | 73f98d25ebe5ec83865f3d9b7d1dbe9540f5c62b (diff) |
rb_ary_slice_bang: do not goto into a branch
I'm not necessarily against every goto in general, but jumping into a
branch is definitely a bad idea. Better refactor.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/3247
Diffstat (limited to 'array.c')
-rw-r--r-- | array.c | 60 |
1 files changed, 38 insertions, 22 deletions
@@ -4407,6 +4407,37 @@ rb_ary_delete_at_m(VALUE ary, VALUE pos) return rb_ary_delete_at(ary, NUM2LONG(pos)); } +static VALUE +ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len) +{ + const long orig_len = RARRAY_LEN(ary); + + if (len < 0) { + return Qnil; + } + else if (pos < -orig_len) { + return Qnil; + } + else if (pos < 0) { + pos += orig_len; + } + else if (orig_len < pos) { + return Qnil; + } + else if (orig_len < pos + len) { + len = orig_len - pos; + } + if (len == 0) { + return rb_ary_new2(0); + } + else { + VALUE arg2 = rb_ary_new4(len, RARRAY_CONST_PTR_TRANSIENT(ary)+pos); + RBASIC_SET_CLASS(arg2, rb_obj_class(ary)); + rb_ary_splice(ary, pos, len, 0, 0); + return arg2; + } +} + /* * call-seq: * ary.slice!(index) -> obj or nil @@ -4431,39 +4462,24 @@ rb_ary_delete_at_m(VALUE ary, VALUE pos) static VALUE rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary) { - VALUE arg1, arg2; - long pos, len, orig_len; + VALUE arg1; + long pos, len; rb_ary_modify_check(ary); + rb_check_arity(argc, 1, 2); + arg1 = argv[0]; + if (argc == 2) { pos = NUM2LONG(argv[0]); len = NUM2LONG(argv[1]); - delete_pos_len: - if (len < 0) return Qnil; - orig_len = RARRAY_LEN(ary); - if (pos < 0) { - pos += orig_len; - if (pos < 0) return Qnil; - } - else if (orig_len < pos) return Qnil; - if (orig_len < pos + len) { - len = orig_len - pos; - } - if (len == 0) return rb_ary_new2(0); - arg2 = rb_ary_new4(len, RARRAY_CONST_PTR_TRANSIENT(ary)+pos); - RBASIC_SET_CLASS(arg2, rb_obj_class(ary)); - rb_ary_splice(ary, pos, len, 0, 0); - return arg2; + return ary_slice_bang_by_rb_ary_splice(ary, pos, len); } - rb_check_arity(argc, 1, 2); - arg1 = argv[0]; - if (!FIXNUM_P(arg1)) { switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) { case Qtrue: /* valid range */ - goto delete_pos_len; + return ary_slice_bang_by_rb_ary_splice(ary, pos, len); case Qnil: /* invalid range */ return Qnil; |