source: npl/mailserver/dspam/dspam-3.10.2/src/hash.c

Last change on this file was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100644
File size: 5.2 KB
Line 
1/* $Id: hash.c,v 1.75 2011/06/28 00:13:48 sbajic Exp $ */
2
3/*
4 DSPAM
5 COPYRIGHT (C) 2002-2012 DSPAM PROJECT
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU Affero General Public License as
9 published by the Free Software Foundation, either version 3 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU Affero General Public License for more details.
16
17 You should have received a copy of the GNU Affero General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20*/
21
22#ifdef HAVE_CONFIG_H
23#include <auto-config.h>
24#endif
25
26#include <string.h>
27#include <stdlib.h>
28#include <stdio.h>
29
30#include "hash.h"
31
32/* Read-only */
33
34static unsigned long bnr_hash_prime_list[bnr_hash_num_primes] = {
35  53ul, 97ul, 193ul, 389ul, 769ul,
36  1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
37  49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
38  1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
39  50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
40  1610612741ul, 3221225473ul, 4294967291ul
41};
42
43struct bnr_hash_node *
44bnr_hash_node_create (const char *name)
45{
46  struct bnr_hash_node *node
47    = (struct bnr_hash_node *) calloc (1, sizeof (struct bnr_hash_node));
48
49  if (node)
50    node->name = strdup(name);
51
52  return node;
53}
54
55struct bnr_hash *
56bnr_hash_create (unsigned long size)
57{
58  unsigned long i = 0;
59  struct bnr_hash *hash = (struct bnr_hash *) malloc (sizeof (struct bnr_hash));
60
61  if (hash == NULL)
62    return NULL;
63  while (bnr_hash_prime_list[i] < size)
64    i++;
65  hash->size = bnr_hash_prime_list[i];
66  hash->items = 0;
67  hash->tbl =
68    (struct bnr_hash_node **) calloc (hash->size, sizeof (struct bnr_hash_node *));
69  if (hash->tbl == NULL) {
70    free (hash);
71    return NULL;
72  }
73  return (hash);
74}
75
76int
77bnr_hash_destroy (struct bnr_hash *hash)
78{
79  struct bnr_hash_node *node, *next;
80  struct bnr_hash_c c;
81
82  if (hash == NULL)
83    return -1;
84
85  node = c_bnr_hash_first (hash, &c);
86  while (node != NULL)
87  {
88    char *x = node->name;
89    next = c_bnr_hash_next (hash, &c);
90    bnr_hash_delete (hash, node->name);
91    free (x);
92    node = next;
93  }
94
95  free (hash->tbl);
96  free (hash);
97
98  return 0;
99}
100
101int
102bnr_hash_delete (struct bnr_hash *hash, const char *name)
103{
104  unsigned long hash_code;
105  struct bnr_hash_node *node;
106  struct bnr_hash_node *del_node = NULL;
107  struct bnr_hash_node *parent = NULL;
108
109  hash_code = bnr_hash_hashcode(hash, name);
110  node = hash->tbl[hash_code];
111
112  while (node)
113  {
114    if (!strcmp(name, node->name))
115    {
116      del_node = node;
117      node = NULL;
118    }
119    else
120    {
121      parent = node;
122      node = node->next;
123    }
124  }
125
126  if (del_node == NULL)
127    return -2;
128
129  if (parent)
130    parent->next = del_node->next;
131  else
132    hash->tbl[hash_code] = del_node->next;
133
134  free (del_node);
135  hash->items--;
136
137  return 0;
138}
139
140struct bnr_hash_node *
141c_bnr_hash_first (struct bnr_hash *hash, struct bnr_hash_c *c)
142{
143  c->iter_index = 0;
144  c->iter_next = (struct bnr_hash_node *) NULL;
145  return (c_bnr_hash_next (hash, c));
146}
147
148struct bnr_hash_node *
149c_bnr_hash_next (struct bnr_hash *hash, struct bnr_hash_c *c)
150{
151  unsigned long index;
152  struct bnr_hash_node *node = c->iter_next;
153
154  if (node) {
155    c->iter_next = node->next;
156    return (node);
157  }
158
159  while (c->iter_index < hash->size)
160  {
161    index = c->iter_index++;
162    if (hash->tbl[index]) {
163      c->iter_next = hash->tbl[index]->next;
164      return (hash->tbl[index]);
165    }
166  }
167  return NULL;
168}
169
170int
171bnr_hash_hit (struct bnr_hash *hash, const char *name)
172{
173  unsigned long hash_code;
174  struct bnr_hash_node *parent;
175  struct bnr_hash_node *node;
176  struct bnr_hash_node *new_node = NULL;
177
178  hash_code = bnr_hash_hashcode(hash, name);
179  parent = NULL;
180  node = hash->tbl[hash_code];
181
182  while (node != NULL)
183  {
184    if (!strcmp(name, node->name)) {
185      new_node = node;
186      node = NULL;
187    } else {
188      parent = node;
189      node = node->next;
190    }
191  }
192
193  if (new_node != NULL)
194    return 0;
195
196  /* Create a new node */
197  new_node = bnr_hash_node_create(name);
198  hash->items++;
199
200  /* Insert */
201  if (parent) {
202    parent->next = new_node;
203    return 0;
204  }
205
206  /* No existing parent; add directly to hash table */
207  hash->tbl[hash_code] = new_node;
208
209  return 0;
210}
211
212float
213bnr_hash_value (struct bnr_hash *hash, const char *name)
214{
215  unsigned long hash_code;
216  struct bnr_hash_node *node;
217
218  hash_code = bnr_hash_hashcode(hash, name);
219  node = hash->tbl[hash_code];
220
221  while (node != NULL)
222  {
223    if (!strcmp(node->name, name))
224      return node->value;
225
226    node = node->next;
227  }
228
229  return 0.00000;
230}
231
232int
233bnr_hash_set (struct bnr_hash *hash, const char *name, float value)
234{
235  unsigned long hash_code;
236  struct bnr_hash_node *node;
237
238  if (!name)
239    return 0;
240
241  hash_code = bnr_hash_hashcode(hash, name);
242  node = hash->tbl[hash_code];
243
244  while (node != NULL)
245  {
246    if (!strcmp(node->name, name)) {
247      node->value = value;
248      return 0;
249    }
250
251    node = node->next;
252  }
253
254  return 0;
255}
256
257long bnr_hash_hashcode(struct bnr_hash *hash, const char *name) {
258  unsigned long val = 0;
259
260  if (!name)
261    return 0;
262  for (; *name; ++name) val = 5 * val + *name;
263  return(val % hash->size);
264}
265
Note: See TracBrowser for help on using the repository browser.