/*
 *  call-seq:
 *     enum.count                   => int
 *     enum.count(item)             => int
 *     enum.count {| obj | block }  => int
 *
 *  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
 *
 */

static VALUE
enum_count(int argc, VALUE *argv, VALUE obj)
{
    VALUE memo[2];      /* [count, condition value] */
    rb_block_call_func *func;

    if (argc == 0) {
        if (rb_block_given_p()) {
            func = count_iter_i;
        }
        else {
            if (rb_respond_to(obj, id_size)) {
                return rb_funcall(obj, id_size, 0, 0);
            }
            func = count_all_i;
        }
    }
    else {
        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]);
}