From 727ae9a4f521251b7273a0edf4e4970960bbee27 Mon Sep 17 00:00:00 2001 From: nobu Date: Wed, 5 Dec 2007 06:15:23 +0000 Subject: * 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 --- range.c | 47 ++++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) (limited to 'range.c') 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); } } -- cgit v1.2.3