diff --git a/glib/ghash.c b/glib/ghash.c index e8d8f1738..fc0a88e55 100644 --- a/glib/ghash.c +++ b/glib/ghash.c @@ -1785,8 +1785,9 @@ g_hash_table_steal (GHashTable *hash_table, * of @hash_table are %NULL-safe. * * The dictionary implementation optimizes for having all values identical to - * their keys, for example by using g_hash_table_add(). When stealing both the - * key and the value from such a dictionary, the value will be %NULL. + * their keys, for example by using g_hash_table_add(). Before 2.82, when + * stealing both the key and the value from such a dictionary, the value was + * %NULL. Since 2.82, the returned value and key will be the same. * * Returns: %TRUE if the key was found in the #GHashTable * Since: 2.58 @@ -1820,10 +1821,15 @@ g_hash_table_steal_extended (GHashTable *hash_table, } if (stolen_value != NULL) - { - *stolen_value = g_hash_table_fetch_key_or_value (hash_table->values, node_index, hash_table->have_big_values); - g_hash_table_assign_key_or_value (hash_table->values, node_index, hash_table->have_big_values, NULL); - } + { + if (stolen_key && hash_table->keys == hash_table->values) + *stolen_value = *stolen_key; + else + { + *stolen_value = g_hash_table_fetch_key_or_value (hash_table->values, node_index, hash_table->have_big_values); + g_hash_table_assign_key_or_value (hash_table->values, node_index, hash_table->have_big_values, NULL); + } + } g_hash_table_remove_node (hash_table, node_index, FALSE); g_hash_table_maybe_resize (hash_table); diff --git a/glib/tests/hash.c b/glib/tests/hash.c index af11c5d07..0d0d07628 100644 --- a/glib/tests/hash.c +++ b/glib/tests/hash.c @@ -1283,8 +1283,9 @@ test_steal_extended (void) g_assert_true (g_hash_table_steal_extended (hash, "a", (gpointer *) &stolen_key, (gpointer *) &stolen_value)); g_assert_cmpstr (stolen_key, ==, "a"); - g_assert_cmpstr (stolen_value, ==, NULL); + g_assert_cmpstr (stolen_value, ==, "a"); g_clear_pointer (&stolen_key, g_free); + stolen_value = NULL; g_assert_true (g_hash_table_steal_extended (hash, "b", (gpointer *) &stolen_key, NULL)); @@ -1299,8 +1300,9 @@ test_steal_extended (void) g_assert_true (g_hash_table_steal_extended (hash, "d", (gpointer *) &stolen_key, (gpointer *) &stolen_value)); g_assert_cmpstr (stolen_key, ==, "d"); - g_assert_cmpstr (stolen_value, ==, NULL); + g_assert_cmpstr (stolen_value, ==, "d"); g_clear_pointer (&stolen_key, g_free); + stolen_value = NULL; /* So far, the GHashTable was used like a set (g_hash_table_add()), where all key/values were * identical. Adding one entry where key/value differs, blows the internal representation