summaryrefslogtreecommitdiff
path: root/range.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-12-05 06:15:23 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-12-05 06:15:23 +0000
commit727ae9a4f521251b7273a0edf4e4970960bbee27 (patch)
treebff600b4954a96bf7422fb17b043e37aacd6b55e /range.c
parent786a92feb034a20aa02076a8b81168d1d119d9d5 (diff)
* range.c (step_i, range_step): support non-fixnum steps.
[ruby-talk:282100] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@14107 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'range.c')
-rw-r--r--range.c47
1 files changed, 30 insertions, 17 deletions
diff --git a/range.c b/range.c
index 568b24d4b8..ee36057fef 100644
--- a/range.c
+++ b/range.c
@@ -254,12 +254,20 @@ range_each_func(range, func, v, e, arg)
}
static VALUE
-step_i(i, iter)
+step_i(i, arg)
VALUE i;
- long *iter;
+ VALUE arg;
{
- iter[0]--;
- if (iter[0] == 0) {
+ VALUE *iter = (VALUE *)arg;
+
+ if (FIXNUM_P(iter[0])) {
+ iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG;
+ }
+ else {
+ VALUE one = INT2FIX(1);
+ iter[0] = rb_funcall(iter[0], '-', 1, &one);
+ }
+ if (iter[0] == INT2FIX(0)) {
rb_yield(i);
iter[0] = iter[1];
}
@@ -307,13 +315,22 @@ range_step(argc, argv, range)
e = rb_ivar_get(range, id_end);
if (rb_scan_args(argc, argv, "01", &step) == 0) {
step = INT2FIX(1);
+ unit = 1;
+ }
+ else if (FIXNUM_P(step)) {
+ unit = NUM2LONG(step);
+ }
+ else {
+ VALUE tmp = rb_to_int(step);
+ unit = rb_cmpint(tmp, step, INT2FIX(0));
+ step = tmp;
}
-
- unit = NUM2LONG(step);
if (unit < 0) {
rb_raise(rb_eArgError, "step can't be negative");
- }
- if (FIXNUM_P(b) && FIXNUM_P(e)) { /* fixnums are special */
+ }
+ 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;
@@ -330,36 +347,32 @@ range_step(argc, argv, range)
VALUE tmp = rb_check_string_type(b);
if (!NIL_P(tmp)) {
- VALUE args[5];
- long iter[2];
+ VALUE args[5], iter[2];
b = tmp;
- if (unit == 0) rb_raise(rb_eArgError, "step can't be 0");
args[0] = b; args[1] = e; args[2] = range;
- iter[0] = 1; iter[1] = unit;
+ iter[0] = INT2FIX(1); iter[1] = step;
rb_iterate((VALUE(*)_((VALUE)))str_step, (VALUE)args, step_i,
(VALUE)iter);
}
else if (rb_obj_is_kind_of(b, rb_cNumeric)) {
ID c = rb_intern(EXCL(range) ? "<" : "<=");
- if (rb_equal(step, INT2FIX(0))) rb_raise(rb_eArgError, "step can't be 0");
while (RTEST(rb_funcall(b, c, 1, e))) {
rb_yield(b);
b = rb_funcall(b, '+', 1, step);
}
}
else {
- long args[2];
+ VALUE args[2];
- if (unit == 0) rb_raise(rb_eArgError, "step can't be 0");
if (!rb_respond_to(b, id_succ)) {
rb_raise(rb_eTypeError, "can't iterate from %s",
rb_obj_classname(b));
}
- args[0] = 1;
- args[1] = unit;
+ args[0] = INT2FIX(1);
+ args[1] = step;
range_each_func(range, step_i, b, e, args);
}
}