summaryrefslogtreecommitdiff
path: root/array.c
diff options
context:
space:
mode:
author卜部昌平 <shyouhei@ruby-lang.org>2020-06-11 11:45:03 +0900
committer卜部昌平 <shyouhei@ruby-lang.org>2020-06-29 11:05:41 +0900
commit4f2425549a870d8c42ff26812aa53ab93bba5bc8 (patch)
tree52066939a9904d85b31d72ad58963d2e54271b3e /array.c
parent73f98d25ebe5ec83865f3d9b7d1dbe9540f5c62b (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.c60
1 files changed, 38 insertions, 22 deletions
diff --git a/array.c b/array.c
index 5bc2eb73bf..5e27926bfb 100644
--- a/array.c
+++ b/array.c
@@ -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;