LAL  7.5.0.1-ec27e42
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 */
23 static 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 
35 struct tagLALHashTbl {
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' */
48 static 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' */
55 static 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 */
62 static 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 
86 LALHashTbl *XLALHashTblCreate(
87  LALHashTblDtorFcn dtor,
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 
101 LALHashTbl *XLALHashTblCreate2(
102  LALHashTblDtorFcn dtor,
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
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
void(* LALHashTblDtorFcn)(void *x)
Function which free memory associated with hash table element x
Definition: LALHashTbl.h:46
UINT8(* LALHashTblHashParamFcn)(void *param, const void *x)
Hash function for the hash table element x, with a parameter param.
Definition: LALHashTbl.h:56
LALHashTbl * XLALHashTblCreate(LALHashTblDtorFcn dtor, LALHashTblHashFcn hash, LALHashTblCmpFcn cmp)
Create a hash table.
Definition: LALHashTbl.c:86
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
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
UINT8(* LALHashTblHashFcn)(const void *x)
Hash function for the hash table element x
Definition: LALHashTbl.h:51
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 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
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
int(* LALHashTblCmpFcn)(const void *x, const void *y)
Function which compares hash table elements x and y
Definition: LALHashTbl.h:61
#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