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
dict_ht_delete(DICT * dict,const char * name)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
dict_ht_lookup(DICT * dict,const char * name)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
dict_ht_update(DICT * dict,const char * name,const char * value)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
dict_ht_sequence(DICT * dict,int how,const char ** name,const char ** value)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
dict_ht_close(DICT * dict)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
dict_ht_open(const char * name,int unused_open_flags,int dict_flags)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