xref: /minix3/usr.bin/m4/lib/ohash_do.c (revision 2e8d1eda1b10b1eefcc41d19325e6baa0615ae5c)
1*2e8d1edaSArun Thomas /* $OpenBSD: ohash_do.c,v 1.4 2004/06/22 20:00:16 espie Exp $ */
2*2e8d1edaSArun Thomas /* ex:ts=8 sw=4:
3*2e8d1edaSArun Thomas  */
4*2e8d1edaSArun Thomas 
5*2e8d1edaSArun Thomas /* Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org>
6*2e8d1edaSArun Thomas  *
7*2e8d1edaSArun Thomas  * Permission to use, copy, modify, and distribute this software for any
8*2e8d1edaSArun Thomas  * purpose with or without fee is hereby granted, provided that the above
9*2e8d1edaSArun Thomas  * copyright notice and this permission notice appear in all copies.
10*2e8d1edaSArun Thomas  *
11*2e8d1edaSArun Thomas  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12*2e8d1edaSArun Thomas  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13*2e8d1edaSArun Thomas  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14*2e8d1edaSArun Thomas  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15*2e8d1edaSArun Thomas  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16*2e8d1edaSArun Thomas  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17*2e8d1edaSArun Thomas  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*2e8d1edaSArun Thomas  */
19*2e8d1edaSArun Thomas 
20*2e8d1edaSArun Thomas #include "ohash_int.h"
21*2e8d1edaSArun Thomas 
22*2e8d1edaSArun Thomas static void ohash_resize(struct ohash *);
23*2e8d1edaSArun Thomas 
24*2e8d1edaSArun Thomas static void
ohash_resize(struct ohash * h)25*2e8d1edaSArun Thomas ohash_resize(struct ohash *h)
26*2e8d1edaSArun Thomas {
27*2e8d1edaSArun Thomas 	struct _ohash_record *n;
28*2e8d1edaSArun Thomas 	unsigned int 	ns, j;
29*2e8d1edaSArun Thomas 	unsigned int	i, incr;
30*2e8d1edaSArun Thomas 
31*2e8d1edaSArun Thomas 	if (4 * h->deleted < h->total)
32*2e8d1edaSArun Thomas 		ns = h->size << 1;
33*2e8d1edaSArun Thomas 	else if (3 * h->deleted > 2 * h->total)
34*2e8d1edaSArun Thomas 		ns = h->size >> 1;
35*2e8d1edaSArun Thomas 	else
36*2e8d1edaSArun Thomas 		ns = h->size;
37*2e8d1edaSArun Thomas 	if (ns < MINSIZE)
38*2e8d1edaSArun Thomas 		ns = MINSIZE;
39*2e8d1edaSArun Thomas #ifdef STATS_HASH
40*2e8d1edaSArun Thomas 	STAT_HASH_EXPAND++;
41*2e8d1edaSArun Thomas 	STAT_HASH_SIZE += ns - h->size;
42*2e8d1edaSArun Thomas #endif
43*2e8d1edaSArun Thomas 	n = (h->info.halloc)(sizeof(struct _ohash_record) * ns, h->info.data);
44*2e8d1edaSArun Thomas 	if (!n)
45*2e8d1edaSArun Thomas 		return;
46*2e8d1edaSArun Thomas 
47*2e8d1edaSArun Thomas 	for (j = 0; j < h->size; j++) {
48*2e8d1edaSArun Thomas 		if (h->t[j].p != NULL && h->t[j].p != DELETED) {
49*2e8d1edaSArun Thomas 			i = h->t[j].hv % ns;
50*2e8d1edaSArun Thomas 			incr = ((h->t[j].hv % (ns - 2)) & ~1) + 1;
51*2e8d1edaSArun Thomas 			while (n[i].p != NULL) {
52*2e8d1edaSArun Thomas 				i += incr;
53*2e8d1edaSArun Thomas 				if (i >= ns)
54*2e8d1edaSArun Thomas 					i -= ns;
55*2e8d1edaSArun Thomas 		    	}
56*2e8d1edaSArun Thomas 			n[i].hv = h->t[j].hv;
57*2e8d1edaSArun Thomas 			n[i].p = h->t[j].p;
58*2e8d1edaSArun Thomas 		}
59*2e8d1edaSArun Thomas 	}
60*2e8d1edaSArun Thomas 	(h->info.hfree)(h->t, sizeof(struct _ohash_record) * h->size,
61*2e8d1edaSArun Thomas 		h->info.data);
62*2e8d1edaSArun Thomas 	h->t = n;
63*2e8d1edaSArun Thomas 	h->size = ns;
64*2e8d1edaSArun Thomas 	h->total -= h->deleted;
65*2e8d1edaSArun Thomas 	h->deleted = 0;
66*2e8d1edaSArun Thomas }
67*2e8d1edaSArun Thomas 
68*2e8d1edaSArun Thomas void *
ohash_remove(struct ohash * h,unsigned int i)69*2e8d1edaSArun Thomas ohash_remove(struct ohash *h, unsigned int i)
70*2e8d1edaSArun Thomas {
71*2e8d1edaSArun Thomas 	void 		*result = __UNCONST(h->t[i].p);
72*2e8d1edaSArun Thomas 
73*2e8d1edaSArun Thomas 	if (result == NULL || result == DELETED)
74*2e8d1edaSArun Thomas 		return NULL;
75*2e8d1edaSArun Thomas 
76*2e8d1edaSArun Thomas #ifdef STATS_HASH
77*2e8d1edaSArun Thomas 	STAT_HASH_ENTRIES--;
78*2e8d1edaSArun Thomas #endif
79*2e8d1edaSArun Thomas 	h->t[i].p = DELETED;
80*2e8d1edaSArun Thomas 	h->deleted++;
81*2e8d1edaSArun Thomas 	if (h->deleted >= MINDELETED && 4 * h->deleted > h->total)
82*2e8d1edaSArun Thomas 		ohash_resize(h);
83*2e8d1edaSArun Thomas 	return result;
84*2e8d1edaSArun Thomas }
85*2e8d1edaSArun Thomas 
86*2e8d1edaSArun Thomas void *
ohash_find(struct ohash * h,unsigned int i)87*2e8d1edaSArun Thomas ohash_find(struct ohash *h, unsigned int i)
88*2e8d1edaSArun Thomas {
89*2e8d1edaSArun Thomas 	if (h->t[i].p == DELETED)
90*2e8d1edaSArun Thomas 		return NULL;
91*2e8d1edaSArun Thomas 	else
92*2e8d1edaSArun Thomas 		return __UNCONST(h->t[i].p);
93*2e8d1edaSArun Thomas }
94*2e8d1edaSArun Thomas 
95*2e8d1edaSArun Thomas void *
ohash_insert(struct ohash * h,unsigned int i,void * p)96*2e8d1edaSArun Thomas ohash_insert(struct ohash *h, unsigned int i, void *p)
97*2e8d1edaSArun Thomas {
98*2e8d1edaSArun Thomas #ifdef STATS_HASH
99*2e8d1edaSArun Thomas 	STAT_HASH_ENTRIES++;
100*2e8d1edaSArun Thomas #endif
101*2e8d1edaSArun Thomas 	if (h->t[i].p == DELETED) {
102*2e8d1edaSArun Thomas 		h->deleted--;
103*2e8d1edaSArun Thomas 		h->t[i].p = p;
104*2e8d1edaSArun Thomas 	} else {
105*2e8d1edaSArun Thomas 		h->t[i].p = p;
106*2e8d1edaSArun Thomas 	/* Arbitrary resize boundary.  Tweak if not efficient enough.  */
107*2e8d1edaSArun Thomas 		if (++h->total * 4 > h->size * 3)
108*2e8d1edaSArun Thomas 			ohash_resize(h);
109*2e8d1edaSArun Thomas 	}
110*2e8d1edaSArun Thomas     	return p;
111*2e8d1edaSArun Thomas }
112