diff --git a/ChangeLog b/ChangeLog index 32e3ab4f1..8975abf42 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,14 @@ WeeChat ChangeLog ================= Sébastien Helleu -v0.4.1-dev, 2013-01-25 +v0.4.1-dev, 2013-01-26 Version 0.4.1 (under dev!) -------------------------- +* core: use default hash/comparison callback for keys of type + integer/pointer/time in hashtable * guile: fix compilation with guile 2.0 * irc: add color in output of /names when result is on server buffer (channel not joined) (bug #38070) diff --git a/doc/en/weechat_plugin_api.en.txt b/doc/en/weechat_plugin_api.en.txt index 1fec6f25c..c28a491a4 100644 --- a/doc/en/weechat_plugin_api.en.txt +++ b/doc/en/weechat_plugin_api.en.txt @@ -3248,14 +3248,14 @@ Arguments: ** 'WEECHAT_HASHTABLE_BUFFER' ** 'WEECHAT_HASHTABLE_TIME' * 'callback_hash_key': callback used to "hash" a key (key as integer value), can - be NULL if key type is "string" (a default function is used for strings, and - only for strings), arguments and return value: + be NULL if key type is not "buffer" (a default hash function is used), + arguments and return value: ** 'struct t_hashtable *hashtable': hashtable pointer ** 'const void *key': key ** return value: hash of the key -* 'callback_keycmp': callback used to compare two keys, can be NULL if value - type is "string" (a default comparison function is used for strings, and only - for strings), arguments and return value: +* 'callback_keycmp': callback used to compare two keys, can be NULL if key type + is not "buffer" (a default comparison function is used), arguments and return + value: ** 'struct t_hashtable *hashtable': hashtable pointer ** 'const void *key1': first key ** 'const void *key2': second key diff --git a/doc/fr/weechat_plugin_api.fr.txt b/doc/fr/weechat_plugin_api.fr.txt index 8d7e1be03..ed1db368c 100644 --- a/doc/fr/weechat_plugin_api.fr.txt +++ b/doc/fr/weechat_plugin_api.fr.txt @@ -3287,15 +3287,15 @@ Paramètres : ** 'WEECHAT_HASHTABLE_BUFFER' ** 'WEECHAT_HASHTABLE_TIME' * 'callback_hash_key' : fonction appelée pour rendre le "hash" d'une clé (la clé - sous forme de nombre entier), peut être NULL si le type de clé est "string" - (une fonction par défaut est utilisée pour les chaînes, et seulement pour les - chaînes). Paramètres et valeur de retour : + sous forme de nombre entier), peut être NULL si le type de clé n'est pas + "buffer" (une fonction de hash par défaut est utilisée), paramètres et valeur + de retour : ** 'struct t_hashtable *hashtable' : pointeur vers la hashtable ** 'const void *key' : clé ** valeur de retour : "hash" de la clé * 'callback_keycmp' : fonction appelée pour comparer deux clés, peut être NULL - si le type de valeur est "string" (une fonction par défaut est utilisée pour - les chaînes, et seulement pour les chaînes). Paramètres et valeur de retour : + si le type de clé n'est pas "buffer" (une fonction de comparaison par défaut + est utilisée), paramètres et valeur de retour : ** 'struct t_hashtable *hashtable' : pointeur vers la hashtable ** 'const void *key1' : première clé ** 'const void *key2' : seconde clé diff --git a/doc/it/weechat_plugin_api.it.txt b/doc/it/weechat_plugin_api.it.txt index d028a0ade..24b158a06 100644 --- a/doc/it/weechat_plugin_api.it.txt +++ b/doc/it/weechat_plugin_api.it.txt @@ -3246,16 +3246,17 @@ Argomenti: ** 'WEECHAT_HASHTABLE_POINTER' ** 'WEECHAT_HASHTABLE_BUFFER' ** 'WEECHAT_HASHTABLE_TIME' -* 'callback_hash_key': callback utilizzata per effettuare un "hash" di una - chiave (chiave come valore intero), può essere NULL se il tipo della chiave è - "string" (viene usata una funzione predefinita per le stringhe, e solo per le - stringhe), argomenti e valore restituito: +// TRANSLATION MISSING +* 'callback_hash_key': callback used to "hash" a key (key as integer value), can + be NULL if key type is not "buffer" (a default hash function is used), + arguments and return value: ** 'struct t_hashtable *hashtable': puntatore alla tabella hash ** 'const void *key': chiave ** return value: hash della chiave -* 'callback_keycmp': callback utilizzata per comparare due chiavi, può essere - NULL se il tipo di valore è "string" (una funzione di confronto predefinita è - usata per le stringhe e solo per le stringhe), argomenti e valore restituito: +// TRANSLATION MISSING +* 'callback_keycmp': callback used to compare two keys, can be NULL if key type + is not "buffer" (a default comparison function is used), arguments and return + value: ** 'struct t_hashtable *hashtable': puntatore alla tabella hash ** 'const void *key1': prima chiave ** 'const void *key2': seconda chiave diff --git a/src/core/wee-hashtable.c b/src/core/wee-hashtable.c index 8694f88ef..945b6c38a 100644 --- a/src/core/wee-hashtable.c +++ b/src/core/wee-hashtable.c @@ -67,43 +67,97 @@ hashtable_get_type (const char *type) } /* - * Hashes a string key (default callback). + * Hashes a key (default callback). * * Returns an unsigned integer between 0 and size-1. */ unsigned int -hashtable_hash_key_string_cb (struct t_hashtable *hashtable, const void *key) +hashtable_hash_key_default_cb (struct t_hashtable *hashtable, const void *key) { - const char *ptr_key; unsigned long hash; + const char *ptr_key; - /* variant of djb2 hash */ - hash = 5381; - for (ptr_key = (const char *)key; ptr_key[0]; ptr_key++) + hash = 0; + + switch (hashtable->type_keys) { - hash ^= (hash << 5) + (hash >> 2) + (int)(ptr_key[0]); + case HASHTABLE_INTEGER: + hash = (unsigned long)(*((int *)key)); + break; + case HASHTABLE_STRING: + /* variant of djb2 hash */ + hash = 5381; + for (ptr_key = (const char *)key; ptr_key[0]; ptr_key++) + { + hash ^= (hash << 5) + (hash >> 2) + (int)(ptr_key[0]); + } + break; + case HASHTABLE_POINTER: + hash = (unsigned long)((void *)key); + break; + case HASHTABLE_BUFFER: + break; + case HASHTABLE_TIME: + hash = (unsigned long)(*((time_t *)key)); + break; + case HASHTABLE_NUM_TYPES: + break; } + return hash % hashtable->size; } /* - * Compares two string keys (default callback). + * Compares two keys (default callback). * * Returns: - * -1: key1 < key2 - * 0: key1 == key2 - * 1: key1 > key2 + * < 0: key1 < key2 + * 0: key1 == key2 + * > 0: key1 > key2 */ int -hashtable_keycmp_string_cb (struct t_hashtable *hashtable, - const void *key1, const void *key2) +hashtable_keycmp_default_cb (struct t_hashtable *hashtable, + const void *key1, const void *key2) { + int rc; + /* make C compiler happy */ (void) hashtable; - return strcmp ((const char *)key1, (const char *)key2); + rc = 0; + + switch (hashtable->type_keys) + { + case HASHTABLE_INTEGER: + if (*((int *)key1) < *((int *)key2)) + rc = -1; + else if (*((int *)key1) > *((int *)key2)) + rc = 1; + break; + case HASHTABLE_STRING: + rc = strcmp ((const char *)key1, (const char *)key2); + break; + case HASHTABLE_POINTER: + if (key1 < key2) + rc = -1; + else if (key1 > key2) + rc = 1; + break; + case HASHTABLE_BUFFER: + break; + case HASHTABLE_TIME: + if (*((time_t *)key1) < *((time_t *)key2)) + rc = -1; + else if (*((time_t *)key1) > *((time_t *)key2)) + rc = 1; + break; + case HASHTABLE_NUM_TYPES: + break; + } + + return rc; } /* @@ -126,6 +180,9 @@ hashtable_new (int size, struct t_hashtable *new_hashtable; int i, type_keys_int, type_values_int; + if (size <= 0) + return NULL; + type_keys_int = hashtable_get_type (type_keys); if (type_keys_int < 0) return NULL; @@ -133,7 +190,8 @@ hashtable_new (int size, if (type_values_int < 0) return NULL; - if ((type_keys_int != HASHTABLE_STRING) && (!callback_hash_key || !callback_keycmp)) + /* the two callbacks are mandatory if type of keys is "buffer" */ + if ((type_keys_int == HASHTABLE_BUFFER) && (!callback_hash_key || !callback_keycmp)) return NULL; new_hashtable = malloc (sizeof (*new_hashtable)); @@ -155,15 +213,10 @@ hashtable_new (int size, } new_hashtable->items_count = 0; - if ((type_keys_int == HASHTABLE_STRING) && !callback_hash_key) - new_hashtable->callback_hash_key = &hashtable_hash_key_string_cb; - else - new_hashtable->callback_hash_key = callback_hash_key; - - if ((type_keys_int == HASHTABLE_STRING) && !callback_keycmp) - new_hashtable->callback_keycmp = &hashtable_keycmp_string_cb; - else - new_hashtable->callback_keycmp = callback_keycmp; + new_hashtable->callback_hash_key = (callback_hash_key) ? + callback_hash_key : &hashtable_hash_key_default_cb; + new_hashtable->callback_keycmp = (callback_keycmp) ? + callback_keycmp : &hashtable_keycmp_default_cb; new_hashtable->callback_free_value = NULL; } diff --git a/src/core/wee-hashtable.h b/src/core/wee-hashtable.h index 0af46b8e2..3a07c30a1 100644 --- a/src/core/wee-hashtable.h +++ b/src/core/wee-hashtable.h @@ -57,13 +57,13 @@ typedef void (t_hashtable_map_string)(void *data, * +-----+ * | 3 | --> "fast" --> "light" * +-----+ - * | 4 | --> "weechat" + * | 4 | * +-----+ * | 5 | --> "chat" * +-----+ * | 6 | --> "client" * +-----+ - * | 7 | + * | 7 | --> "weechat" * +-----+ */