* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
/*
#include "ghash.h"
+#include "glib-private.h"
#include "gstrfuncs.h"
#include "gatomic.h"
#include "gtestutils.h"
* GHashTable:
*
* The #GHashTable struct is an opaque data structure to represent a
- * <link linkend="glib-Hash-Tables">Hash Table</link>. It should only be
- * accessed via the following functions.
+ * [Hash Table][glib-Hash-Tables]. It should only be accessed via the
+ * following functions.
*/
/**
* and #gchar* respectively.
*
* g_direct_hash() is also the appropriate hash function for keys
- * of the form <literal>GINT_TO_POINTER (n)</literal> (or similar macros).
+ * of the form `GINT_TO_POINTER (n)` (or similar macros).
*
* <!-- FIXME: Need more here. --> A good hash functions should produce
* hash values that are evenly distributed over a fairly large range.
* a more secure hash function when using a GHashTable with keys
* that originate in untrusted data (such as HTTP requests).
* Using g_str_hash() in that situation might make your application
- * vulerable to <ulink url="https://lwn.net/Articles/474912/">Algorithmic Complexity Attacks</ulink>.
+ * vulerable to
+ * [Algorithmic Complexity Attacks](https://lwn.net/Articles/474912/).
*
* The key to choosing a good hash is unpredictability. Even
* cryptographic hashes are very easy to find collisions for when the
int version;
} RealIter;
+G_STATIC_ASSERT (sizeof (GHashTableIter) == sizeof (RealIter));
+G_STATIC_ASSERT (_g_alignof (GHashTableIter) >= _g_alignof (RealIter));
+
/* Each table size has an associated prime modulo (the first prime
* lower than the table size) used to find the initial bucket. Probing
* then works modulo 2^n. The prime modulo is necessary to get a
* a similar fashion to g_direct_equal(), but without the overhead of
* a function call.
*
- * Return value: a new #GHashTable
+ * Returns: a new #GHashTable
*/
GHashTable *
g_hash_table_new (GHashFunc hash_func,
* allocated for the key and value that get called when removing the
* entry from the #GHashTable.
*
- * Return value: a new #GHashTable
+ * Returns: a new #GHashTable
*/
GHashTable *
g_hash_table_new_full (GHashFunc hash_func,
* Initializes a key/value pair iterator and associates it with
* @hash_table. Modifying the hash table after calling this function
* invalidates the returned iterator.
- * |[
+ * |[<!-- language="C" -->
* GHashTableIter iter;
* gpointer key, value;
*
* g_hash_table_iter_init (&iter, hash_table);
* while (g_hash_table_iter_next (&iter, &key, &value))
* {
- * /* do something with key and value */
+ * // do something with key and value
* }
* ]|
*
* pointed to as a result of this advancement. If %FALSE is returned,
* @key and @value are not set, and the iterator becomes invalid.
*
- * Return value: %FALSE if the end of the #GHashTable has been reached.
+ * Returns: %FALSE if the end of the #GHashTable has been reached.
*
* Since: 2.16
*/
*
* Returns the #GHashTable associated with @iter.
*
- * Return value: the #GHashTable associated with @iter.
+ * Returns: the #GHashTable associated with @iter.
*
* Since: 2.16
*/
* otherwise you have to make sure that any dynamically allocated
* values are freed yourself.
*
+ * It is safe to continue iterating the #GHashTable afterward:
+ * |[<!-- language="C" -->
+ * while (g_hash_table_iter_next (&iter, &key, &value))
+ * {
+ * if (condition)
+ * g_hash_table_iter_remove (&iter);
+ * }
+ * ]|
+ *
* Since: 2.16
*/
void
* If @key has been taken out of the existing node (ie it is not
* passed in via a g_hash_table_insert/replace) call, then @reusing_key
* should be %TRUE.
+ *
+ * Returns: %TRUE if the key did not exist yet
*/
-static void
+static gboolean
g_hash_table_insert_node (GHashTable *hash_table,
guint node_index,
guint key_hash,
{
gboolean already_exists;
guint old_hash;
- gpointer key_to_free;
- gpointer value_to_free;
+ gpointer key_to_free = NULL;
+ gpointer value_to_free = NULL;
old_hash = hash_table->hashes[node_index];
already_exists = HASH_IS_REAL (old_hash);
if (hash_table->value_destroy_func)
(* hash_table->value_destroy_func) (value_to_free);
}
+
+ return !already_exists;
}
/**
* Atomically increments the reference count of @hash_table by one.
* This function is MT-safe and may be called from any thread.
*
- * Return value: the passed in #GHashTable
+ * Returns: the passed in #GHashTable
*
* Since: 2.10
*/
* and has the value %NULL. If you need this distinction, use
* g_hash_table_lookup_extended().
*
- * Return value: (allow-none): the associated value, or %NULL if the key is not found
+ * Returns: (allow-none): the associated value, or %NULL if the key is not found
*/
gpointer
g_hash_table_lookup (GHashTable *hash_table,
* whether the %NULL key exists, provided the hash and equal functions
* of @hash_table are %NULL-safe.
*
- * Return value: %TRUE if the key was found in the #GHashTable
+ * Returns: %TRUE if the key was found in the #GHashTable
*/
gboolean
g_hash_table_lookup_extended (GHashTable *hash_table,
* Do a lookup of @key. If it is found, replace it with the new
* @value (and perhaps the new @key). If it is not found, create
* a new node.
+ *
+ * Returns: %TRUE if the key did not exist yet
*/
-static void
+static gboolean
g_hash_table_insert_internal (GHashTable *hash_table,
gpointer key,
gpointer value,
guint key_hash;
guint node_index;
- g_return_if_fail (hash_table != NULL);
+ g_return_val_if_fail (hash_table != NULL, FALSE);
node_index = g_hash_table_lookup_node (hash_table, key, &key_hash);
- g_hash_table_insert_node (hash_table, node_index, key_hash, key, value, keep_new_key, FALSE);
+ return g_hash_table_insert_node (hash_table, node_index, key_hash, key, value, keep_new_key, FALSE);
}
/**
* value is freed using that function. If you supplied a
* @key_destroy_func when creating the #GHashTable, the passed
* key is freed using that function.
+ *
+ * Returns: %TRUE if the key did not exist yet
*/
-void
+gboolean
g_hash_table_insert (GHashTable *hash_table,
gpointer key,
gpointer value)
{
- g_hash_table_insert_internal (hash_table, key, value, FALSE);
+ return g_hash_table_insert_internal (hash_table, key, value, FALSE);
}
/**
* the #GHashTable, the old value is freed using that function.
* If you supplied a @key_destroy_func when creating the
* #GHashTable, the old key is freed using that function.
+ *
+ * Returns: %TRUE of the key did not exist yet
*/
-void
+gboolean
g_hash_table_replace (GHashTable *hash_table,
gpointer key,
gpointer value)
{
- g_hash_table_insert_internal (hash_table, key, value, TRUE);
+ return g_hash_table_insert_internal (hash_table, key, value, TRUE);
}
/**
* corresponding value it is able to be stored more efficiently. See
* the discussion in the section description.
*
+ * Returns: %TRUE if the key did not exist yet
+ *
* Since: 2.32
- **/
-void
+ */
+gboolean
g_hash_table_add (GHashTable *hash_table,
gpointer key)
{
- g_hash_table_insert_internal (hash_table, key, key, TRUE);
+ return g_hash_table_insert_internal (hash_table, key, key, TRUE);
}
/**
* @hash_table: our #GHashTable
* @key: the key to remove
* @notify: %TRUE if the destroy notify handlers are to be called
- * Return value: %TRUE if a node was found and removed, else %FALSE
+ * Returns: %TRUE if a node was found and removed, else %FALSE
*
* Implements the common logic for the g_hash_table_remove() and
* g_hash_table_steal() functions.
* See #GHashTableIter for an alternative way to loop over the
* key/value pairs in the hash table.
*
- * Return value: the number of key/value pairs removed
+ * Returns: the number of key/value pairs removed
*/
guint
g_hash_table_foreach_remove (GHashTable *hash_table,
* See #GHashTableIter for an alternative way to loop over the
* key/value pairs in the hash table.
*
- * Return value: the number of key/value pairs removed.
+ * Returns: the number of key/value pairs removed.
*/
guint
g_hash_table_foreach_steal (GHashTable *hash_table,
* (keep in mind that an O(n) find/foreach operation issued for all n
* values in a hash table ends up needing O(n*n) operations).
*
- * Return value: (allow-none): The value of the first key/value pair is returned,
+ * Returns: (allow-none): The value of the first key/value pair is returned,
* for which @predicate evaluates to %TRUE. If no pair with the
* requested property is found, %NULL is returned.
*
*
* Returns the number of elements contained in the #GHashTable.
*
- * Return value: the number of key/value pairs in the #GHashTable.
+ * Returns: the number of key/value pairs in the #GHashTable.
*/
guint
g_hash_table_size (GHashTable *hash_table)
* g_hash_table_get_keys:
* @hash_table: a #GHashTable
*
- * Retrieves every key inside @hash_table. The returned data
- * is valid until @hash_table is modified.
+ * Retrieves every key inside @hash_table. The returned data is valid
+ * until changes to the hash release those keys.
*
- * Return value: a #GList containing all the keys inside the hash
+ * Returns: a #GList containing all the keys inside the hash
* table. The content of the list is owned by the hash table and
* should not be modified or freed. Use g_list_free() when done
* using the list.
}
/**
+ * g_hash_table_get_keys_as_array:
+ * @hash_table: a #GHashTable
+ * @length: (out): the length of the returned array
+ *
+ * Retrieves every key inside @hash_table, as an array.
+ *
+ * The returned array is %NULL-terminated but may contain %NULL as a
+ * key. Use @length to determine the true length if it's possible that
+ * %NULL was used as the value for a key.
+ *
+ * Note: in the common case of a string-keyed #GHashTable, the return
+ * value of this function can be conveniently cast to (gchar **).
+ *
+ * You should always free the return result with g_free(). In the
+ * above-mentioned case of a string-keyed hash table, it may be
+ * appropriate to use g_strfreev() if you call g_hash_table_steal_all()
+ * first to transfer ownership of the keys.
+ *
+ * Returns: (array length=length) (transfer container): a
+ * %NULL-terminated array containing each key from the table.
+ *
+ * Since: 2.40
+ **/
+gpointer *
+g_hash_table_get_keys_as_array (GHashTable *hash_table,
+ guint *length)
+{
+ gpointer *result;
+ guint i, j = 0;
+
+ result = g_new (gpointer, hash_table->nnodes + 1);
+ for (i = 0; i < hash_table->size; i++)
+ {
+ if (HASH_IS_REAL (hash_table->hashes[i]))
+ result[j++] = hash_table->keys[i];
+ }
+ g_assert_cmpint (j, ==, hash_table->nnodes);
+ result[j] = NULL;
+
+ if (length)
+ *length = j;
+
+ return result;
+}
+
+/**
* g_hash_table_get_values:
* @hash_table: a #GHashTable
*
* Retrieves every value inside @hash_table. The returned data
* is valid until @hash_table is modified.
*
- * Return value: a #GList containing all the values inside the hash
+ * Returns: a #GList containing all the values inside the hash
* table. The content of the list is owned by the hash table and
* should not be modified or freed. Use g_list_free() when done
* using the list.
*
* Converts a string to a hash value.
*
- * This function implements the widely used "djb" hash apparently posted
- * by Daniel Bernstein to comp.lang.c some time ago. The 32 bit
- * unsigned hash value starts at 5381 and for each byte 'c' in the
- * string, is updated: <literal>hash = hash * 33 + c</literal>. This
- * function uses the signed value of each byte.
+ * This function implements the widely used "djb" hash apparently
+ * posted by Daniel Bernstein to comp.lang.c some time ago. The 32
+ * bit unsigned hash value starts at 5381 and for each byte 'c' in
+ * the string, is updated: `hash = hash * 33 + c`. This function
+ * uses the signed value of each byte.
*
* It can be passed to g_hash_table_new() as the @hash_func parameter,
* when using non-%NULL strings as keys in a #GHashTable.
* when using opaque pointers compared by pointer value as keys in a
* #GHashTable.
*
- * This hash function is also appropriate for keys that are integers stored
- * in pointers, such as <literal>GINT_TO_POINTER (n)</literal>.
+ * This hash function is also appropriate for keys that are integers
+ * stored in pointers, such as `GINT_TO_POINTER (n)`.
*
* Returns: a hash value corresponding to the key.
*/
*
* Compares two #gpointer arguments and returns %TRUE if they are equal.
* It can be passed to g_hash_table_new() as the @key_equal_func
- * parameter, when using opaque pointers compared by pointer value as keys
- * in a #GHashTable.
+ * parameter, when using opaque pointers compared by pointer value as
+ * keys in a #GHashTable.
*
- * This equality function is also appropriate for keys that are integers stored
- * in pointers, such as <literal>GINT_TO_POINTER (n)</literal>.
+ * This equality function is also appropriate for keys that are integers
+ * stored in pointers, such as `GINT_TO_POINTER (n)`.
*
* Returns: %TRUE if the two keys match.
*/
* parameter, when using non-%NULL pointers to integers as keys in a
* #GHashTable.
*
- * Note that this function acts on pointers to #gint, not on #gint directly:
- * if your hash table's keys are of the form
- * <literal>GINT_TO_POINTER (n)</literal>, use g_direct_equal() instead.
+ * Note that this function acts on pointers to #gint, not on #gint
+ * directly: if your hash table's keys are of the form
+ * `GINT_TO_POINTER (n)`, use g_direct_equal() instead.
*
* Returns: %TRUE if the two keys match.
*/
* It can be passed to g_hash_table_new() as the @hash_func parameter,
* when using non-%NULL pointers to integer values as keys in a #GHashTable.
*
- * Note that this function acts on pointers to #gint, not on #gint directly:
- * if your hash table's keys are of the form
- * <literal>GINT_TO_POINTER (n)</literal>, use g_direct_hash() instead.
+ * Note that this function acts on pointers to #gint, not on #gint
+ * directly: if your hash table's keys are of the form
+ * `GINT_TO_POINTER (n)`, use g_direct_hash() instead.
*
* Returns: a hash value corresponding to the key.
*/