fix regressions
[apps/madmutt.git] / hash.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
4  *
5  * This file is part of mutt-ng, see http://www.muttng.org/.
6  * It's licensed under the GNU General Public License,
7  * please see the file GPL in the top level source directory.
8  */
9
10 #if HAVE_CONFIG_H
11 # include "config.h"
12 #endif
13
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17
18 #include <lib-lib/mem.h>
19
20 #include "mutt.h"
21
22 #include "lib/mem.h"
23
24 #define SOMEPRIME 149711
25
26 int hash_string (const unsigned char *s, int n)
27 {
28   int h = 0;
29
30 #if 0
31   while (*s)
32     h += *s++;
33 #else
34   while (*s)
35     h += (h << 7) + *s++;
36   h = (h * SOMEPRIME) % n;
37   h = (h >= 0) ? h : h + n;
38 #endif
39
40   return (h % n);
41 }
42
43 HASH *hash_create (int nelem)
44 {
45   HASH *table = p_new(HASH, 1);
46
47   if (nelem == 0)
48     nelem = 2;
49   table->nelem = nelem;
50   table->curnelem = 0;
51   table->table = p_new(struct hash_elem *, nelem);
52   return table;
53 }
54
55 HASH *hash_resize(HASH *ptr, int nelem)
56 {
57   HASH *table;
58   struct hash_elem *elem, *tmp;
59   int i;
60
61   table = hash_create (nelem);
62
63   for (i = 0; i < ptr->nelem; i++) {
64     for (elem = ptr->table[i]; elem;) {
65       tmp = elem;
66       elem = elem->next;
67       hash_insert (table, tmp->key, tmp->data, 1);
68       p_delete(&tmp);
69     }
70   }
71   p_delete(&ptr->table);
72   p_delete(&ptr);
73
74   return table;
75 }
76
77 /* table        hash table to update
78  * key          key to hash on
79  * data         data to associate with `key'
80  * allow_dup    if nonzero, duplicate keys are allowed in the table 
81  */
82 int hash_insert (HASH * table, const char *key, void *data, int allow_dup)
83 {
84   struct hash_elem *ptr;
85   int h;
86
87   ptr = p_new(struct hash_elem, 1);
88   h = hash_string ((unsigned char *) key, table->nelem);
89   ptr->key = key;
90   ptr->data = data;
91
92   if (allow_dup) {
93     ptr->next = table->table[h];
94     table->table[h] = ptr;
95     table->curnelem++;
96   }
97   else {
98     struct hash_elem *tmp, *last;
99     int r;
100
101     for (tmp = table->table[h], last = NULL; tmp; last = tmp, tmp = tmp->next) {
102       r = str_cmp (tmp->key, key);
103       if (r == 0) {
104         p_delete(&ptr);
105         return (-1);
106       }
107       if (r > 0)
108         break;
109     }
110     if (last)
111       last->next = ptr;
112     else
113       table->table[h] = ptr;
114     ptr->next = tmp;
115     table->curnelem++;
116   }
117   return h;
118 }
119
120 void *hash_find_hash (const HASH * table, int hash, const char *key)
121 {
122   struct hash_elem *ptr = table->table[hash];
123
124   for (; ptr; ptr = ptr->next) {
125     if (str_cmp (key, ptr->key) == 0)
126       return (ptr->data);
127   }
128   return NULL;
129 }
130
131 void hash_delete_hash (HASH * table, int hash, const char *key, const void *data,
132                        void (*destroy) (void *))
133 {
134   struct hash_elem *ptr = table->table[hash];
135   struct hash_elem **last = &table->table[hash];
136
137   while (ptr) {
138     if ((data == ptr->data || !data) && str_cmp (ptr->key, key) == 0) {
139       *last = ptr->next;
140       if (destroy)
141         destroy (ptr->data);
142       p_delete(&ptr);
143
144       ptr = *last;
145     } else {
146       last = &ptr->next;
147       ptr = ptr->next;
148     }
149   }
150 }
151
152 /* ptr          pointer to the hash table to be freed
153  * destroy()    function to call to free the ->data member (optional) 
154  */
155 void hash_destroy (HASH ** ptr, void (*destroy) (void *))
156 {
157   int i;
158   HASH *pptr = *ptr;
159   struct hash_elem *elem, *tmp;
160
161   for (i = 0; i < pptr->nelem; i++) {
162     for (elem = pptr->table[i]; elem;) {
163       tmp = elem;
164       elem = elem->next;
165       if (destroy)
166         destroy (tmp->data);
167       p_delete(&tmp);
168     }
169   }
170   p_delete(&pptr->table);
171   p_delete(ptr);
172 }
173
174 void hash_map (HASH* table, void (*mapfunc) (const char* key, void* data,
175                                              unsigned long more),
176                unsigned long more) {
177   int i = 0;
178   struct hash_elem* elem = NULL;
179
180   if (!table || !mapfunc)
181     return;
182
183   for (i = 0; i < table->nelem; i++)
184     for (elem = table->table[i]; elem; elem = elem->next)
185       mapfunc (elem->key, elem->data, more);
186 }