Add hashtable in core and plugin API

v2.8-utf8proc
Sebastien Helleu 2010-06-28 10:40:30 +02:00
parent ff97274bca
commit cb18bdb10b
9 changed files with 1646 additions and 0 deletions

View File

@ -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
~~~~~~~~~~~~~~~~~~~

View File

@ -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
~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -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
~~~~~~~~~~~~~~~~~~~~~~

View File

@ -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

View File

@ -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 \

549
src/core/wee-hashtable.c Normal file
View File

@ -0,0 +1,549 @@
/*
* Copyright (C) 2010 Sebastien Helleu <flashcode@flashtux.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/*
* wee-hashtable.c: implementation of hashtable
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <time.h>
#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);
}
}
}

123
src/core/wee-hashtable.h Normal file
View File

@ -0,0 +1,123 @@
/*
* Copyright (C) 2010 Sebastien Helleu <flashcode@flashtux.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#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 */

View File

@ -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;

View File

@ -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) \