summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c58
1 files changed, 14 insertions, 44 deletions
diff --git a/hash.c b/hash.c
index 5a8dd9b1fa..b9a8cb1738 100644
--- a/hash.c
+++ b/hash.c
@@ -2123,34 +2123,15 @@ rb_hash_merge(VALUE hash1, VALUE hash2)
}
static int
-assoc_cmp(VALUE a, VALUE b)
+assoc_i(VALUE key, VALUE val, VALUE arg)
{
- return !RTEST(rb_equal(a, b));
-}
-
-struct lookup2_arg {
- VALUE hash;
- VALUE key;
-};
-
-static VALUE
-lookup2_call(VALUE arg)
-{
- struct lookup2_arg *p = (struct lookup2_arg *)arg;
- return rb_hash_lookup2(p->hash, p->key, Qundef);
-}
-
-struct reset_hash_type_arg {
- VALUE hash;
- const struct st_hash_type *orighash;
-};
+ VALUE *args = (VALUE *)arg;
-static VALUE
-reset_hash_type(VALUE arg)
-{
- struct reset_hash_type_arg *p = (struct reset_hash_type_arg *)arg;
- RHASH(p->hash)->ntbl->type = p->orighash;
- return Qundef;
+ if (RTEST(rb_equal(args[0], key))) {
+ args[1] = rb_assoc_new(key, val);
+ return ST_STOP;
+ }
+ return ST_CONTINUE;
}
/*
@@ -2168,25 +2149,14 @@ reset_hash_type(VALUE arg)
*/
VALUE
-rb_hash_assoc(VALUE hash, VALUE key)
+rb_hash_assoc(VALUE hash, VALUE obj)
{
- VALUE value;
- st_table *table = hash_tbl(hash);
- struct lookup2_arg arg;
- struct reset_hash_type_arg ensure_arg;
- const struct st_hash_type *orighash = table->type;
- struct st_hash_type assochash;
-
- assochash.compare = assoc_cmp;
- assochash.hash = orighash->hash;
- table->type = &assochash;
- arg.hash = hash;
- arg.key = key;
- ensure_arg.hash = hash;
- ensure_arg.orighash = orighash;
- value = rb_ensure(lookup2_call, (VALUE)&arg, reset_hash_type, (VALUE)&ensure_arg);
- if (value == Qundef) return Qnil;
- return rb_assoc_new(key, value);
+ VALUE args[2];
+
+ args[0] = obj;
+ args[1] = Qnil;
+ rb_hash_foreach(hash, assoc_i, (VALUE)args);
+ return args[1];
}
static int