From 3c7b90e93f4553de9308c1dfb761bb7297324ca4 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Wed, 3 Dec 2025 19:10:13 +0100 Subject: [PATCH] Updated with latest Tommy --- tommyds/tommyarray.c | 8 ++++---- tommyds/tommyarray.h | 13 ++++++------ tommyds/tommyarrayblkof.c | 8 ++++---- tommyds/tommyarrayblkof.h | 11 +++++----- tommyds/tommychain.h | 28 ++++++++++++++++++------- tommyds/tommyhash.c | 37 ++++++++++++++++++++++++--------- tommyds/tommyhash.h | 13 ++++++------ tommyds/tommyhashdyn.c | 18 ++++++++-------- tommyds/tommyhashdyn.h | 33 +++++++++++++++--------------- tommyds/tommylist.c | 2 +- tommyds/tommylist.h | 22 +++++++++++--------- tommyds/tommytree.c | 18 ++++++++-------- tommyds/tommytree.h | 29 +++++++++++++------------- tommyds/tommytypes.h | 43 ++++++++++++++++++++++++++------------- 14 files changed, 163 insertions(+), 120 deletions(-) diff --git a/tommyds/tommyarray.c b/tommyds/tommyarray.c index d77db046..44abb6bb 100644 --- a/tommyds/tommyarray.c +++ b/tommyds/tommyarray.c @@ -30,7 +30,7 @@ /******************************************************************************/ /* array */ -void tommy_array_init(tommy_array* array) +TOMMY_API void tommy_array_init(tommy_array* array) { tommy_uint_t i; @@ -44,7 +44,7 @@ void tommy_array_init(tommy_array* array) array->count = 0; } -void tommy_array_done(tommy_array* array) +TOMMY_API void tommy_array_done(tommy_array* array) { tommy_uint_t i; @@ -55,7 +55,7 @@ void tommy_array_done(tommy_array* array) } } -void tommy_array_grow(tommy_array* array, tommy_size_t count) +TOMMY_API void tommy_array_grow(tommy_array* array, tommy_size_t count) { if (array->count >= count) return; @@ -76,7 +76,7 @@ void tommy_array_grow(tommy_array* array, tommy_size_t count) } } -tommy_size_t tommy_array_memory_usage(tommy_array* array) +TOMMY_API tommy_size_t tommy_array_memory_usage(tommy_array* array) { return array->bucket_max * (tommy_size_t)sizeof(void*); } diff --git a/tommyds/tommyarray.h b/tommyds/tommyarray.h index bc124de9..91398749 100644 --- a/tommyds/tommyarray.h +++ b/tommyds/tommyarray.h @@ -26,12 +26,12 @@ */ /** \file - * Dynamic array based on segments of exponential growing size. + * Dynamic array based on segments of exponentially growing size. * * This array is able to grow dynamically upon request, without any reallocation. * * The grow operation involves an allocation of a new array segment, without reallocating - * the already used memory, and then not increasing the heap fragmentation. + * the already used memory, and thus **not increasing** the heap fragmentation. * This also implies that the address of the stored elements never change. * * Allocated segments grow in size exponentially. @@ -67,18 +67,18 @@ typedef struct tommy_array_struct { /** * Initializes the array. */ -void tommy_array_init(tommy_array* array); +TOMMY_API void tommy_array_init(tommy_array* array); /** * Deinitializes the array. */ -void tommy_array_done(tommy_array* array); +TOMMY_API void tommy_array_done(tommy_array* array); /** * Grows the size up to the specified value. * All the new elements in the array are initialized with the 0 value. */ -void tommy_array_grow(tommy_array* array, tommy_size_t size); +TOMMY_API void tommy_array_grow(tommy_array* array, tommy_size_t size); /** * Gets a reference of the element at the specified position. @@ -140,7 +140,6 @@ tommy_inline tommy_size_t tommy_array_size(tommy_array* array) /** * Gets the size of allocated memory. */ -tommy_size_t tommy_array_memory_usage(tommy_array* array); +TOMMY_API tommy_size_t tommy_array_memory_usage(tommy_array* array); #endif - diff --git a/tommyds/tommyarrayblkof.c b/tommyds/tommyarrayblkof.c index 11187bea..2882c827 100644 --- a/tommyds/tommyarrayblkof.c +++ b/tommyds/tommyarrayblkof.c @@ -30,7 +30,7 @@ /******************************************************************************/ /* array */ -void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size) +TOMMY_API void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size) { tommy_array_init(&array->block); @@ -38,7 +38,7 @@ void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size) array->count = 0; } -void tommy_arrayblkof_done(tommy_arrayblkof* array) +TOMMY_API void tommy_arrayblkof_done(tommy_arrayblkof* array) { tommy_size_t i; @@ -48,7 +48,7 @@ void tommy_arrayblkof_done(tommy_arrayblkof* array) tommy_array_done(&array->block); } -void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_size_t count) +TOMMY_API void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_size_t count) { tommy_size_t block_max; tommy_size_t block_mac; @@ -76,7 +76,7 @@ void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_size_t count) } } -tommy_size_t tommy_arrayblkof_memory_usage(tommy_arrayblkof* array) +TOMMY_API tommy_size_t tommy_arrayblkof_memory_usage(tommy_arrayblkof* array) { return tommy_array_memory_usage(&array->block) + tommy_array_size(&array->block) * TOMMY_ARRAYBLKOF_SIZE * array->element_size; } diff --git a/tommyds/tommyarrayblkof.h b/tommyds/tommyarrayblkof.h index 16d70cbf..30e9cccf 100644 --- a/tommyds/tommyarrayblkof.h +++ b/tommyds/tommyarrayblkof.h @@ -30,7 +30,7 @@ * * This array is able to grow dynamically upon request, without any reallocation. * - * This is very similar at ::tommy_arrayblk, but it allows to store elements of any + * This is very similar to ::tommy_arrayblk, but it allows to store elements of any * size and not just pointers. * * Note that in this case tommy_arrayblkof_ref() returns a pointer to the element, @@ -68,18 +68,18 @@ typedef struct tommy_arrayblkof_struct { * Initializes the array. * \param element_size Size in byte of the element to store in the array. */ -void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size); +TOMMY_API void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size); /** * Deinitializes the array. */ -void tommy_arrayblkof_done(tommy_arrayblkof* array); +TOMMY_API void tommy_arrayblkof_done(tommy_arrayblkof* array); /** * Grows the size up to the specified value. * All the new elements in the array are initialized with the 0 value. */ -void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_size_t size); +TOMMY_API void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_size_t size); /** * Gets a reference of the element at the specified position. @@ -108,7 +108,6 @@ tommy_inline tommy_size_t tommy_arrayblkof_size(tommy_arrayblkof* array) /** * Gets the size of allocated memory. */ -tommy_size_t tommy_arrayblkof_memory_usage(tommy_arrayblkof* array); +TOMMY_API tommy_size_t tommy_arrayblkof_memory_usage(tommy_arrayblkof* array); #endif - diff --git a/tommyds/tommychain.h b/tommyds/tommychain.h index 4ff3f1a3..d199b2b5 100644 --- a/tommyds/tommychain.h +++ b/tommyds/tommychain.h @@ -27,7 +27,7 @@ /** \file * Chain of nodes. - * A chain of nodes is an abstraction used to implements complex list operations + * A chain of nodes is an abstraction used to implement complex list operations * like sorting. * * Do not use this directly. Use lists instead. @@ -44,7 +44,7 @@ /** * Chain of nodes. * A chain of nodes is a sequence of nodes with the following properties: - * - It contains at least one node. A chains of zero nodes cannot exist. + * - It contains at least one node. A chain of zero nodes cannot exist. * - The next field of the tail is of *undefined* value. * - The prev field of the head is of *undefined* value. * - All the other inner prev and next fields are correctly set. @@ -56,6 +56,10 @@ typedef struct tommy_chain_struct { /** * Splices a chain in the middle of another chain. + * \param first_before Node before the splice point. + * \param first_after Node after the splice point. + * \param second_head Head of the chain to splice in. + * \param second_tail Tail of the chain to splice in. */ tommy_inline void tommy_chain_splice(tommy_node* first_before, tommy_node* first_after, tommy_node* second_head, tommy_node* second_tail) { @@ -69,7 +73,9 @@ tommy_inline void tommy_chain_splice(tommy_node* first_before, tommy_node* first } /** - * Concats two chains. + * Concatenates two chains. + * \param first_tail Tail of the first chain. + * \param second_head Head of the second chain. */ tommy_inline void tommy_chain_concat(tommy_node* first_tail, tommy_node* second_head) { @@ -82,6 +88,9 @@ tommy_inline void tommy_chain_concat(tommy_node* first_tail, tommy_node* second_ /** * Merges two chains. + * \param first First chain (will contain the result). + * \param second Second chain (will be empty after the merge). + * \param cmp Comparison function. */ tommy_inline void tommy_chain_merge(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) { @@ -114,7 +123,10 @@ tommy_inline void tommy_chain_merge(tommy_chain* first, tommy_chain* second, tom /** * Merges two chains managing special degenerated cases. - * It's functionally equivalent at tommy_chain_merge() but faster with already ordered chains. + * It's functionally equivalent to tommy_chain_merge() but faster with already ordered chains. + * \param first First chain (will contain the result). + * \param second Second chain (will be empty after the merge). + * \param cmp Comparison function. */ tommy_inline void tommy_chain_merge_degenerated(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) { @@ -139,7 +151,7 @@ tommy_inline void tommy_chain_merge_degenerated(tommy_chain* first, tommy_chain* /** * Sorts a chain. * It's a stable merge sort using power of 2 buckets, with O(N*log(N)) complexity, - * similar at the one used in the SGI STL libraries and in the Linux Kernel, + * similar to the one used in the SGI STL libraries and in the Linux Kernel, * but faster on degenerated cases like already ordered lists. * * SGI STL stl_list.h @@ -147,6 +159,9 @@ tommy_inline void tommy_chain_merge_degenerated(tommy_chain* first, tommy_chain* * * Linux Kernel lib/list_sort.c * http://lxr.linux.no/#linux+v2.6.36/lib/list_sort.c + * + * \param chain Chain to sort. + * \param cmp Comparison function. */ tommy_inline void tommy_chain_mergesort(tommy_chain* chain, tommy_compare_func* cmp) { @@ -160,7 +175,7 @@ tommy_inline void tommy_chain_mergesort(tommy_chain* chain, tommy_compare_func* /** * Value stored inside the bit bucket. - * It's used to know which bucket is empty of full. + * It's used to know which bucket is empty or full. */ tommy_size_t counter; tommy_node* node = chain->head; @@ -216,4 +231,3 @@ tommy_inline void tommy_chain_mergesort(tommy_chain* chain, tommy_compare_func* } #endif - diff --git a/tommyds/tommyhash.c b/tommyds/tommyhash.c index dd7546c5..ae9b26eb 100644 --- a/tommyds/tommyhash.c +++ b/tommyds/tommyhash.c @@ -30,16 +30,33 @@ /******************************************************************************/ /* hash */ +#include /* for memcpy */ + +/** + * Swap endianness. + * They are needed only if BigEndian. + */ +#if defined(__GNUC__) +#define tommy_swap32(x) __builtin_bswap32(x) +#else +tommy_inline tommy_uint32_t tommy_swap32(tommy_uint32_t v) +{ + return ((v & 0xFF000000) >> 24) | + ((v & 0x00FF0000) >> 8) | + ((v & 0x0000FF00) << 8) | + ((v & 0x000000FF) << 24); +} +#endif + tommy_inline tommy_uint32_t tommy_le_uint32_read(const void* ptr) { - /* allow unaligned read on Intel x86 and x86_64 platforms */ -#if defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__x86_64__) || defined(_M_X64) - /* defines from http://predef.sourceforge.net/ */ - return *(const tommy_uint32_t*)ptr; -#else - const unsigned char* ptr8 = tommy_cast(const unsigned char*, ptr); - return ptr8[0] + ((tommy_uint32_t)ptr8[1] << 8) + ((tommy_uint32_t)ptr8[2] << 16) + ((tommy_uint32_t)ptr8[3] << 24); + tommy_uint32_t v; + memcpy(&v, ptr, sizeof(v)); +#if defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + v = tommy_swap32(v); #endif + return v; } #define tommy_rot(x, k) \ @@ -66,7 +83,7 @@ tommy_inline tommy_uint32_t tommy_le_uint32_read(const void* ptr) c ^= b; c -= tommy_rot(b, 24); \ } while (0) -tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len) +TOMMY_API tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len) { const unsigned char* key = tommy_cast(const unsigned char*, void_key); tommy_uint32_t a, b, c; @@ -115,7 +132,7 @@ tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tom return c; } -tommy_uint64_t tommy_hash_u64(tommy_uint64_t init_val, const void* void_key, tommy_size_t key_len) +TOMMY_API tommy_uint64_t tommy_hash_u64(tommy_uint64_t init_val, const void* void_key, tommy_size_t key_len) { const unsigned char* key = tommy_cast(const unsigned char*, void_key); tommy_uint32_t a, b, c; @@ -165,7 +182,7 @@ tommy_uint64_t tommy_hash_u64(tommy_uint64_t init_val, const void* void_key, tom return c + ((tommy_uint64_t)b << 32); } -tommy_uint32_t tommy_strhash_u32(tommy_uint32_t init_val, const void* void_key) +TOMMY_API tommy_uint32_t tommy_strhash_u32(tommy_uint32_t init_val, const void* void_key) { const unsigned char* key = tommy_cast(const unsigned char*, void_key); tommy_uint32_t a, b, c; diff --git a/tommyds/tommyhash.h b/tommyds/tommyhash.h index 0715fbec..feea4db7 100644 --- a/tommyds/tommyhash.h +++ b/tommyds/tommyhash.h @@ -42,7 +42,7 @@ * Implementation of the Robert Jenkins "lookup3" hash 32 bits version, * from http://www.burtleburtle.net/bob/hash/doobs.html, function hashlittle(). * - * This hash is designed to provide a good overall performance in all platforms, + * This hash is designed to provide a good overall performance on all platforms, * including 32 bits. If you target only 64 bits, you can use faster hashes, * like SpookyHash or FarmHash. * @@ -55,14 +55,14 @@ * This function is endianness independent. * \return The hash value of 32 bits. */ -tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len); +TOMMY_API tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len); /** * Hash function with a 64 bits result. - * Implementation of the Robert Jenkins "lookup3" hash 64 bits versions, + * Implementation of the Robert Jenkins "lookup3" hash 64 bits version, * from http://www.burtleburtle.net/bob/hash/doobs.html, function hashlittle2(). * - * This hash is designed to provide a good overall performance in all platforms, + * This hash is designed to provide a good overall performance on all platforms, * including 32 bits. If you target only 64 bits, you can use faster hashes, * like SpookyHash or FarmHash. * @@ -75,7 +75,7 @@ tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tom * This function is endianness independent. * \return The hash value of 64 bits. */ -tommy_uint64_t tommy_hash_u64(tommy_uint64_t init_val, const void* void_key, tommy_size_t key_len); +TOMMY_API tommy_uint64_t tommy_hash_u64(tommy_uint64_t init_val, const void* void_key, tommy_size_t key_len); /** * String hash function with a 32 bits result. @@ -93,7 +93,7 @@ tommy_uint64_t tommy_hash_u64(tommy_uint64_t init_val, const void* void_key, tom * This function is endianness independent. * \return The hash value of 32 bits. */ -tommy_uint32_t tommy_strhash_u32(tommy_uint32_t init_val, const void* void_key); +TOMMY_API tommy_uint32_t tommy_strhash_u32(tommy_uint32_t init_val, const void* void_key); /** * Integer reversible hash function for 32 bits. @@ -132,4 +132,3 @@ tommy_inline tommy_uint64_t tommy_inthash_u64(tommy_uint64_t key) } #endif - diff --git a/tommyds/tommyhashdyn.c b/tommyds/tommyhashdyn.c index a00737e7..75565c8d 100644 --- a/tommyds/tommyhashdyn.c +++ b/tommyds/tommyhashdyn.c @@ -31,7 +31,7 @@ /******************************************************************************/ /* hashdyn */ -void tommy_hashdyn_init(tommy_hashdyn* hashdyn) +TOMMY_API void tommy_hashdyn_init(tommy_hashdyn* hashdyn) { /* fixed initial size */ hashdyn->bucket_bit = TOMMY_HASHDYN_BIT; @@ -42,7 +42,7 @@ void tommy_hashdyn_init(tommy_hashdyn* hashdyn) hashdyn->count = 0; } -void tommy_hashdyn_done(tommy_hashdyn* hashdyn) +TOMMY_API void tommy_hashdyn_done(tommy_hashdyn* hashdyn) { tommy_free(hashdyn->bucket); } @@ -50,7 +50,7 @@ void tommy_hashdyn_done(tommy_hashdyn* hashdyn) /** * Resize the bucket vector. */ -static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, tommy_size_t new_bucket_bit) +static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, tommy_uint_t new_bucket_bit) { tommy_size_t bucket_bit; tommy_size_t bucket_max; @@ -134,7 +134,7 @@ tommy_inline void hashdyn_shrink_step(tommy_hashdyn* hashdyn) tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit - 1); } -void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash) +TOMMY_API void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash) { tommy_size_t pos = hash & hashdyn->bucket_mask; @@ -147,7 +147,7 @@ void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void hashdyn_grow_step(hashdyn); } -void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node) +TOMMY_API void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node) { tommy_size_t pos = node->index & hashdyn->bucket_mask; @@ -160,7 +160,7 @@ void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* return node->data; } -void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash) +TOMMY_API void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash) { tommy_size_t pos = hash & hashdyn->bucket_mask; tommy_hashdyn_node* node = hashdyn->bucket[pos]; @@ -182,7 +182,7 @@ void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const return 0; } -void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func) +TOMMY_API void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func) { tommy_size_t bucket_max = hashdyn->bucket_max; tommy_hashdyn_node** bucket = hashdyn->bucket; @@ -199,7 +199,7 @@ void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func) } } -void tommy_hashdyn_foreach_arg(tommy_hashdyn* hashdyn, tommy_foreach_arg_func* func, void* arg) +TOMMY_API void tommy_hashdyn_foreach_arg(tommy_hashdyn* hashdyn, tommy_foreach_arg_func* func, void* arg) { tommy_size_t bucket_max = hashdyn->bucket_max; tommy_hashdyn_node** bucket = hashdyn->bucket; @@ -216,7 +216,7 @@ void tommy_hashdyn_foreach_arg(tommy_hashdyn* hashdyn, tommy_foreach_arg_func* f } } -tommy_size_t tommy_hashdyn_memory_usage(tommy_hashdyn* hashdyn) +TOMMY_API tommy_size_t tommy_hashdyn_memory_usage(tommy_hashdyn* hashdyn) { return hashdyn->bucket_max * (tommy_size_t)sizeof(hashdyn->bucket[0]) + tommy_hashdyn_count(hashdyn) * (tommy_size_t)sizeof(tommy_hashdyn_node); diff --git a/tommyds/tommyhashdyn.h b/tommyds/tommyhashdyn.h index 5a8c125f..3387565a 100644 --- a/tommyds/tommyhashdyn.h +++ b/tommyds/tommyhashdyn.h @@ -29,8 +29,8 @@ * Dynamic chained hashtable. * * This hashtable resizes dynamically. It starts with the minimal size of 16 buckets, it doubles - * the size then it reaches a load factor greater than 0.5 and it halves the size with a load - * factor lower than 0.125. + * the size when it reaches a load factor greater than 0.5 and it halves the size when the load + * factor is lower than 0.125. * * All the elements are reallocated in a single resize operation done inside * tommy_hashdyn_insert() or tommy_hashdyn_remove(). @@ -38,15 +38,15 @@ * Note that the resize operation takes approximately 100 [ms] with 1 million of elements, * and 1 [second] with 10 millions. This could be a problem in real-time applications. * - * The resize also fragment the heap, as it involves allocating a double-sized table, copy elements, - * and deallocating the older table. Leaving a big hole in the heap. + * The resize also **fragments** the heap, as it involves allocating a double-sized table, **copying** elements, + * and deallocating the older table, **leaving** a big hole in the heap. * * The ::tommy_hashlin hashtable fixes both problems. * * To initialize the hashtable you have to call tommy_hashdyn_init(). * * \code - * tommy_hashslin hashdyn; + * tommy_hashdyn hashdyn; * * tommy_hashdyn_init(&hashdyn); * \endcode @@ -72,7 +72,7 @@ * tommy_hashdyn_insert(&hashdyn, &obj->node, obj, tommy_inthash_u32(obj->value)); // inserts the object * \endcode * - * To find and element in the hashtable you have to call tommy_hashtable_search() + * To find an element in the hashtable you have to call tommy_hashtable_search() * providing a comparison function, its argument, and the hash of the key to search. * * \code @@ -92,7 +92,7 @@ * * To iterate over all the elements in the hashtable with the same key, you have to * use tommy_hashdyn_bucket() and follow the tommy_node::next pointer until NULL. - * You have also to check explicitly for the key, as the bucket may contains + * You have also to check explicitly for the key, as the bucket may contain * different keys. * * \code @@ -169,7 +169,7 @@ typedef struct tommy_hashdyn_struct { /** * Initializes the hashtable. */ -void tommy_hashdyn_init(tommy_hashdyn* hashdyn); +TOMMY_API void tommy_hashdyn_init(tommy_hashdyn* hashdyn); /** * Deinitializes the hashtable. @@ -177,12 +177,12 @@ void tommy_hashdyn_init(tommy_hashdyn* hashdyn); * You can call this function with elements still contained, * but such elements are not going to be freed by this call. */ -void tommy_hashdyn_done(tommy_hashdyn* hashdyn); +TOMMY_API void tommy_hashdyn_done(tommy_hashdyn* hashdyn); /** * Inserts an element in the hashtable. */ -void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash); +TOMMY_API void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash); /** * Searches and removes an element from the hashtable. @@ -195,7 +195,7 @@ void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void * \param hash Hash of the element to find and remove. * \return The removed element, or 0 if not found. */ -void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash); +TOMMY_API void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash); /** * Gets the bucket of the specified hash. @@ -225,7 +225,7 @@ tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_fun tommy_hashdyn_node* i = tommy_hashdyn_bucket(hashdyn, hash); while (i) { - /* we first check if the hash matches, as in the same bucket we may have multiples hash values */ + /* we first check if the hash matches, as in the same bucket we may have multiple hash values */ if (i->index == hash && cmp(cmp_arg, i->data) == 0) return i->data; i = i->next; @@ -238,7 +238,7 @@ tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_fun * You must already have the address of the element to remove. * \return The tommy_node::data field of the node removed. */ -void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node); +TOMMY_API void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node); /** * Calls the specified function for each element in the hashtable. @@ -271,12 +271,12 @@ void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* * tommy_hashdyn_done(&hashdyn); * \endcode */ -void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func); +TOMMY_API void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func); /** * Calls the specified function with an argument for each element in the hashtable. */ -void tommy_hashdyn_foreach_arg(tommy_hashdyn* hashdyn, tommy_foreach_arg_func* func, void* arg); +TOMMY_API void tommy_hashdyn_foreach_arg(tommy_hashdyn* hashdyn, tommy_foreach_arg_func* func, void* arg); /** * Gets the number of elements. @@ -290,7 +290,6 @@ tommy_inline tommy_size_t tommy_hashdyn_count(tommy_hashdyn* hashdyn) * Gets the size of allocated memory. * It includes the size of the ::tommy_hashdyn_node of the stored elements. */ -tommy_size_t tommy_hashdyn_memory_usage(tommy_hashdyn* hashdyn); +TOMMY_API tommy_size_t tommy_hashdyn_memory_usage(tommy_hashdyn* hashdyn); #endif - diff --git a/tommyds/tommylist.c b/tommyds/tommylist.c index 1fa1f243..d758c615 100644 --- a/tommyds/tommylist.c +++ b/tommyds/tommylist.c @@ -38,7 +38,7 @@ tommy_inline void tommy_list_set(tommy_list* list, tommy_node* head, tommy_node* *list = head; } -void tommy_list_sort(tommy_list* list, tommy_compare_func* cmp) +TOMMY_API void tommy_list_sort(tommy_list* list, tommy_compare_func* cmp) { tommy_chain chain; tommy_node* head; diff --git a/tommyds/tommylist.h b/tommyds/tommylist.h index f70ad451..b359a89f 100644 --- a/tommyds/tommylist.h +++ b/tommyds/tommylist.h @@ -28,14 +28,14 @@ /** \file * Double linked list for collisions into hashtables. * - * This list is a double linked list mainly targeted for handling collisions - * into an hashtables, but useable also as a generic list. + * This list is a **doubly** linked list mainly targeted for handling collisions + * into an hashtable, but **usable** also as a generic list. * * The main feature of this list is to require only one pointer to represent the - * list, compared to a classic implementation requiring a head an a tail pointers. + * list, compared to a classic implementation requiring a head **and** a tail pointers. * This reduces the memory usage in hashtables. * - * Another feature is to support the insertion at the end of the list. This allow to store + * Another feature is to support the insertion at the end of the list. This **allows** to store * collisions in a stable order. Where for stable order we mean that equal elements keep * their insertion order. * @@ -103,7 +103,7 @@ /* list */ /** - * Double linked list type. + * Doubly linked list type. */ typedef tommy_node* tommy_list; @@ -156,7 +156,7 @@ tommy_inline void tommy_list_insert_first(tommy_list* list, tommy_node* node) } /** \internal - * Inserts an element at the head of a not empty list. + * Inserts an element at the head of a non-empty list. * The element is inserted at the head of the list. The list cannot be empty. * \param list The list. The list cannot be empty. * \param node The node to insert. @@ -176,7 +176,7 @@ tommy_inline void tommy_list_insert_head_not_empty(tommy_list* list, tommy_node* } /** \internal - * Inserts an element at the tail of a not empty list. + * Inserts an element at the tail of a non-empty list. * The element is inserted at the tail of the list. The list cannot be empty. * \param head The node at the list head. It cannot be 0. * \param node The node to insert. @@ -194,6 +194,7 @@ tommy_inline void tommy_list_insert_tail_not_empty(tommy_node* head, tommy_node* /** * Inserts an element at the head of a list. + * \param list The list. * \param node The node to insert. * \param data The object containing the node. It's used to set the tommy_node::data field of the node. */ @@ -211,6 +212,7 @@ tommy_inline void tommy_list_insert_head(tommy_list* list, tommy_node* node, voi /** * Inserts an element at the tail of a list. + * \param list The list. * \param node The node to insert. * \param data The object containing the node. It's used to set the tommy_node::data field of the node. */ @@ -230,7 +232,8 @@ tommy_inline void tommy_list_insert_tail(tommy_list* list, tommy_node* node, voi * Removes an element from the list. * You must already have the address of the element to remove. * \note The node content is left unchanged, including the tommy_node::next - * and tommy_node::prev fields that still contain pointers at the list. + * and tommy_node::prev fields that still contain pointers **in** the list. + * \param list The list. * \param node The node to remove. The node must be in the list. * \return The tommy_node::data field of the node removed. */ @@ -296,7 +299,7 @@ tommy_inline void tommy_list_concat(tommy_list* first, tommy_list* second) * \param cmp Compare function called with two elements. * The function should return <0 if the first element is less than the second, ==0 if equal, and >0 if greater. */ -void tommy_list_sort(tommy_list* list, tommy_compare_func* cmp); +TOMMY_API void tommy_list_sort(tommy_list* list, tommy_compare_func* cmp); /** * Checks if empty. @@ -378,4 +381,3 @@ tommy_inline void tommy_list_foreach_arg(tommy_list* list, tommy_foreach_arg_fun } #endif - diff --git a/tommyds/tommytree.c b/tommyds/tommytree.c index 8ef84783..a2cf728a 100644 --- a/tommyds/tommytree.c +++ b/tommyds/tommytree.c @@ -32,7 +32,7 @@ /******************************************************************************/ /* tree */ -void tommy_tree_init(tommy_tree* tree, tommy_compare_func* cmp) +TOMMY_API void tommy_tree_init(tommy_tree* tree, tommy_compare_func* cmp) { tree->root = 0; tree->count = 0; @@ -138,7 +138,7 @@ static tommy_tree_node* tommy_tree_insert_node(tommy_compare_func* cmp, tommy_tr return root; } -void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data) +TOMMY_API void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data) { tommy_tree_node* insert = node; @@ -180,7 +180,7 @@ static tommy_tree_node* tommy_tree_remove_node(tommy_compare_func* cmp, tommy_tr return tommy_tree_move_right(root->prev, root->next); } -void* tommy_tree_remove(tommy_tree* tree, void* data) +TOMMY_API void* tommy_tree_remove(tommy_tree* tree, void* data) { tommy_tree_node* node = 0; @@ -212,7 +212,7 @@ static tommy_tree_node* tommy_tree_search_node(tommy_compare_func* cmp, tommy_tr return root; } -void* tommy_tree_search(tommy_tree* tree, void* data) +TOMMY_API void* tommy_tree_search(tommy_tree* tree, void* data) { tommy_tree_node* node = tommy_tree_search_node(tree->cmp, tree->root, data); @@ -222,7 +222,7 @@ void* tommy_tree_search(tommy_tree* tree, void* data) return node->data; } -void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg) +TOMMY_API void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg) { tommy_tree_node* node = tommy_tree_search_node(cmp, tree->root, cmp_arg); @@ -232,7 +232,7 @@ void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* return node->data; } -void* tommy_tree_remove_existing(tommy_tree* tree, tommy_tree_node* node) +TOMMY_API void* tommy_tree_remove_existing(tommy_tree* tree, tommy_tree_node* node) { void* data = tommy_tree_remove(tree, node->data); @@ -258,7 +258,7 @@ static void tommy_tree_foreach_node(tommy_tree_node* root, tommy_foreach_func* f tommy_tree_foreach_node(next, func); } -void tommy_tree_foreach(tommy_tree* tree, tommy_foreach_func* func) +TOMMY_API void tommy_tree_foreach(tommy_tree* tree, tommy_foreach_func* func) { tommy_tree_foreach_node(tree->root, func); } @@ -280,12 +280,12 @@ static void tommy_tree_foreach_arg_node(tommy_tree_node* root, tommy_foreach_arg tommy_tree_foreach_arg_node(next, func, arg); } -void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void* arg) +TOMMY_API void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void* arg) { tommy_tree_foreach_arg_node(tree->root, func, arg); } -tommy_size_t tommy_tree_memory_usage(tommy_tree* tree) +TOMMY_API tommy_size_t tommy_tree_memory_usage(tommy_tree* tree) { return tommy_tree_count(tree) * sizeof(tommy_tree_node); } diff --git a/tommyds/tommytree.h b/tommyds/tommytree.h index e56f8658..c0bdb9c4 100644 --- a/tommyds/tommytree.h +++ b/tommyds/tommytree.h @@ -31,7 +31,7 @@ * This tree is a standard AVL tree implementation that stores elements in the * order defined by the comparison function. * - * As difference than other tommy containers, duplicate elements cannot be inserted. + * As a difference from other tommy containers, duplicate elements cannot be inserted. * * To initialize a tree you have to call tommy_tree_init() specifying a comparison * function that will define the order in the tree. @@ -63,7 +63,7 @@ * tommy_tree_insert(&tree, &obj->node, obj); // inserts the object * \endcode * - * To find and element in the tree you have to call tommy_tree_search() providing + * To find an element in the tree you have to call tommy_tree_search() providing * the key to search. * * \code @@ -94,7 +94,7 @@ * tommy_tree_foreach() or tommy_tree_foreach_arg(). * If you need a more precise control with a real iteration, you have to insert * all the elements also in a ::tommy_list, and use the list to iterate. - * See the \ref multiindex example for more detail. + * See the \ref multiindex example for more detail. */ #ifndef __TOMMYTREE_H @@ -125,7 +125,7 @@ typedef struct tommy_tree_struct { * Initializes the tree. * \param cmp The comparison function that defines the order in the tree. */ -void tommy_tree_init(tommy_tree* tree, tommy_compare_func* cmp); +TOMMY_API void tommy_tree_init(tommy_tree* tree, tommy_compare_func* cmp); /** * Inserts an element in the tree. @@ -137,7 +137,7 @@ void tommy_tree_init(tommy_tree* tree, tommy_compare_func* cmp); * \param data Pointer to the object to insert. * \return The element in the tree. Either the already existing one, or the one just inserted. */ -void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data); +TOMMY_API void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data); /** * Searches and removes an element. @@ -145,15 +145,15 @@ void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data); * \param data Element used for comparison. * \return The removed element, or 0 if not found. */ -void* tommy_tree_remove(tommy_tree* tree, void* data); +TOMMY_API void* tommy_tree_remove(tommy_tree* tree, void* data); /** * Searches an element in the tree. - * If the element is not found, 0 is returned. + * If the element is not found, 0 is returned. * \param data Element used for comparison. * \return The first element found, or 0 if none. */ -void* tommy_tree_search(tommy_tree* tree, void* data); +TOMMY_API void* tommy_tree_search(tommy_tree* tree, void* data); /** * Searches an element in the tree with a specific comparison function. @@ -162,16 +162,16 @@ void* tommy_tree_search(tommy_tree* tree, void* data); * Note that this function must define a suborder of the original one. * * The ::data argument will be the first argument of the comparison function, - * and it can be of a different type of the objects in the tree. + * and it can be of a different type than the objects in the tree. */ -void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg); +TOMMY_API void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg); /** * Removes an element from the tree. * You must already have the address of the element to remove. * \return The tommy_node::data field of the node removed. */ -void* tommy_tree_remove_existing(tommy_tree* tree, tommy_tree_node* node); +TOMMY_API void* tommy_tree_remove_existing(tommy_tree* tree, tommy_tree_node* node); /** * Calls the specified function for each element in the tree. @@ -203,12 +203,12 @@ void* tommy_tree_remove_existing(tommy_tree* tree, tommy_tree_node* node); * tommy_tree_foreach(&tree, free); * \endcode */ -void tommy_tree_foreach(tommy_tree* tree, tommy_foreach_func* func); +TOMMY_API void tommy_tree_foreach(tommy_tree* tree, tommy_foreach_func* func); /** * Calls the specified function with an argument for each element in the tree. */ -void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void* arg); +TOMMY_API void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void* arg); /** * Gets the number of elements. @@ -222,7 +222,6 @@ tommy_inline tommy_size_t tommy_tree_count(tommy_tree* tree) * Gets the size of allocated memory. * It includes the size of the ::tommy_tree_node of the stored elements. */ -tommy_size_t tommy_tree_memory_usage(tommy_tree* tree); +TOMMY_API tommy_size_t tommy_tree_memory_usage(tommy_tree* tree); #endif - diff --git a/tommyds/tommytypes.h b/tommyds/tommytypes.h index 8dc206b1..13bcb572 100644 --- a/tommyds/tommytypes.h +++ b/tommyds/tommytypes.h @@ -24,6 +24,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ + /** \file * Generic types. */ @@ -42,8 +43,8 @@ typedef unsigned _int64 tommy_uint64_t; /**< Generic uint64_t type. */ typedef size_t tommy_uintptr_t; /**< Generic uintptr_t type. */ #ifdef _WIN64 #define TOMMY_SIZE_BIT 64 -typedef unsigned _int64_t tommy_size_t; /**< Generic size_t type. */ -typedef _int64_t tommy_ssize_t; /**< Generic ssize_t type. */ +typedef unsigned _int64 tommy_size_t; /**< Generic size_t type. */ +typedef _int64 tommy_ssize_t; /**< Generic ssize_t type. */ #else #define TOMMY_SIZE_BIT 32 typedef unsigned tommy_size_t; /**< Generic size_t type. */ @@ -73,15 +74,22 @@ typedef int tommy_bool_t; /**< Generic boolean type. */ /** * Generic unsigned integer type. * - * It has no specific size, as is used to store only small values. + * It has no specific size, as it is used to store only small values. * To make the code more efficient, a full 32 bit integer is used. */ typedef tommy_uint32_t tommy_uint_t; /** \internal - * Type cast required for the C++ compilation. - * When compiling in C++ we cannot convert a void* pointer to another pointer. - * In such case we need an explicit cast. + * Explicit cast helper used to smooth out the difference between C and C++. + * + * In C, a void* can be assigned to any pointer type without an explicit cast. + * This is not allowed in C++, where converting a void* to another pointer type + * always requires an explicit cast. + * + * tommy_cast should be used only for this specific purpose, so it should be + * applied when converting a void* to a more specific pointer type in code that + * must compile as both C and C++. It is not intended for arbitrary pointer + * conversions or for casts that are unrelated to the C to C++ difference. */ #ifdef __cplusplus #define tommy_cast(type, value) static_cast(value) @@ -117,6 +125,14 @@ typedef tommy_uint32_t tommy_uint_t; /******************************************************************************/ /* modificators */ +/** \internal + * Definition of TOMMY_API. + * Provide the ability to override linkage features of the interface. + */ +#if !defined(TOMMY_API) +#define TOMMY_API +#endif + /** \internal * Definition of the inline keyword if available. */ @@ -167,12 +183,12 @@ typedef tommy_uint32_t tommy_uint_t; /* key/hash */ /** - * Type used in indexed data structures to store the key of a object. + * Type used in indexed data structures to store the key of an object. */ typedef tommy_size_t tommy_key_t; /** - * Type used in hashtables to store the hash of a object. + * Type used in hashtables to store the hash of an object. */ typedef tommy_size_t tommy_hash_t; @@ -227,7 +243,7 @@ typedef struct tommy_node_struct { * Compare function for elements. * \param obj_a Pointer to the first object to compare. * \param obj_b Pointer to the second object to compare. - * \return <0 if the first element is less than the second, ==0 equal, >0 if greater. + * \return <0 if the first element is less than the second, ==0 if equal, >0 if greater. * * This function is like the C strcmp(). * @@ -393,8 +409,8 @@ tommy_inline tommy_uint_t tommy_ilog2_u64(tommy_uint64_t value) #elif defined(__GNUC__) return __builtin_clzll(value) ^ 63; #else - uint32_t l = value & 0xFFFFFFFFU; - uint32_t h = value >> 32; + tommy_uint32_t l = value & 0xFFFFFFFFU; + tommy_uint32_t h = value >> 32; if (h) return tommy_ilog2_u32(h) + 32; else @@ -444,8 +460,8 @@ tommy_inline tommy_uint_t tommy_ctz_u64(tommy_uint64_t value) #elif defined(__GNUC__) return __builtin_ctzll(value); #else - uint32_t l = value & 0xFFFFFFFFU; - uint32_t h = value >> 32; + tommy_uint32_t l = value & 0xFFFFFFFFU; + tommy_uint32_t h = value >> 32; if (l) return tommy_ctz_u32(l); else @@ -515,4 +531,3 @@ tommy_inline int tommy_haszero_u32(tommy_uint32_t value) #endif #endif -