diff options
Diffstat (limited to '')
-rw-r--r-- | src/util/dict_ht.c | 171 |
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); +} |