ThingWorx C SDK
cfuhash.h
1 /*
2  * cfuhash.h - This file is part of the libcfu library
3  *
4  * Copyright (c) 2005 Don Owens. All rights reserved.
5  *
6  * This code is released under the BSD license:
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  *
20  * * Neither the name of the author nor the names of its
21  * contributors may be used to endorse or promote products derived
22  * from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
35  * OF THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 #ifndef CFU_HASH_H_
39 #define CFU_HASH_H_
40 
41 #include <cfu.h>
42 #include <stdio.h>
43 
44 CFU_BEGIN_DECLS
45 
46 /* The hash table itself. */
47 typedef struct cfuhash_table cfuhash_table_t;
48 
49 /* Prototype for a pointer to a hashing function. */
50 typedef unsigned int (*cfuhash_function_t)(const void *key, size_t length);
51 
52 /* Prototype for a pointer to a free function. */
53 typedef void (*cfuhash_free_fn_t)(void *data);
54 
55 /* Prototype for a pointer to a function that determines whether
56  * or not to remove an entry from the hash.
57 */
58 typedef int (*cfuhash_remove_fn_t)(void *key, size_t key_size, void *data, size_t data_size,
59  void *arg);
60 
61 /* Prototype for a pointer to a function to be called foreach
62  * key/value pair in the hash by cfuhash_foreach(). Iteration
63  * stops if a non-zero value is returned.
64  */
65 typedef int (*cfuhash_foreach_fn_t)(void *key, size_t key_size, void *data, size_t data_size,
66  void *arg);
67 
68 /* Creates a new hash table. */
69 cfuhash_table_t * cfuhash_new(void);
70 
71 /* Creates a new hash table with the specified size (number of
72  * buckets).
73  */
74 cfuhash_table_t * cfuhash_new_with_initial_size(size_t size);
75 
76 /* Creates a new hash table with the specified flags. Pass zero
77  * for flags if you want the defaults.
78  */
79 cfuhash_table_t * cfuhash_new_with_flags(unsigned int flags);
80 
81 /* Same as cfuhash_new() except automatically calls cfuhash_set_free_fn(). */
82 cfuhash_table_t * cfuhash_new_with_free_fn(cfuhash_free_fn_t ff);
83 
84 /* Copies entries in src to dst */
85 int cfuhash_copy(cfuhash_table_t *src, cfuhash_table_t *dst);
86 
87 /* Returns a new hash containing entries from both hash tables.
88  * For any entries with the same key, the one from ht2 wins.
89 */
90 cfuhash_table_t * cfuhash_merge(cfuhash_table_t *ht1, cfuhash_table_t *ht2,
91  unsigned int flags);
92 
93 /* Sets the hashing function to use when computing which bucket to add
94  * entries to. It should return a 32-bit unsigned integer. By
95  * default, Perl's hashing algorithm is used.
96  */
97 int cfuhash_set_hash_function(cfuhash_table_t *ht, cfuhash_function_t hf);
98 
99 /* Sets the thresholds for when to rehash. The ratio
100  * num_entries/buckets is compared against low and high. If it is
101  * below 'low' or above 'high', the hash will shrink or grow,
102  * respectively, unless the flags say to do otherwise.
103  */
104 int cfuhash_set_thresholds(cfuhash_table_t *ht, float low, float high);
105 
106 /* Sets the function to use when removing an entry from the hash,
107  * i.e., when replacing an existing entry, deleting an entry, or
108  * clearing the hash. It is passed the value of the entry as a
109  * void *.
110  */
111 int cfuhash_set_free_function(cfuhash_table_t * ht, cfuhash_free_fn_t ff);
112 
113 /* Returns the hash's flags. See below for flag definitions. */
114 unsigned int cfuhash_get_flags(cfuhash_table_t *ht);
115 
116 /* Sets a flag. */
117 unsigned int cfuhash_set_flag(cfuhash_table_t *ht, unsigned int flag);
118 
119 /* Clears a flag. */
120 unsigned int cfuhash_clear_flag(cfuhash_table_t *ht, unsigned int new_flag);
121 
122 /* Returns the value for the entry with given key. If key_size is -1,
123  * key is assumed to be a null-terminated string. If data_size is not
124  * NULL, the size of the value is placed into data_size.
125  */
126 int cfuhash_get_data(cfuhash_table_t *ht, const void *key, size_t key_size,
127  void **data, size_t *data_size);
128 
129 /* Returns 1 if an entry with the given key exists in the hash, 0 otherwise. */
130 int cfuhash_exists_data(cfuhash_table_t *ht, const void *key, size_t key_size);
131 
132 /* Inserts the given data value into the hash and associates it with
133  * key. If key_size is -1, key is assumed to be a null-terminated
134  * string. If data_size is -1, it is assumed to be a null-terminated
135  * string (it's length will be calculated using strlen). If
136  * data_size is zero, it will be returned as zero when the value is
137  * requested.
138  */
139 int cfuhash_put_data(cfuhash_table_t *ht, const void *key, size_t key_size, void *data,
140  size_t data_size, void **r);
141 
142 /* Clears the hash table (deletes all entries). */
143 void cfuhash_clear(cfuhash_table_t *ht);
144 
145 /* Deletes the entry in the hash associated with key. If the entry
146  * existed, it's value will be returned.
147  */
148 void * cfuhash_delete_data(cfuhash_table_t *ht, const void *key, size_t key_size);
149 
150 /* Returns all the keys from the hash. The number of keys is placed
151  * into the value pointed to by num_keys. If key_sizes is not NULL,
152  * it will be set to an array of key sizes. If fast is zero, copies
153  * of the keys are returned. Otherwise, pointers to the real keys
154  * will be returned.
155  */
156 void **cfuhash_keys_data(cfuhash_table_t *ht, size_t *num_keys, size_t **key_sizes,
157  int fast);
158 
159 /* Initializes a loop over all the key/value pairs in the hash. It
160  * returns the first key/value pair (see cfuhash_next_data()). 1 is
161  * returned if there are any entries in the hash. 0 is returned
162  * otherwise.
163  */
164 int cfuhash_each_data(cfuhash_table_t *ht, void **key, size_t *key_size, void **data,
165  size_t *data_size);
166 
167 /* Gets the next key/value pair from the hash. You must initialize
168  * the loop using cfuhash_each_data() before calling this function.
169  * If a entry is left to return, 1 is returned from the function. 0
170  * is returned if there are no more entries in the hash.
171  */
172 int cfuhash_next_data(cfuhash_table_t *ht, void **key, size_t *key_size, void **data,
173  size_t *data_size);
174 
175 /* Iterates over the key/value pairs in the hash, passing each one
176  * to r_fn, and removes all entries for which r_fn returns true.
177  * If ff is not NULL, it is the passed the data to be freed. arg
178  * is passed to r_fn.
179  */
180 size_t cfuhash_foreach_remove(cfuhash_table_t *ht, cfuhash_remove_fn_t r_fn,
181  cfuhash_free_fn_t ff, void *arg);
182 
183 /* Iterates over the key/value pairs in the hash, passing each one
184  * to fe_fn, along with arg. This locks the hash, so do not call
185  * any operations on the hash from within fe_fn unless you really
186  * know what you're doing. A non-zero return value from fe_fn()
187  * stops the iteration.
188  */
189 size_t cfuhash_foreach(cfuhash_table_t *ht, cfuhash_foreach_fn_t fe_fn, void *arg);
190 
191 /* Frees all resources allocated by the hash. If ff is not NULL, it
192  * is called for each hash entry with the value of the entry passed as
193  * its only argument. If ff is not NULL, it overrides any function
194  * set previously with cfuhash_set_free_function().
195  */
196 int cfuhash_destroy(cfuhash_table_t *ht);
197 
198 int cfuhash_destroy_with_free_fn(cfuhash_table_t *ht, cfuhash_free_fn_t ff);
199 
200 /* Rebuild the hash to better accomodate the number of entries. See
201  * cfuhash_set_thresholds().
202  */
203 int cfuhash_rehash(cfuhash_table_t *ht);
204 
205 /* Returns the number entries in the hash. */
206 size_t cfuhash_num_entries(cfuhash_table_t *ht);
207 
208 /* Returns the number of buckets allocated for the hash. */
209 size_t cfuhash_num_buckets(cfuhash_table_t *ht);
210 
211 /* Returns the number of buckets actually used out of the total number
212  * allocated for the hash.
213  */
214 size_t cfuhash_num_buckets_used(cfuhash_table_t *ht);
215 
216 /* Assumes all the keys and values are null-terminated strings and
217  * returns a bencoded string representing the hash (see
218  * http://www.bittorrent.com/protocol.html)
219  */
220 char * cfuhash_bencode_strings(cfuhash_table_t *ht);
221 
222 /* Locks the hash. Use this with the each and next functions for
223  * concurrency control. Note that the hash is locked automatically
224  * when doing inserts and deletes, so if you lock the hash and then
225  * try to insert something into it, you may get into a deadlock,
226  * depending on your system defaults for how mutexes work.
227  */
228 int cfuhash_lock(cfuhash_table_t *ht);
229 
230 /* Unlocks the hash. Use this with the each an next functions for
231  * concurrency control. The caveat for cfuhash_lcok() also applies to
232  * this function.
233  */
234 int cfuhash_unlock(cfuhash_table_t *ht);
235 
236 /* Pretty print the hash's key/value pairs to the stream fp. It is
237  * assumed that all the keys and values are null-terminated strings.
238  */
239 int cfuhash_pretty_print(cfuhash_table_t *ht, FILE *fp);
240 
241 /* These are like the _data versions of these functions, with the
242  * following exceptions:
243  * 1) They assume that the key provided is a null-terminated string.
244  * 2) They don't worry about the size of the data.
245  * 3) Returned keys or values are the return value of the function.
246  */
247 void * cfuhash_get(cfuhash_table_t *ht, const char *key);
248 int cfuhash_exists(cfuhash_table_t *ht, const char *key);
249 void * cfuhash_put(cfuhash_table_t *ht, const char *key, void *data);
250 void * cfuhash_delete(cfuhash_table_t *ht, const char *key);
251 int cfuhash_each(cfuhash_table_t *ht, char **key, void **data);
252 int cfuhash_next(cfuhash_table_t *ht, char **key, void **data);
253 void **cfuhash_keys(cfuhash_table_t *ht, size_t *num_keys, int fast);
254 
255 
256 /* hash table flags */
257 #define CFUHASH_NOCOPY_KEYS 1 /* do not copy the key when inserting a hash entry */
258 #define CFUHASH_NO_LOCKING (1 << 1) /* do not make the hash thread-safe */
259 #define CFUHASH_FROZEN (1 << 2) /* do not rehash when the size thresholds are reached */
260 #define CFUHASH_FROZEN_UNTIL_GROWS (1 << 3) /* do not shrink the hash until it has grown */
261 #define CFUHASH_FREE_DATA (1 << 4) /* call free() on each value when the hash is destroyed */
262 #define CFUHASH_IGNORE_CASE (1 << 5) /* treat keys case-insensitively */
263 
264 
265 CFU_END_DECLS
266 
267 #endif
Definition: cfuhash.c:97