summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-07-18 13:16:48 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-07-18 13:16:48 +0000
commitd738e3e15533e0f500789faaedcef9ed9ca362b9 (patch)
treeae914e671da780385594a4efe45df56cc01412af
parente23d1736797f9b7170c80a7470b8e5cecd308105 (diff)
optimized any? methods
* array.c (rb_ary_any_p), hash.c (rb_hash_any_p): optimized versions. these are bit faster than optimization in Enumerable#any?. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46866 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--array.c24
-rw-r--r--hash.c48
-rw-r--r--test/ruby/test_settracefunc.rb6
3 files changed, 74 insertions, 4 deletions
diff --git a/array.c b/array.c
index 0bfbfb4fd1..92897c4cea 100644
--- a/array.c
+++ b/array.c
@@ -5409,6 +5409,29 @@ rb_ary_drop_while(VALUE ary)
}
/*
+ * call-seq:
+ * ary.any? [{ |obj| block }] -> true or false
+ *
+ * See also Enumerable#any?
+ */
+
+static VALUE
+rb_ary_any_p(VALUE ary)
+{
+ long i, len = RARRAY_LEN(ary);
+ const VALUE *ptr = RARRAY_CONST_PTR(ary);
+
+ if (!len) return Qfalse;
+ if (!rb_block_given_p()) {
+ for (i = 0; i < len; ++i) if (RTEST(ptr[i])) return Qtrue;
+ }
+ else {
+ for (i = 0; i < len; ++i) if (RTEST(rb_yield(ptr[i]))) return Qtrue;
+ }
+ return Qfalse;
+}
+
+/*
* Arrays are ordered, integer-indexed collections of any object.
*
* Array indexing starts at 0, as in C or Java. A negative index is assumed
@@ -5757,6 +5780,7 @@ Init_Array(void)
rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
+ rb_define_method(rb_cArray, "any?", rb_ary_any_p, 0);
id_cmp = rb_intern("<=>");
id_random = rb_intern("random");
diff --git a/hash.c b/hash.c
index c600fd11ab..2e51a08d27 100644
--- a/hash.c
+++ b/hash.c
@@ -2463,6 +2463,52 @@ rb_hash_compare_by_id_p(VALUE hash)
return Qfalse;
}
+static int
+any_p_i(VALUE key, VALUE value, VALUE arg)
+{
+ VALUE ret = rb_yield(rb_assoc_new(key, value));
+ if (RTEST(ret)) {
+ *(VALUE *)arg = Qtrue;
+ return ST_STOP;
+ }
+ return ST_CONTINUE;
+}
+
+static int
+any_p_i_fast(VALUE key, VALUE value, VALUE arg)
+{
+ VALUE ret = rb_yield_values(2, key, value);
+ if (RTEST(ret)) {
+ *(VALUE *)arg = Qtrue;
+ return ST_STOP;
+ }
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * hsh.any? [{ |(key, value)| block }] -> true or false
+ *
+ * See also Enumerable#any?
+ */
+
+static VALUE
+rb_hash_any_p(VALUE hash)
+{
+ VALUE ret = Qfalse;
+
+ if (RHASH_EMPTY_P(hash)) return Qfalse;
+ if (!rb_block_given_p()) {
+ /* yields pairs, never false */
+ return Qtrue;
+ }
+ if (rb_block_arity() > 1)
+ rb_hash_foreach(hash, any_p_i_fast, (VALUE)&ret);
+ else
+ rb_hash_foreach(hash, any_p_i, (VALUE)&ret);
+ return ret;
+}
+
static int path_tainted = -1;
static char **origenviron;
@@ -3861,6 +3907,8 @@ Init_Hash(void)
rb_define_method(rb_cHash,"compare_by_identity", rb_hash_compare_by_id, 0);
rb_define_method(rb_cHash,"compare_by_identity?", rb_hash_compare_by_id_p, 0);
+ rb_define_method(rb_cHash, "any?", rb_hash_any_p, 0);
+
/* Document-class: ENV
*
* ENV is a hash-like accessor for environment variables.
diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb
index ac9f9050f9..b13eea09bd 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -285,11 +285,9 @@ class TestSetTraceFunc < Test::Unit::TestCase
[["c-return", 1, :set_trace_func, Kernel],
["line", 4, __method__, self.class],
- ["c-call", 4, :any?, Enumerable],
- ["c-call", 4, :each, Array],
+ ["c-call", 4, :any?, Array],
["line", 4, __method__, self.class],
- ["c-return", 4, :each, Array],
- ["c-return", 4, :any?, Enumerable],
+ ["c-return", 4, :any?, Array],
["line", 5, __method__, self.class],
["c-call", 5, :set_trace_func, Kernel]].each{|e|
assert_equal(e, events.shift)