Loading [MathJax]/extensions/TeX/AMSsymbols.js
LAL 7.7.0.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
LALHashTbl.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016 Karl Wette
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with with program; see the file COPYING. If not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA
18 */
19
20#include <lal/LALHashTbl.h>
21
22/* Special hash table element value to indicate elements that have been deleted */
23static const void *hash_del = 0;
24#define DEL ((void*) &hash_del)
25
26/* Evaluates to the hash value of x, restricted to the length of the hash table */
27#define HASHIDX(ht, x) ((int)((ht)->hash((ht)->hash_param, (x)) % (ht)->data_len))
28
29/* Increment the next hash index, restricted to the length of the hash table */
30#define INCRIDX(ht, i) do { if (++(i) == (ht)->data_len) { (i) = 0; } } while(0)
31
32/* Evaluates true if the elements x and y are equal, according to the hash table comparison function */
33#define EQUAL(ht, x, y) ((ht)->cmp((ht)->cmp_param, (x), (y)) == 0)
34
36 void **data; /* Hash table with open addressing and linear probing */
37 int data_len; /* Size of the memory block 'data', in number of elements */
38 int n; /* Number of valid elements in the hash */
39 int q; /* Number of non-NULL elements in the hash */
40 LALHashTblDtorFcn dtor; /* Function to free memory of elements of hash, if required */
41 LALHashTblHashParamFcn hash; /* Parameterised hash function for hash table elements */
42 void *hash_param; /* Parameter to pass to hash function */
43 LALHashTblCmpParamFcn cmp; /* Parameterised hash table element comparison function */
44 void *cmp_param; /* Parameter to pass to comparison function */
45};
46
47/* Call a non-parameterised hash function, which is passed in 'param' */
48static UINT8 hashtbl_no_param_hash( void *param, const void *x )
49{
51 return hash( x );
52}
53
54/* Call a non-parameterised compare function, which is passed in 'param' */
55static int hashtbl_no_param_cmp( void *param, const void *x, const void *y )
56{
58 return cmp( x, y );
59}
60
61/* Resize and rebuild the hash table */
62static int hashtbl_resize( LALHashTbl *ht )
63{
64 void **old_data = ht->data;
65 int old_data_len = ht->data_len;
66 ht->data_len = 2;
67 while ( ht->data_len < 3*ht->n ) {
68 ht->data_len *= 2;
69 }
70 ht->data = XLALCalloc( ht->data_len, sizeof( ht->data[0] ) );
71 XLAL_CHECK( ht->data != NULL, XLAL_ENOMEM );
72 ht->q = ht->n;
73 for ( int k = 0; k < old_data_len; ++k ) {
74 if ( old_data[k] != NULL && old_data[k] != DEL ) {
75 int i = HASHIDX( ht, old_data[k] );
76 while ( ht->data[i] != NULL ) {
77 INCRIDX( ht, i );
78 }
79 ht->data[i] = old_data[k];
80 }
81 }
82 XLALFree( old_data );
83 return XLAL_SUCCESS;
84}
85
90 )
91{
92
93 /* Create a hash table using hashtbl_no_param_hash/cmp as the hash/comparison functions */
95 XLAL_CHECK_NULL( ht != NULL, XLAL_EFUNC );
96
97 return ht;
98
99}
100
104 void *hash_param,
106 void *cmp_param
107 )
108{
109
110 /* Check input */
111 XLAL_CHECK_NULL( hash != NULL, XLAL_EFAULT );
112 XLAL_CHECK_NULL( cmp != NULL, XLAL_EFAULT );
113
114 /* Allocate memory for hash table struct */
115 LALHashTbl *ht = XLALCalloc( 1, sizeof( *ht ) );
116 XLAL_CHECK_NULL( ht != NULL, XLAL_ENOMEM );
117
118 /* Set hash table struct parameters */
119 ht->dtor = dtor;
120 ht->hash = hash;
121 ht->hash_param = hash_param;
122 ht->cmp = cmp;
123 ht->cmp_param = cmp_param;
124
125 return ht;
126
127}
128
130 LALHashTbl *ht
131 )
132{
133 if ( ht != NULL ) {
134 if ( ht->data != NULL ) {
135 if ( ht->dtor != NULL ) {
136 for ( int i = 0; i < ht->data_len; ++i ) {
137 if ( ht->data[i] != NULL && ht->data[i] != DEL ) {
138 ht->dtor( ht->data[i] );
139 }
140 }
141 }
142 XLALFree( ht->data );
143 }
144 XLALFree( ht );
145 }
146}
147
149 LALHashTbl *ht
150 )
151{
152
153 /* Check input */
154 XLAL_CHECK( ht != NULL, XLAL_EFAULT );
155
156 /* Free hash table elements */
157 if ( ht->data != NULL ) {
158 if ( ht->dtor != NULL ) {
159 for ( int i = 0; i < ht->data_len; ++i ) {
160 if ( ht->data[i] != NULL ) {
161 if ( ht->data[i] != DEL ) {
162 ht->dtor( ht->data[i] );
163 }
164 ht->data[i] = NULL;
165 }
166 }
167 }
168 }
169
170 /* Remove all elements from hash table */
171 ht->n = 0;
172
173 return XLAL_SUCCESS;
174
175}
176
178 const LALHashTbl *ht
179 )
180{
181 XLAL_CHECK( ht != NULL, XLAL_EFAULT );
182 return ht->n;
183}
184
186 const LALHashTbl *ht,
187 const void *x,
188 const void **y
189 )
190{
191
192 /* Check input */
193 XLAL_CHECK( ht != NULL, XLAL_EFAULT );
194 XLAL_CHECK( x != NULL && x != DEL, XLAL_EINVAL );
195 XLAL_CHECK( y != NULL, XLAL_EFAULT );
196
197 /* Try to find element matching 'x' in hash table, if found return in 'y' */
198 if ( ht->data_len > 0 ) {
199 int i = HASHIDX( ht, x );
200 while ( ht->data[i] != NULL ) {
201 *y = ht->data[i];
202 if ( *y != DEL && EQUAL( ht, x, *y ) ) {
203 return XLAL_SUCCESS;
204 }
205 INCRIDX( ht, i );
206 }
207 }
208
209 /* No element matches 'x' */
210 *y = NULL;
211 return XLAL_SUCCESS;
212
213}
214
216 LALHashTbl *ht,
217 void *x
218 )
219{
220
221 /* Check input */
222 XLAL_CHECK( ht != NULL, XLAL_EFAULT );
223 XLAL_CHECK( x != NULL && x != DEL, XLAL_EINVAL );
224
225 /* Check that no element matching 'x' exists in the hash table */
226 {
227 const void *y;
229 XLAL_CHECK( y == NULL, XLAL_EFAILED, "Hash table already contains given element" );
230 }
231
232 /* Resize hash table to preserve maximum 50% occupancy */
233 if ( 2*( ht->q + 1 ) > ht->data_len ) {
235 }
236
237 /* Add 'x' to the hash table */
238 int i = HASHIDX( ht, x );
239 while ( ht->data[i] != NULL && ht->data[i] != DEL ) {
240 INCRIDX( ht, i );
241 }
242 if ( ht->data[i] == NULL ) {
243 ++ht->q;
244 }
245 ++ht->n;
246 ht->data[i] = x;
247
248 return XLAL_SUCCESS;
249
250}
251
253 LALHashTbl *ht,
254 const void *x,
255 void **y
256 )
257{
258
259 /* Check input */
260 XLAL_CHECK( ht != NULL, XLAL_EFAULT );
261 XLAL_CHECK( x != NULL && x != DEL, XLAL_EINVAL );
262 XLAL_CHECK( y != NULL, XLAL_EFAULT );
263
264 /* Try to find element matching 'x' in hash table, if found remove it from table and return in 'y' */
265 if ( ht->data_len > 0 ) {
266 int i = HASHIDX( ht, x );
267 while ( ht->data[i] != NULL ) {
268 *y = ht->data[i];
269 if ( *y != DEL && EQUAL( ht, x, *y ) ) {
270 ht->data[i] = DEL;
271 --ht->n;
272 if ( 8*ht->n < ht->data_len ) { /* Resize hash table to preserve minimum 50% occupancy */
274 }
275 return XLAL_SUCCESS;
276 }
277 INCRIDX( ht, i );
278 }
279 }
280
281 /* No element matches 'x' */
282 *y = NULL;
283 return XLAL_SUCCESS;
284
285}
286
288 LALHashTbl *ht,
289 const void *x
290 )
291{
292
293 /* Check input */
294 XLAL_CHECK( ht != NULL, XLAL_EFAULT );
295 XLAL_CHECK( x != NULL && x != DEL, XLAL_EINVAL );
296
297 /* Remove element matching 'x' from hash table, if it exists */
298 void *y;
300
301 /* Free memory associated with element, if required */
302 if ( ht->dtor != NULL ) {
303 ht->dtor( y );
304 }
305
306 return XLAL_SUCCESS;
307
308}
static size_t hash(const char *s)
Definition: LALDict.c:51
static int hashtbl_no_param_cmp(void *param, const void *x, const void *y)
Definition: LALHashTbl.c:55
static int hashtbl_resize(LALHashTbl *ht)
Definition: LALHashTbl.c:62
static UINT8 hashtbl_no_param_hash(void *param, const void *x)
Definition: LALHashTbl.c:48
#define INCRIDX(ht, i)
Definition: LALHashTbl.c:30
#define EQUAL(ht, x, y)
Definition: LALHashTbl.c:33
static const void * hash_del
Definition: LALHashTbl.c:23
#define DEL
Definition: LALHashTbl.c:24
#define HASHIDX(ht, x)
Definition: LALHashTbl.c:27
static int cmp(REAL4Sequence *a, REAL4Sequence *b)
Definition: SequenceTest.c:62
uint64_t UINT8
Eight-byte unsigned integer; on some platforms this is equivalent to unsigned long int instead.
int XLALHashTblFind(const LALHashTbl *ht, const void *x, const void **y)
Find the element matching x in a hash table; if found, return in *y
Definition: LALHashTbl.c:185
UINT8(* LALHashTblHashFcn)(const void *x)
Hash function for the hash table element x
Definition: LALHashTbl.h:51
int(* LALHashTblCmpFcn)(const void *x, const void *y)
Function which compares hash table elements x and y
Definition: LALHashTbl.h:61
UINT8(* LALHashTblHashParamFcn)(void *param, const void *x)
Hash function for the hash table element x, with a parameter param.
Definition: LALHashTbl.h:56
int XLALHashTblSize(const LALHashTbl *ht)
Return the size of a hash table.
Definition: LALHashTbl.c:177
int XLALHashTblAdd(LALHashTbl *ht, void *x)
Add an element to a hash table.
Definition: LALHashTbl.c:215
int XLALHashTblExtract(LALHashTbl *ht, const void *x, void **y)
Find the element matching x in a hash table; if found, remove it and return in *y
Definition: LALHashTbl.c:252
int(* LALHashTblCmpParamFcn)(void *param, const void *x, const void *y)
Function which compares hash table elements x and y, with a parameter param.
Definition: LALHashTbl.h:66
LALHashTbl * XLALHashTblCreate2(LALHashTblDtorFcn dtor, LALHashTblHashParamFcn hash, void *hash_param, LALHashTblCmpParamFcn cmp, void *cmp_param)
Create a hash table with parameterised hash and comparison functions.
Definition: LALHashTbl.c:101
int XLALHashTblRemove(LALHashTbl *ht, const void *x)
Find the element matching x in a hash table; if found, remove and destroy it.
Definition: LALHashTbl.c:287
LALHashTbl * XLALHashTblCreate(LALHashTblDtorFcn dtor, LALHashTblHashFcn hash, LALHashTblCmpFcn cmp)
Create a hash table.
Definition: LALHashTbl.c:86
void(* LALHashTblDtorFcn)(void *x)
Function which free memory associated with hash table element x
Definition: LALHashTbl.h:46
void XLALHashTblDestroy(LALHashTbl *ht)
Destroy a hash table and its elements.
Definition: LALHashTbl.c:129
int XLALHashTblClear(LALHashTbl *ht)
Clear a hash table.
Definition: LALHashTbl.c:148
#define XLALCalloc(m, n)
Definition: LALMalloc.h:45
#define XLALFree(p)
Definition: LALMalloc.h:47
#define XLAL_CHECK(assertion,...)
Macro to test an assertion and invoke a failure if it is not true in a function that returns an integ...
Definition: XLALError.h:810
#define XLAL_CHECK_NULL(assertion,...)
Macro to test an assertion and invoke a failure if it is not true in a function that returns a pointe...
Definition: XLALError.h:825
@ XLAL_ENOMEM
Memory allocation error.
Definition: XLALError.h:407
@ XLAL_SUCCESS
Success return value (not an error number)
Definition: XLALError.h:401
@ XLAL_EFAULT
Invalid pointer.
Definition: XLALError.h:408
@ XLAL_EFUNC
Internal function call failed bit: "or" this with existing error number.
Definition: XLALError.h:462
@ XLAL_EINVAL
Invalid argument.
Definition: XLALError.h:409
@ XLAL_EFAILED
Generic failure.
Definition: XLALError.h:418
Generic hash table with elements of type void *
Definition: LALHashTbl.c:35
LALHashTblHashParamFcn hash
Definition: LALHashTbl.c:41
void * cmp_param
Definition: LALHashTbl.c:44
void * hash_param
Definition: LALHashTbl.c:42
void ** data
Definition: LALHashTbl.c:36
LALHashTblCmpParamFcn cmp
Definition: LALHashTbl.c:43
LALHashTblDtorFcn dtor
Definition: LALHashTbl.c:40