1:
2:
3:
4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31:
32:
33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43:
44:
45: #include "namespace.h"
46: #include <assert.h>
47: #include <errno.h>
48: #include <inttypes.h>
49: #include <search.h>
50: #include <stdlib.h>
51: #include <string.h>
52: #include <sys/queue.h>
53:
54: #ifndef _DIAGASSERT
55: #define _DIAGASSERT(x)
56: #endif
57:
58: 59: 60: 61:
62: struct internal_entry {
63: SLIST_ENTRY(internal_entry) link;
64: ENTRY ent;
65: };
66: SLIST_HEAD(internal_head, internal_entry);
67:
68: #define MIN_BUCKETS_LG2 4
69: #define MIN_BUCKETS (1 << MIN_BUCKETS_LG2)
70:
71: 72: 73: 74:
75: #define MAX_BUCKETS_LG2 (sizeof (size_t) * 8 - 1 - 5)
76: #define MAX_BUCKETS ((size_t)1 << MAX_BUCKETS_LG2)
77:
78:
79: extern u_int32_t (*__default_hash)(const void *, size_t);
80:
81: struct hsearch_data
82: {struct internal_head *table; size_t size;};
83:
84: int
85: hcreate_r(size_t nel, struct hsearch_data *htab)
86: {
87: size_t idx;
88: unsigned int p2;
89:
90:
91: _DIAGASSERT(htab->table == NULL);
92: if (htab->table != NULL) {
93: ;
94: return 0;
95: }
96:
97:
98: if (nel < MIN_BUCKETS)
99: nel = MIN_BUCKETS;
100:
101:
102: if (nel > MAX_BUCKETS)
103: nel = MAX_BUCKETS;
104:
105:
106: if ((nel & (nel - 1)) != 0) {
107: for (p2 = 0; nel != 0; p2++)
108: nel >>= 1;
109: _DIAGASSERT(p2 <= MAX_BUCKETS_LG2);
110: nel = 1 << p2;
111: }
112:
113:
114: htab->size = nel;
115: htab->table = calloc(htab->size, sizeof htab->table[0]);
116: if (htab->table == NULL) {
117: ;
118: return 0;
119: }
120:
121:
122: for (idx = 0; idx < htab->size; idx++)
123: SLIST_INIT(&htab->table[idx]);
124:
125: return 1;
126: }
127:
128: void
129: hdestroy_r(struct hsearch_data *htab)
130: {
131: struct internal_entry *ie;
132: size_t idx;
133:
134: _DIAGASSERT(htab->table != NULL);
135: if (htab->table == NULL)
136: return;
137:
138: for (idx = 0; idx < htab->size; idx++) {
139: while (!SLIST_EMPTY(&htab->table[idx])) {
140: ie = SLIST_FIRST(&htab->table[idx]);
141: SLIST_REMOVE_HEAD(&htab->table[idx], link);
142:
143: free(ie);
144: }
145: }
146: free(htab->table);
147: htab->table = NULL;
148: }
149:
150: int
151: hsearch_r(ENTRY item, ACTION action, ENTRY **result, struct hsearch_data *htab)
152: {
153: struct internal_head *head;
154: struct internal_entry *ie;
155: uint32_t hashval;
156: size_t len;
157:
158: _DIAGASSERT(htab->table != NULL);
159: _DIAGASSERT(item.key != NULL);
160: _DIAGASSERT(action == ENTER || action == FIND);
161:
162: len = strlen(item.key);
163: hashval = (*__default_hash)(item.key, len);
164:
165: head = &htab->table[hashval & (htab->size - 1)];
166: ie = SLIST_FIRST(head);
167: while (ie != NULL) {
168: if (strcmp(ie->ent.key, item.key) == 0)
169: break;
170: ie = SLIST_NEXT(ie, link);
171: }
172:
173: if (ie != NULL)
174: return (*result = &ie->ent), 1;
175: else if (action == FIND)
176: return 0;
177:
178: ie = malloc(sizeof *ie);
179: if (ie == NULL)
180: return 0;
181: ie->ent.key = item.key;
182: ie->ent.data = item.data;
183:
184: SLIST_INSERT_HEAD(head, ie, link);
185: return (*result = &ie->ent), 1;
186: }