Add HashMap realloc/clear, fixes
This commit is contained in:
parent
de0a877c70
commit
164a35fbd7
2 changed files with 120 additions and 11 deletions
|
@ -13,7 +13,7 @@ UDPC_HashMap* UDPC_HashMap_init(uint32_t capacity, uint32_t unitSize)
|
||||||
|
|
||||||
int fail = 0;
|
int fail = 0;
|
||||||
m->size = 0;
|
m->size = 0;
|
||||||
m->capacity = (capacity > 10 ? capacity : 10);
|
m->capacity = (capacity > UDPC_HASHMAP_INIT_CAPACITY ? capacity : UDPC_HASHMAP_INIT_CAPACITY);
|
||||||
m->unitSize = unitSize;
|
m->unitSize = unitSize;
|
||||||
|
|
||||||
m->buckets = malloc(sizeof(UDPC_Deque*) * m->capacity);
|
m->buckets = malloc(sizeof(UDPC_Deque*) * m->capacity);
|
||||||
|
@ -30,7 +30,7 @@ UDPC_HashMap* UDPC_HashMap_init(uint32_t capacity, uint32_t unitSize)
|
||||||
m->buckets[x] = NULL;
|
m->buckets[x] = NULL;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
m->buckets[x] = UDPC_Deque_init(unitSize * UDPC_HASHMAP_BUCKET_SIZE);
|
m->buckets[x] = UDPC_Deque_init(UDPC_HASHMAP_BUCKET_SIZE * (sizeof(uint32_t) + unitSize));
|
||||||
if(!m->buckets[x])
|
if(!m->buckets[x])
|
||||||
{
|
{
|
||||||
fail = 1;
|
fail = 1;
|
||||||
|
@ -51,7 +51,7 @@ UDPC_HashMap* UDPC_HashMap_init(uint32_t capacity, uint32_t unitSize)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
m->overflow = UDPC_Deque_init(unitSize * UDPC_HASHMAP_BUCKET_SIZE);
|
m->overflow = UDPC_Deque_init(UDPC_HASHMAP_BUCKET_SIZE * (sizeof(uint32_t) + unitSize));
|
||||||
if(!m->overflow)
|
if(!m->overflow)
|
||||||
{
|
{
|
||||||
for(int x = 0; x < m->capacity; ++x)
|
for(int x = 0; x < m->capacity; ++x)
|
||||||
|
@ -82,6 +82,14 @@ void UDPC_HashMap_destroy(UDPC_HashMap *hashMap)
|
||||||
|
|
||||||
void* UDPC_HashMap_insert(UDPC_HashMap *hm, uint32_t key, void *data)
|
void* UDPC_HashMap_insert(UDPC_HashMap *hm, uint32_t key, void *data)
|
||||||
{
|
{
|
||||||
|
if(hm->capacity <= hm->size)
|
||||||
|
{
|
||||||
|
if(UDPC_HashMap_realloc(hm, hm->capacity * 2) == 0)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t hash = UDPC_HASH32(key) % hm->capacity;
|
uint32_t hash = UDPC_HASH32(key) % hm->capacity;
|
||||||
|
|
||||||
char *temp = malloc(sizeof(uint32_t) + hm->unitSize);
|
char *temp = malloc(sizeof(uint32_t) + hm->unitSize);
|
||||||
|
@ -195,3 +203,88 @@ void* UDPC_HashMap_get(UDPC_HashMap *hm, uint32_t key)
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int UDPC_HashMap_realloc(UDPC_HashMap *hm, uint32_t newCapacity)
|
||||||
|
{
|
||||||
|
if(hm->size > newCapacity)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UDPC_Deque **newBuckets = malloc(sizeof(UDPC_Deque*) * newCapacity);
|
||||||
|
UDPC_Deque *newOverflow = UDPC_Deque_init(UDPC_HASHMAP_BUCKET_SIZE
|
||||||
|
* (sizeof(uint32_t) + hm->unitSize));
|
||||||
|
for(int x = 0; x < newCapacity; ++x)
|
||||||
|
{
|
||||||
|
*newBuckets = UDPC_Deque_init(UDPC_HASHMAP_BUCKET_SIZE
|
||||||
|
* (sizeof(uint32_t) + hm->unitSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t hash;
|
||||||
|
char *data;
|
||||||
|
int fail = 0;
|
||||||
|
for(int x = 0; x < hm->capacity; ++x)
|
||||||
|
{
|
||||||
|
for(int y = 0; y * (sizeof(uint32_t) + hm->unitSize) < hm->buckets[x]->size; ++y)
|
||||||
|
{
|
||||||
|
data = UDPC_Deque_index_ptr(hm->buckets[x], sizeof(uint32_t) + hm->unitSize, y);
|
||||||
|
hash = UDPC_HASH32(*((uint32_t*)data)) % newCapacity;
|
||||||
|
if(newBuckets[hash]->size < newBuckets[hash]->alloc_size)
|
||||||
|
{
|
||||||
|
if(UDPC_Deque_push_back(newBuckets[hash], data, sizeof(uint32_t) + hm->unitSize) == 0)
|
||||||
|
{
|
||||||
|
fail = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(UDPC_Deque_push_back(newOverflow, data, sizeof(uint32_t) + hm->unitSize) == 0)
|
||||||
|
{
|
||||||
|
fail = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(fail != 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fail != 0)
|
||||||
|
{
|
||||||
|
for(int x = 0; x < newCapacity; ++x)
|
||||||
|
{
|
||||||
|
UDPC_Deque_destroy(newBuckets[x]);
|
||||||
|
}
|
||||||
|
free(newBuckets);
|
||||||
|
UDPC_Deque_destroy(newOverflow);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int x = 0; x < hm->capacity; ++x)
|
||||||
|
{
|
||||||
|
UDPC_Deque_destroy(hm->buckets[x]);
|
||||||
|
}
|
||||||
|
free(hm->buckets);
|
||||||
|
UDPC_Deque_destroy(hm->overflow);
|
||||||
|
|
||||||
|
hm->buckets = newBuckets;
|
||||||
|
hm->overflow = newOverflow;
|
||||||
|
|
||||||
|
hm->capacity = newCapacity;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDPC_HashMap_clear(UDPC_HashMap *hm)
|
||||||
|
{
|
||||||
|
for(int x = 0; x < hm->capacity; ++x)
|
||||||
|
{
|
||||||
|
UDPC_Deque_clear(hm->buckets[x]);
|
||||||
|
}
|
||||||
|
UDPC_Deque_clear(hm->overflow);
|
||||||
|
hm->size = 0;
|
||||||
|
}
|
||||||
|
|
|
@ -5,16 +5,17 @@
|
||||||
// 3 2 5 1 8 7 6
|
// 3 2 5 1 8 7 6
|
||||||
#define UDPC_HASH32(x) ( \
|
#define UDPC_HASH32(x) ( \
|
||||||
( \
|
( \
|
||||||
((x & 0xF8000000) >> 5) | \
|
(((x) & 0xF8000000) >> 5) | \
|
||||||
((x & 0x07F80000) >> 6) | \
|
(((x) & 0x07F80000) >> 6) | \
|
||||||
((x & 0x00060000) << 10) | \
|
(((x) & 0x00060000) << 10) | \
|
||||||
((x & 0x0001FC00) >> 4) | \
|
(((x) & 0x0001FC00) >> 4) | \
|
||||||
((x & 0x00000380) << 22) | \
|
(((x) & 0x00000380) << 22) | \
|
||||||
((x & 0x0000007E) >> 1) | \
|
(((x) & 0x0000007E) >> 1) | \
|
||||||
((x & 0x00000001) << 21) \
|
(((x) & 0x00000001) << 21) \
|
||||||
) ^ 0x96969696 \
|
) ^ 0x96969696 \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#define UDPC_HASHMAP_INIT_CAPACITY 8
|
||||||
#define UDPC_HASHMAP_BUCKET_SIZE 4
|
#define UDPC_HASHMAP_BUCKET_SIZE 4
|
||||||
|
|
||||||
#include "UDPC_Deque.h"
|
#include "UDPC_Deque.h"
|
||||||
|
@ -42,7 +43,10 @@ void UDPC_HashMap_destroy(UDPC_HashMap *hashMap);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Inserts a copy of data pointed to by given pointer
|
* \brief Inserts a copy of data pointed to by given pointer
|
||||||
* \return Internally managed pointer to inserted data
|
* Note if size already equals capacity, the hash map's capacity is doubled
|
||||||
|
* with UDPC_HashMap_realloc(). realloc requires rehashing of all items which
|
||||||
|
* may be costly.
|
||||||
|
* \return Internally managed pointer to inserted data, NULL on fail
|
||||||
*/
|
*/
|
||||||
void* UDPC_HashMap_insert(UDPC_HashMap *hm, uint32_t key, void *data);
|
void* UDPC_HashMap_insert(UDPC_HashMap *hm, uint32_t key, void *data);
|
||||||
|
|
||||||
|
@ -58,4 +62,16 @@ int UDPC_HashMap_remove(UDPC_HashMap *hm, uint32_t key);
|
||||||
*/
|
*/
|
||||||
void* UDPC_HashMap_get(UDPC_HashMap *hm, uint32_t key);
|
void* UDPC_HashMap_get(UDPC_HashMap *hm, uint32_t key);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Resizes the maximum capacity of a hash map
|
||||||
|
* Note on fail, the hash map is unchanged.
|
||||||
|
* \return non-zero if resizing was successful
|
||||||
|
*/
|
||||||
|
int UDPC_HashMap_realloc(UDPC_HashMap *hm, uint32_t newCapacity);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Empties the hash map
|
||||||
|
*/
|
||||||
|
void UDPC_HashMap_clear(UDPC_HashMap *hm);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue