1 /* $NetBSD: dict_ht.c,v 1.2 2017/02/14 01:16:49 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* dict_ht 3 6 /* SUMMARY 7 /* dictionary manager interface to hash tables 8 /* SYNOPSIS 9 /* #include <dict_ht.h> 10 /* 11 /* DICT *dict_ht_open(name, open_flags, dict_flags) 12 /* const char *name; 13 /* int open_flags; 14 /* int dict_flags; 15 /* DESCRIPTION 16 /* dict_ht_open() creates a memory-resident hash table and 17 /* makes it accessible via the generic dictionary operations 18 /* documented in dict_open(3). The open_flags argument is 19 /* ignored. 20 /* SEE ALSO 21 /* dict(3) generic dictionary manager 22 /* LICENSE 23 /* .ad 24 /* .fi 25 /* The Secure Mailer license must be distributed with this software. 26 /* AUTHOR(S) 27 /* Wietse Venema 28 /* IBM T.J. Watson Research 29 /* P.O. Box 704 30 /* Yorktown Heights, NY 10598, USA 31 /*--*/ 32 33 /* System library. */ 34 35 #include "sys_defs.h" 36 37 /* Utility library. */ 38 39 #include "mymalloc.h" 40 #include "htable.h" 41 #include "dict.h" 42 #include "dict_ht.h" 43 #include "stringops.h" 44 #include "vstring.h" 45 46 /* Application-specific. */ 47 48 typedef struct { 49 DICT dict; /* generic members */ 50 HTABLE *table; /* hash table */ 51 } DICT_HT; 52 53 /* dict_ht_delete - delete hash-table entry */ 54 55 static int dict_ht_delete(DICT *dict, const char *name) 56 { 57 DICT_HT *dict_ht = (DICT_HT *) dict; 58 59 /* 60 * Optionally fold the key. 61 */ 62 if (dict->flags & DICT_FLAG_FOLD_FIX) { 63 if (dict->fold_buf == 0) 64 dict->fold_buf = vstring_alloc(10); 65 vstring_strcpy(dict->fold_buf, name); 66 name = lowercase(vstring_str(dict->fold_buf)); 67 } 68 if (htable_locate(dict_ht->table, name) == 0) { 69 DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_FAIL); 70 } else { 71 htable_delete(dict_ht->table, name, myfree); 72 DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_SUCCESS); 73 } 74 } 75 76 /* dict_ht_lookup - find hash-table entry */ 77 78 static const char *dict_ht_lookup(DICT *dict, const char *name) 79 { 80 DICT_HT *dict_ht = (DICT_HT *) dict; 81 82 /* 83 * Optionally fold the key. 84 */ 85 if (dict->flags & DICT_FLAG_FOLD_FIX) { 86 if (dict->fold_buf == 0) 87 dict->fold_buf = vstring_alloc(10); 88 vstring_strcpy(dict->fold_buf, name); 89 name = lowercase(vstring_str(dict->fold_buf)); 90 } 91 DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, htable_find(dict_ht->table, name)); 92 } 93 94 /* dict_ht_update - add or update hash-table entry */ 95 96 static int dict_ht_update(DICT *dict, const char *name, const char *value) 97 { 98 DICT_HT *dict_ht = (DICT_HT *) dict; 99 HTABLE_INFO *ht; 100 char *saved_value = mystrdup(value); 101 102 /* 103 * Optionally fold the key. 104 */ 105 if (dict->flags & DICT_FLAG_FOLD_FIX) { 106 if (dict->fold_buf == 0) 107 dict->fold_buf = vstring_alloc(10); 108 vstring_strcpy(dict->fold_buf, name); 109 name = lowercase(vstring_str(dict->fold_buf)); 110 } 111 if ((ht = htable_locate(dict_ht->table, name)) != 0) { 112 myfree(ht->value); 113 } else { 114 ht = htable_enter(dict_ht->table, name, (void *) 0); 115 } 116 ht->value = saved_value; 117 DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_SUCCESS); 118 } 119 120 /* dict_ht_sequence - first/next iterator */ 121 122 static int dict_ht_sequence(DICT *dict, int how, const char **name, 123 const char **value) 124 { 125 DICT_HT *dict_ht = (DICT_HT *) dict; 126 HTABLE_INFO *ht; 127 128 ht = htable_sequence(dict_ht->table, 129 how == DICT_SEQ_FUN_FIRST ? HTABLE_SEQ_FIRST : 130 how == DICT_SEQ_FUN_NEXT ? HTABLE_SEQ_NEXT : 131 HTABLE_SEQ_STOP); 132 if (ht != 0) { 133 *name = ht->key; 134 *value = ht->value; 135 DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_SUCCESS); 136 } else { 137 *name = 0; 138 *value = 0; 139 DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_FAIL); 140 } 141 } 142 143 /* dict_ht_close - disassociate from hash table */ 144 145 static void dict_ht_close(DICT *dict) 146 { 147 DICT_HT *dict_ht = (DICT_HT *) dict; 148 149 htable_free(dict_ht->table, myfree); 150 if (dict_ht->dict.fold_buf) 151 vstring_free(dict_ht->dict.fold_buf); 152 dict_free(dict); 153 } 154 155 /* dict_ht_open - create association with hash table */ 156 157 DICT *dict_ht_open(const char *name, int unused_open_flags, int dict_flags) 158 { 159 DICT_HT *dict_ht; 160 161 dict_ht = (DICT_HT *) dict_alloc(DICT_TYPE_HT, name, sizeof(*dict_ht)); 162 dict_ht->dict.lookup = dict_ht_lookup; 163 dict_ht->dict.update = dict_ht_update; 164 dict_ht->dict.delete = dict_ht_delete; 165 dict_ht->dict.sequence = dict_ht_sequence; 166 dict_ht->dict.close = dict_ht_close; 167 dict_ht->dict.flags = dict_flags | DICT_FLAG_FIXED; 168 if (dict_flags & DICT_FLAG_FOLD_FIX) 169 dict_ht->dict.fold_buf = vstring_alloc(10); 170 dict_ht->table = htable_create(0); 171 dict_ht->dict.owner.status = DICT_OWNER_TRUSTED; 172 return (&dict_ht->dict); 173 } 174