hash_map_insert(): Added parameter 'update' to specify if the value of an existing key should be updated +

hash_map_remove(): Added parameter 'value' to return the value that was associated with the deleted key (optional).
This commit is contained in:
LoRd_MuldeR 2022-12-04 21:47:44 +01:00
parent f229c7ccfb
commit 669bf3a28b
6 changed files with 58 additions and 32 deletions

View File

@ -514,15 +514,14 @@ void hash_map_destroy(
Tries to insert the given key-value pair into the hash map.
If the map already contains the given key, then the value associated with the existing key is updated.
***Note:*** If the key is actually inserted, then the hash map *may* need to grow.
```C
errno_t hash_map_insert(
hash_map_t *const instance,
const value_t key,
const value_t value
const value_t value,
const int update
);
```
@ -537,6 +536,9 @@ errno_t hash_map_insert(
* `value`
The value to be associated with the given key.
* `update`
If the map already contains the specified key, then if this parameter is *non-zero*, the value associated with the existing key will be updated; otherwise, the value currently associated with key remains unchanged.
#### Return value
On success, this function returns *zero*. On error, the appropriate error code is returned. Possible error codes include:
@ -546,7 +548,7 @@ On success, this function returns *zero*. On error, the appropriate error code i
* `EEXIST`
The given key was *not* inserted into the hash map (again), because it was already present.
Nonetheless, the value associated with the existing key has been updated!
Nonetheless, if `update` was non-zero, the value associated with the existing key has been updated.
* `ENOMEM`
The key could *not* be inserted, because the required amount of memory could *not* be allocated.
@ -565,7 +567,8 @@ The value associated with the removed key is discarded.
```C
errno_t hash_map_remove(
hash_map_t *const instance,
const value_t key
const value_t key,
value_t *const value
);
```
@ -577,6 +580,11 @@ errno_t hash_map_remove(
* `key`
The key to be removed from the hash map.
* `value`
A pointer to a variable of type `value_t` where the value that was associated with the deleted key is stored.
The content of the variable should be considered *undefined*, if the key could *not* be removed.
***Note:*** This parameter can be set to `NULL`, in which case the value will *not* be reported to the application.
#### Return value
On success, this function returns *zero*. On error, the appropriate error code is returned. Possible error codes include:

View File

@ -35,7 +35,7 @@ int main(void)
while (have_more_items(offset))
{
const pair_t input = get_next_item(offset++);
const errno_t error = hash_map_insert64(hash_map, input.key, input.value);
const errno_t error = hash_map_insert64(hash_map, input.key, input.value, 1);
if (error)
{
fprintf(stderr, "Insert operation failed! (error: %d)\n", error);

View File

@ -72,13 +72,13 @@ HASHSET_API void hash_map_destroy16(hash_map16_t *const instance);
HASHSET_API void hash_map_destroy32(hash_map32_t *const instance);
HASHSET_API void hash_map_destroy64(hash_map64_t *const instance);
HASHSET_API errno_t hash_map_insert16(hash_map16_t *const instance, const uint16_t key, const uint16_t value);
HASHSET_API errno_t hash_map_insert32(hash_map32_t *const instance, const uint32_t key, const uint32_t value);
HASHSET_API errno_t hash_map_insert64(hash_map64_t *const instance, const uint64_t key, const uint64_t value);
HASHSET_API errno_t hash_map_insert16(hash_map16_t *const instance, const uint16_t key, const uint16_t value, const int update);
HASHSET_API errno_t hash_map_insert32(hash_map32_t *const instance, const uint32_t key, const uint32_t value, const int update);
HASHSET_API errno_t hash_map_insert64(hash_map64_t *const instance, const uint64_t key, const uint64_t value, const int update);
HASHSET_API errno_t hash_map_remove16(hash_map16_t *const instance, const uint16_t key);
HASHSET_API errno_t hash_map_remove32(hash_map32_t *const instance, const uint32_t key);
HASHSET_API errno_t hash_map_remove64(hash_map64_t *const instance, const uint64_t key);
HASHSET_API errno_t hash_map_remove16(hash_map16_t *const instance, const uint16_t key, uint16_t *const value);
HASHSET_API errno_t hash_map_remove32(hash_map32_t *const instance, const uint32_t key, uint32_t *const value);
HASHSET_API errno_t hash_map_remove64(hash_map64_t *const instance, const uint64_t key, uint64_t *const value);
HASHSET_API errno_t hash_map_clear16(hash_map16_t *const instance);
HASHSET_API errno_t hash_map_clear32(hash_map32_t *const instance);

View File

@ -230,7 +230,7 @@ void DECLARE(hash_map_destroy)(hash_map_t *instance)
}
}
errno_t DECLARE(hash_map_insert)(hash_map_t *const instance, const value_t key, const value_t value)
errno_t DECLARE(hash_map_insert)(hash_map_t *const instance, const value_t key, const value_t value, const bool_t update)
{
size_t index = SIZE_MAX;
bool_t slot_reused;
@ -242,20 +242,30 @@ errno_t DECLARE(hash_map_insert)(hash_map_t *const instance, const value_t key,
if (find_slot(&instance->data, instance->basis, key, &index, &slot_reused))
{
instance->data.entries[index].value = value;
if (update)
{
instance->data.entries[index].value = value;
}
return EEXIST;
}
if ((!slot_reused) && (safe_add(instance->valid, instance->deleted) >= instance->limit))
{
const errno_t error = rebuild_map(instance, safe_times2(instance->data.capacity));
if (error)
if (instance->data.capacity < SIZE_MAX)
{
return error;
const errno_t error = rebuild_map(instance, safe_times2(instance->data.capacity));
if (error)
{
return error;
}
if (find_slot(&instance->data, instance->basis, key, &index, &slot_reused))
{
return EFAULT;
}
}
if (find_slot(&instance->data, instance->basis, key, &index, &slot_reused))
else
{
return EFAULT;
return ENOMEM; /*can not grow any futher!*/
}
}
@ -298,7 +308,7 @@ errno_t DECLARE(hash_map_get)(const hash_map_t *const instance, const value_t ke
return 0;
}
errno_t DECLARE(hash_map_remove)(hash_map_t *const instance, const value_t key)
errno_t DECLARE(hash_map_remove)(hash_map_t *const instance, const value_t key, value_t *const value)
{
size_t index;
@ -312,6 +322,7 @@ errno_t DECLARE(hash_map_remove)(hash_map_t *const instance, const value_t key)
return ENOENT;
}
SAFE_SET(value, instance->data.entries[index].value);
set_flag(instance->data.deleted, index);
instance->deleted = safe_incr(instance->deleted);
instance->valid = safe_decr(instance->valid);

View File

@ -238,14 +238,21 @@ errno_t DECLARE(hash_set_insert)(hash_set_t *const instance, const value_t item)
if ((!slot_reused) && (safe_add(instance->valid, instance->deleted) >= instance->limit))
{
const errno_t error = rebuild_set(instance, safe_times2(instance->data.capacity));
if (error)
if (instance->data.capacity < SIZE_MAX)
{
return error;
const errno_t error = rebuild_set(instance, safe_times2(instance->data.capacity));
if (error)
{
return error;
}
if (find_slot(&instance->data, instance->basis, item, &index, &slot_reused))
{
return EFAULT;
}
}
if (find_slot(&instance->data, instance->basis, item, &index, &slot_reused))
else
{
return EFAULT;
return ENOMEM; /*can not grow any futher!*/
}
}

View File

@ -86,7 +86,7 @@ int test_function_1(hash_map64_t *const hash_map)
{
if (test_key1[j])
{
const errno_t error = hash_map_insert64(hash_map, j, test_data[j] = random_next(&random));
const errno_t error = hash_map_insert64(hash_map, j, test_data[j] = random_next(&random), 1);
if (error)
{
printf("Insert operation has failed! (error: %d)\n", error);
@ -153,7 +153,7 @@ int test_function_1(hash_map64_t *const hash_map)
{
if (test_key1[j])
{
const errno_t error = hash_map_remove64(hash_map, j);
const errno_t error = hash_map_remove64(hash_map, j, NULL);
if (error)
{
printf("Remove operation has failed! (error: %d)\n", error);
@ -238,7 +238,7 @@ int test_function_2(hash_map64_t *const hash_map)
{
if (test_key[j])
{
const errno_t error = hash_map_insert64(hash_map, j, test_val[j] = random_next(&random));
const errno_t error = hash_map_insert64(hash_map, j, test_val[j] = random_next(&random), 1);
if (error)
{
printf("Insert operation has failed! (error: %d)\n", error);
@ -255,7 +255,7 @@ int test_function_2(hash_map64_t *const hash_map)
{
if (test_key[j])
{
const errno_t error = hash_map_insert64(hash_map, j, test_val[j] = random_next(&random));
const errno_t error = hash_map_insert64(hash_map, j, test_val[j] = random_next(&random), 1);
if (error != EEXIST)
{
printf("Insert operation has failed! (error: %d)\n", error);
@ -325,7 +325,7 @@ int test_function_3(hash_map64_t *const hash_map)
for (;;)
{
const uint64_t rnd = random_next(&random) & UINT64_C(0x1FFFFFFFFFFFFFF);
const errno_t error = hash_map_insert64(hash_map, rnd, VALUE(rnd));
const errno_t error = hash_map_insert64(hash_map, rnd, VALUE(rnd), 1);
if (error)
{
if (error != EEXIST)
@ -391,7 +391,7 @@ int test_function_4(hash_map64_t *const hash_map)
for (key = 0U; key < LIMIT; ++key)
{
const errno_t error = hash_map_insert64(hash_map, key, VALUE(key));
const errno_t error = hash_map_insert64(hash_map, key, VALUE(key), 1);
if (error)
{
PRINT_SET_INFO(4);
@ -411,7 +411,7 @@ int test_function_4(hash_map64_t *const hash_map)
for (key = 0U; key < LIMIT; ++key)
{
const errno_t error = hash_map_remove64(hash_map, key);
const errno_t error = hash_map_remove64(hash_map, key, NULL);
if (error)
{
PRINT_SET_INFO(4);