another update from CVS HEAD, for QA
[alioth/jupp.git] / hash.c
1 /*
2  *      Simple hash table
3  *      Copyright
4  *              (C) 1992 Joseph H. Allen
5  *
6  *      This file is part of JOE (Joe's Own Editor)
7  */
8 #include "config.h"
9 #include "types.h"
10
11 __RCSID("$MirOS: contrib/code/jupp/hash.c,v 1.6 2017/12/08 02:00:39 tg Exp $");
12
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include "hash.h"
17 #include "utils.h"
18
19 #define hnext(accu, c) (((accu) << 4) + ((accu) >> 28) + (c))
20
21 static HENTRY *freentry = NULL;
22
23 unsigned long hash(const unsigned char *s)
24 {
25         unsigned long accu = 0;
26
27         while (*s) {
28                 accu = hnext(accu, *s++);
29         }
30         return accu;
31 }
32
33 HASH *htmk(int len)
34 {
35         HASH *t = malloc(sizeof(HASH));
36
37         t->len = len - 1;
38         t->tab = calloc(len, sizeof(HENTRY *));
39         return t;
40 }
41
42 void htrm(HASH *ht)
43 {
44         free(ht->tab);
45         free(ht);
46 }
47
48 void *htadd(HASH *ht, const unsigned char *name, void *val)
49 {
50         int idx = hash(name) & ht->len;
51         HENTRY *entry;
52         int x;
53
54         if (!freentry) {
55                 entry = calloc(64, sizeof(HENTRY));
56                 for (x = 0; x != 64; ++x) {
57                         entry[x].next = freentry;
58                         freentry = entry + x;
59                 }
60         }
61         entry = freentry;
62         freentry = entry->next;
63         entry->next = ht->tab[idx];
64         ht->tab[idx] = entry;
65         entry->name = name;
66         return entry->val = val;
67 }
68
69 void *htfind(HASH *ht, const unsigned char *name)
70 {
71         HENTRY *e;
72
73         for (e = ht->tab[hash(name) & ht->len]; e; e = e->next) {
74                 if (!strcmp(e->name, name)) {
75                         return e->val;
76                 }
77         }
78         return NULL;
79 }