xref: /aosp_15_r20/external/kmod/shared/hash.c (revision cc4ad7da8cefe208cb129ac2aa9a357c7c72deb2)
1*cc4ad7daSAndroid Build Coastguard Worker /*
2*cc4ad7daSAndroid Build Coastguard Worker  * libkmod - interface to kernel module operations
3*cc4ad7daSAndroid Build Coastguard Worker  *
4*cc4ad7daSAndroid Build Coastguard Worker  * Copyright (C) 2011-2013  ProFUSION embedded systems
5*cc4ad7daSAndroid Build Coastguard Worker  *
6*cc4ad7daSAndroid Build Coastguard Worker  * This library is free software; you can redistribute it and/or
7*cc4ad7daSAndroid Build Coastguard Worker  * modify it under the terms of the GNU Lesser General Public
8*cc4ad7daSAndroid Build Coastguard Worker  * License as published by the Free Software Foundation; either
9*cc4ad7daSAndroid Build Coastguard Worker  * version 2.1 of the License, or (at your option) any later version.
10*cc4ad7daSAndroid Build Coastguard Worker  *
11*cc4ad7daSAndroid Build Coastguard Worker  * This library is distributed in the hope that it will be useful,
12*cc4ad7daSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*cc4ad7daSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14*cc4ad7daSAndroid Build Coastguard Worker  * Lesser General Public License for more details.
15*cc4ad7daSAndroid Build Coastguard Worker  *
16*cc4ad7daSAndroid Build Coastguard Worker  * You should have received a copy of the GNU Lesser General Public
17*cc4ad7daSAndroid Build Coastguard Worker  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18*cc4ad7daSAndroid Build Coastguard Worker  */
19*cc4ad7daSAndroid Build Coastguard Worker 
20*cc4ad7daSAndroid Build Coastguard Worker #include <errno.h>
21*cc4ad7daSAndroid Build Coastguard Worker #include <inttypes.h>
22*cc4ad7daSAndroid Build Coastguard Worker #include <stdlib.h>
23*cc4ad7daSAndroid Build Coastguard Worker #include <string.h>
24*cc4ad7daSAndroid Build Coastguard Worker 
25*cc4ad7daSAndroid Build Coastguard Worker #include <shared/hash.h>
26*cc4ad7daSAndroid Build Coastguard Worker #include <shared/util.h>
27*cc4ad7daSAndroid Build Coastguard Worker 
28*cc4ad7daSAndroid Build Coastguard Worker struct hash_entry {
29*cc4ad7daSAndroid Build Coastguard Worker 	const char *key;
30*cc4ad7daSAndroid Build Coastguard Worker 	const void *value;
31*cc4ad7daSAndroid Build Coastguard Worker };
32*cc4ad7daSAndroid Build Coastguard Worker 
33*cc4ad7daSAndroid Build Coastguard Worker struct hash_bucket {
34*cc4ad7daSAndroid Build Coastguard Worker 	struct hash_entry *entries;
35*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int used;
36*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int total;
37*cc4ad7daSAndroid Build Coastguard Worker };
38*cc4ad7daSAndroid Build Coastguard Worker 
39*cc4ad7daSAndroid Build Coastguard Worker struct hash {
40*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int count;
41*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int step;
42*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int n_buckets;
43*cc4ad7daSAndroid Build Coastguard Worker 	void (*free_value)(void *value);
44*cc4ad7daSAndroid Build Coastguard Worker 	struct hash_bucket buckets[];
45*cc4ad7daSAndroid Build Coastguard Worker };
46*cc4ad7daSAndroid Build Coastguard Worker 
hash_new(unsigned int n_buckets,void (* free_value)(void * value))47*cc4ad7daSAndroid Build Coastguard Worker struct hash *hash_new(unsigned int n_buckets,
48*cc4ad7daSAndroid Build Coastguard Worker 					void (*free_value)(void *value))
49*cc4ad7daSAndroid Build Coastguard Worker {
50*cc4ad7daSAndroid Build Coastguard Worker 	struct hash *hash;
51*cc4ad7daSAndroid Build Coastguard Worker 
52*cc4ad7daSAndroid Build Coastguard Worker 	n_buckets = ALIGN_POWER2(n_buckets);
53*cc4ad7daSAndroid Build Coastguard Worker 	hash = calloc(1, sizeof(struct hash) +
54*cc4ad7daSAndroid Build Coastguard Worker 		      n_buckets * sizeof(struct hash_bucket));
55*cc4ad7daSAndroid Build Coastguard Worker 	if (hash == NULL)
56*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
57*cc4ad7daSAndroid Build Coastguard Worker 	hash->n_buckets = n_buckets;
58*cc4ad7daSAndroid Build Coastguard Worker 	hash->free_value = free_value;
59*cc4ad7daSAndroid Build Coastguard Worker 	hash->step = n_buckets / 32;
60*cc4ad7daSAndroid Build Coastguard Worker 	if (hash->step == 0)
61*cc4ad7daSAndroid Build Coastguard Worker 		hash->step = 4;
62*cc4ad7daSAndroid Build Coastguard Worker 	else if (hash->step > 64)
63*cc4ad7daSAndroid Build Coastguard Worker 		hash->step = 64;
64*cc4ad7daSAndroid Build Coastguard Worker 	return hash;
65*cc4ad7daSAndroid Build Coastguard Worker }
66*cc4ad7daSAndroid Build Coastguard Worker 
hash_free(struct hash * hash)67*cc4ad7daSAndroid Build Coastguard Worker void hash_free(struct hash *hash)
68*cc4ad7daSAndroid Build Coastguard Worker {
69*cc4ad7daSAndroid Build Coastguard Worker 	struct hash_bucket *bucket, *bucket_end;
70*cc4ad7daSAndroid Build Coastguard Worker 
71*cc4ad7daSAndroid Build Coastguard Worker 	if (hash == NULL)
72*cc4ad7daSAndroid Build Coastguard Worker 		return;
73*cc4ad7daSAndroid Build Coastguard Worker 
74*cc4ad7daSAndroid Build Coastguard Worker 	bucket = hash->buckets;
75*cc4ad7daSAndroid Build Coastguard Worker 	bucket_end = bucket + hash->n_buckets;
76*cc4ad7daSAndroid Build Coastguard Worker 	for (; bucket < bucket_end; bucket++) {
77*cc4ad7daSAndroid Build Coastguard Worker 		if (hash->free_value) {
78*cc4ad7daSAndroid Build Coastguard Worker 			struct hash_entry *entry, *entry_end;
79*cc4ad7daSAndroid Build Coastguard Worker 			entry = bucket->entries;
80*cc4ad7daSAndroid Build Coastguard Worker 			entry_end = entry + bucket->used;
81*cc4ad7daSAndroid Build Coastguard Worker 			for (; entry < entry_end; entry++)
82*cc4ad7daSAndroid Build Coastguard Worker 				hash->free_value((void *)entry->value);
83*cc4ad7daSAndroid Build Coastguard Worker 		}
84*cc4ad7daSAndroid Build Coastguard Worker 		free(bucket->entries);
85*cc4ad7daSAndroid Build Coastguard Worker 	}
86*cc4ad7daSAndroid Build Coastguard Worker 	free(hash);
87*cc4ad7daSAndroid Build Coastguard Worker }
88*cc4ad7daSAndroid Build Coastguard Worker 
hash_superfast(const char * key,unsigned int len)89*cc4ad7daSAndroid Build Coastguard Worker static inline unsigned int hash_superfast(const char *key, unsigned int len)
90*cc4ad7daSAndroid Build Coastguard Worker {
91*cc4ad7daSAndroid Build Coastguard Worker 	/* Paul Hsieh (http://www.azillionmonkeys.com/qed/hash.html)
92*cc4ad7daSAndroid Build Coastguard Worker 	 * used by WebCore (http://webkit.org/blog/8/hashtables-part-2/)
93*cc4ad7daSAndroid Build Coastguard Worker 	 * EFL's eina and possible others.
94*cc4ad7daSAndroid Build Coastguard Worker 	 */
95*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int tmp, hash = len, rem = len & 3;
96*cc4ad7daSAndroid Build Coastguard Worker 
97*cc4ad7daSAndroid Build Coastguard Worker 	len /= 4;
98*cc4ad7daSAndroid Build Coastguard Worker 
99*cc4ad7daSAndroid Build Coastguard Worker 	/* Main loop */
100*cc4ad7daSAndroid Build Coastguard Worker 	for (; len > 0; len--) {
101*cc4ad7daSAndroid Build Coastguard Worker 		hash += get_unaligned((uint16_t *) key);
102*cc4ad7daSAndroid Build Coastguard Worker 		tmp = (get_unaligned((uint16_t *)(key + 2)) << 11) ^ hash;
103*cc4ad7daSAndroid Build Coastguard Worker 		hash = (hash << 16) ^ tmp;
104*cc4ad7daSAndroid Build Coastguard Worker 		key += 4;
105*cc4ad7daSAndroid Build Coastguard Worker 		hash += hash >> 11;
106*cc4ad7daSAndroid Build Coastguard Worker 	}
107*cc4ad7daSAndroid Build Coastguard Worker 
108*cc4ad7daSAndroid Build Coastguard Worker 	/* Handle end cases */
109*cc4ad7daSAndroid Build Coastguard Worker 	switch (rem) {
110*cc4ad7daSAndroid Build Coastguard Worker 	case 3:
111*cc4ad7daSAndroid Build Coastguard Worker 		hash += get_unaligned((uint16_t *) key);
112*cc4ad7daSAndroid Build Coastguard Worker 		hash ^= hash << 16;
113*cc4ad7daSAndroid Build Coastguard Worker 		hash ^= key[2] << 18;
114*cc4ad7daSAndroid Build Coastguard Worker 		hash += hash >> 11;
115*cc4ad7daSAndroid Build Coastguard Worker 		break;
116*cc4ad7daSAndroid Build Coastguard Worker 
117*cc4ad7daSAndroid Build Coastguard Worker 	case 2:
118*cc4ad7daSAndroid Build Coastguard Worker 		hash += get_unaligned((uint16_t *) key);
119*cc4ad7daSAndroid Build Coastguard Worker 		hash ^= hash << 11;
120*cc4ad7daSAndroid Build Coastguard Worker 		hash += hash >> 17;
121*cc4ad7daSAndroid Build Coastguard Worker 		break;
122*cc4ad7daSAndroid Build Coastguard Worker 
123*cc4ad7daSAndroid Build Coastguard Worker 	case 1:
124*cc4ad7daSAndroid Build Coastguard Worker 		hash += *key;
125*cc4ad7daSAndroid Build Coastguard Worker 		hash ^= hash << 10;
126*cc4ad7daSAndroid Build Coastguard Worker 		hash += hash >> 1;
127*cc4ad7daSAndroid Build Coastguard Worker 	}
128*cc4ad7daSAndroid Build Coastguard Worker 
129*cc4ad7daSAndroid Build Coastguard Worker 	/* Force "avalanching" of final 127 bits */
130*cc4ad7daSAndroid Build Coastguard Worker 	hash ^= hash << 3;
131*cc4ad7daSAndroid Build Coastguard Worker 	hash += hash >> 5;
132*cc4ad7daSAndroid Build Coastguard Worker 	hash ^= hash << 4;
133*cc4ad7daSAndroid Build Coastguard Worker 	hash += hash >> 17;
134*cc4ad7daSAndroid Build Coastguard Worker 	hash ^= hash << 25;
135*cc4ad7daSAndroid Build Coastguard Worker 	hash += hash >> 6;
136*cc4ad7daSAndroid Build Coastguard Worker 
137*cc4ad7daSAndroid Build Coastguard Worker 	return hash;
138*cc4ad7daSAndroid Build Coastguard Worker }
139*cc4ad7daSAndroid Build Coastguard Worker 
140*cc4ad7daSAndroid Build Coastguard Worker /*
141*cc4ad7daSAndroid Build Coastguard Worker  * add or replace key in hash map.
142*cc4ad7daSAndroid Build Coastguard Worker  *
143*cc4ad7daSAndroid Build Coastguard Worker  * none of key or value are copied, just references are remembered as is,
144*cc4ad7daSAndroid Build Coastguard Worker  * make sure they are live while pair exists in hash!
145*cc4ad7daSAndroid Build Coastguard Worker  */
hash_add(struct hash * hash,const char * key,const void * value)146*cc4ad7daSAndroid Build Coastguard Worker int hash_add(struct hash *hash, const char *key, const void *value)
147*cc4ad7daSAndroid Build Coastguard Worker {
148*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int keylen = strlen(key);
149*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int hashval = hash_superfast(key, keylen);
150*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int pos = hashval & (hash->n_buckets - 1);
151*cc4ad7daSAndroid Build Coastguard Worker 	struct hash_bucket *bucket = hash->buckets + pos;
152*cc4ad7daSAndroid Build Coastguard Worker 	struct hash_entry *entry, *entry_end;
153*cc4ad7daSAndroid Build Coastguard Worker 
154*cc4ad7daSAndroid Build Coastguard Worker 	if (bucket->used + 1 >= bucket->total) {
155*cc4ad7daSAndroid Build Coastguard Worker 		unsigned new_total = bucket->total + hash->step;
156*cc4ad7daSAndroid Build Coastguard Worker 		size_t size = new_total * sizeof(struct hash_entry);
157*cc4ad7daSAndroid Build Coastguard Worker 		struct hash_entry *tmp = realloc(bucket->entries, size);
158*cc4ad7daSAndroid Build Coastguard Worker 		if (tmp == NULL)
159*cc4ad7daSAndroid Build Coastguard Worker 			return -errno;
160*cc4ad7daSAndroid Build Coastguard Worker 		bucket->entries = tmp;
161*cc4ad7daSAndroid Build Coastguard Worker 		bucket->total = new_total;
162*cc4ad7daSAndroid Build Coastguard Worker 	}
163*cc4ad7daSAndroid Build Coastguard Worker 
164*cc4ad7daSAndroid Build Coastguard Worker 	entry = bucket->entries;
165*cc4ad7daSAndroid Build Coastguard Worker 	entry_end = entry + bucket->used;
166*cc4ad7daSAndroid Build Coastguard Worker 	for (; entry < entry_end; entry++) {
167*cc4ad7daSAndroid Build Coastguard Worker 		int c = strcmp(key, entry->key);
168*cc4ad7daSAndroid Build Coastguard Worker 		if (c == 0) {
169*cc4ad7daSAndroid Build Coastguard Worker 			if (hash->free_value)
170*cc4ad7daSAndroid Build Coastguard Worker 				hash->free_value((void *)entry->value);
171*cc4ad7daSAndroid Build Coastguard Worker 			entry->key = key;
172*cc4ad7daSAndroid Build Coastguard Worker 			entry->value = value;
173*cc4ad7daSAndroid Build Coastguard Worker 			return 0;
174*cc4ad7daSAndroid Build Coastguard Worker 		} else if (c < 0) {
175*cc4ad7daSAndroid Build Coastguard Worker 			memmove(entry + 1, entry,
176*cc4ad7daSAndroid Build Coastguard Worker 				(entry_end - entry) * sizeof(struct hash_entry));
177*cc4ad7daSAndroid Build Coastguard Worker 			break;
178*cc4ad7daSAndroid Build Coastguard Worker 		}
179*cc4ad7daSAndroid Build Coastguard Worker 	}
180*cc4ad7daSAndroid Build Coastguard Worker 
181*cc4ad7daSAndroid Build Coastguard Worker 	entry->key = key;
182*cc4ad7daSAndroid Build Coastguard Worker 	entry->value = value;
183*cc4ad7daSAndroid Build Coastguard Worker 	bucket->used++;
184*cc4ad7daSAndroid Build Coastguard Worker 	hash->count++;
185*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
186*cc4ad7daSAndroid Build Coastguard Worker }
187*cc4ad7daSAndroid Build Coastguard Worker 
188*cc4ad7daSAndroid Build Coastguard Worker /* similar to hash_add(), but fails if key already exists */
hash_add_unique(struct hash * hash,const char * key,const void * value)189*cc4ad7daSAndroid Build Coastguard Worker int hash_add_unique(struct hash *hash, const char *key, const void *value)
190*cc4ad7daSAndroid Build Coastguard Worker {
191*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int keylen = strlen(key);
192*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int hashval = hash_superfast(key, keylen);
193*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int pos = hashval & (hash->n_buckets - 1);
194*cc4ad7daSAndroid Build Coastguard Worker 	struct hash_bucket *bucket = hash->buckets + pos;
195*cc4ad7daSAndroid Build Coastguard Worker 	struct hash_entry *entry, *entry_end;
196*cc4ad7daSAndroid Build Coastguard Worker 
197*cc4ad7daSAndroid Build Coastguard Worker 	if (bucket->used + 1 >= bucket->total) {
198*cc4ad7daSAndroid Build Coastguard Worker 		unsigned new_total = bucket->total + hash->step;
199*cc4ad7daSAndroid Build Coastguard Worker 		size_t size = new_total * sizeof(struct hash_entry);
200*cc4ad7daSAndroid Build Coastguard Worker 		struct hash_entry *tmp = realloc(bucket->entries, size);
201*cc4ad7daSAndroid Build Coastguard Worker 		if (tmp == NULL)
202*cc4ad7daSAndroid Build Coastguard Worker 			return -errno;
203*cc4ad7daSAndroid Build Coastguard Worker 		bucket->entries = tmp;
204*cc4ad7daSAndroid Build Coastguard Worker 		bucket->total = new_total;
205*cc4ad7daSAndroid Build Coastguard Worker 	}
206*cc4ad7daSAndroid Build Coastguard Worker 
207*cc4ad7daSAndroid Build Coastguard Worker 	entry = bucket->entries;
208*cc4ad7daSAndroid Build Coastguard Worker 	entry_end = entry + bucket->used;
209*cc4ad7daSAndroid Build Coastguard Worker 	for (; entry < entry_end; entry++) {
210*cc4ad7daSAndroid Build Coastguard Worker 		int c = strcmp(key, entry->key);
211*cc4ad7daSAndroid Build Coastguard Worker 		if (c == 0)
212*cc4ad7daSAndroid Build Coastguard Worker 			return -EEXIST;
213*cc4ad7daSAndroid Build Coastguard Worker 		else if (c < 0) {
214*cc4ad7daSAndroid Build Coastguard Worker 			memmove(entry + 1, entry,
215*cc4ad7daSAndroid Build Coastguard Worker 				(entry_end - entry) * sizeof(struct hash_entry));
216*cc4ad7daSAndroid Build Coastguard Worker 			break;
217*cc4ad7daSAndroid Build Coastguard Worker 		}
218*cc4ad7daSAndroid Build Coastguard Worker 	}
219*cc4ad7daSAndroid Build Coastguard Worker 
220*cc4ad7daSAndroid Build Coastguard Worker 	entry->key = key;
221*cc4ad7daSAndroid Build Coastguard Worker 	entry->value = value;
222*cc4ad7daSAndroid Build Coastguard Worker 	bucket->used++;
223*cc4ad7daSAndroid Build Coastguard Worker 	hash->count++;
224*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
225*cc4ad7daSAndroid Build Coastguard Worker }
226*cc4ad7daSAndroid Build Coastguard Worker 
hash_entry_cmp(const void * pa,const void * pb)227*cc4ad7daSAndroid Build Coastguard Worker static int hash_entry_cmp(const void *pa, const void *pb)
228*cc4ad7daSAndroid Build Coastguard Worker {
229*cc4ad7daSAndroid Build Coastguard Worker 	const struct hash_entry *a = pa;
230*cc4ad7daSAndroid Build Coastguard Worker 	const struct hash_entry *b = pb;
231*cc4ad7daSAndroid Build Coastguard Worker 	return strcmp(a->key, b->key);
232*cc4ad7daSAndroid Build Coastguard Worker }
233*cc4ad7daSAndroid Build Coastguard Worker 
hash_find(const struct hash * hash,const char * key)234*cc4ad7daSAndroid Build Coastguard Worker void *hash_find(const struct hash *hash, const char *key)
235*cc4ad7daSAndroid Build Coastguard Worker {
236*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int keylen = strlen(key);
237*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int hashval = hash_superfast(key, keylen);
238*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int pos = hashval & (hash->n_buckets - 1);
239*cc4ad7daSAndroid Build Coastguard Worker 	const struct hash_bucket *bucket = hash->buckets + pos;
240*cc4ad7daSAndroid Build Coastguard Worker 	const struct hash_entry se = {
241*cc4ad7daSAndroid Build Coastguard Worker 		.key = key,
242*cc4ad7daSAndroid Build Coastguard Worker 		.value = NULL
243*cc4ad7daSAndroid Build Coastguard Worker 	};
244*cc4ad7daSAndroid Build Coastguard Worker 	const struct hash_entry *entry;
245*cc4ad7daSAndroid Build Coastguard Worker 
246*cc4ad7daSAndroid Build Coastguard Worker 	if (!bucket->entries)
247*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
248*cc4ad7daSAndroid Build Coastguard Worker 
249*cc4ad7daSAndroid Build Coastguard Worker 	entry = bsearch(&se, bucket->entries, bucket->used,
250*cc4ad7daSAndroid Build Coastguard Worker 			sizeof(struct hash_entry), hash_entry_cmp);
251*cc4ad7daSAndroid Build Coastguard Worker 
252*cc4ad7daSAndroid Build Coastguard Worker 	return entry ? (void *)entry->value : NULL;
253*cc4ad7daSAndroid Build Coastguard Worker }
254*cc4ad7daSAndroid Build Coastguard Worker 
hash_del(struct hash * hash,const char * key)255*cc4ad7daSAndroid Build Coastguard Worker int hash_del(struct hash *hash, const char *key)
256*cc4ad7daSAndroid Build Coastguard Worker {
257*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int keylen = strlen(key);
258*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int hashval = hash_superfast(key, keylen);
259*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int pos = hashval & (hash->n_buckets - 1);
260*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int steps_used, steps_total;
261*cc4ad7daSAndroid Build Coastguard Worker 	struct hash_bucket *bucket = hash->buckets + pos;
262*cc4ad7daSAndroid Build Coastguard Worker 	struct hash_entry *entry, *entry_end;
263*cc4ad7daSAndroid Build Coastguard Worker 	const struct hash_entry se = {
264*cc4ad7daSAndroid Build Coastguard Worker 		.key = key,
265*cc4ad7daSAndroid Build Coastguard Worker 		.value = NULL
266*cc4ad7daSAndroid Build Coastguard Worker 	};
267*cc4ad7daSAndroid Build Coastguard Worker 
268*cc4ad7daSAndroid Build Coastguard Worker 	entry = bsearch(&se, bucket->entries, bucket->used,
269*cc4ad7daSAndroid Build Coastguard Worker 		sizeof(struct hash_entry), hash_entry_cmp);
270*cc4ad7daSAndroid Build Coastguard Worker 	if (entry == NULL)
271*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
272*cc4ad7daSAndroid Build Coastguard Worker 
273*cc4ad7daSAndroid Build Coastguard Worker 	if (hash->free_value)
274*cc4ad7daSAndroid Build Coastguard Worker 		hash->free_value((void *)entry->value);
275*cc4ad7daSAndroid Build Coastguard Worker 
276*cc4ad7daSAndroid Build Coastguard Worker 	entry_end = bucket->entries + bucket->used;
277*cc4ad7daSAndroid Build Coastguard Worker 	memmove(entry, entry + 1,
278*cc4ad7daSAndroid Build Coastguard Worker 		(entry_end - entry) * sizeof(struct hash_entry));
279*cc4ad7daSAndroid Build Coastguard Worker 
280*cc4ad7daSAndroid Build Coastguard Worker 	bucket->used--;
281*cc4ad7daSAndroid Build Coastguard Worker 	hash->count--;
282*cc4ad7daSAndroid Build Coastguard Worker 
283*cc4ad7daSAndroid Build Coastguard Worker 	steps_used = bucket->used / hash->step;
284*cc4ad7daSAndroid Build Coastguard Worker 	steps_total = bucket->total / hash->step;
285*cc4ad7daSAndroid Build Coastguard Worker 	if (steps_used + 1 < steps_total) {
286*cc4ad7daSAndroid Build Coastguard Worker 		size_t size = (steps_used + 1) *
287*cc4ad7daSAndroid Build Coastguard Worker 			hash->step * sizeof(struct hash_entry);
288*cc4ad7daSAndroid Build Coastguard Worker 		struct hash_entry *tmp = realloc(bucket->entries, size);
289*cc4ad7daSAndroid Build Coastguard Worker 		if (tmp) {
290*cc4ad7daSAndroid Build Coastguard Worker 			bucket->entries = tmp;
291*cc4ad7daSAndroid Build Coastguard Worker 			bucket->total = (steps_used + 1) * hash->step;
292*cc4ad7daSAndroid Build Coastguard Worker 		}
293*cc4ad7daSAndroid Build Coastguard Worker 	}
294*cc4ad7daSAndroid Build Coastguard Worker 
295*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
296*cc4ad7daSAndroid Build Coastguard Worker }
297*cc4ad7daSAndroid Build Coastguard Worker 
hash_get_count(const struct hash * hash)298*cc4ad7daSAndroid Build Coastguard Worker unsigned int hash_get_count(const struct hash *hash)
299*cc4ad7daSAndroid Build Coastguard Worker {
300*cc4ad7daSAndroid Build Coastguard Worker 	return hash->count;
301*cc4ad7daSAndroid Build Coastguard Worker }
302*cc4ad7daSAndroid Build Coastguard Worker 
hash_iter_init(const struct hash * hash,struct hash_iter * iter)303*cc4ad7daSAndroid Build Coastguard Worker void hash_iter_init(const struct hash *hash, struct hash_iter *iter)
304*cc4ad7daSAndroid Build Coastguard Worker {
305*cc4ad7daSAndroid Build Coastguard Worker 	iter->hash = hash;
306*cc4ad7daSAndroid Build Coastguard Worker 	iter->bucket = 0;
307*cc4ad7daSAndroid Build Coastguard Worker 	iter->entry = -1;
308*cc4ad7daSAndroid Build Coastguard Worker }
309*cc4ad7daSAndroid Build Coastguard Worker 
hash_iter_next(struct hash_iter * iter,const char ** key,const void ** value)310*cc4ad7daSAndroid Build Coastguard Worker bool hash_iter_next(struct hash_iter *iter, const char **key,
311*cc4ad7daSAndroid Build Coastguard Worker 							const void **value)
312*cc4ad7daSAndroid Build Coastguard Worker {
313*cc4ad7daSAndroid Build Coastguard Worker 	const struct hash_bucket *b = iter->hash->buckets + iter->bucket;
314*cc4ad7daSAndroid Build Coastguard Worker 	const struct hash_entry *e;
315*cc4ad7daSAndroid Build Coastguard Worker 
316*cc4ad7daSAndroid Build Coastguard Worker 	iter->entry++;
317*cc4ad7daSAndroid Build Coastguard Worker 
318*cc4ad7daSAndroid Build Coastguard Worker 	if (iter->entry >= b->used) {
319*cc4ad7daSAndroid Build Coastguard Worker 		iter->entry = 0;
320*cc4ad7daSAndroid Build Coastguard Worker 
321*cc4ad7daSAndroid Build Coastguard Worker 		for (iter->bucket++; iter->bucket < iter->hash->n_buckets;
322*cc4ad7daSAndroid Build Coastguard Worker 							iter->bucket++) {
323*cc4ad7daSAndroid Build Coastguard Worker 			b = iter->hash->buckets + iter->bucket;
324*cc4ad7daSAndroid Build Coastguard Worker 
325*cc4ad7daSAndroid Build Coastguard Worker 			if (b->used > 0)
326*cc4ad7daSAndroid Build Coastguard Worker 				break;
327*cc4ad7daSAndroid Build Coastguard Worker 		}
328*cc4ad7daSAndroid Build Coastguard Worker 
329*cc4ad7daSAndroid Build Coastguard Worker 		if (iter->bucket >= iter->hash->n_buckets)
330*cc4ad7daSAndroid Build Coastguard Worker 			return false;
331*cc4ad7daSAndroid Build Coastguard Worker 	}
332*cc4ad7daSAndroid Build Coastguard Worker 
333*cc4ad7daSAndroid Build Coastguard Worker 	e = b->entries + iter->entry;
334*cc4ad7daSAndroid Build Coastguard Worker 
335*cc4ad7daSAndroid Build Coastguard Worker 	if (value != NULL)
336*cc4ad7daSAndroid Build Coastguard Worker 		*value = e->value;
337*cc4ad7daSAndroid Build Coastguard Worker 	if (key != NULL)
338*cc4ad7daSAndroid Build Coastguard Worker 		*key = e->key;
339*cc4ad7daSAndroid Build Coastguard Worker 
340*cc4ad7daSAndroid Build Coastguard Worker 	return true;
341*cc4ad7daSAndroid Build Coastguard Worker }
342