summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog.adoc1
-rw-r--r--ReleaseNotes.adoc11
-rw-r--r--doc/en/weechat_plugin_api.en.adoc9
-rw-r--r--doc/fr/weechat_plugin_api.fr.adoc11
-rw-r--r--doc/it/weechat_plugin_api.it.adoc13
-rw-r--r--doc/ja/weechat_plugin_api.ja.adoc12
-rw-r--r--doc/sr/weechat_plugin_api.sr.adoc12
-rw-r--r--src/core/wee-hashtable.c181
-rw-r--r--src/core/wee-hashtable.h6
-rw-r--r--tests/unit/core/test-core-hashtable.cpp404
10 files changed, 554 insertions, 106 deletions
diff --git a/ChangeLog.adoc b/ChangeLog.adoc
index 21b17d98b..36bd24665 100644
--- a/ChangeLog.adoc
+++ b/ChangeLog.adoc
@@ -21,6 +21,7 @@ https://weechat.org/files/releasenotes/ReleaseNotes-devel.html[release notes]
New features::
* core: add option "certs" in command /debug
+ * api: remember insertion order in hashtables
* api: add keys/values with tags in output of irc_message_parse_to_hashtable (issue #1654)
* irc: implement IRCv3.2 SASL authentication, add command /auth, reconnect by default to the server in case of SASL authentication failure (issue #413)
* irc: add support of capability "message-tags" and TAGMSG messages (issue #1654)
diff --git a/ReleaseNotes.adoc b/ReleaseNotes.adoc
index c453006c2..ca8623cea 100644
--- a/ReleaseNotes.adoc
+++ b/ReleaseNotes.adoc
@@ -20,6 +20,17 @@ https://weechat.org/files/changelog/ChangeLog-devel.html[ChangeLog]
[[v3.3]]
== Version 3.3 (under dev)
+[[v3.3_ordered_hashtables]]
+=== Ordered hashtables
+
+Hashtables entries are now ordered by creation date, the following functions
+are now returning entries sorted by insertion order:
+
+* hashtable_map
+* hashtable_map_string
+* hashtable_get_string (all properties except "keys_sorted" and "keys_values_sorted")
+* hashtable_add_to_infolist
+
[[v3.3_irc_default_capabilities]]
=== IRC default capabilities
diff --git a/doc/en/weechat_plugin_api.en.adoc b/doc/en/weechat_plugin_api.en.adoc
index e2e089d0c..c91069732 100644
--- a/doc/en/weechat_plugin_api.en.adoc
+++ b/doc/en/weechat_plugin_api.en.adoc
@@ -5220,7 +5220,8 @@ This function is not available in scripting API.
_WeeChat ≥ 0.3.3._
-Call a function on all hashtable entries.
+Call a function on all hashtable entries, by insertion order in the hashtable
+(from oldest to newest one).
Prototype:
@@ -5264,7 +5265,8 @@ This function is not available in scripting API.
_WeeChat ≥ 0.3.7._
-Call a function on all hashtable entries, sending keys and values as strings.
+Call a function on all hashtable entries, by insertion order in the hashtable
+(from oldest to newest one), sending keys and values as strings.
Prototype:
@@ -5478,7 +5480,8 @@ This function is not available in scripting API.
_WeeChat ≥ 0.3.3._
-Add hashtable items to an infolist item.
+Add hashtable items to an infolist item, by insertion order in the hashtable
+(from oldest to newest one).
Prototype:
diff --git a/doc/fr/weechat_plugin_api.fr.adoc b/doc/fr/weechat_plugin_api.fr.adoc
index 2dc757f35..b6281f3c4 100644
--- a/doc/fr/weechat_plugin_api.fr.adoc
+++ b/doc/fr/weechat_plugin_api.fr.adoc
@@ -5298,7 +5298,8 @@ Cette fonction n'est pas disponible dans l'API script.
_WeeChat ≥ 0.3.3._
-Appeller une fonction pour chaque entrée d'une table de hachage.
+Appeller une fonction pour chaque entrée d'une table de hachage, par ordre
+d'insertion dans la table de hachage (de la plus ancienne à la plus récente).
Prototype :
@@ -5343,8 +5344,9 @@ Cette fonction n'est pas disponible dans l'API script.
_WeeChat ≥ 0.3.7._
-Appeller une fonction pour chaque entrée d'une table de hachage, en envoyant les
-clés et valeurs sous forme de chaînes.
+Appeller une fonction pour chaque entrée d'une table de hachage, par ordre
+d'insertion dans la table de hachage (de la plus ancienne à la plus récente),
+en envoyant les clés et valeurs sous forme de chaînes.
Prototype :
@@ -5563,7 +5565,8 @@ Cette fonction n'est pas disponible dans l'API script.
_WeeChat ≥ 0.3.3._
-Ajouter les éléments d'une table de hachage dans un objet infolist.
+Ajouter les éléments d'une table de hachage dans un objet infolist, par ordre
+d'insertion dans la table de hachage (de la plus ancienne à la plus récente).
Prototype :
diff --git a/doc/it/weechat_plugin_api.it.adoc b/doc/it/weechat_plugin_api.it.adoc
index f99fe73cf..5b2db4819 100644
--- a/doc/it/weechat_plugin_api.it.adoc
+++ b/doc/it/weechat_plugin_api.it.adoc
@@ -5410,7 +5410,9 @@ Questa funzione non è disponibile nelle API per lo scripting.
_WeeChat ≥ 0.3.3._
-Chiama una funzione su tutte le voci della tabella hash.
+// TRANSLATION MISSING
+Chiama una funzione su tutte le voci della tabella hash, by insertion order
+in the hashtable (from oldest to newest one).
Prototipo:
@@ -5454,8 +5456,9 @@ Questa funzione non è disponibile nelle API per lo scripting.
_WeeChat ≥ 0.3.7._
-Chiama una funzione su tutte le voci della tabella hash, inviando chiavi e
-valori come stringhe.
+// TRANSLATION MISSING
+Chiama una funzione su tutte le voci della tabella hash, by insertion order
+in the hashtable (from oldest to newest one), inviando chiavi e valori come stringhe.
Prototipo:
@@ -5674,7 +5677,9 @@ Questa funzione non è disponibile nelle API per lo scripting.
_WeeChat ≥ 0.3.3._
-Aggiunge elementi della tabella hash ad un elemento della lista info.
+// TRANSLATION MISSING
+Aggiunge elementi della tabella hash ad un elemento della lista info, by insertion
+order in the hashtable (from oldest to newest one).
Prototipo:
diff --git a/doc/ja/weechat_plugin_api.ja.adoc b/doc/ja/weechat_plugin_api.ja.adoc
index a833c0233..cc4cf1c6b 100644
--- a/doc/ja/weechat_plugin_api.ja.adoc
+++ b/doc/ja/weechat_plugin_api.ja.adoc
@@ -5269,7 +5269,9 @@ if (weechat_hashtable_has_key (hashtable, "my_key"))
_WeeChat バージョン 0.3.3 以上で利用可。_
-ハッシュテーブルのすべてのエントリに対して関数を呼び出す。
+// TRANSLATION MISSING
+ハッシュテーブルのすべてのエントリに対して関数を呼び出す,
+by insertion order in the hashtable (from oldest to newest one).
プロトタイプ:
@@ -5313,7 +5315,9 @@ weechat_hashtable_map (hashtable, &map_cb, NULL);
_WeeChat バージョン 0.3.7 以上で利用可。_
-ハッシュテーブルのすべてのエントリに対して関数を呼び出す、キーと値を文字列として関数に渡す。
+// TRANSLATION MISSING
+Call a function on all hashtable entries, by insertion order in the hashtable
+(from oldest to newest one), sending keys and values as strings.
プロトタイプ:
@@ -5527,7 +5531,9 @@ weechat_hashtable_set_pointer (hashtable, "callback_free_key", &my_free_key_cb);
_WeeChat バージョン 0.3.3 以上で利用可。_
-ハッシュテーブルの要素をインフォリスト要素に追加
+// TRANSLATION MISSING
+ハッシュテーブルの要素をインフォリスト要素に追加, by insertion order in the hashtable
+(from oldest to newest one).
プロトタイプ:
diff --git a/doc/sr/weechat_plugin_api.sr.adoc b/doc/sr/weechat_plugin_api.sr.adoc
index 12539794a..e023350aa 100644
--- a/doc/sr/weechat_plugin_api.sr.adoc
+++ b/doc/sr/weechat_plugin_api.sr.adoc
@@ -5057,7 +5057,9 @@ if (weechat_hashtable_has_key (hashtable, "my_key"))
_WeeChat ≥ 0.3.3._
-Позива функцију над свим ставкама хеш табеле.
+// TRANSLATION MISSING
+Позива функцију над свим ставкама хеш табеле, by insertion order in the hashtable
+(from oldest to newest one).
Прототип:
@@ -5101,7 +5103,9 @@ weechat_hashtable_map (hashtable, &map_cb, NULL);
_WeeChat ≥ 0.3.7._
-Позива функцију над свим ставкама хеш табеле и шаље јој кључеве и вредности као стрингове.
+// TRANSLATION MISSING
+Call a function on all hashtable entries, by insertion order in the hashtable
+(from oldest to newest one), sending keys and values as strings.
Прототип:
@@ -5311,7 +5315,9 @@ weechat_hashtable_set_pointer (hashtable, "callback_free_key", &my_free_key_cb);
_WeeChat ≥ 0.3.3._
-Додаје ставе хеш табеле у ставку инфо листе.
+// TRANSLATION MISSING
+Додаје ставе хеш табеле у ставку инфо листе, by insertion order in the hashtable
+(from oldest to newest one).
Прототип:
diff --git a/src/core/wee-hashtable.c b/src/core/wee-hashtable.c
index 0d6ed2602..72743750d 100644
--- a/src/core/wee-hashtable.c
+++ b/src/core/wee-hashtable.c
@@ -228,6 +228,8 @@ hashtable_new (int size,
new_hashtable->htable[i] = NULL;
}
new_hashtable->items_count = 0;
+ new_hashtable->oldest_item = NULL;
+ new_hashtable->newest_item = NULL;
new_hashtable->callback_hash_key = (callback_hash_key) ?
callback_hash_key : &hashtable_hash_key_default_cb;
@@ -439,6 +441,15 @@ hashtable_set_with_size (struct t_hashtable *hashtable,
hashtable->htable[hash] = new_item;
}
+ /* keep items ordered by date of creation */
+ if (hashtable->newest_item)
+ (hashtable->newest_item)->next_created_item = new_item;
+ else
+ hashtable->oldest_item = new_item;
+ new_item->prev_created_item = hashtable->newest_item;
+ new_item->next_created_item = NULL;
+ hashtable->newest_item = new_item;
+
hashtable->items_count++;
return new_item;
@@ -574,26 +585,22 @@ hashtable_map (struct t_hashtable *hashtable,
t_hashtable_map *callback_map,
void *callback_map_data)
{
- int i;
- struct t_hashtable_item *ptr_item, *ptr_next_item;
+ struct t_hashtable_item *ptr_item, *ptr_next_created_item;
if (!hashtable)
return;
- for (i = 0; i < hashtable->size; i++)
+ ptr_item = hashtable->oldest_item;
+ while (ptr_item)
{
- ptr_item = hashtable->htable[i];
- while (ptr_item)
- {
- ptr_next_item = ptr_item->next_item;
+ ptr_next_created_item = ptr_item->next_created_item;
- (void) (callback_map) (callback_map_data,
- hashtable,
- ptr_item->key,
- ptr_item->value);
+ (void) (callback_map) (callback_map_data,
+ hashtable,
+ ptr_item->key,
+ ptr_item->value);
- ptr_item = ptr_next_item;
- }
+ ptr_item = ptr_next_created_item;
}
}
@@ -606,41 +613,37 @@ hashtable_map_string (struct t_hashtable *hashtable,
t_hashtable_map_string *callback_map,
void *callback_map_data)
{
- int i;
- struct t_hashtable_item *ptr_item, *ptr_next_item;
+ struct t_hashtable_item *ptr_item, *ptr_next_created_item;
const char *str_key, *str_value;
char *key, *value;
if (!hashtable)
return;
- for (i = 0; i < hashtable->size; i++)
+ ptr_item = hashtable->oldest_item;
+ while (ptr_item)
{
- ptr_item = hashtable->htable[i];
- while (ptr_item)
- {
- ptr_next_item = ptr_item->next_item;
+ ptr_next_created_item = ptr_item->next_created_item;
- str_key = hashtable_to_string (hashtable->type_keys,
- ptr_item->key);
- key = (str_key) ? strdup (str_key) : NULL;
+ str_key = hashtable_to_string (hashtable->type_keys,
+ ptr_item->key);
+ key = (str_key) ? strdup (str_key) : NULL;
- str_value = hashtable_to_string (hashtable->type_values,
- ptr_item->value);
- value = (str_value) ? strdup (str_value) : NULL;
+ str_value = hashtable_to_string (hashtable->type_values,
+ ptr_item->value);
+ value = (str_value) ? strdup (str_value) : NULL;
- (void) (callback_map) (callback_map_data,
- hashtable,
- key,
- value);
+ (void) (callback_map) (callback_map_data,
+ hashtable,
+ key,
+ value);
- if (key)
- free (key);
- if (value)
- free (value);
+ if (key)
+ free (key);
+ if (value)
+ free (value);
- ptr_item = ptr_next_item;
- }
+ ptr_item = ptr_next_created_item;
}
}
@@ -675,6 +678,9 @@ hashtable_dup (struct t_hashtable *hashtable)
{
struct t_hashtable *new_hashtable;
+ if (!hashtable)
+ return NULL;
+
new_hashtable = hashtable_new (hashtable->size,
hashtable_type_string[hashtable->type_keys],
hashtable_type_string[hashtable->type_values],
@@ -724,6 +730,9 @@ hashtable_get_list_keys (struct t_hashtable *hashtable)
{
struct t_weelist *weelist;
+ if (!hashtable)
+ return NULL;
+
weelist = weelist_new ();
if (weelist)
hashtable_map (hashtable, &hashtable_get_list_keys_map_cb, weelist);
@@ -1044,7 +1053,7 @@ hashtable_add_to_infolist (struct t_hashtable *hashtable,
struct t_infolist_item *infolist_item,
const char *prefix)
{
- int i, item_number;
+ int item_number;
struct t_hashtable_item *ptr_item;
char option_name[128];
@@ -1052,52 +1061,50 @@ hashtable_add_to_infolist (struct t_hashtable *hashtable,
return 0;
item_number = 0;
- for (i = 0; i < hashtable->size; i++)
+ ptr_item = hashtable->oldest_item;
+ while (ptr_item)
{
- for (ptr_item = hashtable->htable[i]; ptr_item;
- ptr_item = ptr_item->next_item)
+ snprintf (option_name, sizeof (option_name),
+ "%s_name_%05d", prefix, item_number);
+ if (!infolist_new_var_string (infolist_item, option_name,
+ hashtable_to_string (hashtable->type_keys,
+ ptr_item->key)))
+ return 0;
+ snprintf (option_name, sizeof (option_name),
+ "%s_value_%05d", prefix, item_number);
+ switch (hashtable->type_values)
{
- snprintf (option_name, sizeof (option_name),
- "%s_name_%05d", prefix, item_number);
- if (!infolist_new_var_string (infolist_item, option_name,
- hashtable_to_string (hashtable->type_keys,
- ptr_item->key)))
- return 0;
- snprintf (option_name, sizeof (option_name),
- "%s_value_%05d", prefix, item_number);
- switch (hashtable->type_values)
- {
- case HASHTABLE_INTEGER:
- if (!infolist_new_var_integer (infolist_item, option_name,
- *((int *)ptr_item->value)))
- return 0;
- break;
- case HASHTABLE_STRING:
- if (!infolist_new_var_string (infolist_item, option_name,
- (const char *)ptr_item->value))
- return 0;
- break;
- case HASHTABLE_POINTER:
- if (!infolist_new_var_pointer (infolist_item, option_name,
- ptr_item->value))
- return 0;
- break;
- case HASHTABLE_BUFFER:
- if (!infolist_new_var_buffer (infolist_item, option_name,
- ptr_item->value,
- ptr_item->value_size))
- return 0;
- break;
- case HASHTABLE_TIME:
- if (!infolist_new_var_time (infolist_item, option_name,
- *((time_t *)ptr_item->value)))
- return 0;
- break;
- case HASHTABLE_NUM_TYPES:
- break;
- }
- item_number++;
+ case HASHTABLE_INTEGER:
+ if (!infolist_new_var_integer (infolist_item, option_name,
+ *((int *)ptr_item->value)))
+ return 0;
+ break;
+ case HASHTABLE_STRING:
+ if (!infolist_new_var_string (infolist_item, option_name,
+ (const char *)ptr_item->value))
+ return 0;
+ break;
+ case HASHTABLE_POINTER:
+ if (!infolist_new_var_pointer (infolist_item, option_name,
+ ptr_item->value))
+ return 0;
+ break;
+ case HASHTABLE_BUFFER:
+ if (!infolist_new_var_buffer (infolist_item, option_name,
+ ptr_item->value,
+ ptr_item->value_size))
+ return 0;
+ break;
+ case HASHTABLE_TIME:
+ if (!infolist_new_var_time (infolist_item, option_name,
+ *((time_t *)ptr_item->value)))
+ return 0;
+ break;
+ case HASHTABLE_NUM_TYPES:
+ break;
}
+ item_number++;
+ ptr_item = ptr_item->next_created_item;
}
return 1;
}
@@ -1203,6 +1210,16 @@ hashtable_remove_item (struct t_hashtable *hashtable,
hashtable_free_value (hashtable, item);
hashtable_free_key (hashtable, item);
+ /* remove item from ordered list (by date of creation) */
+ if (item->prev_created_item)
+ (item->prev_created_item)->next_created_item = item->next_created_item;
+ if (item->next_created_item)
+ (item->next_created_item)->prev_created_item = item->prev_created_item;
+ if (hashtable->oldest_item == item)
+ hashtable->oldest_item = item->next_created_item;
+ if (hashtable->newest_item == item)
+ hashtable->newest_item = item->prev_created_item;
+
/* remove item from list */
if (item->prev_item)
(item->prev_item)->next_item = item->next_item;
@@ -1287,6 +1304,8 @@ hashtable_print_log (struct t_hashtable *hashtable, const char *name)
log_printf (" size . . . . . . . . . : %d", hashtable->size);
log_printf (" htable . . . . . . . . : 0x%lx", hashtable->htable);
log_printf (" items_count. . . . . . : %d", hashtable->items_count);
+ log_printf (" oldest_item. . . . . . : 0x%lx", hashtable->oldest_item);
+ log_printf (" newest_item. . . . . . : 0x%lx", hashtable->newest_item);
log_printf (" type_keys. . . . . . . : %d (%s)",
hashtable->type_keys,
hashtable_type_string[hashtable->type_keys]);
@@ -1350,6 +1369,8 @@ hashtable_print_log (struct t_hashtable *hashtable, const char *name)
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);
+ log_printf (" prev_created_item. : 0x%lx", ptr_item->prev_created_item);
+ log_printf (" next_created_item. : 0x%lx", ptr_item->next_created_item);
}
}
}
diff --git a/src/core/wee-hashtable.h b/src/core/wee-hashtable.h
index 860a7f8da..90c943776 100644
--- a/src/core/wee-hashtable.h
+++ b/src/core/wee-hashtable.h
@@ -117,6 +117,10 @@ struct t_hashtable_item
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 */
+ /* previous/next item by order of creation in the hashtable */
+ struct t_hashtable_item *prev_created_item;
+ struct t_hashtable_item *next_created_item;
+
};
struct t_hashtable
@@ -125,6 +129,8 @@ struct t_hashtable
struct t_hashtable_item **htable; /* table to map hashes with linked */
/* lists */
int items_count; /* number of items in hashtable */
+ struct t_hashtable_item *oldest_item; /* oldest item in hashtable */
+ struct t_hashtable_item *newest_item; /* newest item in hashtable */
/* type for keys and values */
enum t_hashtable_type type_keys; /* type for keys: int/str/pointer */
diff --git a/tests/unit/core/test-core-hashtable.cpp b/tests/unit/core/test-core-hashtable.cpp
index abcaec2ca..2e209847c 100644
--- a/tests/unit/core/test-core-hashtable.cpp
+++ b/tests/unit/core/test-core-hashtable.cpp
@@ -25,6 +25,8 @@ extern "C"
{
#include <string.h>
#include "src/core/wee-hashtable.h"
+#include "src/core/wee-infolist.h"
+#include "src/core/wee-list.h"
#include "src/plugins/plugin.h"
}
@@ -34,8 +36,27 @@ extern "C"
#define HASHTABLE_TEST_KEY_LONG_HASH 11232856562070989738ULL
#define HASHTABLE_TEST_VALUE "this is a value"
+char *test_map_string = NULL;
+
TEST_GROUP(CoreHashtable)
{
+ struct t_hashtable *get_weechat_hashtable ()
+ {
+ struct t_hashtable *hashtable;
+
+ hashtable = hashtable_new (8,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING,
+ NULL,
+ NULL);
+ hashtable_set (hashtable, "weechat", "the first item");
+ hashtable_set (hashtable, "light", "item2");
+ hashtable_set (hashtable, "fast", "item3");
+ hashtable_set (hashtable, "extensible", "item4");
+ hashtable_set (hashtable, "chat", "item5");
+ hashtable_set (hashtable, "client", "last item");
+ return hashtable;
+ }
};
/*
@@ -121,6 +142,8 @@ TEST(CoreHashtable, New)
LONGS_EQUAL(32, hashtable->size);
CHECK(hashtable->htable);
LONGS_EQUAL(0, hashtable->items_count);
+ POINTERS_EQUAL(NULL, hashtable->oldest_item);
+ POINTERS_EQUAL(NULL, hashtable->newest_item);
LONGS_EQUAL(HASHTABLE_STRING, hashtable->type_keys);
LONGS_EQUAL(HASHTABLE_INTEGER, hashtable->type_values);
POINTERS_EQUAL(&test_hashtable_hash_key_cb, hashtable->callback_hash_key);
@@ -169,23 +192,31 @@ TEST(CoreHashtable, SetGetRemove)
item = hashtable_set (hashtable, str_key, NULL);
CHECK(item);
LONGS_EQUAL(1, hashtable->items_count);
+ CHECK(hashtable->oldest_item);
+ CHECK(hashtable->newest_item);
STRCMP_EQUAL(str_key, (const char *)item->key);
LONGS_EQUAL(strlen (str_key) + 1, item->key_size);
POINTERS_EQUAL(NULL, item->value);
LONGS_EQUAL(0, item->value_size);
POINTERS_EQUAL(NULL, item->prev_item);
POINTERS_EQUAL(NULL, item->next_item);
+ POINTERS_EQUAL(NULL, item->prev_created_item);
+ POINTERS_EQUAL(NULL, item->next_created_item);
/* set a string value for the same key */
item = hashtable_set (hashtable, str_key, str_value);
CHECK(item);
LONGS_EQUAL(1, hashtable->items_count);
+ CHECK(hashtable->oldest_item);
+ CHECK(hashtable->newest_item);
STRCMP_EQUAL(str_key, (const char *)item->key);
LONGS_EQUAL(strlen (str_key) + 1, item->key_size);
STRCMP_EQUAL(str_value, (const char *)item->value);
LONGS_EQUAL(strlen (str_value) + 1, item->value_size);
POINTERS_EQUAL(NULL, item->prev_item);
POINTERS_EQUAL(NULL, item->next_item);
+ POINTERS_EQUAL(NULL, item->prev_created_item);
+ POINTERS_EQUAL(NULL, item->next_created_item);
/* get item */
item = hashtable_get_item (hashtable, str_key, &hash);
@@ -208,6 +239,8 @@ TEST(CoreHashtable, SetGetRemove)
/* delete an item */
hashtable_remove (hashtable, str_key);
LONGS_EQUAL(0, hashtable->items_count);
+ POINTERS_EQUAL(NULL, hashtable->oldest_item);
+ POINTERS_EQUAL(NULL, hashtable->newest_item);
/* add an item with size in hashtable */
item = hashtable_set_with_size (hashtable,
@@ -215,6 +248,8 @@ TEST(CoreHashtable, SetGetRemove)
str_value, strlen (str_value) + 1);
CHECK(item);
LONGS_EQUAL(1, hashtable->items_count);
+ CHECK(hashtable->oldest_item);
+ CHECK(hashtable->newest_item);
STRCMP_EQUAL(str_key, (const char *)item->key);
LONGS_EQUAL(strlen (str_key) + 1, item->key_size);
STRCMP_EQUAL(str_value, (const char *)item->value);
@@ -223,6 +258,15 @@ TEST(CoreHashtable, SetGetRemove)
/* add another item */
hashtable_set (hashtable, "xxx", "zzz");
LONGS_EQUAL(2, hashtable->items_count);
+ CHECK(hashtable->oldest_item);
+ CHECK(hashtable->newest_item);
+ CHECK(hashtable->oldest_item != hashtable->newest_item);
+ CHECK(hashtable->oldest_item->next_created_item == hashtable->newest_item);
+ STRCMP_EQUAL(str_key, (const char *)hashtable->oldest_item->key);
+ STRCMP_EQUAL("xxx",
+ (const char *)hashtable->oldest_item->next_created_item->key);
+ STRCMP_EQUAL("xxx",
+ (const char *)hashtable->newest_item->key);
/*
* test duplication of hashtable and check that duplicated content is
@@ -273,7 +317,17 @@ TEST(CoreHashtable, SetGetRemove)
/* remove all items */
hashtable_remove_all (hashtable);
+ POINTERS_EQUAL(NULL, hashtable->htable[0]);
+ POINTERS_EQUAL(NULL, hashtable->htable[1]);
+ POINTERS_EQUAL(NULL, hashtable->htable[2]);
+ POINTERS_EQUAL(NULL, hashtable->htable[3]);
+ POINTERS_EQUAL(NULL, hashtable->htable[4]);
+ POINTERS_EQUAL(NULL, hashtable->htable[5]);
+ POINTERS_EQUAL(NULL, hashtable->htable[6]);
+ POINTERS_EQUAL(NULL, hashtable->htable[7]);
LONGS_EQUAL(0, hashtable->items_count);
+ POINTERS_EQUAL(NULL, hashtable->oldest_item);
+ POINTERS_EQUAL(NULL, hashtable->newest_item);
/* free hashtables */
hashtable_free (hashtable);
@@ -313,13 +367,13 @@ TEST(CoreHashtable, SetGetRemove)
CHECK(item);
POINTERS_EQUAL(item, hashtable->htable[7]);
- item = hashtable_set (hashtable, "fast", NULL);
+ item = hashtable_set (hashtable, "light", NULL);
CHECK(item);
POINTERS_EQUAL(item, hashtable->htable[3]);
- item = hashtable_set (hashtable, "light", NULL);
+ item = hashtable_set (hashtable, "fast", NULL);
CHECK(item);
- POINTERS_EQUAL(item, hashtable->htable[3]->next_item);
+ POINTERS_EQUAL(item, hashtable->htable[3]);
item = hashtable_set (hashtable, "extensible", NULL);
CHECK(item);
@@ -333,32 +387,335 @@ TEST(CoreHashtable, SetGetRemove)
CHECK(item);
POINTERS_EQUAL(item, hashtable->htable[6]);
+ /* check items by order of creation */
+ ptr_item = hashtable->oldest_item;
+ STRCMP_EQUAL("weechat", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("light", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("fast", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("extensible", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("chat", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("client", (const char *)ptr_item->key);
+ STRCMP_EQUAL("client", (const char *)hashtable->newest_item->key);
+ ptr_item = ptr_item->next_created_item;
+ POINTERS_EQUAL(NULL, ptr_item);
+
+ /* remove items and check again by order of creation */
+ hashtable_remove (hashtable, "fast");
+ LONGS_EQUAL(5, hashtable->items_count);
+ ptr_item = hashtable->oldest_item;
+ STRCMP_EQUAL("weechat", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("light", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("extensible", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("chat", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("client", (const char *)ptr_item->key);
+ STRCMP_EQUAL("client", (const char *)hashtable->newest_item->key);
+ ptr_item = ptr_item->next_created_item;
+ POINTERS_EQUAL(NULL, ptr_item);
+
+ hashtable_remove (hashtable, "light");
+ LONGS_EQUAL(4, hashtable->items_count);
+ ptr_item = hashtable->oldest_item;
+ STRCMP_EQUAL("weechat", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("extensible", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("chat", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("client", (const char *)ptr_item->key);
+ STRCMP_EQUAL("client", (const char *)hashtable->newest_item->key);
+ ptr_item = ptr_item->next_created_item;
+ POINTERS_EQUAL(NULL, ptr_item);
+
+ hashtable_remove (hashtable, "weechat");
+ LONGS_EQUAL(3, hashtable->items_count);
+ ptr_item = hashtable->oldest_item;
+ STRCMP_EQUAL("extensible", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("chat", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("client", (const char *)ptr_item->key);
+ STRCMP_EQUAL("client", (const char *)hashtable->newest_item->key);
+ ptr_item = ptr_item->next_created_item;
+ POINTERS_EQUAL(NULL, ptr_item);
+
+ hashtable_remove (hashtable, "client");
+ LONGS_EQUAL(2, hashtable->items_count);
+ ptr_item = hashtable->oldest_item;
+ STRCMP_EQUAL("extensible", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("chat", (const char *)ptr_item->key);
+ STRCMP_EQUAL("chat", (const char *)hashtable->newest_item->key);
+ ptr_item = ptr_item->next_created_item;
+ POINTERS_EQUAL(NULL, ptr_item);
+
+ /* check current content of hashtable */
+ POINTERS_EQUAL(NULL, hashtable->htable[0]);
+ POINTERS_EQUAL(NULL, hashtable->htable[1]);
+ STRCMP_EQUAL("extensible", (const char *)hashtable->htable[2]->key);
+ POINTERS_EQUAL(NULL, hashtable->htable[3]);
+ POINTERS_EQUAL(NULL, hashtable->htable[4]);
+ STRCMP_EQUAL("chat", (const char *)hashtable->htable[5]->key);
+ POINTERS_EQUAL(NULL, hashtable->htable[6]);
+ POINTERS_EQUAL(NULL, hashtable->htable[7]);
+
/* free hashtable */
hashtable_free (hashtable);
}
+void
+test_hashtable_map_string_cb (void *data,
+ struct t_hashtable *hashtable,
+ const char *key, const char *value)
+{
+ /* make C++ compiler happy */
+ (void) hashtable;
+ (void) data;
+
+ if (test_map_string[0])
+ strcat (test_map_string, ";");
+ strcat (test_map_string, key);
+ strcat (test_map_string, ":");
+ strcat (test_map_string, value);
+}
+
/*
* Tests functions:
- * hashtable_map
* hashtable_map_string
*/
-TEST(CoreHashtable, Map)
+TEST(CoreHashtable, MapString)
{
- /* TODO: write tests */
+ struct t_hashtable *hashtable;
+ int value_int;
+ void *value_ptr;
+ time_t value_time;
+ char result[1024], value_buffer[3] = { 0x01, 0x05, 0x09 };
+
+ test_map_string = (char *)malloc (1024);
+
+ /* string -> string */
+ test_map_string[0] = '\0';
+ hashtable = get_weechat_hashtable ();
+ hashtable_map_string (hashtable, &test_hashtable_map_string_cb, NULL);
+ STRCMP_EQUAL("weechat:the first item;light:item2;fast:item3;"
+ "extensible:item4;chat:item5;client:last item",
+ test_map_string);
+
+ /* integer -> pointer */
+ test_map_string[0] = '\0';
+ hashtable = hashtable_new (8,
+ WEECHAT_HASHTABLE_INTEGER,
+ WEECHAT_HASHTABLE_POINTER,
+ NULL,
+ NULL);
+ value_int = 123;
+ value_ptr = (void *)0x123abc;
+ hashtable_set (hashtable, &value_int, value_ptr);
+ value_int = 45678;
+ value_ptr = (void *)0xdef789;
+ hashtable_set (hashtable, &value_int, value_ptr);
+ hashtable_map_string (hashtable, &test_hashtable_map_string_cb, NULL);
+ STRCMP_EQUAL("123:0x123abc;45678:0xdef789", test_map_string);
+
+ /* time -> buffer */
+ test_map_string[0] = '\0';
+ hashtable = hashtable_new (8,
+ WEECHAT_HASHTABLE_TIME,
+ WEECHAT_HASHTABLE_BUFFER,
+ NULL,
+ NULL);
+ value_time = 1624693124;
+ hashtable_set_with_size (hashtable,
+ &value_time, 0,
+ value_buffer, sizeof (value_buffer));
+ hashtable_map_string (hashtable, &test_hashtable_map_string_cb, NULL);
+ snprintf (result, sizeof (result),
+ "1624693124:0x%lx",
+ (unsigned long)(hashtable->newest_item->value));
+ STRCMP_EQUAL(result, test_map_string);
+
+ free (test_map_string);
+}
+
+/*
+ * Tests functions:
+ * hashtable_map
+ * hashtable_dup
+ */
+
+TEST(CoreHashtable, Dup)
+{
+ struct t_hashtable *hashtable, *hashtable2;
+ struct t_hashtable_item *ptr_item;
+
+ hashtable = get_weechat_hashtable ();
+
+ POINTERS_EQUAL(NULL, hashtable_dup (NULL));
+
+ hashtable2 = hashtable_dup (hashtable);
+
+ LONGS_EQUAL(6, hashtable2->items_count);
+ ptr_item = hashtable2->oldest_item;
+ STRCMP_EQUAL("weechat", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("light", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("fast", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("extensible", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("chat", (const char *)ptr_item->key);
+ ptr_item = ptr_item->next_created_item;
+ STRCMP_EQUAL("client", (const char *)ptr_item->key);
+ STRCMP_EQUAL("client", (const char *)hashtable2->newest_item->key);
+ ptr_item = ptr_item->next_created_item;
+ POINTERS_EQUAL(NULL, ptr_item);
+
+ hashtable_free (hashtable);
+ hashtable_free (hashtable2);
}
/*
* Tests functions:
* hashtable_get_list_keys
+ */
+
+TEST(CoreHashtable, GetListKeys)
+{
+ struct t_hashtable *hashtable;
+ struct t_weelist *list_keys;
+
+ hashtable = get_weechat_hashtable ();
+
+ POINTERS_EQUAL(NULL, hashtable_get_list_keys (NULL));
+
+ list_keys = hashtable_get_list_keys (hashtable);
+ CHECK(list_keys);
+ STRCMP_EQUAL("chat", weelist_string (weelist_get (list_keys, 0)));
+ STRCMP_EQUAL("client", weelist_string (weelist_get (list_keys, 1)));
+ STRCMP_EQUAL("extensible", weelist_string (weelist_get (list_keys, 2)));
+ STRCMP_EQUAL("fast", weelist_string (weelist_get (list_keys, 3)));
+ STRCMP_EQUAL("light", weelist_string (weelist_get (list_keys, 4)));
+ STRCMP_EQUAL("weechat", weelist_string (weelist_get (list_keys, 5)));
+
+ hashtable_free (hashtable);
+}
+
+/*
+ * Tests functions:
* hashtable_get_integer
+ */
+
+TEST(CoreHashtable, GetInteger)
+{
+ struct t_hashtable *hashtable;
+
+ hashtable = get_weechat_hashtable ();
+
+ LONGS_EQUAL(0, hashtable_get_integer (NULL, NULL));
+ LONGS_EQUAL(0, hashtable_get_integer (hashtable, NULL));
+ LONGS_EQUAL(0, hashtable_get_integer (hashtable, ""));
+ LONGS_EQUAL(0, hashtable_get_integer (hashtable, "unknown"));
+
+ LONGS_EQUAL(8, hashtable_get_integer (hashtable, "size"));
+ LONGS_EQUAL(6, hashtable_get_integer (hashtable, "items_count"));
+
+ hashtable_free (hashtable);
+}
+
+/*
+ * Tests functions:
* hashtable_get_string
+ */
+
+TEST(CoreHashtable, GetString)
+{
+ struct t_hashtable *hashtable;
+
+ hashtable = get_weechat_hashtable ();
+
+ POINTERS_EQUAL(NULL, hashtable_get_string (NULL, NULL));
+ POINTERS_EQUAL(NULL, hashtable_get_string (hashtable, NULL));
+ POINTERS_EQUAL(NULL, hashtable_get_string (hashtable, ""));
+ POINTERS_EQUAL(NULL, hashtable_get_string (hashtable, "unknown"));
+
+ STRCMP_EQUAL("string", hashtable_get_string (hashtable, "type_keys"));
+ STRCMP_EQUAL("string", hashtable_get_string (hashtable, "type_values"));
+ STRCMP_EQUAL("weechat,light,fast,extensible,chat,client",
+ hashtable_get_string (hashtable, "keys"));
+ STRCMP_EQUAL("chat,client,extensible,fast,light,weechat",
+ hashtable_get_string (hashtable, "keys_sorted"));
+ STRCMP_EQUAL("the first item,item2,item3,item4,item5,last item",
+ hashtable_get_string (hashtable, "values"));
+ STRCMP_EQUAL("weechat:the first item,light:item2,fast:item3,"
+ "extensible:item4,chat:item5,client:last item",
+ hashtable_get_string (hashtable, "keys_values"));
+ STRCMP_EQUAL("chat:item5,client:last item,extensible:item4,fast:item3,"
+ "light:item2,weechat:the first item",
+ hashtable_get_string (hashtable, "keys_values_sorted"));
+
+ hashtable_free (hashtable);
+}
+
+/*
+ * Test callback freeing key (it does nothing).
+ */
+
+void
+test_hashtable_free_key (struct t_hashtable *hashtable, void *key)
+{
+ /* make C++ compiler happy */
+ (void) hashtable;
+ (void) key;
+}
+
+/*
+ * Test callback freeing value (it does nothing).
+ */
+
+void
+test_hashtable_free_value (struct t_hashtable *hashtable,
+ const void *key, void *value)
+{
+ /* make C++ compiler happy */
+ (void) hashtable;
+ (void) key;
+ (void) value;
+}
+
+/*
+ * Tests functions:
* hashtable_set_pointer
*/
-TEST(CoreHashtable, Properties)
+TEST(CoreHashtable, SetPointer)
{
- /* TODO: write tests */
+ struct t_hashtable *hashtable;
+
+ hashtable = get_weechat_hashtable ();
+
+ hashtable_set_pointer (NULL, NULL, NULL);
+ hashtable_set_pointer (hashtable, NULL, NULL);
+ hashtable_set_pointer (hashtable, "", NULL);
+ hashtable_set_pointer (hashtable, "unknown", NULL);
+
+ hashtable_set_pointer (hashtable,
+ "callback_free_key", (void *)&test_hashtable_free_key);
+ POINTERS_EQUAL(&test_hashtable_free_key, hashtable->callback_free_key);
+ hashtable_set_pointer (hashtable,
+ "callback_free_value", (void *)&test_hashtable_free_value);
+ POINTERS_EQUAL(&test_hashtable_free_value, hashtable->callback_free_value);
+
+ hashtable_free (hashtable);
}
/*
@@ -369,7 +726,36 @@ TEST(CoreHashtable, Properties)
TEST(CoreHashtable, Infolist)
{
- /* TODO: write tests */
+ struct t_hashtable *hashtable;
+ struct t_infolist *infolist;
+ struct t_infolist_item *infolist_item;
+
+ hashtable = get_weechat_hashtable ();
+
+ infolist = infolist_new (NULL);
+ infolist_item = infolist_new_item (infolist);
+
+ LONGS_EQUAL(0, hashtable_add_to_infolist (NULL, NULL, NULL));
+ LONGS_EQUAL(0, hashtable_add_to_infolist (hashtable, NULL, NULL));
+ LONGS_EQUAL(0, hashtable_add_to_infolist (hashtable, infolist_item, NULL));
+
+ LONGS_EQUAL(1, hashtable_add_to_infolist (hashtable, infolist_item, "test"));
+
+ infolist_reset_item_cursor (infolist);
+ infolist_next (infolist);
+
+ STRCMP_EQUAL("weechat", infolist_string (infolist, "test_name_00000"));
+ STRCMP_EQUAL("the first item", infolist_string (infolist, "test_value_00000"));
+ STRCMP_EQUAL("light", infolist_string (infolist, "test_name_00001"));
+ STRCMP_EQUAL("item2", infolist_string (infolist, "test_value_00001"));
+ STRCMP_EQUAL("fast", infolist_string (infolist, "test_name_00002"));
+ STRCMP_EQUAL("item3", infolist_string (infolist, "test_value_00002"));
+ STRCMP_EQUAL("extensible", infolist_string (infolist, "test_name_00003"));
+ STRCMP_EQUAL("item4", infolist_string (infolist, "test_value_00003"));
+ STRCMP_EQUAL("chat", infolist_string (infolist, "test_name_00004"));
+ STRCMP_EQUAL("item5", infolist_string (infolist, "test_value_00004"));
+ STRCMP_EQUAL("client", infolist_string (infolist, "test_name_00005"));
+ STRCMP_EQUAL("last item", infolist_string (infolist, "test_value_00005"));
}
/*