mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* enum.c (enum_each_slice): Support for Enumerable#each_slice.size
[Feature #6636] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37508 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
c82ad6d207
commit
df8451e606
2 changed files with 29 additions and 1 deletions
22
enum.c
22
enum.c
|
@ -18,8 +18,12 @@
|
||||||
#define STATIC_ASSERT(name, expr) typedef int static_assert_##name##_check[1 - 2*!(expr)]
|
#define STATIC_ASSERT(name, expr) typedef int static_assert_##name##_check[1 - 2*!(expr)]
|
||||||
|
|
||||||
VALUE rb_mEnumerable;
|
VALUE rb_mEnumerable;
|
||||||
|
|
||||||
static ID id_next;
|
static ID id_next;
|
||||||
|
static ID id_div;
|
||||||
static ID id_call;
|
static ID id_call;
|
||||||
|
static ID id_size;
|
||||||
|
|
||||||
#define id_each idEach
|
#define id_each idEach
|
||||||
#define id_eqq idEqq
|
#define id_eqq idEqq
|
||||||
#define id_cmp idCmp
|
#define id_cmp idCmp
|
||||||
|
@ -1778,6 +1782,20 @@ each_slice_i(VALUE i, VALUE m, int argc, VALUE *argv)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
enum_each_slice_size(VALUE obj, VALUE args)
|
||||||
|
{
|
||||||
|
VALUE n, size;
|
||||||
|
long slice_size = NUM2LONG(RARRAY_PTR(args)[0]);
|
||||||
|
if (slice_size <= 0) rb_raise(rb_eArgError, "invalid slice size");
|
||||||
|
|
||||||
|
size = enum_size(obj, 0);
|
||||||
|
if (size == Qnil) return Qnil;
|
||||||
|
|
||||||
|
n = rb_funcall(size, '+', 1, LONG2NUM(slice_size-1));
|
||||||
|
return rb_funcall(n, id_div, 1, LONG2FIX(slice_size));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* enum.each_slice(n) { ... } -> nil
|
* enum.each_slice(n) { ... } -> nil
|
||||||
|
@ -1802,7 +1820,7 @@ enum_each_slice(VALUE obj, VALUE n)
|
||||||
NODE *memo;
|
NODE *memo;
|
||||||
|
|
||||||
if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
|
if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
|
||||||
RETURN_ENUMERATOR(obj, 1, &n);
|
RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_slice_size);
|
||||||
ary = rb_ary_new2(size);
|
ary = rb_ary_new2(size);
|
||||||
memo = NEW_MEMO(ary, 0, size);
|
memo = NEW_MEMO(ary, 0, size);
|
||||||
rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
|
rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
|
||||||
|
@ -2743,4 +2761,6 @@ Init_Enumerable(void)
|
||||||
|
|
||||||
id_next = rb_intern("next");
|
id_next = rb_intern("next");
|
||||||
id_call = rb_intern("call");
|
id_call = rb_intern("call");
|
||||||
|
id_size = rb_intern("size");
|
||||||
|
id_div = rb_intern("div");
|
||||||
}
|
}
|
||||||
|
|
|
@ -482,5 +482,13 @@ class TestEnumerator < Test::Unit::TestCase
|
||||||
def test_size_for_loops
|
def test_size_for_loops
|
||||||
assert_equal Float::INFINITY, loop.size
|
assert_equal Float::INFINITY, loop.size
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_size_for_each_slice
|
||||||
|
assert_equal nil, @obj.each_slice(3).size
|
||||||
|
assert_equal 6, @sized.each_slice(7).size
|
||||||
|
assert_equal 5, @sized.each_slice(10).size
|
||||||
|
assert_equal 1, @sized.each_slice(70).size
|
||||||
|
assert_raise(ArgumentError){ @obj.each_slice(0).size }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue