@@ -4155,30 +4155,70 @@ rb_hash_update_i(VALUE key, VALUE value, VALUE hash)
41554155 return ST_CONTINUE ;
41564156}
41574157
4158+ struct update_call_args {
4159+ VALUE hash , newvalue , * argv ;
4160+ int argc ;
4161+ bool block_given ;
4162+ bool iterating ;
4163+ };
4164+
41584165static int
41594166rb_hash_update_block_callback (st_data_t * key , st_data_t * value , struct update_arg * arg , int existing )
41604167{
4161- st_data_t newvalue = arg -> arg ;
4168+ VALUE k = (VALUE )* key , v = (VALUE )* value ;
4169+ struct update_call_args * ua = (void * )arg -> arg ;
4170+ VALUE newvalue = ua -> newvalue , hash = arg -> hash ;
41624171
41634172 if (existing ) {
4164- newvalue = (st_data_t )rb_yield_values (3 , (VALUE )* key , (VALUE )* value , (VALUE )newvalue );
4173+ hash_iter_lev_inc (hash );
4174+ ua -> iterating = true;
4175+ newvalue = rb_yield_values (3 , k , v , newvalue );
4176+ hash_iter_lev_dec (hash );
4177+ ua -> iterating = false;
41654178 }
4166- else if (RHASH_STRING_KEY_P (arg -> hash , * key ) && !RB_OBJ_FROZEN (* key )) {
4167- * key = rb_hash_key_str (* key );
4179+ else if (RHASH_STRING_KEY_P (hash , k ) && !RB_OBJ_FROZEN (k )) {
4180+ * key = ( st_data_t ) rb_hash_key_str (k );
41684181 }
4169- * value = newvalue ;
4182+ * value = ( st_data_t ) newvalue ;
41704183 return ST_CONTINUE ;
41714184}
41724185
41734186NOINSERT_UPDATE_CALLBACK (rb_hash_update_block_callback )
41744187
41754188static int
4176- rb_hash_update_block_i (VALUE key , VALUE value , VALUE hash )
4189+ rb_hash_update_block_i (VALUE key , VALUE value , VALUE args )
41774190{
4178- RHASH_UPDATE (hash , key , rb_hash_update_block_callback , value );
4191+ struct update_call_args * ua = (void * )args ;
4192+ ua -> newvalue = value ;
4193+ RHASH_UPDATE (ua -> hash , key , rb_hash_update_block_callback , args );
41794194 return ST_CONTINUE ;
41804195}
41814196
4197+ static VALUE
4198+ rb_hash_update_call (VALUE args )
4199+ {
4200+ struct update_call_args * arg = (void * )args ;
4201+
4202+ for (int i = 0 ; i < arg -> argc ; i ++ ){
4203+ VALUE hash = to_hash (arg -> argv [i ]);
4204+ if (arg -> block_given ) {
4205+ rb_hash_foreach (hash , rb_hash_update_block_i , args );
4206+ }
4207+ else {
4208+ rb_hash_foreach (hash , rb_hash_update_i , arg -> hash );
4209+ }
4210+ }
4211+ return arg -> hash ;
4212+ }
4213+
4214+ static VALUE
4215+ rb_hash_update_ensure (VALUE args )
4216+ {
4217+ struct update_call_args * ua = (void * )args ;
4218+ if (ua -> iterating ) hash_iter_lev_dec (ua -> hash );
4219+ return Qnil ;
4220+ }
4221+
41824222/*
41834223 * call-seq:
41844224 * update(*other_hashes) -> self
@@ -4225,20 +4265,17 @@ rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash)
42254265static VALUE
42264266rb_hash_update (int argc , VALUE * argv , VALUE self )
42274267{
4228- int i ;
4229- bool block_given = rb_block_given_p ();
4268+ struct update_call_args args = {
4269+ .hash = self ,
4270+ .argv = argv ,
4271+ .argc = argc ,
4272+ .block_given = rb_block_given_p (),
4273+ .iterating = false,
4274+ };
4275+ VALUE arg = (VALUE )& args ;
42304276
42314277 rb_hash_modify (self );
4232- for (i = 0 ; i < argc ; i ++ ){
4233- VALUE hash = to_hash (argv [i ]);
4234- if (block_given ) {
4235- rb_hash_foreach (hash , rb_hash_update_block_i , self );
4236- }
4237- else {
4238- rb_hash_foreach (hash , rb_hash_update_i , self );
4239- }
4240- }
4241- return self ;
4278+ return rb_ensure (rb_hash_update_call , arg , rb_hash_update_ensure , arg );
42424279}
42434280
42444281struct update_func_arg {
0 commit comments