summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws/aws-c-http/source/random_access_set.c
diff options
context:
space:
mode:
authordakovalkov <[email protected]>2023-12-03 13:33:55 +0300
committerdakovalkov <[email protected]>2023-12-03 14:04:39 +0300
commit2a718325637e5302334b6d0a6430f63168f8dbb3 (patch)
tree64be81080b7df9ec1d86d053a0c394ae53fcf1fe /contrib/restricted/aws/aws-c-http/source/random_access_set.c
parente0d94a470142d95c3007e9c5d80380994940664a (diff)
Update contrib/libs/aws-sdk-cpp to 1.11.37
Diffstat (limited to 'contrib/restricted/aws/aws-c-http/source/random_access_set.c')
-rw-r--r--contrib/restricted/aws/aws-c-http/source/random_access_set.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/contrib/restricted/aws/aws-c-http/source/random_access_set.c b/contrib/restricted/aws/aws-c-http/source/random_access_set.c
new file mode 100644
index 00000000000..20fc12309fa
--- /dev/null
+++ b/contrib/restricted/aws/aws-c-http/source/random_access_set.c
@@ -0,0 +1,187 @@
+
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/common/allocator.h>
+#include <aws/common/device_random.h>
+#include <aws/http/private/random_access_set.h>
+
+struct aws_random_access_set_impl {
+ struct aws_allocator *allocator;
+ struct aws_array_list list; /* Always store the pointer of the element. */
+ struct aws_hash_table map; /* Map from the element to the index in the array. */
+ aws_hash_callback_destroy_fn *destroy_element_fn;
+};
+
+static void s_impl_destroy(struct aws_random_access_set_impl *impl) {
+ if (!impl) {
+ return;
+ }
+ aws_array_list_clean_up(&impl->list);
+ aws_hash_table_clean_up(&impl->map);
+ aws_mem_release(impl->allocator, impl);
+}
+
+static struct aws_random_access_set_impl *s_impl_new(
+ struct aws_allocator *allocator,
+ aws_hash_fn *hash_fn,
+ aws_hash_callback_eq_fn *equals_fn,
+ aws_hash_callback_destroy_fn *destroy_element_fn,
+ size_t initial_item_allocation) {
+ struct aws_random_access_set_impl *impl = aws_mem_calloc(allocator, 1, sizeof(struct aws_random_access_set_impl));
+ impl->allocator = allocator;
+ /* Will always store the pointer of the element. */
+ if (aws_array_list_init_dynamic(&impl->list, allocator, initial_item_allocation, sizeof(void *))) {
+ s_impl_destroy(impl);
+ return NULL;
+ }
+
+ if (aws_hash_table_init(
+ &impl->map, allocator, initial_item_allocation, hash_fn, equals_fn, destroy_element_fn, NULL)) {
+ s_impl_destroy(impl);
+ return NULL;
+ }
+ impl->destroy_element_fn = destroy_element_fn;
+ return impl;
+}
+
+int aws_random_access_set_init(
+ struct aws_random_access_set *set,
+ struct aws_allocator *allocator,
+ aws_hash_fn *hash_fn,
+ aws_hash_callback_eq_fn *equals_fn,
+ aws_hash_callback_destroy_fn *destroy_element_fn,
+ size_t initial_item_allocation) {
+ AWS_FATAL_PRECONDITION(set);
+ AWS_FATAL_PRECONDITION(allocator);
+ AWS_FATAL_PRECONDITION(hash_fn);
+ AWS_FATAL_PRECONDITION(equals_fn);
+
+ struct aws_random_access_set_impl *impl =
+ s_impl_new(allocator, hash_fn, equals_fn, destroy_element_fn, initial_item_allocation);
+ if (!impl) {
+ return AWS_OP_ERR;
+ }
+ set->impl = impl;
+ return AWS_OP_SUCCESS;
+}
+
+void aws_random_access_set_clean_up(struct aws_random_access_set *set) {
+ if (!set) {
+ return;
+ }
+ s_impl_destroy(set->impl);
+}
+
+int aws_random_access_set_add(struct aws_random_access_set *set, const void *element, bool *added) {
+ AWS_PRECONDITION(set);
+ AWS_PRECONDITION(element);
+ AWS_PRECONDITION(added);
+ bool exist = false;
+ if (aws_random_access_set_exist(set, element, &exist) || exist) {
+ *added = false;
+ return AWS_OP_SUCCESS;
+ }
+ /* deep copy the pointer of element to store at the array list */
+ if (aws_array_list_push_back(&set->impl->list, (void *)&element)) {
+ goto list_push_error;
+ }
+ if (aws_hash_table_put(&set->impl->map, element, (void *)(aws_array_list_length(&set->impl->list) - 1), NULL)) {
+ goto error;
+ }
+ *added = true;
+ return AWS_OP_SUCCESS;
+error:
+ aws_array_list_pop_back(&set->impl->list);
+list_push_error:
+ *added = false;
+ return AWS_OP_ERR;
+}
+
+int aws_random_access_set_remove(struct aws_random_access_set *set, const void *element) {
+ AWS_PRECONDITION(set);
+ AWS_PRECONDITION(element);
+ size_t current_length = aws_array_list_length(&set->impl->list);
+ if (current_length == 0) {
+ /* Nothing to remove */
+ return AWS_OP_SUCCESS;
+ }
+ struct aws_hash_element *find = NULL;
+ /* find and remove the element from table */
+ if (aws_hash_table_find(&set->impl->map, element, &find)) {
+ return AWS_OP_ERR;
+ }
+ if (!find) {
+ /* It's removed already */
+ return AWS_OP_SUCCESS;
+ }
+
+ size_t index_to_remove = (size_t)find->value;
+ if (aws_hash_table_remove_element(&set->impl->map, find)) {
+ return AWS_OP_ERR;
+ }
+ /* If assert code failed, we won't be recovered from the failure */
+ int assert_re = AWS_OP_SUCCESS;
+ (void)assert_re;
+ /* Nothing else can fail after here. */
+ if (index_to_remove != current_length - 1) {
+ /* It's not the last element, we need to swap it with the end of the list and remove the last element */
+ void *last_element = NULL;
+ /* The last element is a pointer of pointer of element. */
+ assert_re = aws_array_list_get_at_ptr(&set->impl->list, &last_element, current_length - 1);
+ AWS_ASSERT(assert_re == AWS_OP_SUCCESS);
+ /* Update the last element index in the table */
+ struct aws_hash_element *element_to_update = NULL;
+ assert_re = aws_hash_table_find(&set->impl->map, *(void **)last_element, &element_to_update);
+ AWS_ASSERT(assert_re == AWS_OP_SUCCESS);
+ AWS_ASSERT(element_to_update != NULL);
+ element_to_update->value = (void *)index_to_remove;
+ /* Swap the last element with the element to remove in the list */
+ aws_array_list_swap(&set->impl->list, index_to_remove, current_length - 1);
+ }
+ /* Remove the current last element from the list */
+ assert_re = aws_array_list_pop_back(&set->impl->list);
+ AWS_ASSERT(assert_re == AWS_OP_SUCCESS);
+ if (set->impl->destroy_element_fn) {
+ set->impl->destroy_element_fn((void *)element);
+ }
+ return AWS_OP_SUCCESS;
+}
+
+int aws_random_access_set_random_get_ptr(const struct aws_random_access_set *set, void **out) {
+ AWS_PRECONDITION(set);
+ AWS_PRECONDITION(out != NULL);
+ size_t length = aws_array_list_length(&set->impl->list);
+ if (length == 0) {
+ return aws_raise_error(AWS_ERROR_LIST_EMPTY);
+ }
+
+ uint64_t random_64_bit_num = 0;
+ aws_device_random_u64(&random_64_bit_num);
+
+ size_t index = (size_t)random_64_bit_num % length;
+ /* The array list stores the pointer of the element. */
+ return aws_array_list_get_at(&set->impl->list, (void *)out, index);
+}
+
+size_t aws_random_access_set_get_size(const struct aws_random_access_set *set) {
+ return aws_array_list_length(&set->impl->list);
+}
+
+int aws_random_access_set_exist(const struct aws_random_access_set *set, const void *element, bool *exist) {
+ AWS_PRECONDITION(set);
+ AWS_PRECONDITION(element);
+ AWS_PRECONDITION(exist);
+ struct aws_hash_element *find = NULL;
+ int re = aws_hash_table_find(&set->impl->map, element, &find);
+ *exist = find != NULL;
+ return re;
+}
+
+int aws_random_access_set_random_get_ptr_index(const struct aws_random_access_set *set, void **out, size_t index) {
+ AWS_PRECONDITION(set);
+ AWS_PRECONDITION(out != NULL);
+ return aws_array_list_get_at(&set->impl->list, (void *)out, index);
+}