xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/dict_ht.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
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