diff options
author | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/restricted/aws/aws-c-common/source/linked_hash_table.c |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/restricted/aws/aws-c-common/source/linked_hash_table.c')
-rw-r--r-- | contrib/restricted/aws/aws-c-common/source/linked_hash_table.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/contrib/restricted/aws/aws-c-common/source/linked_hash_table.c b/contrib/restricted/aws/aws-c-common/source/linked_hash_table.c new file mode 100644 index 00000000000..42c6a1b530c --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/linked_hash_table.c @@ -0,0 +1,137 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include <aws/common/linked_hash_table.h> + +static void s_element_destroy(void *value) { + struct aws_linked_hash_table_node *node = value; + + if (node->table->user_on_value_destroy) { + node->table->user_on_value_destroy(node->value); + } + + aws_linked_list_remove(&node->node); + aws_mem_release(node->table->allocator, node); +} + +int aws_linked_hash_table_init( + struct aws_linked_hash_table *table, + struct aws_allocator *allocator, + aws_hash_fn *hash_fn, + aws_hash_callback_eq_fn *equals_fn, + aws_hash_callback_destroy_fn *destroy_key_fn, + aws_hash_callback_destroy_fn *destroy_value_fn, + size_t initial_item_count) { + AWS_ASSERT(table); + AWS_ASSERT(allocator); + AWS_ASSERT(hash_fn); + AWS_ASSERT(equals_fn); + + table->allocator = allocator; + table->user_on_value_destroy = destroy_value_fn; + + aws_linked_list_init(&table->list); + return aws_hash_table_init( + &table->table, allocator, initial_item_count, hash_fn, equals_fn, destroy_key_fn, s_element_destroy); +} + +void aws_linked_hash_table_clean_up(struct aws_linked_hash_table *table) { + /* clearing the table will remove all elements. That will also deallocate + * any table entries we currently have. */ + aws_hash_table_clean_up(&table->table); + AWS_ZERO_STRUCT(*table); +} + +int aws_linked_hash_table_find(struct aws_linked_hash_table *table, const void *key, void **p_value) { + + struct aws_hash_element *element = NULL; + int err_val = aws_hash_table_find(&table->table, key, &element); + + if (err_val || !element) { + *p_value = NULL; + return err_val; + } + + struct aws_linked_hash_table_node *linked_node = element->value; + *p_value = linked_node->value; + + return AWS_OP_SUCCESS; +} + +int aws_linked_hash_table_find_and_move_to_back(struct aws_linked_hash_table *table, const void *key, void **p_value) { + + struct aws_hash_element *element = NULL; + int err_val = aws_hash_table_find(&table->table, key, &element); + + if (err_val || !element) { + *p_value = NULL; + return err_val; + } + + struct aws_linked_hash_table_node *linked_node = element->value; + *p_value = linked_node->value; + /* on access, remove from current place in list and move it to the back. */ + aws_linked_hash_table_move_node_to_end_of_list(table, linked_node); + return AWS_OP_SUCCESS; +} + +int aws_linked_hash_table_put(struct aws_linked_hash_table *table, const void *key, void *p_value) { + + struct aws_linked_hash_table_node *node = + aws_mem_calloc(table->allocator, 1, sizeof(struct aws_linked_hash_table_node)); + + if (!node) { + return AWS_OP_ERR; + } + + struct aws_hash_element *element = NULL; + int was_added = 0; + int err_val = aws_hash_table_create(&table->table, key, &element, &was_added); + + if (err_val) { + aws_mem_release(table->allocator, node); + return err_val; + } + + if (element->value) { + s_element_destroy(element->value); + } + + node->value = p_value; + node->key = key; + node->table = table; + element->value = node; + + aws_linked_list_push_back(&table->list, &node->node); + + return AWS_OP_SUCCESS; +} + +int aws_linked_hash_table_remove(struct aws_linked_hash_table *table, const void *key) { + /* allocated table memory and the linked list entry will be removed in the + * callback. */ + return aws_hash_table_remove(&table->table, key, NULL, NULL); +} + +void aws_linked_hash_table_clear(struct aws_linked_hash_table *table) { + /* clearing the table will remove all elements. That will also deallocate + * any entries we currently have. */ + aws_hash_table_clear(&table->table); +} + +size_t aws_linked_hash_table_get_element_count(const struct aws_linked_hash_table *table) { + return aws_hash_table_get_entry_count(&table->table); +} + +void aws_linked_hash_table_move_node_to_end_of_list( + struct aws_linked_hash_table *table, + struct aws_linked_hash_table_node *node) { + + aws_linked_list_remove(&node->node); + aws_linked_list_push_back(&table->list, &node->node); +} + +const struct aws_linked_list *aws_linked_hash_table_get_iteration_list(const struct aws_linked_hash_table *table) { + return &table->list; +} |