Rocco Rutte:
[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 "mutt.h"
19
20 #include "lib/mem.h"
21
22 #define SOMEPRIME 149711
23
24 int hash_string (const unsigned char *s, int n)
25 {
26   int h = 0;
27
28 #if 0
29   while (*s)
30     h += *s++;
31 #else
32   while (*s)
33     h += (h << 7) + *s++;
34   h = (h * SOMEPRIME) % n;
35   h = (h >= 0) ? h : h + n;
36 #endif
37
38   return (h % n);
39 }
40
41 HASH *hash_create (int nelem)
42 {
43   HASH *table = mem_malloc (sizeof (HASH));
44
45   if (nelem == 0)
46     nelem = 2;
47   table->nelem = nelem;
48   table->curnelem = 0;
49   table->table = mem_calloc (nelem, sizeof (struct hash_elem *));
50   return table;
51 }
52
53 HASH *hash_resize (HASH * ptr, int nelem)
54 {
55   HASH *table;
56   struct hash_elem *elem, *tmp;
57   int i;
58
59   table = hash_create (nelem);
60
61   for (i = 0; i < ptr->nelem; i++) {
62     for (elem = ptr->table[i]; elem;) {
63       tmp = elem;
64       elem = elem->next;
65       hash_insert (table, tmp->key, tmp->data, 1);
66       mem_free (&tmp);
67     }
68   }
69   mem_free (&ptr->table);
70   mem_free (&ptr);
71
72   return table;
73 }
74
75 /* table        hash table to update
76  * key          key to hash on
77  * data         data to associate with `key'
78  * allow_dup    if nonzero, duplicate keys are allowed in the table 
79  */
80 int hash_insert (HASH * table, const char *key, void *data, int allow_dup)
81 {
82   struct hash_elem *ptr;
83   int h;
84
85   ptr = (struct hash_elem *) mem_malloc (sizeof (struct hash_elem));
86   h = hash_string ((unsigned char *) key, table->nelem);
87   ptr->key = key;
88   ptr->data = data;
89
90   if (allow_dup) {
91     ptr->next = table->table[h];
92     table->table[h] = ptr;
93     table->curnelem++;
94   }
95   else {
96     struct hash_elem *tmp, *last;
97     int r;
98
99     for (tmp = table->table[h], last = NULL; tmp; last = tmp, tmp = tmp->next) {
100       r = str_cmp (tmp->key, key);
101       if (r == 0) {
102         mem_free (&ptr);
103         return (-1);
104       }
105       if (r > 0)
106         break;
107     }
108     if (last)
109       last->next = ptr;
110     else
111       table->table[h] = ptr;
112     ptr->next = tmp;
113     table->curnelem++;
114   }
115   return h;
116 }
117
118 void *hash_find_hash (const HASH * table, int hash, const char *key)
119 {
120   struct hash_elem *ptr = table->table[hash];
121
122   for (; ptr; ptr = ptr->next) {
123     if (str_cmp (key, ptr->key) == 0)
124       return (ptr->data);
125   }
126   return NULL;
127 }
128
129 void hash_delete_hash (HASH * table, int hash, const char *key, const void *data,
130                        void (*destroy) (void *))
131 {
132   struct hash_elem *ptr = table->table[hash];
133   struct hash_elem **last = &table->table[hash];
134
135   while (ptr) {
136     if ((data == ptr->data || !data) && str_cmp (ptr->key, key) == 0) {
137       *last = ptr->next;
138       if (destroy)
139         destroy (ptr->data);
140       mem_free (&ptr);
141
142       ptr = *last;
143     } else {
144       last = &ptr->next;
145       ptr = ptr->next;
146     }
147   }
148 }
149
150 /* ptr          pointer to the hash table to be freed
151  * destroy()    function to call to free the ->data member (optional) 
152  */
153 void hash_destroy (HASH ** ptr, void (*destroy) (void *))
154 {
155   int i;
156   HASH *pptr = *ptr;
157   struct hash_elem *elem, *tmp;
158
159   for (i = 0; i < pptr->nelem; i++) {
160     for (elem = pptr->table[i]; elem;) {
161       tmp = elem;
162       elem = elem->next;
163       if (destroy)
164         destroy (tmp->data);
165       mem_free (&tmp);
166     }
167   }
168   mem_free (&pptr->table);
169   mem_free (ptr);
170 }
171
172 void hash_map (HASH* table, void (*mapfunc) (const char* key, void* data,
173                                              unsigned long more),
174                unsigned long more) {
175   int i = 0;
176   struct hash_elem* elem = NULL;
177
178   if (!table || !mapfunc)
179     return;
180
181   for (i = 0; i < table->nelem; i++)
182     for (elem = table->table[i]; elem; elem = elem->next)
183       mapfunc (elem->key, elem->data, more);
184 }