xref: /netbsd-src/usr.bin/m4/lib/ohash_do.c (revision 315c7490d2bf841fb2c781a53547925ddf7b7e2d)
171dafaa1Schristos /* $OpenBSD: ohash_do.c,v 1.4 2004/06/22 20:00:16 espie Exp $ */
271dafaa1Schristos /* ex:ts=8 sw=4:
371dafaa1Schristos  */
471dafaa1Schristos 
571dafaa1Schristos /* Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org>
671dafaa1Schristos  *
771dafaa1Schristos  * Permission to use, copy, modify, and distribute this software for any
871dafaa1Schristos  * purpose with or without fee is hereby granted, provided that the above
971dafaa1Schristos  * copyright notice and this permission notice appear in all copies.
1071dafaa1Schristos  *
1171dafaa1Schristos  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1271dafaa1Schristos  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1371dafaa1Schristos  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1471dafaa1Schristos  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1571dafaa1Schristos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1671dafaa1Schristos  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1771dafaa1Schristos  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1871dafaa1Schristos  */
1971dafaa1Schristos 
2071dafaa1Schristos #include "ohash_int.h"
2171dafaa1Schristos 
2271dafaa1Schristos static void ohash_resize(struct ohash *);
2371dafaa1Schristos 
2471dafaa1Schristos static void
ohash_resize(struct ohash * h)2571dafaa1Schristos ohash_resize(struct ohash *h)
2671dafaa1Schristos {
2771dafaa1Schristos 	struct _ohash_record *n;
2871dafaa1Schristos 	unsigned int 	ns, j;
2971dafaa1Schristos 	unsigned int	i, incr;
3071dafaa1Schristos 
3171dafaa1Schristos 	if (4 * h->deleted < h->total)
3271dafaa1Schristos 		ns = h->size << 1;
3371dafaa1Schristos 	else if (3 * h->deleted > 2 * h->total)
3471dafaa1Schristos 		ns = h->size >> 1;
3571dafaa1Schristos 	else
3671dafaa1Schristos 		ns = h->size;
3771dafaa1Schristos 	if (ns < MINSIZE)
3871dafaa1Schristos 		ns = MINSIZE;
3971dafaa1Schristos #ifdef STATS_HASH
4071dafaa1Schristos 	STAT_HASH_EXPAND++;
4171dafaa1Schristos 	STAT_HASH_SIZE += ns - h->size;
4271dafaa1Schristos #endif
4371dafaa1Schristos 	n = (h->info.halloc)(sizeof(struct _ohash_record) * ns, h->info.data);
4471dafaa1Schristos 	if (!n)
4571dafaa1Schristos 		return;
4671dafaa1Schristos 
4771dafaa1Schristos 	for (j = 0; j < h->size; j++) {
4871dafaa1Schristos 		if (h->t[j].p != NULL && h->t[j].p != DELETED) {
4971dafaa1Schristos 			i = h->t[j].hv % ns;
5071dafaa1Schristos 			incr = ((h->t[j].hv % (ns - 2)) & ~1) + 1;
5171dafaa1Schristos 			while (n[i].p != NULL) {
5271dafaa1Schristos 				i += incr;
5371dafaa1Schristos 				if (i >= ns)
5471dafaa1Schristos 					i -= ns;
5571dafaa1Schristos 		    	}
5671dafaa1Schristos 			n[i].hv = h->t[j].hv;
5771dafaa1Schristos 			n[i].p = h->t[j].p;
5871dafaa1Schristos 		}
5971dafaa1Schristos 	}
6071dafaa1Schristos 	(h->info.hfree)(h->t, sizeof(struct _ohash_record) * h->size,
6171dafaa1Schristos 		h->info.data);
6271dafaa1Schristos 	h->t = n;
6371dafaa1Schristos 	h->size = ns;
6471dafaa1Schristos 	h->total -= h->deleted;
6571dafaa1Schristos 	h->deleted = 0;
6671dafaa1Schristos }
6771dafaa1Schristos 
6871dafaa1Schristos void *
ohash_remove(struct ohash * h,unsigned int i)6971dafaa1Schristos ohash_remove(struct ohash *h, unsigned int i)
7071dafaa1Schristos {
71*315c7490Schristos 	void 		*result = __UNCONST(h->t[i].p);
7271dafaa1Schristos 
7371dafaa1Schristos 	if (result == NULL || result == DELETED)
7471dafaa1Schristos 		return NULL;
7571dafaa1Schristos 
7671dafaa1Schristos #ifdef STATS_HASH
7771dafaa1Schristos 	STAT_HASH_ENTRIES--;
7871dafaa1Schristos #endif
7971dafaa1Schristos 	h->t[i].p = DELETED;
8071dafaa1Schristos 	h->deleted++;
8171dafaa1Schristos 	if (h->deleted >= MINDELETED && 4 * h->deleted > h->total)
8271dafaa1Schristos 		ohash_resize(h);
8371dafaa1Schristos 	return result;
8471dafaa1Schristos }
8571dafaa1Schristos 
8671dafaa1Schristos void *
ohash_find(struct ohash * h,unsigned int i)8771dafaa1Schristos ohash_find(struct ohash *h, unsigned int i)
8871dafaa1Schristos {
8971dafaa1Schristos 	if (h->t[i].p == DELETED)
9071dafaa1Schristos 		return NULL;
9171dafaa1Schristos 	else
92*315c7490Schristos 		return __UNCONST(h->t[i].p);
9371dafaa1Schristos }
9471dafaa1Schristos 
9571dafaa1Schristos void *
ohash_insert(struct ohash * h,unsigned int i,void * p)9671dafaa1Schristos ohash_insert(struct ohash *h, unsigned int i, void *p)
9771dafaa1Schristos {
9871dafaa1Schristos #ifdef STATS_HASH
9971dafaa1Schristos 	STAT_HASH_ENTRIES++;
10071dafaa1Schristos #endif
10171dafaa1Schristos 	if (h->t[i].p == DELETED) {
10271dafaa1Schristos 		h->deleted--;
10371dafaa1Schristos 		h->t[i].p = p;
10471dafaa1Schristos 	} else {
10571dafaa1Schristos 		h->t[i].p = p;
10671dafaa1Schristos 	/* Arbitrary resize boundary.  Tweak if not efficient enough.  */
10771dafaa1Schristos 		if (++h->total * 4 > h->size * 3)
10871dafaa1Schristos 			ohash_resize(h);
10971dafaa1Schristos 	}
11071dafaa1Schristos     	return p;
11171dafaa1Schristos }
112