summaryrefslogtreecommitdiff
path: root/st.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-07-06 14:19:47 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-07-06 14:19:47 +0000
commite6be6ebc7701c31e83cc25a7463bc72c59b2782d (patch)
treef225402526e9e071173ef217148f13baca7cb69e /st.c
parent9f051c80dcaaf05d5597b6b8830fade30e131031 (diff)
downloadruby-e6be6ebc7701c31e83cc25a7463bc72c59b2782d.tar.gz
st.c: update the key too if changed
* st.c (st_update): fix a bug that the key was not updated even if it was changed by the callback function. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46720 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'st.c')
-rw-r--r--st.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/st.c b/st.c
index f26443f99c..1d78ffebad 100644
--- a/st.c
+++ b/st.c
@@ -834,6 +834,7 @@ st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data
existing = 1;
}
{
+ const st_data_t old_key = key;
retval = (*func)(&key, &value, arg, existing);
if (!table->entries_packed) {
FIND_ENTRY(table, ptr, hash_val, bin_pos);
@@ -845,6 +846,14 @@ st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data
add_packed_direct(table, key, value, hash_val);
break;
}
+ if (old_key != PKEY(table, i)) return -1;
+ if (old_key != key) {
+ if (do_hash(key, table) != hash_val &&
+ !EQUAL(table, key, old_key)) {
+ return -1;
+ }
+ PKEY(table, i) = key;
+ }
PVAL_SET(table, i, value);
break;
case ST_DELETE:
@@ -863,6 +872,7 @@ st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data
existing = 1;
}
{
+ const st_data_t old_key = key;
retval = (*func)(&key, &value, arg, existing);
unpacked:
switch (retval) {
@@ -871,6 +881,14 @@ st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data
add_direct(table, key, value, hash_val, hash_pos(hash_val, table->num_bins));
break;
}
+ if (old_key != ptr->key) return -1;
+ if (old_key != key) {
+ if (do_hash(key, table) != hash_val &&
+ !EQUAL(table, key, old_key)) {
+ return -1;
+ }
+ ptr->key = key;
+ }
ptr->record = value;
break;
case ST_DELETE: