278 lines
12 KiB
C
278 lines
12 KiB
C
|
/* Creation date: 2005-06-24 21:22:09
|
||
|
* Authors: Don
|
||
|
* Change log:
|
||
|
*/
|
||
|
|
||
|
/* Copyright (c) 2005 Don Owens
|
||
|
All rights reserved.
|
||
|
|
||
|
This code is released under the BSD license:
|
||
|
|
||
|
Redistribution and use in source and binary forms, with or without
|
||
|
modification, are permitted provided that the following conditions
|
||
|
are met:
|
||
|
|
||
|
* Redistributions of source code must retain the above copyright
|
||
|
notice, this list of conditions and the following disclaimer.
|
||
|
|
||
|
* Redistributions in binary form must reproduce the above
|
||
|
copyright notice, this list of conditions and the following
|
||
|
disclaimer in the documentation and/or other materials provided
|
||
|
with the distribution.
|
||
|
|
||
|
* Neither the name of the author nor the names of its
|
||
|
contributors may be used to endorse or promote products derived
|
||
|
from this software without specific prior written permission.
|
||
|
|
||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||
|
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||
|
OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
*/
|
||
|
|
||
|
#ifndef _CFU_HASH_H_
|
||
|
#define _CFU_HASH_H_
|
||
|
|
||
|
#include <cfu.h>
|
||
|
|
||
|
#include <sys/types.h>
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
extern "C" {
|
||
|
#endif
|
||
|
|
||
|
/* The hash table itself. */
|
||
|
struct cfuhash_table;
|
||
|
typedef struct cfuhash_table cfuhash_table_t;
|
||
|
|
||
|
/* Prototype for a pointer to a hashing function. */
|
||
|
typedef u_int32_t (*cfuhash_function_t)(const void *key, size_t length);
|
||
|
|
||
|
/* Prototype for a pointer to a free function. */
|
||
|
typedef void (*cfuhash_free_fn_t)(void *data);
|
||
|
|
||
|
/* Prototype for a pointer to a function that determines whether
|
||
|
* or not to remove an entry from the hash.
|
||
|
*/
|
||
|
typedef int (*cfuhash_remove_fn_t)(void *key, size_t key_size, void *data, size_t data_size,
|
||
|
void *arg);
|
||
|
|
||
|
/* Prototype for a pointer to a function to be called foreach
|
||
|
* key/value pair in the hash by cfuhash_foreach(). Iteration
|
||
|
* stops if a non-zero value is returned.
|
||
|
*/
|
||
|
typedef int (*cfuhash_foreach_fn_t)(void *key, size_t key_size, void *data, size_t data_size,
|
||
|
void *arg);
|
||
|
|
||
|
/* Creates a new hash table. */
|
||
|
extern cfuhash_table_t * cfuhash_new();
|
||
|
|
||
|
/* Creates a new hash table with the specified size (number of
|
||
|
* buckets).
|
||
|
*/
|
||
|
extern cfuhash_table_t * cfuhash_new_with_initial_size(size_t size);
|
||
|
|
||
|
/* Creates a new hash table with the specified flags. Pass zero
|
||
|
* for flags if you want the defaults.
|
||
|
*/
|
||
|
extern cfuhash_table_t * cfuhash_new_with_flags(u_int32_t flags);
|
||
|
|
||
|
/* Same as cfuhash_new() except automatically calls cfuhash_set_free_fn(). */
|
||
|
extern cfuhash_table_t * cfuhash_new_with_free_fn(cfuhash_free_fn_t ff);
|
||
|
|
||
|
/* Copies entries in src to dst */
|
||
|
extern int cfuhash_copy(cfuhash_table_t *src, cfuhash_table_t *dst);
|
||
|
|
||
|
/* Returns a new hash containing entries from both hash tables.
|
||
|
* For any entries with the same key, the one from ht2 wins.
|
||
|
*/
|
||
|
extern cfuhash_table_t * cfuhash_merge(cfuhash_table_t *ht1, cfuhash_table_t *ht2,
|
||
|
u_int32_t flags);
|
||
|
|
||
|
/* Sets the hashing function to use when computing which bucket to add
|
||
|
* entries to. It should return a 32-bit unsigned integer. By
|
||
|
* default, Perl's hashing algorithm is used.
|
||
|
*/
|
||
|
extern int cfuhash_set_hash_function(cfuhash_table_t *ht, cfuhash_function_t hf);
|
||
|
|
||
|
/* Sets the thresholds for when to rehash. The ratio
|
||
|
* num_entries/buckets is compared against low and high. If it is
|
||
|
* below 'low' or above 'high', the hash will shrink or grow,
|
||
|
* respectively, unless the flags say to do otherwise.
|
||
|
*/
|
||
|
extern int cfuhash_set_thresholds(cfuhash_table_t *ht, float low, float high);
|
||
|
|
||
|
/* Sets the function to use when removing an entry from the hash,
|
||
|
* i.e., when replacing an existing entry, deleting an entry, or
|
||
|
* clearing the hash. It is passed the value of the entry as a
|
||
|
* void *.
|
||
|
*/
|
||
|
extern int cfuhash_set_free_function(cfuhash_table_t * ht, cfuhash_free_fn_t ff);
|
||
|
|
||
|
/* Returns the hash's flags. See below for flag definitions. */
|
||
|
extern u_int32_t cfuhash_get_flags(cfuhash_table_t *ht);
|
||
|
|
||
|
/* Sets a flag. */
|
||
|
extern u_int32_t cfuhash_set_flag(cfuhash_table_t *ht, u_int32_t flag);
|
||
|
|
||
|
/* Clears a flag. */
|
||
|
extern u_int32_t cfuhash_clear_flag(cfuhash_table_t *ht, u_int32_t new_flag);
|
||
|
|
||
|
/* Returns the value for the entry with given key. If key_size is -1,
|
||
|
* key is assumed to be a null-terminated string. If data_size is not
|
||
|
* NULL, the size of the value is placed into data_size.
|
||
|
*/
|
||
|
extern int cfuhash_get_data(cfuhash_table_t *ht, const void *key, size_t key_size,
|
||
|
void **data, size_t *data_size);
|
||
|
|
||
|
/* Returns 1 if an entry with the given key exists in the hash, 0 otherwise. */
|
||
|
extern int cfuhash_exists_data(cfuhash_table_t *ht, const void *key, size_t key_size);
|
||
|
|
||
|
/* Inserts the given data value into the hash and associates it with
|
||
|
* key. If key_size is -1, key is assumed to be a null-terminated
|
||
|
* string. If data_size is -1, it is assumed to be a null-terminated
|
||
|
* string (it's length will be calculated using strlen). If
|
||
|
* data_size is zero, it will be returned as zero when the value is
|
||
|
* requested.
|
||
|
*/
|
||
|
extern int cfuhash_put_data(cfuhash_table_t *ht, const void *key, size_t key_size, void *data,
|
||
|
size_t data_size, void **r);
|
||
|
|
||
|
/* Clears the hash table (deletes all entries). */
|
||
|
extern void cfuhash_clear(cfuhash_table_t *ht);
|
||
|
|
||
|
/* Deletes the entry in the hash associated with key. If the entry
|
||
|
* existed, it's value will be returned.
|
||
|
*/
|
||
|
extern void * cfuhash_delete_data(cfuhash_table_t *ht, const void *key, size_t key_size);
|
||
|
|
||
|
/* Returns all the keys from the hash. The number of keys is placed
|
||
|
* into the value pointed to by num_keys. If key_sizes is not NULL,
|
||
|
* it will be set to an array of key sizes. If fast is zero, copies
|
||
|
* of the keys are returned. Otherwise, pointers to the real keys
|
||
|
* will be returned.
|
||
|
*/
|
||
|
extern void **cfuhash_keys_data(cfuhash_table_t *ht, size_t *num_keys, size_t **key_sizes,
|
||
|
int fast);
|
||
|
|
||
|
/* Initializes a loop over all the key/value pairs in the hash. It
|
||
|
* returns the first key/value pair (see cfuhash_next_data()). 1 is
|
||
|
* returned if there are any entries in the hash. 0 is returned
|
||
|
* otherwise.
|
||
|
*/
|
||
|
extern int cfuhash_each_data(cfuhash_table_t *ht, void **key, size_t *key_size, void **data,
|
||
|
size_t *data_size);
|
||
|
|
||
|
/* Gets the next key/value pair from the hash. You must initialize
|
||
|
* the loop using cfuhash_each_data() before calling this function.
|
||
|
* If a entry is left to return, 1 is returned from the function. 0
|
||
|
* is returned if there are no more entries in the hash.
|
||
|
*/
|
||
|
extern int cfuhash_next_data(cfuhash_table_t *ht, void **key, size_t *key_size, void **data,
|
||
|
size_t *data_size);
|
||
|
|
||
|
/* Iterates over the key/value pairs in the hash, passing each one
|
||
|
* to r_fn, and removes all entries for which r_fn returns true.
|
||
|
* If ff is not NULL, it is the passed the data to be freed. arg
|
||
|
* is passed to r_fn.
|
||
|
*/
|
||
|
extern size_t cfuhash_foreach_remove(cfuhash_table_t *ht, cfuhash_remove_fn_t r_fn,
|
||
|
cfuhash_free_fn_t ff, void *arg);
|
||
|
|
||
|
/* Iterates over the key/value pairs in the hash, passing each one
|
||
|
* to fe_fn, along with arg. This locks the hash, so do not call
|
||
|
* any operations on the hash from within fe_fn unless you really
|
||
|
* know what you're doing. A non-zero return value from fe_fn()
|
||
|
* stops the iteration.
|
||
|
*/
|
||
|
extern size_t cfuhash_foreach(cfuhash_table_t *ht, cfuhash_foreach_fn_t fe_fn, void *arg);
|
||
|
|
||
|
/* Frees all resources allocated by the hash. If ff is not NULL, it
|
||
|
* is called for each hash entry with the value of the entry passed as
|
||
|
* its only argument. If ff is not NULL, it overrides any function
|
||
|
* set previously with cfuhash_set_free_function().
|
||
|
*/
|
||
|
extern int cfuhash_destroy(cfuhash_table_t *ht);
|
||
|
|
||
|
extern int cfuhash_destroy_with_free_fn(cfuhash_table_t *ht, cfuhash_free_fn_t ff);
|
||
|
|
||
|
/* Rebuild the hash to better accomodate the number of entries. See
|
||
|
* cfuhash_set_thresholds().
|
||
|
*/
|
||
|
extern int cfuhash_rehash(cfuhash_table_t *ht);
|
||
|
|
||
|
/* Returns the number entries in the hash. */
|
||
|
extern size_t cfuhash_num_entries(cfuhash_table_t *ht);
|
||
|
|
||
|
/* Returns the number of buckets allocated for the hash. */
|
||
|
extern size_t cfuhash_num_buckets(cfuhash_table_t *ht);
|
||
|
|
||
|
/* Returns the number of buckets actually used out of the total number
|
||
|
* allocated for the hash.
|
||
|
*/
|
||
|
extern size_t cfuhash_num_buckets_used(cfuhash_table_t *ht);
|
||
|
|
||
|
/* Assumes all the keys and values are null-terminated strings and
|
||
|
* returns a bencoded string representing the hash (see
|
||
|
* http://www.bittorrent.com/protocol.html)
|
||
|
*/
|
||
|
extern char * cfuhash_bencode_strings(cfuhash_table_t *ht);
|
||
|
|
||
|
/* Locks the hash. Use this with the each and next functions for
|
||
|
* concurrency control. Note that the hash is locked automatically
|
||
|
* when doing inserts and deletes, so if you lock the hash and then
|
||
|
* try to insert something into it, you may get into a deadlock,
|
||
|
* depending on your system defaults for how mutexes work.
|
||
|
*/
|
||
|
extern int cfuhash_lock(cfuhash_table_t *ht);
|
||
|
|
||
|
/* Unlocks the hash. Use this with the each an next functions for
|
||
|
* concurrency control. The caveat for cfuhash_lcok() also applies to
|
||
|
* this function.
|
||
|
*/
|
||
|
extern int cfuhash_unlock(cfuhash_table_t *ht);
|
||
|
|
||
|
/* Pretty print the hash's key/value pairs to the stream fp. It is
|
||
|
* assumed that all the keys and values are null-terminated strings.
|
||
|
*/
|
||
|
extern int cfuhash_pretty_print(cfuhash_table_t *ht, FILE *fp);
|
||
|
|
||
|
/* These are like the _data versions of these functions, with the
|
||
|
* following exceptions:
|
||
|
* 1) They assume that the key provided is a null-terminated string.
|
||
|
* 2) They don't worry about the size of the data.
|
||
|
* 3) Returned keys or values are the return value of the function.
|
||
|
*/
|
||
|
extern void * cfuhash_get(cfuhash_table_t *ht, const char *key);
|
||
|
extern int cfuhash_exists(cfuhash_table_t *ht, const char *key);
|
||
|
extern void * cfuhash_put(cfuhash_table_t *ht, const char *key, void *data);
|
||
|
extern void * cfuhash_delete(cfuhash_table_t *ht, const char *key);
|
||
|
extern int cfuhash_each(cfuhash_table_t *ht, char **key, void **data);
|
||
|
extern int cfuhash_next(cfuhash_table_t *ht, char **key, void **data);
|
||
|
extern void **cfuhash_keys(cfuhash_table_t *ht, size_t *num_keys, int fast);
|
||
|
|
||
|
|
||
|
/* hash table flags */
|
||
|
#define CFUHASH_NOCOPY_KEYS 1 /* do not copy the key when inserting a hash entry */
|
||
|
#define CFUHASH_NO_LOCKING (1 << 1) /* do not make the hash thread-safe */
|
||
|
#define CFUHASH_FROZEN (1 << 2) /* do not rehash when the size thresholds are reached */
|
||
|
#define CFUHASH_FROZEN_UNTIL_GROWS (1 << 3) /* do not shrink the hash until it has grown */
|
||
|
#define CFUHASH_FREE_DATA (1 << 4) /* call free() on each value when the hash is destroyed */
|
||
|
#define CFUHASH_IGNORE_CASE (1 << 5) /* treat keys case-insensitively */
|
||
|
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#endif
|