summaryrefslogtreecommitdiffstats
path: root/src/util/dict_ht.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/dict_ht.c')
-rw-r--r--src/util/dict_ht.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/src/util/dict_ht.c b/src/util/dict_ht.c
new file mode 100644
index 0000000..74020d5
--- /dev/null
+++ b/src/util/dict_ht.c
@@ -0,0 +1,171 @@
+/*++
+/* NAME
+/* dict_ht 3
+/* SUMMARY
+/* dictionary manager interface to hash tables
+/* SYNOPSIS
+/* #include <dict_ht.h>
+/*
+/* DICT *dict_ht_open(name, open_flags, dict_flags)
+/* const char *name;
+/* int open_flags;
+/* int dict_flags;
+/* DESCRIPTION
+/* dict_ht_open() creates a memory-resident hash table and
+/* makes it accessible via the generic dictionary operations
+/* documented in dict_open(3). The open_flags argument is
+/* ignored.
+/* SEE ALSO
+/* dict(3) generic dictionary manager
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include "sys_defs.h"
+
+/* Utility library. */
+
+#include "mymalloc.h"
+#include "htable.h"
+#include "dict.h"
+#include "dict_ht.h"
+#include "stringops.h"
+#include "vstring.h"
+
+/* Application-specific. */
+
+typedef struct {
+ DICT dict; /* generic members */
+ HTABLE *table; /* hash table */
+} DICT_HT;
+
+/* dict_ht_delete - delete hash-table entry */
+
+static int dict_ht_delete(DICT *dict, const char *name)
+{
+ DICT_HT *dict_ht = (DICT_HT *) dict;
+
+ /*
+ * Optionally fold the key.
+ */
+ if (dict->flags & DICT_FLAG_FOLD_FIX) {
+ if (dict->fold_buf == 0)
+ dict->fold_buf = vstring_alloc(10);
+ vstring_strcpy(dict->fold_buf, name);
+ name = lowercase(vstring_str(dict->fold_buf));
+ }
+ if (htable_locate(dict_ht->table, name) == 0) {
+ DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_FAIL);
+ } else {
+ htable_delete(dict_ht->table, name, myfree);
+ DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_SUCCESS);
+ }
+}
+
+/* dict_ht_lookup - find hash-table entry */
+
+static const char *dict_ht_lookup(DICT *dict, const char *name)
+{
+ DICT_HT *dict_ht = (DICT_HT *) dict;
+
+ /*
+ * Optionally fold the key.
+ */
+ if (dict->flags & DICT_FLAG_FOLD_FIX) {
+ if (dict->fold_buf == 0)
+ dict->fold_buf = vstring_alloc(10);
+ vstring_strcpy(dict->fold_buf, name);
+ name = lowercase(vstring_str(dict->fold_buf));
+ }
+ DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, htable_find(dict_ht->table, name));
+}
+
+/* dict_ht_update - add or update hash-table entry */
+
+static int dict_ht_update(DICT *dict, const char *name, const char *value)
+{
+ DICT_HT *dict_ht = (DICT_HT *) dict;
+ HTABLE_INFO *ht;
+ char *saved_value = mystrdup(value);
+
+ /*
+ * Optionally fold the key.
+ */
+ if (dict->flags & DICT_FLAG_FOLD_FIX) {
+ if (dict->fold_buf == 0)
+ dict->fold_buf = vstring_alloc(10);
+ vstring_strcpy(dict->fold_buf, name);
+ name = lowercase(vstring_str(dict->fold_buf));
+ }
+ if ((ht = htable_locate(dict_ht->table, name)) != 0) {
+ myfree(ht->value);
+ } else {
+ ht = htable_enter(dict_ht->table, name, (void *) 0);
+ }
+ ht->value = saved_value;
+ DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_SUCCESS);
+}
+
+/* dict_ht_sequence - first/next iterator */
+
+static int dict_ht_sequence(DICT *dict, int how, const char **name,
+ const char **value)
+{
+ DICT_HT *dict_ht = (DICT_HT *) dict;
+ HTABLE_INFO *ht;
+
+ ht = htable_sequence(dict_ht->table,
+ how == DICT_SEQ_FUN_FIRST ? HTABLE_SEQ_FIRST :
+ how == DICT_SEQ_FUN_NEXT ? HTABLE_SEQ_NEXT :
+ HTABLE_SEQ_STOP);
+ if (ht != 0) {
+ *name = ht->key;
+ *value = ht->value;
+ DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_SUCCESS);
+ } else {
+ *name = 0;
+ *value = 0;
+ DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_FAIL);
+ }
+}
+
+/* dict_ht_close - disassociate from hash table */
+
+static void dict_ht_close(DICT *dict)
+{
+ DICT_HT *dict_ht = (DICT_HT *) dict;
+
+ htable_free(dict_ht->table, myfree);
+ if (dict_ht->dict.fold_buf)
+ vstring_free(dict_ht->dict.fold_buf);
+ dict_free(dict);
+}
+
+/* dict_ht_open - create association with hash table */
+
+DICT *dict_ht_open(const char *name, int unused_open_flags, int dict_flags)
+{
+ DICT_HT *dict_ht;
+
+ dict_ht = (DICT_HT *) dict_alloc(DICT_TYPE_HT, name, sizeof(*dict_ht));
+ dict_ht->dict.lookup = dict_ht_lookup;
+ dict_ht->dict.update = dict_ht_update;
+ dict_ht->dict.delete = dict_ht_delete;
+ dict_ht->dict.sequence = dict_ht_sequence;
+ dict_ht->dict.close = dict_ht_close;
+ dict_ht->dict.flags = dict_flags | DICT_FLAG_FIXED;
+ if (dict_flags & DICT_FLAG_FOLD_FIX)
+ dict_ht->dict.fold_buf = vstring_alloc(10);
+ dict_ht->table = htable_create(0);
+ dict_ht->dict.owner.status = DICT_OWNER_TRUSTED;
+ return (&dict_ht->dict);
+}