su
1.13.18
Toggle main menu visibility
Loading...
Searching...
No Matches
htable.h
Go to the documentation of this file.
1
/*
2
* This file is part of the Sofia-SIP package
3
*
4
* Copyright (C) 2005 Nokia Corporation.
5
*
6
* Contact: Pekka Pessi <pekka.pessi@nokia-email.address.hidden>
7
*
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public License
10
* as published by the Free Software Foundation; either version 2.1 of
11
* the License, or (at your option) any later version.
12
*
13
* This library is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
17
*
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21
* 02110-1301 USA
22
*
23
*/
24
25
#ifndef HTABLE_H
27
#define HTABLE_H
28
58
59
typedef
unsigned
long
hash_value_t;
60
62
#define HTABLE_MIN_SIZE 31
63
74
#define HTABLE_DECLARE(prefix, pr, entry_t) \
75
HTABLE_DECLARE_WITH(prefix, pr, entry_t, unsigned, hash_value_t)
76
77
#define HTABLE_DECLARE_WITH(prefix, pr, entry_t, size_t, hash_value_t) \
78
typedef struct prefix##_s { \
79
size_t pr##_size; \
80
size_t pr##_used; \
81
entry_t**pr##_table;
\
82
} prefix##_t
83
84
#ifndef HTABLE_SCOPE
86
#define HTABLE_SCOPE su_inline
87
#endif
88
99
#define HTABLE_PROTOS(prefix, pr, entry_t) \
100
HTABLE_PROTOS_WITH(prefix, pr, entry_t, unsigned, hash_value_t)
101
102
#define HTABLE_PROTOS_WITH(prefix, pr, entry_t, size_t, hash_value_t) \
103
HTABLE_SCOPE int prefix##_resize(su_home_t *, prefix##_t pr[1], size_t); \
104
HTABLE_SCOPE int prefix##_is_full(prefix##_t const *); \
105
HTABLE_SCOPE entry_t **prefix##_hash(prefix##_t const *, hash_value_t hv); \
106
HTABLE_SCOPE entry_t **prefix##_next(prefix##_t const *, entry_t * const *ee); \
107
HTABLE_SCOPE void prefix##_append(prefix##_t *pr, entry_t const *e); \
108
HTABLE_SCOPE void prefix##_insert(prefix##_t *pr, entry_t const *e); \
109
HTABLE_SCOPE int prefix##_remove(prefix##_t *, entry_t const *e)
110
123
#define HTABLE_BODIES(prefix, pr, entry_t, hfun) \
124
HTABLE_BODIES_WITH(prefix, pr, entry_t, hfun, unsigned, hash_value_t)
125
126
#define HTABLE_BODIES_WITH(prefix, pr, entry_t, hfun, size_t, hash_value_t) \
127
\
128
HTABLE_SCOPE \
129
int prefix##_resize(su_home_t *home, \
130
prefix##_t pr[], \
131
size_t new_size) \
132
{ \
133
entry_t **new_hash; \
134
entry_t **old_hash = pr->pr##_table; \
135
size_t old_size; \
136
size_t i, j, i0; \
137
unsigned again = 0; \
138
size_t used = 0; \
139
\
140
if (new_size == 0) \
141
new_size = 2 * pr->pr##_size + 1; \
142
if (new_size < HTABLE_MIN_SIZE) \
143
new_size = HTABLE_MIN_SIZE; \
144
if (new_size < 5 * pr->pr##_used / 4) \
145
new_size = 5 * pr->pr##_used / 4; \
146
\
147
if (!(new_hash = su_zalloc(home, sizeof(*new_hash) * new_size))) \
148
return -1; \
149
\
150
old_size = pr->pr##_size; \
151
\
152
do for (j = 0; j < old_size; j++) { \
153
if (!old_hash[j]) \
154
continue; \
155
\
156
if (again < 2 && hfun(old_hash[j]) % old_size > j) { \
157
/* Wrapped, leave entry for second pass */
\
158
again = 1; continue; \
159
} \
160
\
161
i0 = hfun(old_hash[j]) % new_size; \
162
\
163
for (i = i0; new_hash[i]; i = (i + 1) % new_size, assert(i != i0)); \
164
\
165
new_hash[i] = old_hash[j], old_hash[j] = NULL; \
166
used++; \
167
} \
168
while (again++ == 1); \
169
\
170
pr->pr##_table = new_hash, pr->pr##_size = new_size; \
171
\
172
assert(pr->pr##_used == used); \
173
\
174
su_free(home, old_hash); \
175
\
176
return 0; \
177
} \
178
\
179
HTABLE_SCOPE \
180
int prefix##_is_full(prefix##_t const *pr) \
181
{ \
182
return pr->pr##_table == NULL || 3 * pr->pr##_used > 2 * pr->pr##_size; \
183
} \
184
\
185
HTABLE_SCOPE \
186
entry_t **prefix##_hash(prefix##_t const *pr, hash_value_t hv) \
187
{ \
188
return pr->pr##_table + hv % pr->pr##_size; \
189
} \
190
\
191
HTABLE_SCOPE \
192
entry_t **prefix##_next(prefix##_t const *pr, entry_t * const *ee) \
193
{ \
194
if (++ee < pr->pr##_table + pr->pr##_size && ee >= pr->pr##_table) \
195
return (entry_t **)ee; \
196
else \
197
return pr->pr##_table; \
198
} \
199
\
200
HTABLE_SCOPE \
201
void prefix##_append(prefix##_t *pr, entry_t const *e) \
202
{ \
203
entry_t **ee; \
204
\
205
pr->pr##_used++; \
206
for (ee = prefix##_hash(pr, hfun(e)); *ee; ee = prefix##_next(pr, ee)) \
207
; \
208
*ee = (entry_t *)e; \
209
} \
210
\
211
HTABLE_SCOPE \
212
void prefix##_insert(prefix##_t *pr, entry_t const *e) \
213
{ \
214
entry_t *e0, **ee; \
215
\
216
pr->pr##_used++; \
217
/* Insert entry into hash table (before other entries with same hash) */
\
218
for (ee = prefix##_hash(pr, hfun(e)); \
219
(e0 = *ee); \
220
ee = prefix##_next(pr, ee)) \
221
*ee = (entry_t *)e, e = e0; \
222
*ee = (entry_t *)e; \
223
} \
224
\
225
HTABLE_SCOPE \
226
int prefix##_remove(prefix##_t *pr, entry_t const *e) \
227
{ \
228
size_t i, j, k; \
229
size_t size = pr->pr##_size; \
230
entry_t **htable = pr->pr##_table; \
231
\
232
if (!e) return -1; \
233
\
234
/* Search for entry */
\
235
for (i = hfun(e) % size; htable[i]; i = (i + 1) % size) \
236
if (e == htable[i]) \
237
break; \
238
\
239
/* Entry is not in table? */
\
240
if (!htable[i]) return -1; \
241
\
242
/* Move table entries towards their primary place */
\
243
for (j = (i + 1) % size; htable[j]; j = (j + 1) % size) { \
244
/* k is primary place for entry */
\
245
k = hfun(htable[j]) % size; \
246
if (k == j)
/* entry is in its primary place? */
\
247
continue; \
248
/* primary place is between i and j - do not move this to i */
\
249
if (j > i ? (i < k && k < j) : (i < k || k < j)) \
250
continue; \
251
\
252
htable[i] = htable[j], i = j; \
253
} \
254
\
255
pr->pr##_used--; \
256
\
257
htable[i] = NULL; \
258
\
259
return 0; \
260
} \
261
extern int prefix##_dummy
262
263
#endif
Sofia-SIP 1.13.18 - Copyright (C) 2006 Nokia Corporation. All rights reserved. Licensed under the terms of the GNU Lesser General Public License.