summaryrefslogtreecommitdiff
path: root/enumerator.c
diff options
context:
space:
mode:
authorKenta Murata <mrkn@users.noreply.github.com>2020-10-21 02:40:18 +0900
committerGitHub <noreply@github.com>2020-10-21 02:40:18 +0900
commita6a8576e877b02b83cabd0e712ecd377e7bc156b (patch)
tree3802e57e38cb467462d19dd266dc4e848d428cc6 /enumerator.c
parent081cc4eb283cb01ddffb364397e5175dbfacab66 (diff)
Feature #16812: Allow slicing arrays with ArithmeticSequence (#3241)
* Support ArithmeticSequence in Array#slice * Extract rb_range_component_beg_len * Use rb_range_values to check Range object * Fix ary_make_partial_step * Fix for negative step cases * range.c: Describe the role of err argument in rb_range_component_beg_len * Raise a RangeError when an arithmetic sequence refers the outside of an array [Feature #16812]
Notes
Notes: Merged-By: mrkn <mrkn@ruby-lang.org>
Diffstat (limited to 'enumerator.c')
-rw-r--r--enumerator.c44
1 files changed, 40 insertions, 4 deletions
diff --git a/enumerator.c b/enumerator.c
index 3ea308a7cd..6e88c5db4a 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -3410,17 +3410,53 @@ rb_arithmetic_sequence_extract(VALUE obj, rb_arithmetic_sequence_components_t *c
component->exclude_end = arith_seq_exclude_end_p(obj);
return 1;
}
- else if (rb_obj_is_kind_of(obj, rb_cRange)) {
- component->begin = RANGE_BEG(obj);
- component->end = RANGE_END(obj);
+ else if (rb_range_values(obj, &component->begin, &component->end, &component->exclude_end)) {
component->step = INT2FIX(1);
- component->exclude_end = RTEST(RANGE_EXCL(obj));
return 1;
}
return 0;
}
+VALUE
+rb_arithmetic_sequence_beg_len_step(VALUE obj, long *begp, long *lenp, long *stepp, long len, int err)
+{
+ RUBY_ASSERT(begp != NULL);
+ RUBY_ASSERT(lenp != NULL);
+ RUBY_ASSERT(stepp != NULL);
+
+ rb_arithmetic_sequence_components_t aseq;
+ if (!rb_arithmetic_sequence_extract(obj, &aseq)) {
+ return Qfalse;
+ }
+
+ long step = NIL_P(aseq.step) ? 1 : NUM2LONG(aseq.step);
+ *stepp = step;
+
+ if (step < 0) {
+ VALUE tmp = aseq.begin;
+ aseq.begin = aseq.end;
+ aseq.end = tmp;
+ }
+
+ if (err == 0 && (step < -1 || step > 1)) {
+ if (rb_range_component_beg_len(aseq.begin, aseq.end, aseq.exclude_end, begp, lenp, len, 1) == Qtrue) {
+ if (*begp > len)
+ goto out_of_range;
+ if (*lenp > len)
+ goto out_of_range;
+ return Qtrue;
+ }
+ }
+ else {
+ return rb_range_component_beg_len(aseq.begin, aseq.end, aseq.exclude_end, begp, lenp, len, err);
+ }
+
+ out_of_range:
+ rb_raise(rb_eRangeError, "%+"PRIsVALUE" out of range", obj);
+ return Qnil;
+}
+
/*
* call-seq:
* aseq.first -> num or nil