diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | array.c | 15 | ||||
-rw-r--r-- | enum.c | 80 | ||||
-rw-r--r-- | test/ruby/test_array.rb | 1 | ||||
-rw-r--r-- | test/ruby/test_enum.rb | 1 | ||||
-rw-r--r-- | version.h | 6 |
6 files changed, 72 insertions, 38 deletions
@@ -1,3 +1,10 @@ +Fri May 30 04:32:07 2008 Akinori MUSHA <knu@iDaemons.org> + + * enum.c (count_i, count_iter_i): Sync with trunk. + enum.c (enum_count, count_all_i, Init_Enumerable), + array.c (rb_ary_count): Sync with trunk. If no argument or + block is given, count the number of all elements. + Fri May 30 03:12:18 2008 Akinori MUSHA <knu@iDaemons.org> * ext/openssl/ossl_bn.c (ossl_bn_s_rand, ossl_bn_s_pseudo_rand): @@ -3064,27 +3064,34 @@ rb_ary_nitems(ary) /* * call-seq: + * array.count -> int * array.count(obj) -> int * array.count { |item| block } -> int * - * Returns the number of elements which equals to <i>obj</i>. - * If a block is given, counts the number of elements yielding a true value. + * Returns the number of elements. If an argument is given, counts + * the number of elements which equals to <i>obj</i>. If a block is + * given, counts the number of elements yielding a true value. * * ary = [1, 2, 4, 2] + * ary.count # => 4 * ary.count(2) # => 2 * ary.count{|x|x%2==0} # => 3 * */ static VALUE -rb_ary_count(int argc, VALUE *argv, VALUE ary) +rb_ary_count(argc, argv, ary) + int argc; + VALUE *argv; + VALUE ary; { long n = 0; if (argc == 0) { VALUE *p, *pend; - RETURN_ENUMERATOR(ary, 0, 0); + if (!rb_block_given_p()) + return LONG2NUM(RARRAY_LEN(ary)); for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) { if (RTEST(rb_yield(*p))) n++; @@ -15,7 +15,7 @@ #include "util.h" VALUE rb_mEnumerable; -static ID id_each, id_eqq, id_cmp; +static ID id_each, id_eqq, id_cmp, id_size; struct iter_method_arg { VALUE obj; @@ -114,36 +114,53 @@ enum_grep(obj, pat) } static VALUE -count_i(i, arg) - VALUE i; - VALUE *arg; +count_i(i, memop) + VALUE i, memop; { - if (rb_equal(i, arg[0])) { - arg[1]++; + VALUE *memo = (VALUE*)memop; + + if (rb_equal(i, memo[1])) { + memo[0]++; } return Qnil; } static VALUE -count_iter_i(i, n) - VALUE i; - long *n; +count_iter_i(i, memop) + VALUE i, memop; { + VALUE *memo = (VALUE*)memop; + if (RTEST(rb_yield(i))) { - (*n)++; + memo[0]++; } return Qnil; } +static VALUE +count_all_i(i, memop) + VALUE i, memop; +{ + VALUE *memo = (VALUE*)memop; + + memo[0]++; + return Qnil; +} + /* * call-seq: + * enum.count => int * enum.count(item) => int * enum.count {| obj | block } => int * - * Returns the number of items in <i>enum</i> for which equals to <i>item</i>. - * If a block is given, counts the number of elements yielding a true value. + * Returns the number of items in <i>enum</i>, where #size is called + * if it responds to it, otherwise the items are counted through + * enumeration. If an argument is given, counts the number of items + * in <i>enum</i>, for which equals to <i>item</i>. If a block is + * given, counts the number of elements yielding a true value. * * ary = [1, 2, 4, 2] + * ary.count # => 4 * ary.count(2) # => 2 * ary.count{|x|x%2==0} # => 3 * @@ -155,31 +172,31 @@ enum_count(argc, argv, obj) VALUE *argv; VALUE obj; { - if (argc == 1) { - VALUE item, args[2]; + VALUE memo[2]; /* [count, condition value] */ + rb_block_call_func *func; + if (argc == 0) { if (rb_block_given_p()) { - rb_warn("given block not used"); + func = count_iter_i; + } + else { + if (rb_respond_to(obj, id_size)) { + return rb_funcall(obj, id_size, 0, 0); + } + func = count_all_i; } - rb_scan_args(argc, argv, "1", &item); - args[0] = item; - args[1] = 0; - rb_block_call(obj, id_each, 0, 0, count_i, (VALUE)&args); - return INT2NUM(args[1]); - } - else if (argc == 0) { - long n; - - RETURN_ENUMERATOR(obj, 0, 0); - n = 0; - rb_block_call(obj, id_each, 0, 0, count_iter_i, (VALUE)&n); - return INT2NUM(n); } else { - VALUE v; - rb_scan_args(argc, argv, "1", &v); - return Qnil; /* not reached */ + rb_scan_args(argc, argv, "1", &memo[1]); + if (rb_block_given_p()) { + rb_warn("given block not used"); + } + func = count_i; } + + memo[0] = 0; + rb_block_call(obj, id_each, 0, 0, func, (VALUE)&memo); + return INT2NUM(memo[0]); } static VALUE @@ -1866,5 +1883,6 @@ Init_Enumerable() id_eqq = rb_intern("==="); id_each = rb_intern("each"); id_cmp = rb_intern("<=>"); + id_size = rb_intern("size"); } diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb index 58ffe52675..4c7c3dfb6d 100644 --- a/test/ruby/test_array.rb +++ b/test/ruby/test_array.rb @@ -530,6 +530,7 @@ class TestArray < Test::Unit::TestCase def test_count a = @cls[1, 2, 3, 1, 2] + assert_equal(5, a.count) assert_equal(2, a.count(1)) assert_equal(3, a.count {|x| x % 2 == 1 }) assert_equal(2, a.count(1) {|x| x % 2 == 1 }) diff --git a/test/ruby/test_enum.rb b/test/ruby/test_enum.rb index 6171c9a234..e541d566c0 100644 --- a/test/ruby/test_enum.rb +++ b/test/ruby/test_enum.rb @@ -29,6 +29,7 @@ class TestEnumerable < Test::Unit::TestCase end def test_count + assert_equal(5, @obj.count) assert_equal(2, @obj.count(1)) assert_equal(3, @obj.count {|x| x % 2 == 1 }) assert_equal(2, @obj.count(1) {|x| x % 2 == 1 }) @@ -1,7 +1,7 @@ #define RUBY_VERSION "1.8.7" -#define RUBY_RELEASE_DATE "2008-05-28" +#define RUBY_RELEASE_DATE "2008-05-30" #define RUBY_VERSION_CODE 187 -#define RUBY_RELEASE_CODE 20080528 +#define RUBY_RELEASE_CODE 20080530 #define RUBY_PATCHLEVEL 0 #define RUBY_VERSION_MAJOR 1 @@ -9,7 +9,7 @@ #define RUBY_VERSION_TEENY 7 #define RUBY_RELEASE_YEAR 2008 #define RUBY_RELEASE_MONTH 5 -#define RUBY_RELEASE_DAY 28 +#define RUBY_RELEASE_DAY 30 #ifdef RUBY_EXTERN RUBY_EXTERN const char ruby_version[]; |