@@ -3942,30 +3942,70 @@ rb_hash_update_i(VALUE key, VALUE value, VALUE hash)
39423942 return ST_CONTINUE ;
39433943}
39443944
3945+ struct update_call_args {
3946+ VALUE hash , newvalue , * argv ;
3947+ int argc ;
3948+ bool block_given ;
3949+ bool iterating ;
3950+ };
3951+
39453952static int
39463953rb_hash_update_block_callback (st_data_t * key , st_data_t * value , struct update_arg * arg , int existing )
39473954{
3948- st_data_t newvalue = arg -> arg ;
3955+ VALUE k = (VALUE )* key , v = (VALUE )* value ;
3956+ struct update_call_args * ua = (void * )arg -> arg ;
3957+ VALUE newvalue = ua -> newvalue , hash = arg -> hash ;
39493958
39503959 if (existing ) {
3951- newvalue = (st_data_t )rb_yield_values (3 , (VALUE )* key , (VALUE )* value , (VALUE )newvalue );
3960+ hash_iter_lev_inc (hash );
3961+ ua -> iterating = true;
3962+ newvalue = rb_yield_values (3 , k , v , newvalue );
3963+ hash_iter_lev_dec (hash );
3964+ ua -> iterating = false;
39523965 }
3953- else if (RHASH_STRING_KEY_P (arg -> hash , * key ) && !RB_OBJ_FROZEN (* key )) {
3954- * key = rb_hash_key_str (* key );
3966+ else if (RHASH_STRING_KEY_P (hash , k ) && !RB_OBJ_FROZEN (k )) {
3967+ * key = ( st_data_t ) rb_hash_key_str (k );
39553968 }
3956- * value = newvalue ;
3969+ * value = ( st_data_t ) newvalue ;
39573970 return ST_CONTINUE ;
39583971}
39593972
39603973NOINSERT_UPDATE_CALLBACK (rb_hash_update_block_callback )
39613974
39623975static int
3963- rb_hash_update_block_i (VALUE key , VALUE value , VALUE hash )
3976+ rb_hash_update_block_i (VALUE key , VALUE value , VALUE args )
39643977{
3965- RHASH_UPDATE (hash , key , rb_hash_update_block_callback , value );
3978+ struct update_call_args * ua = (void * )args ;
3979+ ua -> newvalue = value ;
3980+ RHASH_UPDATE (ua -> hash , key , rb_hash_update_block_callback , args );
39663981 return ST_CONTINUE ;
39673982}
39683983
3984+ static VALUE
3985+ rb_hash_update_call (VALUE args )
3986+ {
3987+ struct update_call_args * arg = (void * )args ;
3988+
3989+ for (int i = 0 ; i < arg -> argc ; i ++ ){
3990+ VALUE hash = to_hash (arg -> argv [i ]);
3991+ if (arg -> block_given ) {
3992+ rb_hash_foreach (hash , rb_hash_update_block_i , args );
3993+ }
3994+ else {
3995+ rb_hash_foreach (hash , rb_hash_update_i , arg -> hash );
3996+ }
3997+ }
3998+ return arg -> hash ;
3999+ }
4000+
4001+ static VALUE
4002+ rb_hash_update_ensure (VALUE args )
4003+ {
4004+ struct update_call_args * ua = (void * )args ;
4005+ if (ua -> iterating ) hash_iter_lev_dec (ua -> hash );
4006+ return Qnil ;
4007+ }
4008+
39694009/*
39704010 * call-seq:
39714011 * hash.merge! -> self
@@ -4017,20 +4057,17 @@ rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash)
40174057static VALUE
40184058rb_hash_update (int argc , VALUE * argv , VALUE self )
40194059{
4020- int i ;
4021- bool block_given = rb_block_given_p ();
4060+ struct update_call_args args = {
4061+ .hash = self ,
4062+ .argv = argv ,
4063+ .argc = argc ,
4064+ .block_given = rb_block_given_p (),
4065+ .iterating = false,
4066+ };
4067+ VALUE arg = (VALUE )& args ;
40224068
40234069 rb_hash_modify (self );
4024- for (i = 0 ; i < argc ; i ++ ){
4025- VALUE hash = to_hash (argv [i ]);
4026- if (block_given ) {
4027- rb_hash_foreach (hash , rb_hash_update_block_i , self );
4028- }
4029- else {
4030- rb_hash_foreach (hash , rb_hash_update_i , self );
4031- }
4032- }
4033- return self ;
4070+ return rb_ensure (rb_hash_update_call , arg , rb_hash_update_ensure , arg );
40344071}
40354072
40364073struct update_func_arg {
0 commit comments