This repository has been archived on 2024-08-17. You can view files and clone it, but cannot push or open issues or pull requests.
freeswitch_rs/include/switch_hashtable.h

304 lines
9.9 KiB
C

/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* switch_hashtable.h -- Hashtable
*
*/
/* hashtable.h Copyright (C) 2002 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
#ifndef __HASHTABLE_CWC22_H__
#define __HASHTABLE_CWC22_H__
#ifdef _MSC_VER
#ifndef __inline__
#define __inline__ __inline
#endif
#endif
#include "switch.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct switch_hashtable switch_hashtable_t;
typedef struct switch_hashtable_iterator switch_hashtable_iterator_t;
/* Example of use:
*
* switch_hashtable_t *h;
* struct some_key *k;
* struct some_value *v;
*
* static unsigned int hash_from_key_fn( void *k );
* static int keys_equal_fn ( void *key1, void *key2 );
*
* h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
* k = (struct some_key *) malloc(sizeof(struct some_key));
* v = (struct some_value *) malloc(sizeof(struct some_value));
*
* (initialise k and v to suitable values)
*
* if (! hashtable_insert(h,k,v) )
* { exit(-1); }
*
* if (NULL == (found = hashtable_search(h,k) ))
* { printf("not found!"); }
*
* if (NULL == (found = hashtable_remove(h,k) ))
* { printf("Not found\n"); }
*
*/
/* Macros may be used to define type-safe(r) hashtable access functions, with
* methods specialized to take known key and value types as parameters.
*
* Example:
*
* Insert this at the start of your file:
*
* DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
* DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
* DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
*
* This defines the functions 'insert_some', 'search_some' and 'remove_some'.
* These operate just like hashtable_insert etc., with the same parameters,
* but their function signatures have 'struct some_key *' rather than
* 'void *', and hence can generate compile time errors if your program is
* supplying incorrect data as a key (and similarly for value).
*
* Note that the hash and key equality functions passed to create_hashtable
* still take 'void *' parameters instead of 'some key *'. This shouldn't be
* a difficult issue as they're only defined and passed once, and the other
* functions will ensure that only valid keys are supplied to them.
*
* The cost for this checking is increased code size and runtime overhead
* - if performance is important, it may be worth switching back to the
* unsafe methods once your program has been debugged with the safe methods.
* This just requires switching to some simple alternative defines - eg:
* #define insert_some hashtable_insert
*
*/
/*****************************************************************************
* create_hashtable
* @name create_hashtable
* @param minsize minimum initial size of hashtable
* @param hashfunction function for hashing keys
* @param key_eq_fn function for determining key equality
* @return newly created hashtable or NULL on failure
*/
SWITCH_DECLARE(switch_status_t)
switch_create_hashtable(switch_hashtable_t **hp, unsigned int minsize,
unsigned int (*hashfunction) (void*),
int (*key_eq_fn) (void*,void*));
/*****************************************************************************
* hashtable_insert
* @name hashtable_insert
* @param h the hashtable to insert into
* @param k the key - hashtable claims ownership and will free on removal
* @param v the value - does not claim ownership
* @return non-zero for successful insertion
*
* This function will cause the table to expand if the insertion would take
* the ratio of entries to table size over the maximum load factor.
*
* This function does not check for repeated insertions with a duplicate key.
* The value returned when using a duplicate key is undefined -- when
* the hashtable changes size, the order of retrieval of duplicate key
* entries is reversed.
* If in doubt, remove before insert.
*/
typedef enum {
HASHTABLE_FLAG_NONE = 0,
HASHTABLE_FLAG_FREE_KEY = (1 << 0),
HASHTABLE_FLAG_FREE_VALUE = (1 << 1),
HASHTABLE_DUP_CHECK = (1 << 2)
} hashtable_flag_t;
SWITCH_DECLARE(int)
switch_hashtable_insert_destructor(switch_hashtable_t *h, void *k, void *v, hashtable_flag_t flags, hashtable_destructor_t destructor);
#define switch_hashtable_insert(_h, _k, _v, _f) switch_hashtable_insert_destructor(_h, _k, _v, _f, NULL)
#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
int fnname (switch_hashtable_t *h, keytype *k, valuetype *v) \
{ \
return hashtable_insert(h,k,v); \
}
/*****************************************************************************
* hashtable_search
* @name hashtable_search
* @param h the hashtable to search
* @param k the key to search for - does not claim ownership
* @return the value associated with the key, or NULL if none found
*/
SWITCH_DECLARE(void *)
switch_hashtable_search(switch_hashtable_t *h, void *k);
#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
valuetype * fnname (switch_hashtable_t *h, keytype *k) \
{ \
return (valuetype *) (hashtable_search(h,k)); \
}
/*****************************************************************************
* hashtable_remove
* @name hashtable_remove
* @param h the hashtable to remove the item from
* @param k the key to search for - does not claim ownership
* @return the value associated with the key, or NULL if none found
*/
SWITCH_DECLARE(void *) /* returns value */
switch_hashtable_remove(switch_hashtable_t *h, void *k);
#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
valuetype * fnname (switch_hashtable_t *h, keytype *k) \
{ \
return (valuetype *) (hashtable_remove(h,k)); \
}
/*****************************************************************************
* hashtable_count
* @name hashtable_count
* @param h the hashtable
* @return the number of items stored in the hashtable
*/
SWITCH_DECLARE(unsigned int)
switch_hashtable_count(switch_hashtable_t *h);
/*****************************************************************************
* hashtable_destroy
* @name hashtable_destroy
* @param h the hashtable
* @param free_values whether to call 'free' on the remaining values
*/
SWITCH_DECLARE(void)
switch_hashtable_destroy(switch_hashtable_t **h);
SWITCH_DECLARE(switch_hashtable_iterator_t*) switch_hashtable_first_iter(switch_hashtable_t *h, switch_hashtable_iterator_t *it);
#define switch_hashtable_first(_h) switch_hashtable_first_iter(_h, NULL)
SWITCH_DECLARE(switch_hashtable_iterator_t*) switch_hashtable_next(switch_hashtable_iterator_t **iP);
SWITCH_DECLARE(void) switch_hashtable_this(switch_hashtable_iterator_t *i, const void **key, switch_ssize_t *klen, void **val);
SWITCH_DECLARE(void) switch_hashtable_this_val(switch_hashtable_iterator_t *i, void *val);
static inline uint32_t switch_hash_default_int(void *ky) {
uint32_t x = *((uint32_t *)ky);
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = ((x >> 16) ^ x);
return x;
}
static inline int switch_hash_equalkeys_int(void *k1, void *k2)
{
return *(uint32_t *)k1 == *(uint32_t *)k2;
}
static inline int switch_hash_equalkeys(void *k1, void *k2)
{
return strcmp((char *) k1, (char *) k2) ? 0 : 1;
}
static inline int switch_hash_equalkeys_ci(void *k1, void *k2)
{
return strcasecmp((char *) k1, (char *) k2) ? 0 : 1;
}
static inline uint32_t switch_hash_default(void *ky)
{
unsigned char *str = (unsigned char *) ky;
uint32_t hash = 0;
int c;
while ((c = *str)) {
str++;
hash = c + (hash << 6) + (hash << 16) - hash;
}
return hash;
}
static inline uint32_t switch_hash_default_ci(void *ky)
{
unsigned char *str = (unsigned char *) ky;
uint32_t hash = 0;
int c;
while ((c = switch_tolower(*str))) {
str++;
hash = c + (hash << 6) + (hash << 16) - hash;
}
return hash;
}
#ifdef __cplusplus
} /* extern C */
#endif
#endif /* __HASHTABLE_CWC22_H__ */
/*
* Copyright (c) 2002, Christopher Clark
* All rights reserved.
*
* 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 original author; nor the names of any 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.
*/
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/