* 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"
*
* To destroy a #GHashTable use g_hash_table_destroy().
*
- * <example>
- * <title>Using a GHashTable as a set</title>
- * <para>
- * A common use-case for hash tables is to store information about
- * a set of keys, without associating any particular value with each
+ * A common use-case for hash tables is to store information about a
+ * set of keys, without associating any particular value with each
* key. GHashTable optimizes one way of doing so: If you store only
* key-value pairs where key == value, then GHashTable does not
* allocate memory to store the values, which can be a considerable
- * space saving, if your set is large.
- * </para>
- * <programlisting>
- * GHashTable *
- * set_new (GHashFunc hash_func,
- * GEqualFunc equal_func,
- * GDestroyNotify destroy)
- * {
- * return g_hash_table_new_full (hash_func, equal_func, destroy, NULL);
- * }
- *
- * void
- * set_insert (GHashTable *set,
- * gpointer element)
- * {
- * g_hash_table_insert (set, element, element);
- * }
- *
- * gboolean
- * set_contains (GHashTable *set,
- * gpointer element)
- * {
- * return g_hash_table_lookup_extended (set, element, NULL, NULL);
- * }
- *
- * gboolean
- * set_remove (GHashTable *set,
- * gpointer element)
- * {
- * return g_hash_table_remove (set, element);
- * }
- * </programlisting>
- * </example>
+ * space saving, if your set is large. The functions
+ * g_hash_table_add() and g_hash_table_contains() are designed to be
+ * used when using #GHashTable this way.
*/
/**
* 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).
- *
- * <!-- FIXME: Need more here. --> The hash values should be evenly
- * distributed over a fairly large range? The modulus is taken with the
- * hash table size (a prime number) to find the 'bucket' to place each
- * key into. The function should also be very fast, since it is called
- * for each key lookup.
+ * 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.
+ * The modulus is taken with the hash table size (a prime number) to
+ * find the 'bucket' to place each key into. The function should also
+ * be very fast, since it is called for each key lookup.
+ *
+ * Note that the hash functions provided by GLib have these qualities,
+ * but are not particularly robust against manufactured keys that
+ * cause hash collisions. Therefore, you should consider choosing
+ * 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
+ * [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
+ * remainder is taken modulo a somewhat predictable prime number. There
+ * must be an element of randomness that an attacker is unable to guess.
*
* Returns: the hash value corresponding to the key
*/
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,
* g_hash_table_new_full:
* @hash_func: a function to create a hash value from a key
* @key_equal_func: a function to check two keys for equality
- * @key_destroy_func: a function to free the memory allocated for the key
+ * @key_destroy_func: (allow-none): a function to free the memory allocated for the key
* used when removing the entry from the #GHashTable, or %NULL
* if you don't want to supply such a function.
- * @value_destroy_func: a function to free the memory allocated for the
+ * @value_destroy_func: (allow-none): a function to free the memory allocated for the
* value used when removing the entry from the #GHashTable, or %NULL
* if you don't want to supply such a function.
*
* 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
* }
* ]|
*
/**
* g_hash_table_iter_next:
* @iter: an initialized #GHashTableIter
- * @key: a location to store the key, or %NULL
- * @value: a location to store the value, or %NULL
+ * @key: (allow-none): a location to store the key, or %NULL
+ * @value: (allow-none): a location to store the value, or %NULL
*
* Advances @iter and retrieves the key and/or value that are now
* 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
* @hash_table: our #GHashTable
* @node_index: pointer to node to insert/replace
* @key_hash: key hash
- * @key: key to replace with
+ * @key: (allow-none): key to replace with, or %NULL
* @value: value to replace with
+ * @keep_new_key: whether to replace the key in the node with @key
+ * @reusing_key: whether @key was taken out of the existing node
*
* Inserts a value at @node_index in the hash table and updates it.
+ *
+ * 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,
- gpointer key,
- gpointer value,
- gboolean keep_new_key)
+ gpointer new_key,
+ gpointer new_value,
+ gboolean keep_new_key,
+ gboolean reusing_key)
{
+ gboolean already_exists;
guint old_hash;
- gpointer old_key;
- gpointer old_value;
-
- if (G_UNLIKELY (hash_table->keys == hash_table->values && key != value))
- hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size);
+ gpointer key_to_free = NULL;
+ gpointer value_to_free = NULL;
old_hash = hash_table->hashes[node_index];
- old_key = hash_table->keys[node_index];
- old_value = hash_table->values[node_index];
-
- if (HASH_IS_REAL (old_hash))
+ already_exists = HASH_IS_REAL (old_hash);
+
+ /* Proceed in three steps. First, deal with the key because it is the
+ * most complicated. Then consider if we need to split the table in
+ * two (because writing the value will result in the set invariant
+ * becoming broken). Then deal with the value.
+ *
+ * There are three cases for the key:
+ *
+ * - entry already exists in table, reusing key:
+ * free the just-passed-in new_key and use the existing value
+ *
+ * - entry already exists in table, not reusing key:
+ * free the entry in the table, use the new key
+ *
+ * - entry not already in table:
+ * use the new key, free nothing
+ *
+ * We update the hash at the same time...
+ */
+ if (already_exists)
{
+ /* Note: we must record the old value before writing the new key
+ * because we might change the value in the event that the two
+ * arrays are shared.
+ */
+ value_to_free = hash_table->values[node_index];
+
if (keep_new_key)
- hash_table->keys[node_index] = key;
- hash_table->values[node_index] = value;
+ {
+ key_to_free = hash_table->keys[node_index];
+ hash_table->keys[node_index] = new_key;
+ }
+ else
+ key_to_free = new_key;
}
else
{
- hash_table->keys[node_index] = key;
- hash_table->values[node_index] = value;
hash_table->hashes[node_index] = key_hash;
+ hash_table->keys[node_index] = new_key;
+ }
+
+ /* Step two: check if the value that we are about to write to the
+ * table is the same as the key in the same position. If it's not,
+ * split the table.
+ */
+ if (G_UNLIKELY (hash_table->keys == hash_table->values && hash_table->keys[node_index] != new_value))
+ hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size);
+
+ /* Step 3: Actually do the write */
+ hash_table->values[node_index] = new_value;
+ /* Now, the bookkeeping... */
+ if (!already_exists)
+ {
hash_table->nnodes++;
if (HASH_IS_UNUSED (old_hash))
#endif
}
- if (HASH_IS_REAL (old_hash))
+ if (already_exists)
{
- if (hash_table->key_destroy_func)
- hash_table->key_destroy_func (keep_new_key ? old_key : key);
+ if (hash_table->key_destroy_func && !reusing_key)
+ (* hash_table->key_destroy_func) (key_to_free);
if (hash_table->value_destroy_func)
- hash_table->value_destroy_func (old_value);
+ (* hash_table->value_destroy_func) (value_to_free);
}
+
+ return !already_exists;
}
/**
node_hash = ri->hash_table->hashes[ri->position];
key = ri->hash_table->keys[ri->position];
- g_hash_table_insert_node (ri->hash_table, ri->position, node_hash, key, value, TRUE);
+ g_hash_table_insert_node (ri->hash_table, ri->position, node_hash, key, value, TRUE, TRUE);
#ifndef G_DISABLE_ASSERT
ri->version++;
* 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: 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,
* g_hash_table_lookup_extended:
* @hash_table: a #GHashTable
* @lookup_key: the key to look up
- * @orig_key: return location for the original key, or %NULL
- * @value: return location for the value associated with the key, or %NULL
+ * @orig_key: (allow-none): return location for the original key, or %NULL
+ * @value: (allow-none): return location for the value associated with the key, or %NULL
*
* Looks up a key in the #GHashTable, returning the original key and the
* associated value and a #gboolean which is %TRUE if the key was found. This
* 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);
+ 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);
+}
+
+/**
+ * g_hash_table_add:
+ * @hash_table: a #GHashTable
+ * @key: a key to insert
+ *
+ * This is a convenience function for using a #GHashTable as a set. It
+ * is equivalent to calling g_hash_table_replace() with @key as both the
+ * key and the value.
+ *
+ * When a hash table only ever contains keys that have themselves as the
+ * 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
+ */
+gboolean
+g_hash_table_add (GHashTable *hash_table,
+ gpointer key)
+{
+ return g_hash_table_insert_internal (hash_table, key, key, TRUE);
+}
+
+/**
+ * g_hash_table_contains:
+ * @hash_table: a #GHashTable
+ * @key: a key to check
+ *
+ * Checks if @key is in @hash_table.
+ *
+ * Since: 2.32
+ **/
+gboolean
+g_hash_table_contains (GHashTable *hash_table,
+ gconstpointer key)
+{
+ guint node_index;
+ guint node_hash;
+
+ g_return_val_if_fail (hash_table != NULL, FALSE);
+
+ node_index = g_hash_table_lookup_node (hash_table, key, &node_hash);
+
+ return HASH_IS_REAL (hash_table->hashes[node_index]);
}
/*
* @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,
{
gint i;
#ifndef G_DISABLE_ASSERT
- gint version = hash_table->version;
+ gint version;
#endif
g_return_if_fail (hash_table != NULL);
g_return_if_fail (func != NULL);
+#ifndef G_DISABLE_ASSERT
+ version = hash_table->version;
+#endif
+
for (i = 0; i < hash_table->size; i++)
{
guint node_hash = hash_table->hashes[i];
* (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: 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.
*
{
gint i;
#ifndef G_DISABLE_ASSERT
- gint version = hash_table->version;
+ gint version;
#endif
gboolean match;
g_return_val_if_fail (hash_table != NULL, NULL);
g_return_val_if_fail (predicate != NULL, NULL);
+#ifndef G_DISABLE_ASSERT
+ version = hash_table->version;
+#endif
+
match = FALSE;
for (i = 0; i < hash_table->size; i++)
*
* 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.
*
* Compares two strings for byte-by-byte equality and returns %TRUE
* if they are equal. It can be passed to g_hash_table_new() as the
- * @key_equal_func parameter, when using strings as keys in a #GHashTable.
+ * @key_equal_func parameter, when using non-%NULL strings as keys in a
+ * #GHashTable.
*
* Note that this function is primarily meant as a hash table comparison
* function. For a general-purpose, %NULL-safe string comparison function,
*
* 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 strings as keys in a #GHashTable.
+ * when using non-%NULL strings as keys in a #GHashTable.
*
* Returns: a hash value corresponding to the key
*/
* 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.
*/
* Compares the two #gint values being pointed to and returns
* %TRUE if they are equal.
* It can be passed to g_hash_table_new() as the @key_equal_func
- * parameter, when using pointers to integers as keys in a #HashTable.
+ * 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.
*/
*
* Converts a pointer to a #gint to a hash value.
* It can be passed to g_hash_table_new() as the @hash_func parameter,
- * when using pointers to integers values as keys in a #GHashTable.
+ * 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.
*/
* Compares the two #gint64 values being pointed to and returns
* %TRUE if they are equal.
* It can be passed to g_hash_table_new() as the @key_equal_func
- * parameter, when using pointers to 64-bit integers as keys in a #GHashTable.
+ * parameter, when using non-%NULL pointers to 64-bit integers as keys in a
+ * #GHashTable.
*
* Returns: %TRUE if the two keys match.
*
* @v: a pointer to a #gint64 key
*
* Converts a pointer to a #gint64 to a hash value.
+ *
* It can be passed to g_hash_table_new() as the @hash_func parameter,
- * when using pointers to 64-bit integers values as keys in a #GHashTable.
+ * when using non-%NULL pointers to 64-bit integer values as keys in a
+ * #GHashTable.
*
* Returns: a hash value corresponding to the key.
*
* Compares the two #gdouble values being pointed to and returns
* %TRUE if they are equal.
* It can be passed to g_hash_table_new() as the @key_equal_func
- * parameter, when using pointers to doubles as keys in a #GHashTable.
+ * parameter, when using non-%NULL pointers to doubles as keys in a
+ * #GHashTable.
*
* Returns: %TRUE if the two keys match.
*
*
* Converts a pointer to a #gdouble to a hash value.
* It can be passed to g_hash_table_new() as the @hash_func parameter,
- * when using pointers to doubles as keys in a #GHashTable.
+ * It can be passed to g_hash_table_new() as the @hash_func parameter,
+ * when using non-%NULL pointers to doubles as keys in a #GHashTable.
*
* Returns: a hash value corresponding to the key.
*