summaryrefslogtreecommitdiffstats
path: root/src/lib/str-table.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/str-table.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/lib/str-table.c b/src/lib/str-table.c
new file mode 100644
index 0000000..10eddd6
--- /dev/null
+++ b/src/lib/str-table.c
@@ -0,0 +1,78 @@
+/* Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "hash.h"
+#include "str-table.h"
+
+struct str_table {
+ HASH_TABLE(char *, void *) hash;
+};
+
+struct str_table *str_table_init(void)
+{
+ struct str_table *table;
+
+ table = i_new(struct str_table, 1);
+ hash_table_create(&table->hash, default_pool, 0, str_hash, strcmp);
+ return table;
+}
+
+void str_table_deinit(struct str_table **_table)
+{
+ struct str_table *table = *_table;
+ struct hash_iterate_context *iter;
+ char *key;
+ void *value;
+
+ *_table = NULL;
+
+ iter = hash_table_iterate_init(table->hash);
+ while (hash_table_iterate(iter, table->hash, &key, &value))
+ i_free(key);
+ hash_table_iterate_deinit(&iter);
+ hash_table_destroy(&table->hash);
+ i_free(table);
+}
+
+bool str_table_is_empty(struct str_table *table)
+{
+ return hash_table_count(table->hash) == 0;
+}
+
+const char *str_table_ref(struct str_table *table, const char *str)
+{
+ char *key;
+ void *value;
+ unsigned int ref;
+
+ if (!hash_table_lookup_full(table->hash, str, &key, &value)) {
+ key = i_strdup(str);
+ ref = 1;
+ } else {
+ ref = POINTER_CAST_TO(value, unsigned int);
+ i_assert(ref > 0);
+ ref++;
+ }
+ hash_table_update(table->hash, key, POINTER_CAST(ref));
+ return key;
+}
+
+void str_table_unref(struct str_table *table, const char **str)
+{
+ char *key;
+ void *value;
+ unsigned int ref;
+
+ if (!hash_table_lookup_full(table->hash, *str, &key, &value))
+ i_unreached();
+
+ ref = POINTER_CAST_TO(value, unsigned int);
+ i_assert(ref > 0);
+ if (--ref > 0)
+ hash_table_update(table->hash, key, POINTER_CAST(ref));
+ else {
+ hash_table_remove(table->hash, key);
+ i_free(key);
+ }
+ *str = NULL;
+}