/*1* Copyright (c) 1997 Kungliga Tekniska Högskolan2* (Royal Institute of Technology, Stockholm, Sweden).3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8*9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11*12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* 3. Neither the name of the Institute nor the names of its contributors17* may be used to endorse or promote products derived from this software18* without specific prior written permission.19*20* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND21* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE23* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE24* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL25* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS26* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)27* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT28* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY29* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF30* SUCH DAMAGE.31*/3233/*34* Hash table functions35*/3637#include "gen_locl.h"3839RCSID("$Id$");4041static Hashentry *_search(Hashtab * htab, /* The hash table */42void *ptr); /* And key */4344Hashtab *45hashtabnew(int sz,46int (*cmp) (void *, void *),47unsigned (*hash) (void *))48{49Hashtab *htab;50int i;5152assert(sz > 0);5354htab = (Hashtab *) malloc(sizeof(Hashtab) + (sz - 1) * sizeof(Hashentry *));55if (htab == NULL)56return NULL;5758for (i = 0; i < sz; ++i)59htab->tab[i] = NULL;6061htab->cmp = cmp;62htab->hash = hash;63htab->sz = sz;64return htab;65}6667/* Intern search function */6869static Hashentry *70_search(Hashtab * htab, void *ptr)71{72Hashentry *hptr;7374assert(htab && ptr);7576for (hptr = htab->tab[(*htab->hash) (ptr) % htab->sz];77hptr;78hptr = hptr->next)79if ((*htab->cmp) (ptr, hptr->ptr) == 0)80break;81return hptr;82}8384/* Search for element in hash table */8586void *87hashtabsearch(Hashtab * htab, void *ptr)88{89Hashentry *tmp;9091tmp = _search(htab, ptr);92return tmp ? tmp->ptr : tmp;93}9495/* add element to hash table */96/* if already there, set new value */97/* !NULL if succesful */9899void *100hashtabadd(Hashtab * htab, void *ptr)101{102Hashentry *h = _search(htab, ptr);103Hashentry **tabptr;104105assert(htab && ptr);106107if (h)108free((void *) h->ptr);109else {110h = (Hashentry *) malloc(sizeof(Hashentry));111if (h == NULL) {112return NULL;113}114tabptr = &htab->tab[(*htab->hash) (ptr) % htab->sz];115h->next = *tabptr;116*tabptr = h;117h->prev = tabptr;118if (h->next)119h->next->prev = &h->next;120}121h->ptr = ptr;122return h;123}124125/* delete element with key key. Iff freep, free Hashentry->ptr */126127int128_hashtabdel(Hashtab * htab, void *ptr, int freep)129{130Hashentry *h;131132assert(htab && ptr);133134h = _search(htab, ptr);135if (h) {136if (freep)137free(h->ptr);138if ((*(h->prev) = h->next))139h->next->prev = h->prev;140free(h);141return 0;142} else143return -1;144}145146/* Do something for each element */147148void149hashtabforeach(Hashtab * htab, int (*func) (void *ptr, void *arg),150void *arg)151{152Hashentry **h, *g;153154assert(htab);155156for (h = htab->tab; h < &htab->tab[htab->sz]; ++h)157for (g = *h; g; g = g->next)158if ((*func) (g->ptr, arg))159return;160}161162/* standard hash-functions for strings */163164unsigned165hashadd(const char *s)166{ /* Standard hash function */167unsigned i;168169assert(s);170171for (i = 0; *s; ++s)172i += *s;173return i;174}175176unsigned177hashcaseadd(const char *s)178{ /* Standard hash function */179unsigned i;180181assert(s);182183for (i = 0; *s; ++s)184i += toupper((unsigned char)*s);185return i;186}187188#define TWELVE (sizeof(unsigned))189#define SEVENTYFIVE (6*sizeof(unsigned))190#define HIGH_BITS (~((unsigned)(~0) >> TWELVE))191192unsigned193hashjpw(const char *ss)194{ /* another hash function */195unsigned h = 0;196unsigned g;197const unsigned char *s = (const unsigned char *)ss;198199for (; *s; ++s) {200h = (h << TWELVE) + *s;201if ((g = h & HIGH_BITS))202h = (h ^ (g >> SEVENTYFIVE)) & ~HIGH_BITS;203}204return h;205}206207208