summaryrefslogtreecommitdiffstats
path: root/range.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-04-06 17:11:50 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-04-06 17:11:50 +0000
commit5dbd12698fde521dbf79216d4c3ea25d767ffd3f (patch)
tree89f1305b01dd6a98f5db131b1a235dcd767bd4ad /range.c
parent7f38f071de1d061b480c6fbea18547572f517489 (diff)
downloadruby-5dbd12698fde521dbf79216d4c3ea25d767ffd3f.tar.gz
ruby-5dbd12698fde521dbf79216d4c3ea25d767ffd3f.tar.xz
ruby-5dbd12698fde521dbf79216d4c3ea25d767ffd3f.zip
* bignum.c (rb_cmpint): moved from compar.c, to check bignum
zero. * range.c (range_step): add step for each iteration if begin and end are numeric. [ruby-core:15990] git-svn-id: http://svn.ruby-lang.org/repos/ruby/trunk@15911 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'range.c')
-rw-r--r--range.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/range.c b/range.c
index be6b3e52b..078219e18 100644
--- a/range.c
+++ b/range.c
@@ -223,10 +223,12 @@ range_hash(VALUE range)
}
static void
-range_each_func(VALUE range, VALUE (*func) (VALUE, void *), VALUE v, VALUE e,
- void *arg)
+range_each_func(VALUE range, VALUE (*func) (VALUE, void *), void *arg)
{
int c;
+ VALUE b = RANGE_BEG(range);
+ VALUE e = RANGE_END(range);
+ VALUE v;
if (EXCL(range)) {
while (r_lt(v, e)) {
@@ -267,7 +269,7 @@ step_i(VALUE i, void *arg)
* rng.step(n=1) {| obj | block } => rng
*
* Iterates over <i>rng</i>, passing each <i>n</i>th element to the block. If
- * the range contains numbers or strings, natural ordering is used. Otherwise
+ * the range contains numbers, <i>n</i> is added for each iteration. Otherwise
* <code>step</code> invokes <code>succ</code> to iterate through range
* elements. The following code uses class <code>Xs</code>, which is defined
* in the class-level documentation.
@@ -293,8 +295,9 @@ step_i(VALUE i, void *arg)
static VALUE
range_step(int argc, VALUE *argv, VALUE range)
{
- VALUE b, e, step;
+ VALUE b, e, step, tmp, c;
long unit;
+ int nv;
RETURN_ENUMERATOR(range, argc, argv);
@@ -312,14 +315,15 @@ range_step(int argc, VALUE *argv, VALUE range)
else {
VALUE tmp = rb_to_int(step);
unit = rb_cmpint(tmp, step, INT2FIX(0));
- step = tmp;
}
}
if (unit < 0) {
rb_raise(rb_eArgError, "step can't be negative");
}
- if (unit == 0)
+ if (unit == 0) {
rb_raise(rb_eArgError, "step can't be 0");
+ }
+
if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */
long end = FIX2LONG(e);
long i;
@@ -332,9 +336,20 @@ range_step(int argc, VALUE *argv, VALUE range)
if (i + unit < i) break;
i += unit;
}
+
+ }
+ else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
+ !NIL_P(rb_check_to_integer(b, "to_int")) ||
+ !NIL_P(rb_check_to_integer(e, "to_int"))) {
+ ID op = EXCL(range) ? '<' : rb_intern("<=");
+
+ while (RTEST(rb_funcall(b, op, 1, e))) {
+ rb_yield(b);
+ b = rb_funcall(b, '+', 1, step);
+ }
}
else {
- VALUE tmp = rb_check_string_type(b);
+ tmp = rb_check_string_type(b);
if (!NIL_P(tmp)) {
VALUE args[2], iter[2];
@@ -365,7 +380,7 @@ range_step(int argc, VALUE *argv, VALUE range)
}
args[0] = INT2FIX(1);
args[1] = step;
- range_each_func(range, step_i, b, e, args);
+ range_each_func(range, step_i, args);
}
}
return range;
@@ -428,7 +443,7 @@ range_each(VALUE range)
rb_block_call(beg, rb_intern("upto"), 2, args, rb_yield, 0);
}
else {
- range_each_func(range, each_i, beg, end, NULL);
+ range_each_func(range, each_i, NULL);
}
return range;
}