Small improvement to map entry handling.

This commit is contained in:
LoRd_MuldeR 2022-12-03 22:44:14 +01:00
parent fb8ec13127
commit d1cf093e76
2 changed files with 40 additions and 40 deletions

View File

@ -143,17 +143,17 @@ static INLINE void zero_memory(void *const addr, const size_t count, const size_
/* Flags */ /* Flags */
/* ------------------------------------------------- */ /* ------------------------------------------------- */
static INLINE bool_t get_flag(const uint8_t *const flags, const size_t index) static FORCE_INLINE bool_t get_flag(const uint8_t *const flags, const size_t index)
{ {
return (flags[index / 8U] >> (index % 8U)) & UINT8_C(1); return (flags[index / 8U] >> (index % 8U)) & UINT8_C(1);
} }
static INLINE void set_flag(uint8_t *const flags, const size_t index) static FORCE_INLINE void set_flag(uint8_t *const flags, const size_t index)
{ {
flags[index / 8U] |= UINT8_C(1) << (index % 8U); flags[index / 8U] |= UINT8_C(1) << (index % 8U);
} }
static INLINE void clear_flag(uint8_t *const flags, const size_t index) static FORCE_INLINE void clear_flag(uint8_t *const flags, const size_t index)
{ {
flags[index / 8U] &= ~(UINT8_C(1) << (index % 8U)); flags[index / 8U] &= ~(UINT8_C(1) << (index % 8U));
} }

View File

@ -18,9 +18,16 @@
/* Data types */ /* Data types */
/* ------------------------------------------------- */ /* ------------------------------------------------- */
typedef struct
{
value_t key;
value_t value;
}
entry_t;
typedef struct DECLARE(_hash_map_data) typedef struct DECLARE(_hash_map_data)
{ {
value_t *keys, *values; entry_t *entries;
uint8_t *used, *deleted; uint8_t *used, *deleted;
size_t capacity; size_t capacity;
} }
@ -42,33 +49,24 @@ static INLINE bool_t alloc_data(hash_data_t *const data, const size_t capacity)
{ {
zero_memory(data, 1U, sizeof(hash_data_t)); zero_memory(data, 1U, sizeof(hash_data_t));
data->keys = (value_t*) calloc(capacity, sizeof(value_t)); data->entries = (entry_t*) calloc(capacity, sizeof(entry_t));
if (!data->keys) if (!data->entries)
{ {
return FALSE; return FALSE;
} }
data->values = (value_t*) calloc(capacity, sizeof(value_t));
if (!data->values)
{
SAFE_FREE(data->keys);
return FALSE;
}
data->used = (uint8_t*) calloc(div_ceil(capacity, 8U), sizeof(uint8_t)); data->used = (uint8_t*) calloc(div_ceil(capacity, 8U), sizeof(uint8_t));
if (!data->used) if (!data->used)
{ {
SAFE_FREE(data->keys); SAFE_FREE(data->entries);
SAFE_FREE(data->values);
return FALSE; return FALSE;
} }
data->deleted = (uint8_t*) calloc(div_ceil(capacity, 8U), sizeof(uint8_t)); data->deleted = (uint8_t*) calloc(div_ceil(capacity, 8U), sizeof(uint8_t));
if (!data->deleted) if (!data->deleted)
{ {
SAFE_FREE(data->keys);
SAFE_FREE(data->values);
SAFE_FREE(data->used); SAFE_FREE(data->used);
SAFE_FREE(data->entries);
return FALSE; return FALSE;
} }
@ -80,8 +78,7 @@ static INLINE void free_data(hash_data_t *const data)
{ {
if (data) if (data)
{ {
SAFE_FREE(data->keys); SAFE_FREE(data->entries);
SAFE_FREE(data->values);
SAFE_FREE(data->used); SAFE_FREE(data->used);
SAFE_FREE(data->deleted); SAFE_FREE(data->deleted);
data->capacity = 0U; data->capacity = 0U;
@ -113,7 +110,7 @@ static INLINE bool_t find_slot(const hash_data_t *const data, const uint64_t bas
} }
else else
{ {
if (data->keys[index] == key) if (data->entries[index].key == key)
{ {
SAFE_SET(index_out, index); SAFE_SET(index_out, index);
SAFE_SET(reused_out, FALSE); SAFE_SET(reused_out, FALSE);
@ -131,10 +128,11 @@ static INLINE bool_t find_slot(const hash_data_t *const data, const uint64_t bas
return FALSE; return FALSE;
} }
static INLINE void put_value(hash_data_t *const data, const size_t index, const value_t key, const value_t value, const bool_t reusing) static INLINE void put_entry(hash_data_t *const data, const size_t index, const value_t key, const value_t value, const bool_t reusing)
{ {
data->keys[index] = key; entry_t *const entry = &data->entries[index];
data->values[index] = value; entry->key = key;
entry->value = value;
if (reusing) if (reusing)
{ {
@ -179,13 +177,13 @@ static INLINE errno_t rebuild_map(hash_map_t *const instance, const size_t new_c
{ {
if (IS_VALID(instance->data, k)) if (IS_VALID(instance->data, k))
{ {
const value_t key = instance->data.keys[k], value = instance->data.values[k]; const entry_t entry = instance->data.entries[k];
if (find_slot(&temp, instance->basis, key, &index, NULL)) if (find_slot(&temp, instance->basis, entry.key, &index, NULL))
{ {
free_data(&temp); free_data(&temp);
return EFAULT; /*this should never happen!*/ return EFAULT; /*this should never happen!*/
} }
put_value(&temp, index, key, value, FALSE); put_entry(&temp, index, entry.key, entry.value, FALSE);
} }
} }
@ -237,14 +235,14 @@ errno_t DECLARE(hash_map_insert)(hash_map_t *const instance, const value_t key,
size_t index = SIZE_MAX; size_t index = SIZE_MAX;
bool_t slot_reused; bool_t slot_reused;
if ((!instance) || (!instance->data.keys)) if ((!instance) || (!instance->data.entries))
{ {
return EINVAL; return EINVAL;
} }
if (find_slot(&instance->data, instance->basis, key, &index, &slot_reused)) if (find_slot(&instance->data, instance->basis, key, &index, &slot_reused))
{ {
instance->data.values[index] = value; instance->data.entries[index].value = value;
return EEXIST; return EEXIST;
} }
@ -261,7 +259,7 @@ errno_t DECLARE(hash_map_insert)(hash_map_t *const instance, const value_t key,
} }
} }
put_value(&instance->data, index, key, value, slot_reused); put_entry(&instance->data, index, key, value, slot_reused);
instance->valid = safe_incr(instance->valid); instance->valid = safe_incr(instance->valid);
if (slot_reused) if (slot_reused)
@ -274,7 +272,7 @@ errno_t DECLARE(hash_map_insert)(hash_map_t *const instance, const value_t key,
errno_t DECLARE(hash_map_contains)(const hash_map_t *const instance, const value_t key) errno_t DECLARE(hash_map_contains)(const hash_map_t *const instance, const value_t key)
{ {
if ((!instance) || (!instance->data.keys)) if ((!instance) || (!instance->data.entries))
{ {
return EINVAL; return EINVAL;
} }
@ -286,7 +284,7 @@ errno_t DECLARE(hash_map_get)(const hash_map_t *const instance, const value_t ke
{ {
size_t index; size_t index;
if ((!instance) || (!instance->data.keys)) if ((!instance) || (!instance->data.entries))
{ {
return EINVAL; return EINVAL;
} }
@ -296,7 +294,7 @@ errno_t DECLARE(hash_map_get)(const hash_map_t *const instance, const value_t ke
return ENOENT; return ENOENT;
} }
*value = instance->data.values[index]; *value = instance->data.entries[index].value;
return 0; return 0;
} }
@ -304,7 +302,7 @@ errno_t DECLARE(hash_map_remove)(hash_map_t *const instance, const value_t key)
{ {
size_t index; size_t index;
if ((!instance) || (!instance->data.keys)) if ((!instance) || (!instance->data.entries))
{ {
return EINVAL; return EINVAL;
} }
@ -338,7 +336,7 @@ errno_t DECLARE(hash_map_remove)(hash_map_t *const instance, const value_t key)
errno_t DECLARE(hash_map_clear)(hash_map_t *const instance) errno_t DECLARE(hash_map_clear)(hash_map_t *const instance)
{ {
if ((!instance) || (!instance->data.values)) if ((!instance) || (!instance->data.entries))
{ {
return EINVAL; return EINVAL;
} }
@ -371,7 +369,7 @@ errno_t DECLARE(hash_map_iterate)(const hash_map_t *const instance, size_t *cons
{ {
size_t index; size_t index;
if ((!instance) || (!cursor) || (*cursor >= SIZE_MAX) || (!instance->data.values)) if ((!instance) || (!cursor) || (*cursor >= SIZE_MAX) || (!instance->data.entries))
{ {
return EINVAL; return EINVAL;
} }
@ -380,8 +378,9 @@ errno_t DECLARE(hash_map_iterate)(const hash_map_t *const instance, size_t *cons
{ {
if (IS_VALID(instance->data, index)) if (IS_VALID(instance->data, index))
{ {
SAFE_SET(key, instance->data.keys[index]); const entry_t* const entntry = &instance->data.entries[index];
SAFE_SET(value, instance->data.values[index]); SAFE_SET(key, entntry->key);
SAFE_SET(value, entntry->value);
*cursor = index + 1U; *cursor = index + 1U;
return 0; return 0;
} }
@ -398,7 +397,7 @@ size_t DECLARE(hash_map_size)(const hash_map_t *const instance)
errno_t DECLARE(hash_map_info)(const hash_map_t *const instance, size_t *const capacity, size_t *const valid, size_t *const deleted, size_t *const limit) errno_t DECLARE(hash_map_info)(const hash_map_t *const instance, size_t *const capacity, size_t *const valid, size_t *const deleted, size_t *const limit)
{ {
if ((!instance) || (!instance->data.values)) if ((!instance) || (!instance->data.entries))
{ {
return EINVAL; return EINVAL;
} }
@ -415,14 +414,15 @@ HASHSET_API errno_t DECLARE(hash_map_dump)(const hash_map_t *const instance, con
{ {
size_t index; size_t index;
if ((!instance) || (!instance->data.values) || (!callback)) if ((!instance) || (!instance->data.entries) || (!callback))
{ {
return EINVAL; return EINVAL;
} }
for (index = 0U; index < instance->data.capacity; ++index) for (index = 0U; index < instance->data.capacity; ++index)
{ {
if (!callback(index, get_flag(instance->data.used, index) ? (get_flag(instance->data.deleted, index) ? 'd' : 'v') : 'u', instance->data.keys[index], instance->data.values[index])) const entry_t* const entntry = &instance->data.entries[index];
if (!callback(index, get_flag(instance->data.used, index) ? (get_flag(instance->data.deleted, index) ? 'd' : 'v') : 'u', entntry->key, entntry->value))
{ {
return ECANCELED; return ECANCELED;
} }