diff --git a/doc/en/weechat_plugin_api.en.txt b/doc/en/weechat_plugin_api.en.txt index 77d2993e5..bd7362405 100644 --- a/doc/en/weechat_plugin_api.en.txt +++ b/doc/en/weechat_plugin_api.en.txt @@ -2541,6 +2541,305 @@ weechat.list_free(list) weechat.list_free(list) ---------------------------------------- +[[hashtables]] +Hashtables +~~~~~~~~~~ + +Hashtable functions. + +weechat_hashtable_new +^^^^^^^^^^^^^^^^^^^^^ + +Create a new hashtable. + +Prototype: + +[source,C] +---------------------------------------- +struct t_hashtable *weechat_hashtable_new (int size, + const char *type_keys, + const char *type_values, + unsigned int (*callback_hash_key)(struct t_hashtable *hashtable, + const void *key), + int (*callback_keycmp)(struct t_hashtable *hashtable, + const void *key1, + const void *key2)); +---------------------------------------- + +Arguments: + +* 'size': size of internal array to store hashed keys, a high value uses more + memory, but has better performance (this is *not* a limit for number of items + in hashtable) +* 'type_keys': type for keys in hashtable: +** 'WEECHAT_HASHTABLE_INTEGER' +** 'WEECHAT_HASHTABLE_STRING' +** 'WEECHAT_HASHTABLE_POINTER' +** 'WEECHAT_HASHTABLE_BUFFER' +** 'WEECHAT_HASHTABLE_TIME' +* 'type_values': type for values in hashtable: +** 'WEECHAT_HASHTABLE_INTEGER' +** 'WEECHAT_HASHTABLE_STRING' +** 'WEECHAT_HASHTABLE_POINTER' +** '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) +* '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) + +Return value: + +* pointer to new hashtable, NULL if an error occured + +C example: + +[source,C] +---------------------------------------- +struct t_hashtable *hashtable = weechat_hashtable_new (8, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); +---------------------------------------- + +weechat_hashtable_set_with_size +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Add or update item in a hashtable with size for key and value. + +Prototype: + +[source,C] +---------------------------------------- +int weechat_hashtable_set_with_size (struct t_hashtable *hashtable, + void *key, int key_size, + void *value, int value_size); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer +* 'key': key pointer +* 'key_size': size of key (in bytes), used only if type of keys in hashtable + is "buffer" +* 'value': value pointer +* 'value_size': size of value (in bytes), used only if type of values in + hashtable is "buffer" + +Return value: + +* 1 if ok, 0 if error + +C example: + +[source,C] +---------------------------------------- +weechat_hashtable_set_with_size (hashtable, "my_key", 0, + my_buffer, sizeof (my_buffer_struct)); +---------------------------------------- + +weechat_hashtable_set +^^^^^^^^^^^^^^^^^^^^^ + +Add or update item in a hashtable. + +Prototype: + +[source,C] +---------------------------------------- +int weechat_hashtable_set (struct t_hashtable *hashtable, + void *key, void *value); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer +* 'key': key pointer +* 'value': value pointer + +Return value: + +* 1 if ok, 0 if error + +C example: + +[source,C] +---------------------------------------- +weechat_hashtable_set (hashtable, "my_key", "my_value"); +---------------------------------------- + +weechat_hashtable_get +^^^^^^^^^^^^^^^^^^^^^ + +Get value associated with a key in a hashtable. + +Prototype: + +[source,C] +---------------------------------------- +void *weechat_hashtable_get (struct t_hashtable *hashtable, void *key); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer +* 'key': key pointer + +Return value: + +* value for key, NULL if key is not found + +C example: + +[source,C] +---------------------------------------- +void *value = weechat_hashtable_get (hashtable, "my_key"); +---------------------------------------- + +weechat_hashtable_map +^^^^^^^^^^^^^^^^^^^^^ + +Call a function on all hashtable entries. + +Prototype: + +[source,C] +---------------------------------------- +void hashtable_map (struct t_hashlist *hashlist, + int (*callback_map)(void *data, + struct t_hashtable *hashtable, + const void *key, + const void *value), + void *callback_map_data); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer +* 'callback_map': function called for each entry in hashtable +* 'callback_map_data': pointer given to map callback when it is called + +C example: + +[source,C] +---------------------------------------- +void +map_cb (void *data, struct t_hashtable *hashtable, + const void *key, const void *value) +{ + /* display key and value (they are both strings here) */ + weechat_printf (NULL, "key: '%s', value: '%s'", + (const char *)key, + (const char *)value); +} +/* ... */ +weechat_hashtable_map (hashtable, &map_cb, NULL); +---------------------------------------- + +weechat_hashtable_get_integer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Return integer value of a hashtable property. + +Prototype: + +[source,C] +---------------------------------------- +int weechat_hashtable_get_integer (struct t_hashtable *hashtable, + void *property); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer +* 'property': property name: +** 'size': size of internal array "htable" in hashtable +** 'items_count': number of items in hashtable + +Return value: + +* integer value of property + +C example: + +[source,C] +---------------------------------------- +int items_count = weechat_hashtable_get_integer (hashtable, "items_count"); +---------------------------------------- + +weechat_hashtable_remove +^^^^^^^^^^^^^^^^^^^^^^^^ + +Remove an item in a hashtable. + +Prototype: + +[source,C] +---------------------------------------- +void weechat_hashtable_remove (struct t_hashtable *hashtable, const void *key); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer +* 'key': key pointer + +C example: + +[source,C] +---------------------------------------- +weechat_hashtable_remove (hashtable, "my_key"); +---------------------------------------- + +weechat_hashtable_remove_all +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Remove all items in a hashtable. + +Prototype: + +[source,C] +---------------------------------------- +void weechat_hashtable_remove_all (struct t_hashtable *hashtable); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer + +C example: + +[source,C] +---------------------------------------- +weechat_hashtable_remove_all (hashtable); +---------------------------------------- + +weechat_hashtable_free +^^^^^^^^^^^^^^^^^^^^^^ + +Free a hashtable. + +Prototype: + +[source,C] +---------------------------------------- +void weechat_hashtable_free (struct t_hashtable *hashtable); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer + +C example: + +[source,C] +---------------------------------------- +weechat_hashtable_free (hashtable); +---------------------------------------- + [[configuration_files]] Configuration files ~~~~~~~~~~~~~~~~~~~ diff --git a/doc/fr/weechat_plugin_api.fr.txt b/doc/fr/weechat_plugin_api.fr.txt index 9037f949e..e2cdcb185 100644 --- a/doc/fr/weechat_plugin_api.fr.txt +++ b/doc/fr/weechat_plugin_api.fr.txt @@ -2567,6 +2567,308 @@ weechat.list_free(list) weechat.list_free(list) ---------------------------------------- +[[hashtables]] +Hashtables +~~~~~~~~~~ + +Hashtable functions. + +weechat_hashtable_new +^^^^^^^^^^^^^^^^^^^^^ + +Crée une nouvelle hashtable. + +Prototype : + +[source,C] +---------------------------------------- +struct t_hashtable *weechat_hashtable_new (int size, + const char *type_keys, + const char *type_values, + unsigned int (*callback_hash_key)(struct t_hashtable *hashtable, + const void *key), + int (*callback_keycmp)(struct t_hashtable *hashtable, + const void *key1, + const void *key2)); +---------------------------------------- + +Paramètres : + +* 'size' : taille du tableau interne pour stocker les clés sous forme de "hash", + une grande valeur utilise plus de mémoire mais présente une meilleure + performance (cela n'est *pas* une limite sur le nombre d'entrées de la + hashtable) +* 'type_keys' : type pour les clés dans la hashtable : +** 'WEECHAT_HASHTABLE_INTEGER' +** 'WEECHAT_HASHTABLE_STRING' +** 'WEECHAT_HASHTABLE_POINTER' +** 'WEECHAT_HASHTABLE_BUFFER' +** 'WEECHAT_HASHTABLE_TIME' +* 'type_values' : type pour les valeurs dans la hashtable : +** 'WEECHAT_HASHTABLE_INTEGER' +** 'WEECHAT_HASHTABLE_STRING' +** 'WEECHAT_HASHTABLE_POINTER' +** '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) +* '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) + +Valeur de retour : + +* pointeur vers la nouvelle hashtable, NULL en cas d'erreur + +Exemple en C : + +[source,C] +---------------------------------------- +struct t_hashtable *hashtable = weechat_hashtable_new (8, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); +---------------------------------------- + +weechat_hashtable_set_with_size +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Ajoute ou met à jour une entrée dans une hashtable avec une taille pour la clé +et la valeur. + +Prototype : + +[source,C] +---------------------------------------- +int weechat_hashtable_set_with_size (struct t_hashtable *hashtable, + void *key, int key_size, + void *value, int value_size); +---------------------------------------- + +Paramètres : + +* 'hashtable' : pointeur vers la hashtable +* 'key' : pointeur vers la clé +* 'key_size' : taille de la clé (en octets), utilisée seulement si le type de + clés dans la hashtable est "buffer" +* 'value' : pointeur vers la valeur +* 'value_size' : taille de la valeur (en octets), utilisée seulement si le type + de valeurs dans la hashtable est "buffer" + +Valeur de retour : + +* 1 si ok, 0 en cas d'erreur + +Exemple en C : + +[source,C] +---------------------------------------- +weechat_hashtable_set_with_size (hashtable, "ma_cle", 0, + my_buffer, sizeof (my_buffer_struct)); +---------------------------------------- + +weechat_hashtable_set +^^^^^^^^^^^^^^^^^^^^^ + +Ajoute ou met à jour une entrée dans la hashtable. + +Prototype : + +[source,C] +---------------------------------------- +int weechat_hashtable_set (struct t_hashtable *hashtable, + void *key, void *value); +---------------------------------------- + +Paramètres : + +* 'hashtable' : pointeur vers la hashtable +* 'key' : pointeur vers la clé +* 'value' : pointeur vers la valeur + +Valeur de retour : + +* 1 si ok, 0 en cas d'erreur + +Exemple en C : + +[source,C] +---------------------------------------- +weechat_hashtable_set (hashtable, "ma_cle", "ma_valeur"); +---------------------------------------- + +weechat_hashtable_get +^^^^^^^^^^^^^^^^^^^^^ + +Retourne la valeur associée à une clé dans une hashtable. + +Prototype : + +[source,C] +---------------------------------------- +void *weechat_hashtable_get (struct t_hashtable *hashtable, void *key); +---------------------------------------- + +Paramètres : + +* 'hashtable' : pointeur vers la hashtable +* 'key' : pointeur vers la clé + +Valeur en retour : + +* valeur pour la clé, NULL si la clé n'est pas trouvée + +Exemple en C : + +[source,C] +---------------------------------------- +void *value = weechat_hashtable_get (hashtable, "ma_cle"); +---------------------------------------- + +weechat_hashtable_map +^^^^^^^^^^^^^^^^^^^^^ + +Appelle une fonction pour chaque entrée d'une hashtable. + +Prototype : + +[source,C] +---------------------------------------- +void hashtable_map (struct t_hashlist *hashlist, + int (*callback_map)(void *data, + struct t_hashtable *hashtable, + const void *key, + const void *value), + void *callback_map_data); +---------------------------------------- + +Paramètres : + +* 'hashtable' : pointeur vers la hashtable +* 'callback_map' : fonction appelée pour chaque entrée de la hashtable +* 'callback_map_data' : pointeur donné au "callback" lorsqu'il est appelé + +Exemple en C : + +[source,C] +---------------------------------------- +void +map_cb (void *data, struct t_hashtable *hashtable, + const void *key, const void *value) +{ + /* afficher la clé et la valeur (elles sont des chaînes ici) */ + weechat_printf (NULL, "clé: '%s', valeur: '%s'", + (const char *)key, + (const char *)value); +} +/* ... */ +weechat_hashtable_map (hashtable, &map_cb, NULL); +---------------------------------------- + +weechat_hashtable_get_integer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Retourne une valeur entière pour une propriété d'une hashtable. + +Prototype : + +[source,C] +---------------------------------------- +int weechat_hashtable_get_integer (struct t_hashtable *hashtable, + void *property); +---------------------------------------- + +Paramètres : + +* 'hashtable' : pointeur vers la hashtable +* 'property' : nom de propriété : +** 'size' : taille du tableau interne "htable" dans la hashtable +** 'items_count' : nombre d'éléments dans la hashtable + +Valeur en retour : + +* valeur entière de l'option + +Exemple en C : + +[source,C] +---------------------------------------- +int items_count = weechat_hashtable_get_integer (hashtable, "items_count"); +---------------------------------------- + +weechat_hashtable_remove +^^^^^^^^^^^^^^^^^^^^^^^^ + +Supprime un élément d'une hashtable. + +Prototype : + +[source,C] +---------------------------------------- +void weechat_hashtable_remove (struct t_hashtable *hashtable, const void *key); +---------------------------------------- + +Paramètres : + +* 'hashtable' : pointeur vers la hashtable +* 'key' : pointeur vers la clé + +Exemple en C : + +[source,C] +---------------------------------------- +weechat_hashtable_remove (hashtable, "ma_cle"); +---------------------------------------- + +weechat_hashtable_remove_all +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Supprime tous les éléments d'une hashtable. + +Prototype : + +[source,C] +---------------------------------------- +void weechat_hashtable_remove_all (struct t_hashtable *hashtable); +---------------------------------------- + +Paramètres : + +* 'hashtable' : pointeur vers la hashtable + +Exemple en C : + +[source,C] +---------------------------------------- +weechat_hashtable_remove_all (hashtable); +---------------------------------------- + +weechat_hashtable_free +^^^^^^^^^^^^^^^^^^^^^^ + +Supprime une hashtable. + +Prototype : + +[source,C] +---------------------------------------- +void weechat_hashtable_free (struct t_hashtable *hashtable); +---------------------------------------- + +Paramètres : + +* 'hashtable' : pointeur vers la hashtable + +Exemple en C : + +[source,C] +---------------------------------------- +weechat_hashtable_free (hashtable); +---------------------------------------- + [[configuration_files]] Fichiers de configuration ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/it/weechat_plugin_api.it.txt b/doc/it/weechat_plugin_api.it.txt index b01728fb9..dfe399b54 100644 --- a/doc/it/weechat_plugin_api.it.txt +++ b/doc/it/weechat_plugin_api.it.txt @@ -2579,6 +2579,305 @@ weechat.list_free(list) weechat.list_free(list) ---------------------------------------- +[[hashtables]] +Hashtables +~~~~~~~~~~ + +Hashtable functions. + +weechat_hashtable_new +^^^^^^^^^^^^^^^^^^^^^ + +Create a new hashtable. + +Prototype: + +[source,C] +---------------------------------------- +struct t_hashtable *weechat_hashtable_new (int size, + const char *type_keys, + const char *type_values, + unsigned int (*callback_hash_key)(struct t_hashtable *hashtable, + const void *key), + int (*callback_keycmp)(struct t_hashtable *hashtable, + const void *key1, + const void *key2)); +---------------------------------------- + +Arguments: + +* 'size': size of internal array to store hashed keys, a high value uses more + memory, but has better performance (this is *not* a limit for number of items + in hashtable) +* 'type_keys': type for keys in hashtable: +** 'WEECHAT_HASHTABLE_INTEGER' +** 'WEECHAT_HASHTABLE_STRING' +** 'WEECHAT_HASHTABLE_POINTER' +** 'WEECHAT_HASHTABLE_BUFFER' +** 'WEECHAT_HASHTABLE_TIME' +* 'type_values': type for values in hashtable: +** 'WEECHAT_HASHTABLE_INTEGER' +** 'WEECHAT_HASHTABLE_STRING' +** 'WEECHAT_HASHTABLE_POINTER' +** '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) +* '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) + +Return value: + +* pointer to new hashtable, NULL if an error occured + +C example: + +[source,C] +---------------------------------------- +struct t_hashtable *hashtable = weechat_hashtable_new (8, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); +---------------------------------------- + +weechat_hashtable_set_with_size +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Add or update item in a hashtable with size for key and value. + +Prototype: + +[source,C] +---------------------------------------- +int weechat_hashtable_set_with_size (struct t_hashtable *hashtable, + void *key, int key_size, + void *value, int value_size); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer +* 'key': key pointer +* 'key_size': size of key (in bytes), used only if type of keys in hashtable + is "buffer" +* 'value': value pointer +* 'value_size': size of value (in bytes), used only if type of values in + hashtable is "buffer" + +Return value: + +* 1 if ok, 0 if error + +C example: + +[source,C] +---------------------------------------- +weechat_hashtable_set_with_size (hashtable, "my_key", 0, + my_buffer, sizeof (my_buffer_struct)); +---------------------------------------- + +weechat_hashtable_set +^^^^^^^^^^^^^^^^^^^^^ + +Add or update item in a hashtable. + +Prototype: + +[source,C] +---------------------------------------- +int weechat_hashtable_set (struct t_hashtable *hashtable, + void *key, void *value); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer +* 'key': key pointer +* 'value': value pointer + +Return value: + +* 1 if ok, 0 if error + +C example: + +[source,C] +---------------------------------------- +weechat_hashtable_set (hashtable, "my_key", "my_value"); +---------------------------------------- + +weechat_hashtable_get +^^^^^^^^^^^^^^^^^^^^^ + +Get value associated with a key in a hashtable. + +Prototype: + +[source,C] +---------------------------------------- +void *weechat_hashtable_get (struct t_hashtable *hashtable, void *key); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer +* 'key': key pointer + +Return value: + +* value for key, NULL if key is not found + +C example: + +[source,C] +---------------------------------------- +void *value = weechat_hashtable_get (hashtable, "my_key"); +---------------------------------------- + +weechat_hashtable_map +^^^^^^^^^^^^^^^^^^^^^ + +Call a function on all hashtable entries. + +Prototype: + +[source,C] +---------------------------------------- +void hashtable_map (struct t_hashlist *hashlist, + int (*callback_map)(void *data, + struct t_hashtable *hashtable, + const void *key, + const void *value), + void *callback_map_data); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer +* 'callback_map': function called for each entry in hashtable +* 'callback_map_data': pointer given to map callback when it is called + +C example: + +[source,C] +---------------------------------------- +void +map_cb (void *data, struct t_hashtable *hashtable, + const void *key, const void *value) +{ + /* display key and value (they are both strings here) */ + weechat_printf (NULL, "key: '%s', value: '%s'", + (const char *)key, + (const char *)value); +} +/* ... */ +weechat_hashtable_map (hashtable, &map_cb, NULL); +---------------------------------------- + +weechat_hashtable_get_integer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Return integer value of a hashtable property. + +Prototype: + +[source,C] +---------------------------------------- +int weechat_hashtable_get_integer (struct t_hashtable *hashtable, + void *property); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer +* 'property': property name: +** 'size': size of internal array "htable" in hashtable +** 'items_count': number of items in hashtable + +Return value: + +* integer value of property + +C example: + +[source,C] +---------------------------------------- +int items_count = weechat_hashtable_get_integer (hashtable, "items_count"); +---------------------------------------- + +weechat_hashtable_remove +^^^^^^^^^^^^^^^^^^^^^^^^ + +Remove an item in a hashtable. + +Prototype: + +[source,C] +---------------------------------------- +void weechat_hashtable_remove (struct t_hashtable *hashtable, const void *key); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer +* 'key': key pointer + +C example: + +[source,C] +---------------------------------------- +weechat_hashtable_remove (hashtable, "my_key"); +---------------------------------------- + +weechat_hashtable_remove_all +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Remove all items in a hashtable. + +Prototype: + +[source,C] +---------------------------------------- +void weechat_hashtable_remove_all (struct t_hashtable *hashtable); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer + +C example: + +[source,C] +---------------------------------------- +weechat_hashtable_remove_all (hashtable); +---------------------------------------- + +weechat_hashtable_free +^^^^^^^^^^^^^^^^^^^^^^ + +Free a hashtable. + +Prototype: + +[source,C] +---------------------------------------- +void weechat_hashtable_free (struct t_hashtable *hashtable); +---------------------------------------- + +Arguments: + +* 'hashtable': hashtable pointer + +C example: + +[source,C] +---------------------------------------- +weechat_hashtable_free (hashtable); +---------------------------------------- + [[configuration_files]] File di configurazione ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 88800f59a..c1a22c81e 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -26,6 +26,7 @@ wee-command.c wee-command.h wee-config.c wee-config.h wee-config-file.c wee-config-file.h wee-debug.c wee-debug.h +wee-hashtable.c wee-hashtable.h wee-hook.c wee-hook.h wee-infolist.c wee-infolist.h wee-input.c wee-input.h diff --git a/src/core/Makefile.am b/src/core/Makefile.am index ab6f4a0df..aa663769e 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -33,6 +33,8 @@ lib_weechat_core_a_SOURCES = weechat.c \ wee-config-file.h \ wee-debug.c \ wee-debug.h \ + wee-hashtable.c \ + wee-hashtable.h \ wee-hook.c \ wee-hook.h \ wee-infolist.c \ diff --git a/src/core/wee-hashtable.c b/src/core/wee-hashtable.c new file mode 100644 index 000000000..e967fc6a6 --- /dev/null +++ b/src/core/wee-hashtable.c @@ -0,0 +1,549 @@ +/* + * Copyright (C) 2010 Sebastien Helleu + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see . + */ + +/* + * wee-hashtable.c: implementation of hashtable + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "weechat.h" +#include "wee-hashtable.h" +#include "wee-log.h" +#include "wee-string.h" +#include "../plugins/weechat-plugin.h" + + +char *hashtable_type_names[HASHTABLE_NUM_TYPES] = +{ "integer", "string", "pointer", "buffer", "time" }; + + +/* + * hashtable_get_type: get integer for type (string) + */ + +int +hashtable_get_type (const char *type) +{ + int i; + + if (!type) + return -1; + + for (i = 0; i < HASHTABLE_NUM_TYPES; i++) + { + if (string_strcasecmp (hashtable_type_names[i], type) == 0) + return i; + } + + /* type not found */ + return -1; +} + +/* + * hashtable_hash_key_string_cb: default callback to hash a string key + */ + +unsigned int +hashtable_hash_key_string_cb (struct t_hashtable *hashtable, const void *key) +{ + const char *ptr_key; + unsigned long hash; + + /* 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]); + } + return hash % hashtable->size; +} + +/* + * hashtable_keycmp_string_cb: default callback for string comparison on keys + */ + +int +hashtable_keycmp_string_cb (struct t_hashtable *hashtable, + const void *key1, const void *key2) +{ + /* make C compiler happy */ + (void) hashtable; + + return strcmp ((const char *)key1, (const char *)key2); +} + +/* + * hashtable_new: create a new hash table + */ + +struct t_hashtable * +hashtable_new (int size, + const char *type_keys, const char *type_values, + t_hashtable_hash_key *callback_hash_key, + t_hashtable_keycmp *callback_keycmp) +{ + struct t_hashtable *new_hashtable; + int i, type_keys_int, type_values_int; + + type_keys_int = hashtable_get_type (type_keys); + if (type_keys_int < 0) + return NULL; + type_values_int = hashtable_get_type (type_values); + if (type_values_int < 0) + return NULL; + + if ((type_keys_int != HASHTABLE_STRING) && (!callback_hash_key || !callback_keycmp)) + return NULL; + + new_hashtable = malloc (sizeof (*new_hashtable)); + if (new_hashtable) + { + new_hashtable->size = size; + new_hashtable->type_keys = type_keys_int; + new_hashtable->type_values = type_values_int; + new_hashtable->htable = malloc (size * sizeof (*(new_hashtable->htable))); + if (!new_hashtable->htable) + { + free (new_hashtable); + return NULL; + } + for (i = 0; i < size; i++) + { + new_hashtable->htable[i] = NULL; + } + 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; + } + return new_hashtable; +} + +/* + * hashtable_alloc_type: alloc space for a key or value + */ + +void +hashtable_alloc_type (enum t_hashtable_type type, void *value, int size_value, + void **pointer, int *size) +{ + switch (type) + { + case HASHTABLE_INTEGER: + *pointer = malloc (sizeof (int)); + if (*pointer) + *((int *)(*pointer)) = *((int *)value); + *size = (*pointer) ? sizeof (int) : 0; + break; + case HASHTABLE_STRING: + *pointer = strdup ((const char *)value); + *size = (*pointer) ? strlen (*pointer) + 1 : 0; + break; + case HASHTABLE_POINTER: + *pointer = value; + *size = sizeof (void *); + break; + case HASHTABLE_BUFFER: + *pointer = malloc (size_value); + if (*pointer) + memcpy (*pointer, value, size_value); + *size = (*pointer) ? size_value : 0; + break; + case HASHTABLE_TIME: + *pointer = malloc (sizeof (time_t)); + if (*pointer) + *((time_t *)(*pointer)) = *((time_t *)value); + *size = (*pointer) ? sizeof (time_t) : 0; + break; + case HASHTABLE_NUM_TYPES: + break; + } +} + +/* + * hashtable_free_type: free space used by a key or value + */ + +void +hashtable_free_type (enum t_hashtable_type type, void *value) +{ + switch (type) + { + case HASHTABLE_INTEGER: + case HASHTABLE_STRING: + case HASHTABLE_BUFFER: + case HASHTABLE_TIME: + free (value); + break; + case HASHTABLE_POINTER: + break; + case HASHTABLE_NUM_TYPES: + break; + } +} + +/* + * hashtable_set_with_size: set value for item in hash table + * argument size is used only for type "buffer" + * return 1 if ok, 0 if error + */ + +int +hashtable_set_with_size (struct t_hashtable *hashtable, + void *key, int key_size, + void *value, int value_size) +{ + unsigned int hash; + struct t_hashtable_item *ptr_item, *pos_item, *new_item; + + if (!hashtable + || ((hashtable->type_keys == HASHTABLE_BUFFER) && (key_size <= 0)) + || ((hashtable->type_values == HASHTABLE_BUFFER) && (value_size <= 0))) + { + return 0; + } + + /* search position for item in hash table */ + hash = hashtable->callback_hash_key (hashtable, key); + pos_item = NULL; + for (ptr_item = hashtable->htable[hash]; + ptr_item + && ((int)(hashtable->callback_keycmp) (hashtable, key, ptr_item->key) > 0); + ptr_item = ptr_item->next_item) + { + pos_item = ptr_item; + } + + /* replace value if item is already in hash table */ + if (ptr_item && (hashtable->callback_keycmp (hashtable, key, ptr_item->key) == 0)) + { + ptr_item->value = value; + return 1; + } + + /* create new item */ + new_item = malloc (sizeof (*new_item)); + if (!new_item) + return 0; + + /* set key and value */ + hashtable_alloc_type (hashtable->type_keys, + key, key_size, + &new_item->key, &new_item->key_size); + hashtable_alloc_type (hashtable->type_values, + value, value_size, + &new_item->value, &new_item->value_size); + + /* add item */ + if (pos_item) + { + /* insert item after position found */ + new_item->prev_item = pos_item; + new_item->next_item = pos_item->next_item; + if (pos_item->next_item) + (pos_item->next_item)->prev_item = new_item; + pos_item->next_item = new_item; + } + else + { + /* insert item at beginning of list */ + new_item->prev_item = NULL; + new_item->next_item = hashtable->htable[hash]; + if (hashtable->htable[hash]) + (hashtable->htable[hash])->prev_item = new_item; + hashtable->htable[hash] = new_item; + } + + hashtable->items_count++; + + return 1; +} + +/* + * hashtable_set: set value for item in hash table + * return 1 if ok, 0 if error + * Note: this function can be called *only* if key AND value are + * *not* of type "buffer" + */ + +int +hashtable_set (struct t_hashtable *hashtable, void *key, void *value) +{ + return hashtable_set_with_size (hashtable, key, 0, value, 0); +} + +/* + * hashtable_get_item: search an item in hashtable + * if hash is non NULL pointer, then it is set with + * hash value of key (even if key is not found) + */ + +struct t_hashtable_item * +hashtable_get_item (struct t_hashtable *hashtable, const void *key, + unsigned int *hash) +{ + unsigned int key_hash; + struct t_hashtable_item *ptr_item; + + if (!hashtable) + return NULL; + + key_hash = hashtable->callback_hash_key (hashtable, key); + if (hash) + *hash = key_hash; + for (ptr_item = hashtable->htable[key_hash]; + ptr_item && hashtable->callback_keycmp (hashtable, key, ptr_item->key) > 0; + ptr_item = ptr_item->next_item) + { + } + + if (ptr_item + && (hashtable->callback_keycmp (hashtable, key, ptr_item->key) == 0)) + { + return ptr_item; + } + + return NULL; +} + +/* + * hashtable_get: get value for a key in hash table + * return pointer to "value" for key, + * or NULL if key is not found in hash table + */ + +void * +hashtable_get (struct t_hashtable *hashtable, const void *key) +{ + struct t_hashtable_item *ptr_item; + + ptr_item = hashtable_get_item (hashtable, key, NULL); + + return (ptr_item) ? ptr_item->value : NULL; +} + +/* + * hashtable_map: call a function on all hashtable entries + */ + +void +hashtable_map (struct t_hashtable *hashtable, + t_hashtable_map *callback_map, + void *callback_map_data) +{ + int i; + struct t_hashtable_item *ptr_item; + + if (!hashtable) + return; + + for (i = 0; i < hashtable->size; i++) + { + for (ptr_item = hashtable->htable[i]; ptr_item; + ptr_item = ptr_item->next_item) + { + (void) (callback_map) (callback_map_data, + hashtable, + ptr_item->key, + ptr_item->value); + } + } +} + +/* + * hashtable_get_integer: get a hashtable property as integer + */ + +int +hashtable_get_integer (struct t_hashtable *hashtable, const char *property) +{ + if (hashtable && property) + { + if (string_strcasecmp (property, "size") == 0) + return hashtable->size; + else if (string_strcasecmp (property, "items_count") == 0) + return hashtable->items_count; + } + + return 0; +} + +/* + * hashtable_remove_item: remove an item from hashmap + */ + +void +hashtable_remove_item (struct t_hashtable *hashtable, + struct t_hashtable_item *item, + unsigned int hash) +{ + if (!hashtable || !item) + return; + + /* free key and value */ + hashtable_free_type (hashtable->type_keys, item->key); + hashtable_free_type (hashtable->type_values, item->value); + + /* remove item from list */ + if (item->prev_item) + (item->prev_item)->next_item = item->next_item; + if (item->next_item) + (item->next_item)->prev_item = item->prev_item; + if (hashtable->htable[hash] == item) + hashtable->htable[hash] = item->next_item; + + hashtable->items_count--; +} + +/* + * hashtable_remove: remove an item from hashmap (search it with key) + */ + +void +hashtable_remove (struct t_hashtable *hashtable, const void *key) +{ + struct t_hashtable_item *ptr_item; + unsigned int hash; + + ptr_item = hashtable_get_item (hashtable, key, &hash); + if (ptr_item) + hashtable_remove_item (hashtable, ptr_item, hash); +} + +/* + * hashtable_remove_all: remove all items from hashmap + */ + +void +hashtable_remove_all (struct t_hashtable *hashtable) +{ + int i; + + if (!hashtable) + return; + + for (i = 0; i < hashtable->size; i++) + { + while (hashtable->htable[i]) + { + hashtable_remove_item (hashtable, hashtable->htable[i], i); + } + } +} + +/* + * hashtable_free: free hashtable (remove all items and free hashtable) + */ + +void +hashtable_free (struct t_hashtable *hashtable) +{ + hashtable_remove_all (hashtable); + free (hashtable->htable); + free (hashtable); +} + +/* + * hashtable_print_log: print hashtable in log (usually for crash dump) + */ + +void +hashtable_print_log (struct t_hashtable *hashtable, const char *name) +{ + struct t_hashtable_item *ptr_item; + int i; + + log_printf (""); + log_printf ("[hashtable %s (addr:0x%lx)]", name, hashtable); + log_printf (" size . . . . . . . . . : %d", hashtable->size); + log_printf (" htable . . . . . . . . : 0x%lx", hashtable->htable); + log_printf (" items_count. . . . . . : %d", hashtable->items_count); + log_printf (" type_keys. . . . . . . : %d", hashtable->type_keys); + log_printf (" type_values. . . . . . : %d", hashtable->type_values); + log_printf (" callback_hash_key. . . : 0x%lx", hashtable->callback_hash_key); + log_printf (" callback_keycmp. . . . : 0x%lx", hashtable->callback_keycmp); + + for (i = 0; i < hashtable->size; i++) + { + log_printf (" htable[%06d] . . . . : 0x%lx", i, hashtable->htable[i]); + for (ptr_item = hashtable->htable[i]; ptr_item; + ptr_item = ptr_item->next_item) + { + log_printf (" [item 0x%lx]", hashtable->htable); + switch (hashtable->type_keys) + { + case HASHTABLE_INTEGER: + log_printf (" key (integer). . . : %d", *((int *)ptr_item->key)); + break; + case HASHTABLE_STRING: + log_printf (" key (string) . . . : '%s'", (char *)ptr_item->key); + break; + case HASHTABLE_POINTER: + log_printf (" key (pointer). . . : 0x%lx", ptr_item->key); + break; + case HASHTABLE_BUFFER: + log_printf (" key (buffer) . . . : 0x%lx", ptr_item->key); + break; + case HASHTABLE_TIME: + log_printf (" key (time) . . . . : %ld", *((time_t *)ptr_item->key)); + break; + case HASHTABLE_NUM_TYPES: + break; + } + log_printf (" key_size . . . . . : %d", ptr_item->key_size); + switch (hashtable->type_values) + { + case HASHTABLE_INTEGER: + log_printf (" value (integer). . : %d", *((int *)ptr_item->value)); + break; + case HASHTABLE_STRING: + log_printf (" value (string) . . : '%s'", (char *)ptr_item->value); + break; + case HASHTABLE_POINTER: + log_printf (" value (pointer). . : 0x%lx", ptr_item->value); + break; + case HASHTABLE_BUFFER: + log_printf (" value (buffer) . . : 0x%lx", ptr_item->value); + break; + case HASHTABLE_TIME: + log_printf (" value (time) . . . : %d", *((time_t *)ptr_item->value)); + break; + case HASHTABLE_NUM_TYPES: + break; + } + log_printf (" value_size . . . . : %d", ptr_item->value_size); + log_printf (" prev_item. . . . . : 0x%lx", ptr_item->prev_item); + log_printf (" next_item. . . . . : 0x%lx", ptr_item->next_item); + } + } +} diff --git a/src/core/wee-hashtable.h b/src/core/wee-hashtable.h new file mode 100644 index 000000000..392cbe416 --- /dev/null +++ b/src/core/wee-hashtable.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2010 Sebastien Helleu + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see . + */ + +#ifndef __WEECHAT_HASHTABLE_H +#define __WEECHAT_HASHTABLE_H 1 + +struct t_hashtable; + +typedef unsigned int (t_hashtable_hash_key)(struct t_hashtable *hashtable, + const void *key); +typedef int (t_hashtable_keycmp)(struct t_hashtable *hashtable, + const void *key1, const void *key2); +typedef void (t_hashtable_map)(void *data, + struct t_hashtable *hashtable, + const void *key, const void *value); + +/* + * Hashtable is a structure with an array "htable", each entry is a pointer + * to a linked list, and it is read with hashed key (as unsigned int). + * Keys with same hashed key are grouped in a linked list pointed by htable. + * htable is not sorted, linked list is sorted. + * + * Example of a hashtable with size 8 and 6 items added inside, items are: + * "weechat", "fast", "light", "extensible", "chat", "client" + * Keys "fast" and "light" have same hashed value, so they are together in + * linked list. + * + * Result is: + * +-----+ + * | 0 | + * +-----+ + * | 1 | + * +-----+ + * | 2 | --> "extensible" + * +-----+ + * | 3 | --> "fast" --> "light" + * +-----+ + * | 4 | --> "weechat" + * +-----+ + * | 5 | --> "chat" + * +-----+ + * | 6 | --> "client" + * +-----+ + * | 7 | + * +-----+ + */ + +enum t_hashtable_type +{ + HASHTABLE_INTEGER = 0, + HASHTABLE_STRING, + HASHTABLE_POINTER, + HASHTABLE_BUFFER, + HASHTABLE_TIME, + /* number of hashtable types */ + HASHTABLE_NUM_TYPES, +}; + +struct t_hashtable_item +{ + void *key; /* item key */ + int key_size; /* size of key (in bytes) */ + void *value; /* pointer to value */ + int value_size; /* size of value (in bytes) */ + struct t_hashtable_item *prev_item; /* link to previous item */ + struct t_hashtable_item *next_item; /* link to next item */ +}; + +struct t_hashtable +{ + int size; /* hashtable size */ + struct t_hashtable_item **htable; /* table to map hashes with linked */ + /* lists */ + int items_count; /* number of items in hashtable */ + + /* type for keys and values */ + enum t_hashtable_type type_keys; /* type for keys: int/str/pointer */ + enum t_hashtable_type type_values; /* type for values: int/str/pointer */ + + /* callbacks */ + t_hashtable_hash_key *callback_hash_key; /* hash key to integer value */ + t_hashtable_keycmp *callback_keycmp; /* compare two keys */ +}; + +extern struct t_hashtable *hashtable_new (int size, + const char *type_keys, + const char *type_values, + t_hashtable_hash_key *hash_key_cb, + t_hashtable_keycmp *keycmp_cb); +extern int hashtable_set_with_size (struct t_hashtable *hashtable, + void *key, int key_size, + void *value, int value_size); +extern int hashtable_set (struct t_hashtable *hashtable, void *key, + void *value); +extern void *hashtable_get (struct t_hashtable *hashtable, const void *key); +extern void hashtable_map (struct t_hashtable *hashtable, + t_hashtable_map *callback_map, + void *callback_map_data); +extern int hashtable_get_integer (struct t_hashtable *hashtable, + const char *property); +extern void hashtable_remove (struct t_hashtable *hashtable, const void *key); +extern void hashtable_remove_all (struct t_hashtable *hashtable); +extern void hashtable_free (struct t_hashtable *hashtable); +extern void hashtable_print_log (struct t_hashtable *hashtable, + const char *name); + +#endif /* __WEECHAT_HASHTABLE_H */ diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index fd1118138..b1a37e53c 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -38,6 +38,7 @@ #include "../core/weechat.h" #include "../core/wee-config.h" +#include "../core/wee-hashtable.h" #include "../core/wee-hook.h" #include "../core/wee-infolist.h" #include "../core/wee-list.h" @@ -520,6 +521,16 @@ plugin_load (const char *filename) new_plugin->list_remove_all = &weelist_remove_all; new_plugin->list_free = &weelist_free; + new_plugin->hashtable_new = &hashtable_new; + new_plugin->hashtable_set_with_size = &hashtable_set_with_size; + new_plugin->hashtable_set = &hashtable_set; + new_plugin->hashtable_get = &hashtable_get; + new_plugin->hashtable_map = &hashtable_map; + new_plugin->hashtable_get_integer = &hashtable_get_integer; + new_plugin->hashtable_remove = &hashtable_remove; + new_plugin->hashtable_remove_all = &hashtable_remove_all; + new_plugin->hashtable_free = &hashtable_free; + new_plugin->config_new = &config_file_new; new_plugin->config_new_section = &config_file_new_section; new_plugin->config_search_section = &config_file_search_section; diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h index 8b3a74f84..feb1f8d3a 100644 --- a/src/plugins/weechat-plugin.h +++ b/src/plugins/weechat-plugin.h @@ -35,6 +35,7 @@ struct t_gui_bar_item; struct t_gui_completion; struct t_infolist; struct t_weelist; +struct t_hashtable; struct timeval; /* @@ -93,6 +94,13 @@ struct timeval; #define WEECHAT_LIST_POS_BEGINNING "beginning" #define WEECHAT_LIST_POS_END "end" +/* type for keys and values in hashtable */ +#define WEECHAT_HASHTABLE_INTEGER "integer" +#define WEECHAT_HASHTABLE_STRING "string" +#define WEECHAT_HASHTABLE_POINTER "pointer" +#define WEECHAT_HASHTABLE_BUFFER "buffer" +#define WEECHAT_HASHTABLE_TIME "time" + /* buffer hotlist */ #define WEECHAT_HOTLIST_LOW "0" #define WEECHAT_HOTLIST_MESSAGE "1" @@ -241,6 +249,33 @@ struct t_weechat_plugin void (*list_remove_all) (struct t_weelist *weelist); void (*list_free) (struct t_weelist *weelist); + /* hash tables */ + struct t_hashtable *(*hashtable_new) (int size, + const char *type_keys, + const char *type_values, + unsigned int (*callback_hash_key)(struct t_hashtable *hashtable, + const void *key), + int (*callback_keycmp)(struct t_hashtable *hashtable, + const void *key1, + const void *key2)); + int (*hashtable_set_with_size) (struct t_hashtable *hashtable, + void *key, int key_size, + void *value, int value_size); + int (*hashtable_set) (struct t_hashtable *hashtable, void *key, + void *value); + void *(*hashtable_get) (struct t_hashtable *hashtable, const void *key); + void (*hashtable_map) (struct t_hashtable *hashtable, + void (*callback_map) (void *data, + struct t_hashtable *hashtable, + const void *key, + const void *value), + void *callback_map_data); + int (*hashtable_get_integer) (struct t_hashtable *hashtable, + const char *property); + void (*hashtable_remove) (struct t_hashtable *hashtable, const void *key); + void (*hashtable_remove_all) (struct t_hashtable *hashtable); + void (*hashtable_free) (struct t_hashtable *hashtable); + /* config files */ struct t_config_file *(*config_new) (struct t_weechat_plugin *plugin, const char *name, @@ -829,6 +864,31 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin); #define weechat_list_free(__list) \ weechat_plugin->list_free(__list) +/* hash tables */ +#define weechat_hashtable_new(__size, __type_keys, __type_values, \ + __hash_key_cb, __keycmp_cb) \ + weechat_plugin->hashtable_new(__size, __type_keys, __type_values, \ + __hash_key_cb, __keycmp_cb) +#define weechat_hashtable_set_with_size(__hashtable, __key, __key_size, \ + __value, __value_size) \ + weechat_plugin->hashtable_set_with_size(__hashtable, __key, \ + __key_size, __value, \ + __value_size) +#define weechat_hashtable_set(__hashtable, __key, __value) \ + weechat_plugin->hashtable_set(__hashtable, __key, __value) +#define weechat_hashtable_get(__hashtable, __key) \ + weechat_plugin->hashtable_get(__hashtable, __key) +#define weechat_hashtable_map(__hashtable, __cb_map, __cb_map_data) \ + weechat_plugin->hashtable_map(__hashtable, __cb_map, __cb_map_data) +#define weechat_hashtable_get_integer(__hashtable, __property) \ + weechat_plugin->hashtable_get_integer(__hashtable, __property) +#define weechat_hashtable_remove(__hashtable, __key) \ + weechat_plugin->hashtable_remove(__hashtable, __key) +#define weechat_hashtable_remove_all(__hashtable) \ + weechat_plugin->hashtable_remove_all(__hashtable) +#define weechat_hashtable_free(__hashtable) \ + weechat_plugin->hashtable_free(__hashtable) + /* config files */ #define weechat_config_new(__name, __callback_reload, \ __callback_reload_data) \