diff options
author | nagachika <nagachika@ruby-lang.org> | 2021-04-15 10:11:19 +0900 |
---|---|---|
committer | nagachika <nagachika@ruby-lang.org> | 2021-04-15 10:25:30 +0900 |
commit | 84d9a9afc0b49d095541acb9832f8b12fb506e19 (patch) | |
tree | 1f6b27559c103dfffbe0977f0fe014e20ac07537 /hash.c | |
parent | d5a34e1b142eccc54971494be2243a0c6ac01d94 (diff) |
merge revision(s) 31e0382723bfb35cffe3ca485dd0577668cafa07,5e5fb72f99701dc27c66ab148471893f14e6d6f0,fb6ebe55d91187d9635e0183d47dbf38e95b1141,522d4cd32f7727886f4fcbc28ed29c08d361ee20: [Backport #17735]
Keep non evaluated keys in `Hash#transform_keys!` [Bug #17735]
---
hash.c | 6 +++++-
spec/ruby/core/hash/transform_keys_spec.rb | 12 +++++++++++-
test/ruby/test_hash.rb | 8 ++++++++
3 files changed, 24 insertions(+), 2 deletions(-)
Clear an intermediate hash [Bug #17735]
---
hash.c | 1 +
1 file changed, 1 insertion(+)
Hide an intermediate array
---
hash.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
Force recycle intermediate collection in Hash#transform_keys! [Bug
#17735]
* Force recycle intermediate hash
* Force recycle intermediate array too
https://github.com/ruby/ruby/pull/4329#issuecomment-808840718
---
hash.c | 2 ++
1 file changed, 2 insertions(+)
Diffstat (limited to 'hash.c')
-rw-r--r-- | hash.c | 15 |
1 files changed, 12 insertions, 3 deletions
@@ -3249,7 +3249,7 @@ rb_hash_transform_keys(int argc, VALUE *argv, VALUE hash) return result; } -static VALUE rb_hash_flatten(int argc, VALUE *argv, VALUE hash); +static int flatten_i(VALUE key, VALUE val, VALUE ary); /* * call-seq: @@ -3278,8 +3278,9 @@ rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash) rb_hash_modify_check(hash); if (!RHASH_TABLE_EMPTY_P(hash)) { long i; - VALUE pairs = rb_hash_flatten(0, NULL, hash); - rb_hash_clear(hash); + VALUE new_keys = hash_alloc(0); + VALUE pairs = rb_ary_tmp_new(RHASH_SIZE(hash) * 2); + rb_hash_foreach(hash, flatten_i, pairs); for (i = 0; i < RARRAY_LEN(pairs); i += 2) { VALUE key = RARRAY_AREF(pairs, i), new_key, val; @@ -3296,8 +3297,16 @@ rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash) new_key = key; } val = RARRAY_AREF(pairs, i+1); + if (!hash_stlike_lookup(new_keys, key, NULL)) { + rb_hash_stlike_delete(hash, &key, NULL); + } rb_hash_aset(hash, new_key, val); + rb_hash_aset(new_keys, new_key, Qnil); } + rb_ary_clear(pairs); + rb_gc_force_recycle(pairs); + rb_hash_clear(new_keys); + rb_gc_force_recycle(new_keys); } return hash; } |