summaryrefslogtreecommitdiff
path: root/range.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-10-18 06:58:35 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-10-18 06:58:35 +0000
commitfada885be6a030cc91d297f83c7a2a35a6f5206a (patch)
tree0ab00b29111ee1cd6dc6f5f380e4d9cf28ccf448 /range.c
parentae7ea35916567109103a7b585272f107e15ad8ad (diff)
* range.c (range_first): takes first n element if argument is
given. [ruby-core:12697] * range.c (range_last): returns last n elements if argument is given. * array.c (rb_ary_subseq, rb_ary_last): export. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13736 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'range.c')
-rw-r--r--range.c72
1 files changed, 65 insertions, 7 deletions
diff --git a/range.c b/range.c
index 4823391d3b..ee0dc5e52f 100644
--- a/range.c
+++ b/range.c
@@ -437,14 +437,13 @@ range_each(VALUE range)
/*
* call-seq:
- * rng.first => obj
* rng.begin => obj
*
* Returns the first object in <i>rng</i>.
*/
static VALUE
-range_first(VALUE range)
+range_begin(VALUE range)
{
return RANGE_BEG(range);
}
@@ -453,7 +452,6 @@ range_first(VALUE range)
/*
* call-seq:
* rng.end => obj
- * rng.last => obj
*
* Returns the object that defines the end of <i>rng</i>.
*
@@ -463,11 +461,71 @@ range_first(VALUE range)
static VALUE
-range_last(VALUE range)
+range_end(VALUE range)
{
return RANGE_END(range);
}
+
+static VALUE
+first_i(VALUE i, VALUE *ary)
+{
+ long n = NUM2LONG(ary[0]);
+
+ if (n <= 0) {
+ rb_iter_break();
+ }
+ rb_ary_push(ary[1], i);
+ n--;
+ ary[0] = INT2NUM(n);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * rng.first => obj
+ * rng.first(n) => an_array
+ *
+ * Returns the first object in <i>rng</i>, or the first +n+ elements.
+ */
+
+static VALUE
+range_first(int argc, VALUE *argv, VALUE range)
+{
+ VALUE n, ary[2];
+
+ if (argc == 0) return RANGE_BEG(range);
+
+ rb_scan_args(argc, argv, "1", &n);
+ ary[0] = n;
+ ary[1] = rb_ary_new2(NUM2LONG(n));
+ rb_block_call(range, rb_intern("each"), 0, 0, first_i, (VALUE)ary);
+
+ return ary[1];
+}
+
+
+/*
+ * call-seq:
+ * rng.last => obj
+ * rng.last(n) => an_array
+ *
+ * Returns the last object in <i>rng</i>, or the last +n+ elements.
+ */
+
+static VALUE
+range_last(int argc, VALUE *argv, VALUE range)
+{
+ VALUE n, a;
+ long i, nelem, len;
+
+ if (argc == 0) return RANGE_END(range);
+
+ rb_scan_args(argc, argv, "1", &n);
+ return rb_ary_last(argc, argv, rb_Array(range));
+}
+
+
/*
* call-seq:
* rng.min => obj
@@ -858,10 +916,10 @@ Init_Range(void)
rb_define_method(rb_cRange, "hash", range_hash, 0);
rb_define_method(rb_cRange, "each", range_each, 0);
rb_define_method(rb_cRange, "step", range_step, -1);
- rb_define_method(rb_cRange, "first", range_first, 0);
- rb_define_method(rb_cRange, "last", range_last, 0);
- rb_define_method(rb_cRange, "begin", range_first, 0);
+ rb_define_method(rb_cRange, "begin", range_begin, 0);
rb_define_method(rb_cRange, "end", range_last, 0);
+ rb_define_method(rb_cRange, "first", range_first, -1);
+ rb_define_method(rb_cRange, "last", range_last, -1);
rb_define_method(rb_cRange, "min", range_min, 0);
rb_define_method(rb_cRange, "max", range_max, 0);
rb_define_method(rb_cRange, "to_s", range_to_s, 0);