mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Updates to latest TommyDS version.
This commit is contained in:
parent
acb1bad9b0
commit
aff9f97d50
11 changed files with 188 additions and 117 deletions
|
|
@ -27,14 +27,12 @@
|
|||
|
||||
#include "tommyarray.h"
|
||||
|
||||
#include <stddef.h> /* for ptrdiff_t */
|
||||
|
||||
/******************************************************************************/
|
||||
/* array */
|
||||
|
||||
void tommy_array_init(tommy_array* array)
|
||||
{
|
||||
unsigned i;
|
||||
tommy_uint_t i;
|
||||
|
||||
/* fixed initial size */
|
||||
array->bucket_bit = TOMMY_ARRAY_BIT;
|
||||
|
|
@ -43,28 +41,27 @@ void tommy_array_init(tommy_array* array)
|
|||
for (i = 1; i < TOMMY_ARRAY_BIT; ++i)
|
||||
array->bucket[i] = array->bucket[0];
|
||||
|
||||
array->bucket_mac = TOMMY_ARRAY_BIT;
|
||||
array->size = 0;
|
||||
array->count = 0;
|
||||
}
|
||||
|
||||
void tommy_array_done(tommy_array* array)
|
||||
{
|
||||
unsigned i;
|
||||
tommy_uint_t i;
|
||||
|
||||
tommy_free(array->bucket[0]);
|
||||
for (i = TOMMY_ARRAY_BIT; i < array->bucket_mac; ++i) {
|
||||
for (i = TOMMY_ARRAY_BIT; i < array->bucket_bit; ++i) {
|
||||
void** segment = array->bucket[i];
|
||||
tommy_free(&segment[1 << i]);
|
||||
tommy_free(&segment[((tommy_ptrdiff_t)1) << i]);
|
||||
}
|
||||
}
|
||||
|
||||
void tommy_array_grow(tommy_array* array, unsigned size)
|
||||
void tommy_array_grow(tommy_array* array, tommy_count_t count)
|
||||
{
|
||||
if (array->size >= size)
|
||||
if (array->count >= count)
|
||||
return;
|
||||
array->size = size;
|
||||
array->count = count;
|
||||
|
||||
while (size > array->bucket_max) {
|
||||
while (count > array->bucket_max) {
|
||||
void** segment;
|
||||
|
||||
/* allocate one more segment */
|
||||
|
|
@ -72,9 +69,8 @@ void tommy_array_grow(tommy_array* array, unsigned size)
|
|||
|
||||
/* store it adjusting the offset */
|
||||
/* cast to ptrdiff_t to ensure to get a negative value */
|
||||
array->bucket[array->bucket_mac] = &segment[-(ptrdiff_t)array->bucket_max];
|
||||
array->bucket[array->bucket_bit] = &segment[-(tommy_ptrdiff_t)array->bucket_max];
|
||||
|
||||
++array->bucket_mac;
|
||||
++array->bucket_bit;
|
||||
array->bucket_max = 1 << array->bucket_bit;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@
|
|||
/** \file
|
||||
* Dynamic array based on segments of exponential growing size.
|
||||
*
|
||||
* This array is able to grow dynamically upon request.
|
||||
* This array is able to grow dynamically upon request, without any reallocation.
|
||||
*
|
||||
* The resize involve an allocation of a new array segment, without reallocating
|
||||
* the already allocated memory, and then not increasing the heap fragmentation.
|
||||
* This means that the address of the allocated segments never change.
|
||||
* The grow operation involves an allocation of a new array segment, without reallocating
|
||||
* the already used memory, and then not increasing the heap fragmentation.
|
||||
* This also implies that the address of the stored elements never change.
|
||||
*
|
||||
* Allocated segments grow in size exponentially.
|
||||
*/
|
||||
|
|
@ -59,14 +59,14 @@
|
|||
#define TOMMY_ARRAY_BIT_MAX 32
|
||||
|
||||
/**
|
||||
* Array.
|
||||
* Array container type.
|
||||
* \note Don't use internal fields directly, but access the container only using functions.
|
||||
*/
|
||||
typedef struct tommy_array_struct {
|
||||
void** bucket[TOMMY_ARRAY_BIT_MAX]; /**< Dynamic array of buckets. */
|
||||
unsigned bucket_bit; /**< Bits used in the bit mask. */
|
||||
unsigned bucket_max; /**< Number of buckets. */
|
||||
unsigned bucket_mac; /**< Number of vectors allocated. */
|
||||
unsigned size; /**< Currently allocated and initialized size. */
|
||||
tommy_uint_t bucket_bit; /**< Bits used in the bit mask. */
|
||||
tommy_count_t bucket_max; /**< Number of buckets. */
|
||||
tommy_count_t count; /**< Number of initialized elements in the array. */
|
||||
} tommy_array;
|
||||
|
||||
/**
|
||||
|
|
@ -80,21 +80,21 @@ void tommy_array_init(tommy_array* array);
|
|||
void tommy_array_done(tommy_array* array);
|
||||
|
||||
/**
|
||||
* Grow the size up to the specified value.
|
||||
* 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, unsigned size);
|
||||
void tommy_array_grow(tommy_array* array, tommy_count_t size);
|
||||
|
||||
/**
|
||||
* Gets a reference of the element at the specified position.
|
||||
* You must be sure that space for this position is already
|
||||
* allocated calling tommy_array_grow().
|
||||
*/
|
||||
tommy_inline void** tommy_array_ref(tommy_array* array, unsigned pos)
|
||||
tommy_inline void** tommy_array_ref(tommy_array* array, tommy_count_t pos)
|
||||
{
|
||||
unsigned bsr;
|
||||
tommy_uint_t bsr;
|
||||
|
||||
assert(pos < array->size);
|
||||
assert(pos < array->count);
|
||||
|
||||
/* get the highest bit set, in case of all 0, return 0 */
|
||||
bsr = tommy_ilog2_u32(pos | 1);
|
||||
|
|
@ -107,7 +107,7 @@ tommy_inline void** tommy_array_ref(tommy_array* array, unsigned pos)
|
|||
* You must be sure that space for this position is already
|
||||
* allocated calling tommy_array_grow().
|
||||
*/
|
||||
tommy_inline void tommy_array_set(tommy_array* array, unsigned pos, void* element)
|
||||
tommy_inline void tommy_array_set(tommy_array* array, tommy_count_t pos, void* element)
|
||||
{
|
||||
*tommy_array_ref(array, pos) = element;
|
||||
}
|
||||
|
|
@ -117,7 +117,7 @@ tommy_inline void tommy_array_set(tommy_array* array, unsigned pos, void* elemen
|
|||
* You must be sure that space for this position is already
|
||||
* allocated calling tommy_array_grow().
|
||||
*/
|
||||
tommy_inline void* tommy_array_get(tommy_array* array, unsigned pos)
|
||||
tommy_inline void* tommy_array_get(tommy_array* array, tommy_count_t pos)
|
||||
{
|
||||
return *tommy_array_ref(array, pos);
|
||||
}
|
||||
|
|
@ -127,7 +127,7 @@ tommy_inline void* tommy_array_get(tommy_array* array, unsigned pos)
|
|||
*/
|
||||
tommy_inline void tommy_array_insert(tommy_array* array, void* element)
|
||||
{
|
||||
unsigned pos = array->size;
|
||||
tommy_count_t pos = array->count;
|
||||
|
||||
tommy_array_grow(array, pos + 1);
|
||||
|
||||
|
|
@ -137,9 +137,9 @@ tommy_inline void tommy_array_insert(tommy_array* array, void* element)
|
|||
/**
|
||||
* Gets the initialized size of the array.
|
||||
*/
|
||||
tommy_inline unsigned tommy_array_size(tommy_array* array)
|
||||
tommy_inline tommy_count_t tommy_array_size(tommy_array* array)
|
||||
{
|
||||
return array->size;
|
||||
return array->count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -34,12 +34,12 @@ void tommy_arrayblk_init(tommy_arrayblk* array)
|
|||
{
|
||||
tommy_array_init(&array->block);
|
||||
|
||||
array->size = 0;
|
||||
array->count = 0;
|
||||
}
|
||||
|
||||
void tommy_arrayblk_done(tommy_arrayblk* array)
|
||||
{
|
||||
unsigned i;
|
||||
tommy_count_t i;
|
||||
|
||||
for (i = 0; i < tommy_array_size(&array->block); ++i)
|
||||
tommy_free(tommy_array_get(&array->block, i));
|
||||
|
|
@ -47,16 +47,16 @@ void tommy_arrayblk_done(tommy_arrayblk* array)
|
|||
tommy_array_done(&array->block);
|
||||
}
|
||||
|
||||
void tommy_arrayblk_grow(tommy_arrayblk* array, unsigned size)
|
||||
void tommy_arrayblk_grow(tommy_arrayblk* array, tommy_count_t count)
|
||||
{
|
||||
unsigned block_max;
|
||||
unsigned block_mac;
|
||||
tommy_count_t block_max;
|
||||
tommy_count_t block_mac;
|
||||
|
||||
if (array->size >= size)
|
||||
if (array->count >= count)
|
||||
return;
|
||||
array->size = size;
|
||||
array->count = count;
|
||||
|
||||
block_max = (size + TOMMY_ARRAYBLK_SIZE - 1) / TOMMY_ARRAYBLK_SIZE;
|
||||
block_max = (count + TOMMY_ARRAYBLK_SIZE - 1) / TOMMY_ARRAYBLK_SIZE;
|
||||
block_mac = tommy_array_size(&array->block);
|
||||
|
||||
if (block_mac < block_max) {
|
||||
|
|
|
|||
|
|
@ -26,16 +26,16 @@
|
|||
*/
|
||||
|
||||
/** \file
|
||||
* Dynamic array based on blocks of fixed sizes.
|
||||
* Dynamic array based on blocks of fixed size.
|
||||
*
|
||||
* This array is able to grow dynamically upon request.
|
||||
* This array is able to grow dynamically upon request, without any reallocation.
|
||||
*
|
||||
* The resize involve an allocation of a new array block, without reallocating
|
||||
* the already allocated memory, and then not increasing the heap fragmentation,
|
||||
* The grow operation involves an allocation of a new array block, without reallocating
|
||||
* the already used memory, and then not increasing the heap fragmentation,
|
||||
* and minimize the space occupation.
|
||||
* This means that the address of the allocated blocks never change.
|
||||
* This also implies that the address of the stored elements never change.
|
||||
*
|
||||
* Allocated blocks are always of the same fixed size of 64 Ki pointers.
|
||||
* Allocated blocks are always of the same fixed size of 4 Ki pointers.
|
||||
*/
|
||||
|
||||
#ifndef __TOMMYARRAYBLK_H
|
||||
|
|
@ -55,11 +55,12 @@
|
|||
#define TOMMY_ARRAYBLK_SIZE (4 * 1024)
|
||||
|
||||
/**
|
||||
* Array.
|
||||
* Array container type.
|
||||
* \note Don't use internal fields directly, but access the container only using functions.
|
||||
*/
|
||||
typedef struct tommy_arrayblk_struct {
|
||||
tommy_array block; /**< Array of blocks. */
|
||||
unsigned size; /**< Currently allocated and initialized size. */
|
||||
tommy_count_t count; /**< Number of initialized elements in the array. */
|
||||
} tommy_arrayblk;
|
||||
|
||||
/**
|
||||
|
|
@ -73,21 +74,21 @@ void tommy_arrayblk_init(tommy_arrayblk* array);
|
|||
void tommy_arrayblk_done(tommy_arrayblk* array);
|
||||
|
||||
/**
|
||||
* Grow the size up to the specified value.
|
||||
* Grows the size up to the specified value.
|
||||
* All the new elements in the array are initialized with the 0 value.
|
||||
*/
|
||||
void tommy_arrayblk_grow(tommy_arrayblk* array, unsigned size);
|
||||
void tommy_arrayblk_grow(tommy_arrayblk* array, tommy_count_t size);
|
||||
|
||||
/**
|
||||
* Gets a reference of the element at the specified position.
|
||||
* You must be sure that space for this position is already
|
||||
* allocated calling tommy_arrayblk_grow().
|
||||
*/
|
||||
tommy_inline void** tommy_arrayblk_ref(tommy_arrayblk* array, unsigned pos)
|
||||
tommy_inline void** tommy_arrayblk_ref(tommy_arrayblk* array, tommy_count_t pos)
|
||||
{
|
||||
void** ptr;
|
||||
|
||||
assert(pos < array->size);
|
||||
assert(pos < array->count);
|
||||
|
||||
ptr = tommy_cast(void**, tommy_array_get(&array->block, pos / TOMMY_ARRAYBLK_SIZE));
|
||||
|
||||
|
|
@ -99,7 +100,7 @@ tommy_inline void** tommy_arrayblk_ref(tommy_arrayblk* array, unsigned pos)
|
|||
* You must be sure that space for this position is already
|
||||
* allocated calling tommy_arrayblk_grow().
|
||||
*/
|
||||
tommy_inline void tommy_arrayblk_set(tommy_arrayblk* array, unsigned pos, void* element)
|
||||
tommy_inline void tommy_arrayblk_set(tommy_arrayblk* array, tommy_count_t pos, void* element)
|
||||
{
|
||||
*tommy_arrayblk_ref(array, pos) = element;
|
||||
}
|
||||
|
|
@ -109,7 +110,7 @@ tommy_inline void tommy_arrayblk_set(tommy_arrayblk* array, unsigned pos, void*
|
|||
* You must be sure that space for this position is already
|
||||
* allocated calling tommy_arrayblk_grow().
|
||||
*/
|
||||
tommy_inline void* tommy_arrayblk_get(tommy_arrayblk* array, unsigned pos)
|
||||
tommy_inline void* tommy_arrayblk_get(tommy_arrayblk* array, tommy_count_t pos)
|
||||
{
|
||||
return *tommy_arrayblk_ref(array, pos);
|
||||
}
|
||||
|
|
@ -119,7 +120,7 @@ tommy_inline void* tommy_arrayblk_get(tommy_arrayblk* array, unsigned pos)
|
|||
*/
|
||||
tommy_inline void tommy_arrayblk_insert(tommy_arrayblk* array, void* element)
|
||||
{
|
||||
unsigned pos = array->size;
|
||||
tommy_count_t pos = array->count;
|
||||
|
||||
tommy_arrayblk_grow(array, pos + 1);
|
||||
|
||||
|
|
@ -129,9 +130,9 @@ tommy_inline void tommy_arrayblk_insert(tommy_arrayblk* array, void* element)
|
|||
/**
|
||||
* Gets the initialized size of the array.
|
||||
*/
|
||||
tommy_inline unsigned tommy_arrayblk_size(tommy_arrayblk* array)
|
||||
tommy_inline tommy_count_t tommy_arrayblk_size(tommy_arrayblk* array)
|
||||
{
|
||||
return array->size;
|
||||
return array->count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -30,16 +30,17 @@
|
|||
/******************************************************************************/
|
||||
/* array */
|
||||
|
||||
void tommy_arrayblkof_init(tommy_arrayblkof* array, unsigned element_size)
|
||||
void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size)
|
||||
{
|
||||
tommy_array_init(&array->block);
|
||||
|
||||
array->element_size = element_size;
|
||||
array->size = 0;
|
||||
array->count = 0;
|
||||
}
|
||||
|
||||
void tommy_arrayblkof_done(tommy_arrayblkof* array)
|
||||
{
|
||||
unsigned i;
|
||||
tommy_count_t i;
|
||||
|
||||
for (i = 0; i < tommy_array_size(&array->block); ++i)
|
||||
tommy_free(tommy_array_get(&array->block, i));
|
||||
|
|
@ -47,16 +48,16 @@ void tommy_arrayblkof_done(tommy_arrayblkof* array)
|
|||
tommy_array_done(&array->block);
|
||||
}
|
||||
|
||||
void tommy_arrayblkof_grow(tommy_arrayblkof* array, unsigned size)
|
||||
void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_count_t count)
|
||||
{
|
||||
unsigned block_max;
|
||||
unsigned block_mac;
|
||||
tommy_count_t block_max;
|
||||
tommy_count_t block_mac;
|
||||
|
||||
if (array->size >= size)
|
||||
if (array->count >= count)
|
||||
return;
|
||||
array->size = size;
|
||||
array->count = count;
|
||||
|
||||
block_max = (size + TOMMY_ARRAYBLK_SIZE - 1) / TOMMY_ARRAYBLK_SIZE;
|
||||
block_max = (count + TOMMY_ARRAYBLK_SIZE - 1) / TOMMY_ARRAYBLK_SIZE;
|
||||
block_mac = tommy_array_size(&array->block);
|
||||
|
||||
if (block_mac < block_max) {
|
||||
|
|
|
|||
|
|
@ -26,15 +26,16 @@
|
|||
*/
|
||||
|
||||
/** \file
|
||||
* Dynamic array based on blocks of fixed sizes.
|
||||
* Dynamic array based on blocks of fixed size.
|
||||
*
|
||||
* This array is able to grow dynamically upon request.
|
||||
* 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
|
||||
* size and not just pointers.
|
||||
*
|
||||
* Note that in this case tommy_arrayblkof_ref() returns a pointer at the element,
|
||||
* and it should be used for both get() and set() operation.
|
||||
* that should be used for getting and setting elements in the array,
|
||||
* as generic getter and setter are not available.
|
||||
*/
|
||||
|
||||
#ifndef __TOMMYARRAYBLKOF_H
|
||||
|
|
@ -54,19 +55,20 @@
|
|||
#define TOMMY_ARRAYBLKOF_SIZE (4 * 1024)
|
||||
|
||||
/**
|
||||
* Array.
|
||||
* Array container type.
|
||||
* \note Don't use internal fields directly, but access the container only using functions.
|
||||
*/
|
||||
typedef struct tommy_arrayblkof_struct {
|
||||
tommy_array block; /**< Array of blocks. */
|
||||
unsigned element_size; /**< Size of the stored element in bytes. */
|
||||
unsigned size; /**< Currently allocated and initialized size. */
|
||||
tommy_size_t element_size; /**< Size of the stored element in bytes. */
|
||||
tommy_count_t count; /**< Number of initialized elements in the array. */
|
||||
} tommy_arrayblkof;
|
||||
|
||||
/**
|
||||
* Initializes the array.
|
||||
* \param element_size Size in byte of the element to store in the array.
|
||||
*/
|
||||
void tommy_arrayblkof_init(tommy_arrayblkof* array, unsigned element_size);
|
||||
void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size);
|
||||
|
||||
/**
|
||||
* Deinitializes the array.
|
||||
|
|
@ -74,21 +76,21 @@ void tommy_arrayblkof_init(tommy_arrayblkof* array, unsigned element_size);
|
|||
void tommy_arrayblkof_done(tommy_arrayblkof* array);
|
||||
|
||||
/**
|
||||
* Grow the size up to the specified value.
|
||||
* 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, unsigned size);
|
||||
void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_count_t size);
|
||||
|
||||
/**
|
||||
* Gets a reference of the element at the specified position.
|
||||
* You must be sure that space for this position is already
|
||||
* allocated calling tommy_arrayblkof_grow().
|
||||
*/
|
||||
tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, unsigned pos)
|
||||
tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, tommy_count_t pos)
|
||||
{
|
||||
unsigned char* base;
|
||||
|
||||
assert(pos < array->size);
|
||||
assert(pos < array->count);
|
||||
|
||||
base = tommy_cast(unsigned char*, tommy_array_get(&array->block, pos / TOMMY_ARRAYBLKOF_SIZE));
|
||||
|
||||
|
|
@ -98,9 +100,9 @@ tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, unsigned pos)
|
|||
/**
|
||||
* Gets the initialized size of the array.
|
||||
*/
|
||||
tommy_inline unsigned tommy_arrayblkof_size(tommy_arrayblkof* array)
|
||||
tommy_inline tommy_count_t tommy_arrayblkof_size(tommy_arrayblkof* array)
|
||||
{
|
||||
return array->size;
|
||||
return array->count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -167,11 +167,11 @@ 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.
|
||||
*/
|
||||
unsigned counter;
|
||||
tommy_count_t counter;
|
||||
tommy_node* node = chain->head;
|
||||
tommy_node* tail = chain->tail;
|
||||
unsigned mask;
|
||||
unsigned i;
|
||||
tommy_count_t mask;
|
||||
tommy_count_t i;
|
||||
|
||||
counter = 0;
|
||||
while (1) {
|
||||
|
|
|
|||
|
|
@ -50,12 +50,12 @@ void tommy_hashdyn_done(tommy_hashdyn* hashdyn)
|
|||
/**
|
||||
* Resize the bucket vector.
|
||||
*/
|
||||
static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, unsigned new_bucket_bit)
|
||||
static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, tommy_count_t new_bucket_bit)
|
||||
{
|
||||
unsigned bucket_bit;
|
||||
unsigned bucket_max;
|
||||
unsigned new_bucket_max;
|
||||
unsigned new_bucket_mask;
|
||||
tommy_count_t bucket_bit;
|
||||
tommy_count_t bucket_max;
|
||||
tommy_count_t new_bucket_max;
|
||||
tommy_count_t new_bucket_mask;
|
||||
tommy_hashdyn_node** new_bucket;
|
||||
|
||||
bucket_bit = hashdyn->bucket_bit;
|
||||
|
|
@ -70,7 +70,7 @@ static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, unsigned new_bucket_bit
|
|||
|
||||
/* reinsert all the elements */
|
||||
if (new_bucket_bit > bucket_bit) {
|
||||
unsigned i;
|
||||
tommy_count_t i;
|
||||
|
||||
/* grow */
|
||||
for (i = 0; i < bucket_max; ++i) {
|
||||
|
|
@ -84,7 +84,7 @@ static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, unsigned new_bucket_bit
|
|||
j = hashdyn->bucket[i];
|
||||
while (j) {
|
||||
tommy_hashdyn_node* j_next = j->next;
|
||||
unsigned index = j->key & new_bucket_mask;
|
||||
tommy_count_t index = j->key & new_bucket_mask;
|
||||
if (new_bucket[index])
|
||||
tommy_list_insert_tail_not_empty(new_bucket[index], j);
|
||||
else
|
||||
|
|
@ -93,7 +93,7 @@ static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, unsigned new_bucket_bit
|
|||
}
|
||||
}
|
||||
} else {
|
||||
unsigned i;
|
||||
tommy_count_t i;
|
||||
|
||||
/* shrink */
|
||||
for (i = 0; i < new_bucket_max; ++i) {
|
||||
|
|
@ -138,7 +138,7 @@ tommy_inline void hashdyn_shrink_step(tommy_hashdyn* hashdyn)
|
|||
|
||||
void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash)
|
||||
{
|
||||
unsigned pos = hash & hashdyn->bucket_mask;
|
||||
tommy_count_t pos = hash & hashdyn->bucket_mask;
|
||||
|
||||
tommy_list_insert_tail(&hashdyn->bucket[pos], node, data);
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void
|
|||
|
||||
void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node)
|
||||
{
|
||||
unsigned pos = node->key & hashdyn->bucket_mask;
|
||||
tommy_count_t pos = node->key & hashdyn->bucket_mask;
|
||||
|
||||
tommy_list_remove_existing(&hashdyn->bucket[pos], node);
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node*
|
|||
|
||||
void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash)
|
||||
{
|
||||
unsigned pos = hash % hashdyn->bucket_max;
|
||||
tommy_count_t pos = hash % hashdyn->bucket_max;
|
||||
tommy_hashdyn_node* node = hashdyn->bucket[pos];
|
||||
|
||||
while (node) {
|
||||
|
|
@ -186,9 +186,9 @@ void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const
|
|||
|
||||
void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func)
|
||||
{
|
||||
unsigned bucket_max = hashdyn->bucket_max;
|
||||
tommy_count_t bucket_max = hashdyn->bucket_max;
|
||||
tommy_hashdyn_node** bucket = hashdyn->bucket;
|
||||
unsigned pos;
|
||||
tommy_count_t pos;
|
||||
|
||||
for (pos = 0; pos < bucket_max; ++pos) {
|
||||
tommy_hashdyn_node* node = bucket[pos];
|
||||
|
|
@ -203,9 +203,9 @@ 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)
|
||||
{
|
||||
unsigned bucket_max = hashdyn->bucket_max;
|
||||
tommy_count_t bucket_max = hashdyn->bucket_max;
|
||||
tommy_hashdyn_node** bucket = hashdyn->bucket;
|
||||
unsigned pos;
|
||||
tommy_count_t pos;
|
||||
|
||||
for (pos = 0; pos < bucket_max; ++pos) {
|
||||
tommy_hashdyn_node* node = bucket[pos];
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@
|
|||
* and remove.
|
||||
*
|
||||
* \code
|
||||
* struct object* obj = tommy_trie_remove(&hashtable, compare, &value_to_remove, tommy_inthash_u32(value_to_remove));
|
||||
* struct object* obj = tommy_hashdyn_remove(&hashdyn, compare, &value_to_remove, tommy_inthash_u32(value_to_remove));
|
||||
* if (obj) {
|
||||
* free(obj); // frees the object allocated memory
|
||||
* }
|
||||
|
|
@ -127,9 +127,11 @@
|
|||
* tommy_hashdyn_done(&hashdyn);
|
||||
* \endcode
|
||||
*
|
||||
* Note that you cannot iterates over all the elements in the hashtable using the
|
||||
* hashtable itself. 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.
|
||||
* If you need to iterate over all the elements in the hashtable, you can use
|
||||
* tommy_hashdyn_foreach() or tommy_hashdyn_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.
|
||||
*/
|
||||
|
||||
#ifndef __TOMMYHASHDYN_H
|
||||
|
|
@ -147,20 +149,21 @@
|
|||
#define TOMMY_HASHDYN_BIT 4
|
||||
|
||||
/**
|
||||
* Dynamic hashtable node.
|
||||
* Hashtable node.
|
||||
* This is the node that you have to include inside your objects.
|
||||
*/
|
||||
typedef tommy_node tommy_hashdyn_node;
|
||||
|
||||
/**
|
||||
* Dynamic chained hashtable.
|
||||
* Hashtable container type.
|
||||
* \note Don't use internal fields directly, but access the container only using functions.
|
||||
*/
|
||||
typedef struct tommy_hashdyn_struct {
|
||||
tommy_hashdyn_node** bucket; /**< Hash buckets. One list for each hash modulus. */
|
||||
unsigned bucket_bit; /**< Bits used in the bit mask. */
|
||||
unsigned bucket_max; /**< Number of buckets. */
|
||||
unsigned bucket_mask; /**< Bit mask to access the buckets. */
|
||||
unsigned count; /**< Number of elements. */
|
||||
tommy_uint_t bucket_bit; /**< Bits used in the bit mask. */
|
||||
tommy_count_t bucket_max; /**< Number of buckets. */
|
||||
tommy_count_t bucket_mask; /**< Bit mask to access the buckets. */
|
||||
tommy_count_t count; /**< Number of elements. */
|
||||
} tommy_hashdyn;
|
||||
|
||||
/**
|
||||
|
|
@ -240,6 +243,33 @@ void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node*
|
|||
|
||||
/**
|
||||
* Calls the specified function for each element in the hashtable.
|
||||
*
|
||||
* You can use this function to deallocate all the elements inserted.
|
||||
*
|
||||
* \code
|
||||
* tommy_hashdyn hashdyn;
|
||||
*
|
||||
* // initializes the hashtable
|
||||
* tommy_hashdyn_init(&hashdyn);
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* // creates an object
|
||||
* struct object* obj = malloc(sizeof(struct object));
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* // insert it in the hashtable
|
||||
* tommy_hashdyn_insert(&hashdyn, &obj->node, obj, tommy_inthash_u32(obj->value));
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* // deallocates all the objects iterating the hashtable
|
||||
* tommy_hashdyn_foreach(&hashdyn, free);
|
||||
*
|
||||
* // deallocates the hashtable
|
||||
* tommy_hashdyn_done(&hashdyn);
|
||||
* \endcode
|
||||
*/
|
||||
void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func);
|
||||
|
||||
|
|
@ -251,7 +281,7 @@ void tommy_hashdyn_foreach_arg(tommy_hashdyn* hashdyn, tommy_foreach_arg_func* f
|
|||
/**
|
||||
* Gets the number of elements.
|
||||
*/
|
||||
tommy_inline unsigned tommy_hashdyn_count(tommy_hashdyn* hashdyn)
|
||||
tommy_inline tommy_count_t tommy_hashdyn_count(tommy_hashdyn* hashdyn)
|
||||
{
|
||||
return hashdyn->count;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@
|
|||
/* list */
|
||||
|
||||
/**
|
||||
* Double linked list for collisions into hashtables.
|
||||
* Double linked list type.
|
||||
*/
|
||||
typedef tommy_node* tommy_list;
|
||||
|
||||
|
|
@ -309,6 +309,31 @@ tommy_inline tommy_bool_t tommy_list_empty(tommy_list* list)
|
|||
|
||||
/**
|
||||
* Calls the specified function for each element in the list.
|
||||
*
|
||||
* You can use this function to deallocate all the elements
|
||||
* inserted in a list.
|
||||
*
|
||||
* \code
|
||||
* tommy_list list;
|
||||
*
|
||||
* // initializes the list
|
||||
* tommy_list_init(&list);
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* // creates an object
|
||||
* struct object* obj = malloc(sizeof(struct object));
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* // insert it in the list
|
||||
* tommy_list_insert_tail(&list, &obj->node, obj);
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* // deallocates all the objects iterating the list
|
||||
* tommy_list_foreach(&list, free);
|
||||
* \endcode
|
||||
*/
|
||||
tommy_inline void tommy_list_foreach(tommy_list* list, tommy_foreach_func* func)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,21 +35,37 @@
|
|||
/******************************************************************************/
|
||||
/* types */
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
typedef unsigned tommy_uint32_t; /**< Generic uint32_t type. */
|
||||
typedef unsigned _int64 tommy_uint64_t; /**< Generic uint64_t type. */
|
||||
typedef size_t tommy_size_t; /**< Generic size_t type. */
|
||||
typedef size_t tommy_uintptr_t; /**< Generic uintptr_t type. */
|
||||
#else
|
||||
#include <stdint.h>
|
||||
typedef uint32_t tommy_uint32_t; /**< Generic uint32_t type. */
|
||||
typedef uint64_t tommy_uint64_t; /**< Generic uint64_t type. */
|
||||
typedef uintptr_t tommy_size_t; /**< Generic size_t type. */
|
||||
typedef uintptr_t tommy_uintptr_t; /**< Generic uintptr_t type. */
|
||||
#endif
|
||||
typedef size_t tommy_size_t; /**< Generic size_t type. */
|
||||
typedef ptrdiff_t tommy_ptrdiff_t; /**< Generic ptrdiff_t type. */
|
||||
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.
|
||||
* To make the code more efficient, a full 32 bit integer is used.
|
||||
*/
|
||||
typedef tommy_uint32_t tommy_uint_t;
|
||||
|
||||
/**
|
||||
* Generic unsigned integer for counting objects.
|
||||
*
|
||||
* TommyDS doesn't support more than 2^32-1 objects.
|
||||
*/
|
||||
typedef tommy_uint32_t tommy_count_t;
|
||||
|
||||
/** \internal
|
||||
* Type cast required for the C++ compilation.
|
||||
* When compiling in C++ we cannot convert a void* pointer to another pointer.
|
||||
|
|
@ -307,7 +323,7 @@ typedef void tommy_foreach_arg_func(void* arg, void* obj);
|
|||
* \param value Value to scan. 0 is not allowed.
|
||||
* \return The index of the most significan bit set.
|
||||
*/
|
||||
tommy_inline unsigned tommy_ilog2_u32(tommy_uint32_t value)
|
||||
tommy_inline tommy_uint_t tommy_ilog2_u32(tommy_uint32_t value)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
unsigned long count;
|
||||
|
|
@ -326,7 +342,7 @@ tommy_inline unsigned tommy_ilog2_u32(tommy_uint32_t value)
|
|||
#else
|
||||
/* Find the log base 2 of an N-bit integer in O(lg(N)) operations with multiply and lookup */
|
||||
/* from http://graphics.stanford.edu/~seander/bithacks.html */
|
||||
static const int TOMMY_DE_BRUIJN_INDEX_ILOG2[32] = {
|
||||
static unsigned char TOMMY_DE_BRUIJN_INDEX_ILOG2[32] = {
|
||||
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
|
||||
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
|
||||
};
|
||||
|
|
@ -349,7 +365,7 @@ tommy_inline unsigned tommy_ilog2_u32(tommy_uint32_t value)
|
|||
* \param value Value to scan. 0 is not allowed.
|
||||
* \return The index of the least significant bit set.
|
||||
*/
|
||||
tommy_inline unsigned tommy_ctz_u32(tommy_uint32_t value)
|
||||
tommy_inline tommy_uint_t tommy_ctz_u32(tommy_uint32_t value)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
unsigned long count;
|
||||
|
|
@ -360,7 +376,7 @@ tommy_inline unsigned tommy_ctz_u32(tommy_uint32_t value)
|
|||
#else
|
||||
/* Count the consecutive zero bits (trailing) on the right with multiply and lookup */
|
||||
/* from http://graphics.stanford.edu/~seander/bithacks.html */
|
||||
static const tommy_uint32_t TOMMY_DE_BRUIJN_INDEX_CTZ[32] = {
|
||||
static const unsigned char TOMMY_DE_BRUIJN_INDEX_CTZ[32] = {
|
||||
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
|
||||
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue