[前][次][番号順一覧][スレッド一覧]

ruby-changes:25451

From: marcandre <ko1@a...>
Date: Wed, 7 Nov 2012 02:13:01 +0900 (JST)
Subject: [ruby-changes:25451] marcandRe: r37508 (trunk): * enum.c (enum_each_slice): Support for Enumerable#each_slice.size

marcandre	2012-11-07 02:12:50 +0900 (Wed, 07 Nov 2012)

  New Revision: 37508

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=37508

  Log:
    * enum.c (enum_each_slice): Support for Enumerable#each_slice.size
      [Feature #6636]

  Modified files:
    trunk/enum.c
    trunk/test/ruby/test_enumerator.rb

Index: enum.c
===================================================================
--- enum.c	(revision 37507)
+++ enum.c	(revision 37508)
@@ -18,8 +18,12 @@
 #define STATIC_ASSERT(name, expr) typedef int static_assert_##name##_check[1 - 2*!(expr)]
 
 VALUE rb_mEnumerable;
+
 static ID id_next;
+static ID id_div;
 static ID id_call;
+static ID id_size;
+
 #define id_each idEach
 #define id_eqq  idEqq
 #define id_cmp  idCmp
@@ -1778,6 +1782,20 @@
     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:
  *    enum.each_slice(n) { ... }  ->  nil
@@ -1802,7 +1820,7 @@
     NODE *memo;
 
     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);
     memo = NEW_MEMO(ary, 0, size);
     rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
@@ -2743,4 +2761,6 @@
 
     id_next = rb_intern("next");
     id_call = rb_intern("call");
+    id_size = rb_intern("size");
+    id_div = rb_intern("div");
 }
Index: test/ruby/test_enumerator.rb
===================================================================
--- test/ruby/test_enumerator.rb	(revision 37507)
+++ test/ruby/test_enumerator.rb	(revision 37508)
@@ -482,5 +482,13 @@
   def test_size_for_loops
     assert_equal Float::INFINITY, loop.size
   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
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]