chiark / gitweb /
Infrastructure: Strip away crufty CVS $Id$ tags.
[mLib] / hash.c
CommitLineData
03d53b73 1/* -*-c-*-
03d53b73 2 *
3 * General hashtable infrastructure
4 *
5 * (c) 1999 Straylight/Edgeware
6 */
7
d4efbcd9 8/*----- Licensing notice --------------------------------------------------*
03d53b73 9 *
10 * This file is part of the mLib utilities library.
11 *
12 * mLib is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
d4efbcd9 16 *
03d53b73 17 * mLib is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
d4efbcd9 21 *
03d53b73 22 * You should have received a copy of the GNU Library General Public
23 * License along with mLib; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
26 */
27
03d53b73 28/*----- Header files ------------------------------------------------------*/
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33
34#include "alloc.h"
20eb516f 35#include "arena.h"
03d53b73 36#include "bits.h"
37#include "exc.h"
38#include "hash.h"
03d53b73 39
40/*----- Main code ---------------------------------------------------------*/
41
42/* --- @hash_create@ --- *
43 *
44 * Arguments: @hash_table *t@ = pointer to hashtable to initialize
45 * @size_t n@ = number of bins to allocate (zero initially)
46 *
47 * Returns: ---
48 *
49 * Use: Initializes a hashtable with a given number of bins. The
50 * bins are initially empty. The number of bins must be a power
51 * of two. This is not checked.
52 */
53
54void hash_create(hash_table *t, size_t n)
55{
56 hash_base **v;
20eb516f 57
58 t->a = arena_global;
59 t->v = x_alloc(t->a, n * sizeof(hash_base *));
03d53b73 60 t->mask = n - 1;
61 for (v = t->v; n; v++, n--)
62 *v = 0;
03d53b73 63}
64
65/* --- @hash_destroy@ --- *
66 *
67 * Arguments: @hash_table *t@ = pointer to hashtable to destroy
68 *
69 * Returns: ---
70 *
71 * Use: Frees a hashtable. The items are not freed: they are the
72 * responsibility of the implementation.
73 */
74
e983c846 75void hash_destroy(hash_table *t) { x_free(t->a, t->v); }
03d53b73 76
77/* --- @hash_bin@ --- *
78 *
79 * Arguments: @hash_table *t@ = pointer to hashtable
80 * @uint32 hash@ = hash value to look up
81 *
82 * Returns: Pointer to the bin's list head.
83 *
84 * Use: Given a hash value return the address of the appropriate list
85 * head. It is safe to remove the current entry from the table.
86 */
87
88hash_base **hash_bin(hash_table *t, uint32 hash)
e983c846 89 { return (HASH_BIN(t, hash)); }
03d53b73 90
91/* --- @hash_extend@ --- *
92 *
93 * Arguments: @hash_table *t@ = pointer to hashtable to extend
94 *
95 * Returns: Nonzero if extension was successful.
96 *
97 * Use: Extends a hashtable. The number of bins is doubled and the
98 * entries are redistributed.
99 */
100
101int hash_extend(hash_table *t)
102{
103 hash_base **v;
104 uint32 m = t->mask + 1;
105 size_t i;
106
03d53b73 107 /* --- Allocate a new hash bin vector --- */
108
b5ea4de3 109 if ((v = A_REALLOC(t->a, t->v,
110 2 * m * sizeof(hash_base *),
111 m * sizeof(hash_base *))) == 0) {
03d53b73 112 return (0);
113 }
114 t->v = v;
115 t->mask = (m * 2) - 1;
116
117 /* --- Wander through the table rehashing things --- */
118
119 for (i = 0; i < m; i++) {
120 hash_base **p = v + i;
121 hash_base **q = p + m;
122
123 while (*p) {
124 if (!((*p)->hash & m))
125 p = &(*p)->next;
126 else {
127 *q = *p;
128 q = &(*q)->next;
129 *p = (*p)->next;
130 }
131 }
132 *p = 0;
133 *q = 0;
134 }
135
03d53b73 136 return (1);
137}
138
139/* --- @hash_remove@ --- *
140 *
141 * Arguments: @hash_table *t@ = pointer to hashtable
142 * @hash_base *p@ = pointer to item to remove
143 *
144 * Returns: ---
145 *
146 * Use: Removes an item from a hashtable. The item itself is not
147 * freed, although it is removed from the data structure and is
148 * safe to free.
149 */
150
151void hash_remove(hash_table *t, hash_base *p)
152{
153 hash_base **b = HASH_BIN(t, p->hash);
154 while (*b) {
155 if (*b == p) {
156 *b = p->next;
157 return;
158 }
159 b = &(*b)->next;
160 }
161 return;
162}
163
164/* --- @hash_mkiter@ --- *
165 *
166 * Arguments: @hash_iter *i@ = pointer to iterator to create
167 * @hash_table *t@ = pointer to hashtable to iterate
168 *
169 * Returns: ---
170 *
171 * Use: Initializes a hashtable iterator.
172 */
173
174void hash_mkiter(hash_iter *i, hash_table *t) { HASH_MKITER(i, t); }
175
176/* --- @hash_next@ --- *
177 *
178 * Arguments: @hash_iter *i@ = pointer to iterator
179 *
180 * Returns: Pointer to the next hashtable entry found, or null.
181 *
182 * Use: Returns the next entry from the hashtable.
183 */
184
185hash_base *hash_next(hash_iter *i)
186{
187 hash_base *b;
188 HASH_NEXT(i, b);
189 return (b);
190}
191
192/*----- That's all, folks -------------------------------------------------*/