/* * $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $ * * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. * Michael Clark * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. * * This library is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See COPYING for details. * */ /** * @file * @brief Internal methods for working with json_type_object objects. Although * this is exposed by the json_object_get_object() function and within the * json_object_iter type, it is not recommended for direct use. */ #ifndef _json_c_linkhash_h_ #define _json_c_linkhash_h_ #include "json_object.h" #ifdef __cplusplus extern "C" { #endif /** * golden prime used in hash functions */ #define LH_PRIME 0x9e370001UL /** * The fraction of filled hash buckets until an insert will cause the table * to be resized. * This can range from just above 0 up to 1.0. */ #define LH_LOAD_FACTOR 0.66 /** * sentinel pointer value for empty slots */ #define LH_EMPTY (void *)-1 /** * sentinel pointer value for freed slots */ #define LH_FREED (void *)-2 /** * default string hash function */ #define JSON_C_STR_HASH_DFLT 0 /** * perl-like string hash function */ #define JSON_C_STR_HASH_PERLLIKE 1 /** * This function sets the hash function to be used for strings. * Must be one of the JSON_C_STR_HASH_* values. * @returns 0 - ok, -1 if parameter was invalid */ int json_global_set_string_hash(const int h); struct lh_entry; /** * callback function prototypes */ typedef void(lh_entry_free_fn)(struct lh_entry *e); /** * callback function prototypes */ typedef unsigned long(lh_hash_fn)(const void *k); /** * callback function prototypes */ typedef int(lh_equal_fn)(const void *k1, const void *k2); /** * An entry in the hash table. Outside of linkhash.c, treat this as opaque. */ struct lh_entry { /** * The key. * @deprecated Use lh_entry_k() instead of accessing this directly. */ const void *k; /** * A flag for users of linkhash to know whether or not they * need to free k. * @deprecated use lh_entry_k_is_constant() instead. */ int k_is_constant; /** * The value. * @deprecated Use lh_entry_v() instead of accessing this directly. */ const void *v; /** * The next entry. * @deprecated Use lh_entry_next() instead of accessing this directly. */ struct lh_entry *next; /** * The previous entry. * @deprecated Use lh_entry_prev() instead of accessing this directly. */ struct lh_entry *prev; }; /** * The hash table structure. Outside of linkhash.c, treat this as opaque. */ struct lh_table { /** * Size of our hash. * @deprecated do not use outside of linkhash.c */ int size; /** * Numbers of entries. * @deprecated Use lh_table_length() instead. */ int count; /** * The first entry. * @deprecated Use lh_table_head() instead. */ struct lh_entry *head; /** * The last entry. * @deprecated Do not use, may be removed in a future release. */ struct lh_entry *tail; /** * Internal storage of the actual table of entries. * @deprecated do not use outside of linkhash.c */ struct lh_entry *table; /** * A pointer to the function responsible for freeing an entry. * @deprecated do not use outside of linkhash.c */ lh_entry_free_fn *free_fn; /** * @deprecated do not use outside of linkhash.c */ lh_hash_fn *hash_fn; /** * @deprecated do not use outside of linkhash.c */ lh_equal_fn *equal_fn; }; typedef struct lh_table lh_table; /** * Convenience list iterator. */ #define lh_foreach(table, entry) for (entry = lh_table_head(table); entry; entry = lh_entry_next(entry)) /** * lh_foreach_safe allows calling of deletion routine while iterating. * * @param table a struct lh_table * to iterate over * @param entry a struct lh_entry * variable to hold each element * @param tmp a struct lh_entry * variable to hold a temporary pointer to the next element */ #define lh_foreach_safe(table, entry, tmp) \ for (entry = lh_table_head(table); entry && ((tmp = lh_entry_next(entry)) || 1); entry = tmp) /** * Create a new linkhash table. * * @param size initial table size. The table is automatically resized * although this incurs a performance penalty. * @param free_fn callback function used to free memory for entries * when lh_table_free or lh_table_delete is called. * If NULL is provided, then memory for keys and values * must be freed by the caller. * @param hash_fn function used to hash keys. 2 standard ones are defined: * lh_ptr_hash and lh_char_hash for hashing pointer values * and C strings respectively. * @param equal_fn comparison function to compare keys. 2 standard ones defined: * lh_ptr_hash and lh_char_hash for comparing pointer values * and C strings respectively. * @return On success, a pointer to the new linkhash table is returned. * On error, a null pointer is returned. */ extern struct lh_table *lh_table_new(int size, lh_entry_free_fn *free_fn, lh_hash_fn *hash_fn, lh_equal_fn *equal_fn); /** * Convenience function to create a new linkhash table with char keys. * * @param size initial table size. * @param free_fn callback function used to free memory for entries. * @return On success, a pointer to the new linkhash table is returned. * On error, a null pointer is returned. */ extern struct lh_table *lh_kchar_table_new(int size, lh_entry_free_fn *free_fn); /** * Convenience function to create a new linkhash table with ptr keys. * * @param size initial table size. * @param free_fn callback function used to free memory for entries. * @return On success, a pointer to the new linkhash table is returned. * On error, a null pointer is returned. */ extern struct lh_table *lh_kptr_table_new(int size, lh_entry_free_fn *free_fn); /** * Free a linkhash table. * * If a lh_entry_free_fn callback free function was provided then it is * called for all entries in the table. * * @param t table to free. */ extern void lh_table_free(struct lh_table *t); /** * Insert a record into the table. * * @param t the table to insert into. * @param k a pointer to the key to insert. * @param v a pointer to the value to insert. * * @return On success, 0 is returned. * On error, a negative value is returned. */ extern int lh_table_insert(struct lh_table *t, const void *k, const void *v); /** * Insert a record into the table using a precalculated key hash. * * The hash h, which should be calculated with lh_get_hash() on k, is provided by * the caller, to allow for optimization when multiple operations with the same * key are known to be needed. * * @param t the table to insert into. * @param k a pointer to the key to insert. * @param v a pointer to the value to insert. * @param h hash value of the key to insert * @param opts if set to JSON_C_OBJECT_ADD_CONSTANT_KEY, sets lh_entry.k_is_constant * so t's free function knows to avoid freeing the key. */ extern int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, const unsigned long h, const unsigned opts); /** * Lookup a record in the table. * * @param t the table to lookup * @param k a pointer to the key to lookup * @return a pointer to the record structure of the value or NULL if it does not exist. */ extern struct lh_entry *lh_table_lookup_entry(struct lh_table *t, const void *k); /** * Lookup a record in the table using a precalculated key hash. * * The hash h, which should be calculated with lh_get_hash() on k, is provided by * the caller, to allow for optimization when multiple operations with the same * key are known to be needed. * * @param t the table to lookup * @param k a pointer to the key to lookup * @param h hash value of the key to lookup * @return a pointer to the record structure of the value or NULL if it does not exist. */ extern struct lh_entry *lh_table_lookup_entry_w_hash(struct lh_table *t, const void *k, const unsigned long h); /** * Lookup a record in the table. * * @param t the table to lookup * @param k a pointer to the key to lookup * @param v a pointer to a where to store the found value (set to NULL if it doesn't exist). * @return whether or not the key was found */ extern json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v); /** * Delete a record from the table. * * If a callback free function is provided then it is called for the * for the item being deleted. * @param t the table to delete from. * @param e a pointer to the entry to delete. * @return 0 if the item was deleted. * @return -1 if it was not found. */ extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e); /** * Delete a record from the table. * * If a callback free function is provided then it is called for the * for the item being deleted. * @param t the table to delete from. * @param k a pointer to the key to delete. * @return 0 if the item was deleted. * @return -1 if it was not found. */ extern int lh_table_delete(struct lh_table *t, const void *k); /** * Return the number of entries in the table. */ extern int lh_table_length(struct lh_table *t); /** * Resizes the specified table. * * @param t Pointer to table to resize. * @param new_size New table size. Must be positive. * * @return On success, 0 is returned. * On error, a negative value is returned. */ int lh_table_resize(struct lh_table *t, int new_size); /** * @deprecated Don't use this outside of linkhash.h: */ #if (defined(AIX_CC) || (defined(_MSC_VER) && (_MSC_VER <= 1800)) ) /* VS2010 can't handle inline funcs, so skip it there */ #define _LH_INLINE #else #define _LH_INLINE inline #endif /** * Return the first entry in the lh_table. * @see lh_entry_next() */ static _LH_INLINE struct lh_entry *lh_table_head(const lh_table *t) { return t->head; } /** * Calculate the hash of a key for a given table. * * This is an extension to support functions that need to calculate * the hash several times and allows them to do it just once and then pass * in the hash to all utility functions. Depending on use case, this can be a * considerable performance improvement. * @param t the table (used to obtain hash function) * @param k a pointer to the key to lookup * @return the key's hash */ static _LH_INLINE unsigned long lh_get_hash(const struct lh_table *t, const void *k) { return t->hash_fn(k); } /** * @deprecated Don't use this outside of linkhash.h: */ #ifdef __UNCONST #define _LH_UNCONST(a) __UNCONST(a) #else #define _LH_UNCONST(a) ((void *)(uintptr_t)(const void *)(a)) #endif /** * Return a non-const version of lh_entry.k. * * lh_entry.k is const to indicate and help ensure that linkhash itself doesn't modify * it, but callers are allowed to do what they want with it. * @see lh_entry_k_is_constant() */ static _LH_INLINE void *lh_entry_k(const struct lh_entry *e) { return _LH_UNCONST(e->k); } /** * Returns 1 if the key for the given entry is constant, and thus * does not need to be freed when the lh_entry is freed. * @see lh_table_insert_w_hash() */ static _LH_INLINE int lh_entry_k_is_constant(const struct lh_entry *e) { return e->k_is_constant; } /** * Return a non-const version of lh_entry.v. * * v is const to indicate and help ensure that linkhash itself doesn't modify * it, but callers are allowed to do what they want with it. */ static _LH_INLINE void *lh_entry_v(const struct lh_entry *e) { return _LH_UNCONST(e->v); } /** * Change the value for an entry. The caller is responsible for freeing * the previous value. */ static _LH_INLINE void lh_entry_set_val(struct lh_entry *e, void *newval) { e->v = newval; } /** * Return the next element, or NULL if there is no next element. * @see lh_table_head() * @see lh_entry_prev() */ static _LH_INLINE struct lh_entry *lh_entry_next(const struct lh_entry *e) { return e->next; } /** * Return the previous element, or NULL if there is no previous element. * @see lh_table_head() * @see lh_entry_next() */ static _LH_INLINE struct lh_entry *lh_entry_prev(const struct lh_entry *e) { return e->prev; } #undef _LH_INLINE #ifdef __cplusplus } #endif #endif