1*d3273b5bSchristos /* $NetBSD: hash.c,v 1.2 2017/01/28 21:31:45 christos Exp $ */
2ca1c9b0cSelric
3ca1c9b0cSelric /*
4ca1c9b0cSelric * Copyright (c) 1997 Kungliga Tekniska Högskolan
5ca1c9b0cSelric * (Royal Institute of Technology, Stockholm, Sweden).
6ca1c9b0cSelric * All rights reserved.
7ca1c9b0cSelric *
8ca1c9b0cSelric * Redistribution and use in source and binary forms, with or without
9ca1c9b0cSelric * modification, are permitted provided that the following conditions
10ca1c9b0cSelric * are met:
11ca1c9b0cSelric *
12ca1c9b0cSelric * 1. Redistributions of source code must retain the above copyright
13ca1c9b0cSelric * notice, this list of conditions and the following disclaimer.
14ca1c9b0cSelric *
15ca1c9b0cSelric * 2. Redistributions in binary form must reproduce the above copyright
16ca1c9b0cSelric * notice, this list of conditions and the following disclaimer in the
17ca1c9b0cSelric * documentation and/or other materials provided with the distribution.
18ca1c9b0cSelric *
19ca1c9b0cSelric * 3. Neither the name of the Institute nor the names of its contributors
20ca1c9b0cSelric * may be used to endorse or promote products derived from this software
21ca1c9b0cSelric * without specific prior written permission.
22ca1c9b0cSelric *
23ca1c9b0cSelric * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ca1c9b0cSelric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ca1c9b0cSelric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ca1c9b0cSelric * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ca1c9b0cSelric * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ca1c9b0cSelric * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ca1c9b0cSelric * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ca1c9b0cSelric * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ca1c9b0cSelric * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ca1c9b0cSelric * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ca1c9b0cSelric * SUCH DAMAGE.
34ca1c9b0cSelric */
35ca1c9b0cSelric
36ca1c9b0cSelric /*
37ca1c9b0cSelric * Hash table functions
38ca1c9b0cSelric */
39ca1c9b0cSelric
40ca1c9b0cSelric #include "gen_locl.h"
41ca1c9b0cSelric
42*d3273b5bSchristos __RCSID("$NetBSD: hash.c,v 1.2 2017/01/28 21:31:45 christos Exp $");
43ca1c9b0cSelric
44ca1c9b0cSelric static Hashentry *_search(Hashtab * htab, /* The hash table */
45ca1c9b0cSelric void *ptr); /* And key */
46ca1c9b0cSelric
47ca1c9b0cSelric Hashtab *
hashtabnew(int sz,int (* cmp)(void *,void *),unsigned (* hash)(void *))48ca1c9b0cSelric hashtabnew(int sz,
49ca1c9b0cSelric int (*cmp) (void *, void *),
50ca1c9b0cSelric unsigned (*hash) (void *))
51ca1c9b0cSelric {
52ca1c9b0cSelric Hashtab *htab;
53ca1c9b0cSelric int i;
54ca1c9b0cSelric
55ca1c9b0cSelric assert(sz > 0);
56ca1c9b0cSelric
57ca1c9b0cSelric htab = (Hashtab *) malloc(sizeof(Hashtab) + (sz - 1) * sizeof(Hashentry *));
58ca1c9b0cSelric if (htab == NULL)
59ca1c9b0cSelric return NULL;
60ca1c9b0cSelric
61ca1c9b0cSelric for (i = 0; i < sz; ++i)
62ca1c9b0cSelric htab->tab[i] = NULL;
63ca1c9b0cSelric
64ca1c9b0cSelric htab->cmp = cmp;
65ca1c9b0cSelric htab->hash = hash;
66ca1c9b0cSelric htab->sz = sz;
67ca1c9b0cSelric return htab;
68ca1c9b0cSelric }
69ca1c9b0cSelric
70ca1c9b0cSelric /* Intern search function */
71ca1c9b0cSelric
72ca1c9b0cSelric static Hashentry *
_search(Hashtab * htab,void * ptr)73ca1c9b0cSelric _search(Hashtab * htab, void *ptr)
74ca1c9b0cSelric {
75ca1c9b0cSelric Hashentry *hptr;
76ca1c9b0cSelric
77ca1c9b0cSelric assert(htab && ptr);
78ca1c9b0cSelric
79ca1c9b0cSelric for (hptr = htab->tab[(*htab->hash) (ptr) % htab->sz];
80ca1c9b0cSelric hptr;
81ca1c9b0cSelric hptr = hptr->next)
82ca1c9b0cSelric if ((*htab->cmp) (ptr, hptr->ptr) == 0)
83ca1c9b0cSelric break;
84ca1c9b0cSelric return hptr;
85ca1c9b0cSelric }
86ca1c9b0cSelric
87ca1c9b0cSelric /* Search for element in hash table */
88ca1c9b0cSelric
89ca1c9b0cSelric void *
hashtabsearch(Hashtab * htab,void * ptr)90ca1c9b0cSelric hashtabsearch(Hashtab * htab, void *ptr)
91ca1c9b0cSelric {
92ca1c9b0cSelric Hashentry *tmp;
93ca1c9b0cSelric
94ca1c9b0cSelric tmp = _search(htab, ptr);
95ca1c9b0cSelric return tmp ? tmp->ptr : tmp;
96ca1c9b0cSelric }
97ca1c9b0cSelric
98ca1c9b0cSelric /* add element to hash table */
99ca1c9b0cSelric /* if already there, set new value */
100ca1c9b0cSelric /* !NULL if succesful */
101ca1c9b0cSelric
102ca1c9b0cSelric void *
hashtabadd(Hashtab * htab,void * ptr)103ca1c9b0cSelric hashtabadd(Hashtab * htab, void *ptr)
104ca1c9b0cSelric {
105ca1c9b0cSelric Hashentry *h = _search(htab, ptr);
106ca1c9b0cSelric Hashentry **tabptr;
107ca1c9b0cSelric
108ca1c9b0cSelric assert(htab && ptr);
109ca1c9b0cSelric
110ca1c9b0cSelric if (h)
111ca1c9b0cSelric free((void *) h->ptr);
112ca1c9b0cSelric else {
113ca1c9b0cSelric h = (Hashentry *) malloc(sizeof(Hashentry));
114ca1c9b0cSelric if (h == NULL) {
115ca1c9b0cSelric return NULL;
116ca1c9b0cSelric }
117ca1c9b0cSelric tabptr = &htab->tab[(*htab->hash) (ptr) % htab->sz];
118ca1c9b0cSelric h->next = *tabptr;
119ca1c9b0cSelric *tabptr = h;
120ca1c9b0cSelric h->prev = tabptr;
121ca1c9b0cSelric if (h->next)
122ca1c9b0cSelric h->next->prev = &h->next;
123ca1c9b0cSelric }
124ca1c9b0cSelric h->ptr = ptr;
125ca1c9b0cSelric return h;
126ca1c9b0cSelric }
127ca1c9b0cSelric
128ca1c9b0cSelric /* delete element with key key. Iff freep, free Hashentry->ptr */
129ca1c9b0cSelric
130ca1c9b0cSelric int
_hashtabdel(Hashtab * htab,void * ptr,int freep)131ca1c9b0cSelric _hashtabdel(Hashtab * htab, void *ptr, int freep)
132ca1c9b0cSelric {
133ca1c9b0cSelric Hashentry *h;
134ca1c9b0cSelric
135ca1c9b0cSelric assert(htab && ptr);
136ca1c9b0cSelric
137ca1c9b0cSelric h = _search(htab, ptr);
138ca1c9b0cSelric if (h) {
139ca1c9b0cSelric if (freep)
140ca1c9b0cSelric free(h->ptr);
141ca1c9b0cSelric if ((*(h->prev) = h->next))
142ca1c9b0cSelric h->next->prev = h->prev;
143ca1c9b0cSelric free(h);
144ca1c9b0cSelric return 0;
145ca1c9b0cSelric } else
146ca1c9b0cSelric return -1;
147ca1c9b0cSelric }
148ca1c9b0cSelric
149ca1c9b0cSelric /* Do something for each element */
150ca1c9b0cSelric
151ca1c9b0cSelric void
hashtabforeach(Hashtab * htab,int (* func)(void * ptr,void * arg),void * arg)152ca1c9b0cSelric hashtabforeach(Hashtab * htab, int (*func) (void *ptr, void *arg),
153ca1c9b0cSelric void *arg)
154ca1c9b0cSelric {
155ca1c9b0cSelric Hashentry **h, *g;
156ca1c9b0cSelric
157ca1c9b0cSelric assert(htab);
158ca1c9b0cSelric
159ca1c9b0cSelric for (h = htab->tab; h < &htab->tab[htab->sz]; ++h)
160ca1c9b0cSelric for (g = *h; g; g = g->next)
161ca1c9b0cSelric if ((*func) (g->ptr, arg))
162ca1c9b0cSelric return;
163ca1c9b0cSelric }
164ca1c9b0cSelric
165ca1c9b0cSelric /* standard hash-functions for strings */
166ca1c9b0cSelric
167ca1c9b0cSelric unsigned
hashadd(const char * s)168ca1c9b0cSelric hashadd(const char *s)
169ca1c9b0cSelric { /* Standard hash function */
170ca1c9b0cSelric unsigned i;
171ca1c9b0cSelric
172ca1c9b0cSelric assert(s);
173ca1c9b0cSelric
174ca1c9b0cSelric for (i = 0; *s; ++s)
175ca1c9b0cSelric i += *s;
176ca1c9b0cSelric return i;
177ca1c9b0cSelric }
178ca1c9b0cSelric
179ca1c9b0cSelric unsigned
hashcaseadd(const char * s)180ca1c9b0cSelric hashcaseadd(const char *s)
181ca1c9b0cSelric { /* Standard hash function */
182ca1c9b0cSelric unsigned i;
183ca1c9b0cSelric
184ca1c9b0cSelric assert(s);
185ca1c9b0cSelric
186ca1c9b0cSelric for (i = 0; *s; ++s)
187ca1c9b0cSelric i += toupper((unsigned char)*s);
188ca1c9b0cSelric return i;
189ca1c9b0cSelric }
190ca1c9b0cSelric
191ca1c9b0cSelric #define TWELVE (sizeof(unsigned))
192ca1c9b0cSelric #define SEVENTYFIVE (6*sizeof(unsigned))
193ca1c9b0cSelric #define HIGH_BITS (~((unsigned)(~0) >> TWELVE))
194ca1c9b0cSelric
195ca1c9b0cSelric unsigned
hashjpw(const char * ss)196ca1c9b0cSelric hashjpw(const char *ss)
197ca1c9b0cSelric { /* another hash function */
198ca1c9b0cSelric unsigned h = 0;
199ca1c9b0cSelric unsigned g;
200ca1c9b0cSelric const unsigned char *s = (const unsigned char *)ss;
201ca1c9b0cSelric
202ca1c9b0cSelric for (; *s; ++s) {
203ca1c9b0cSelric h = (h << TWELVE) + *s;
204ca1c9b0cSelric if ((g = h & HIGH_BITS))
205ca1c9b0cSelric h = (h ^ (g >> SEVENTYFIVE)) & ~HIGH_BITS;
206ca1c9b0cSelric }
207ca1c9b0cSelric return h;
208ca1c9b0cSelric }
209