#ifndef AWS_COMMON_LINKED_LIST_H #define AWS_COMMON_LINKED_LIST_H /** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ #include #include struct aws_linked_list_node { struct aws_linked_list_node *next; struct aws_linked_list_node *prev; }; struct aws_linked_list { struct aws_linked_list_node head; struct aws_linked_list_node tail; }; AWS_EXTERN_C_BEGIN /** * Set node's next and prev pointers to NULL. */ AWS_STATIC_IMPL void aws_linked_list_node_reset(struct aws_linked_list_node *node); /** * These functions need to be defined first as they are used in pre * and post conditions. */ /** * Tests if the list is empty. */ AWS_STATIC_IMPL bool aws_linked_list_empty(const struct aws_linked_list *list); /** * Checks that a linked list is valid. */ AWS_STATIC_IMPL bool aws_linked_list_is_valid(const struct aws_linked_list *list); /** * Checks that the prev of the next pointer of a node points to the * node. As this checks whether the [next] connection of a node is * bidirectional, it returns false if used for the list tail. */ AWS_STATIC_IMPL bool aws_linked_list_node_next_is_valid(const struct aws_linked_list_node *node); /** * Checks that the next of the prev pointer of a node points to the * node. Similarly to the above, this returns false if used for the * head of a list. */ AWS_STATIC_IMPL bool aws_linked_list_node_prev_is_valid(const struct aws_linked_list_node *node); /** * Checks that a linked list satisfies double linked list connectivity * constraints. This check is O(n) as it traverses the whole linked * list to ensure that tail is reachable from head (and vice versa) * and that every connection is bidirectional. * * Note: This check *cannot* go into an infinite loop, because we * ensure that the connection to the next node is * bidirectional. Therefore, if a node's [a] a.next is a previous node * [b] in the list, b.prev != &a and so this check would fail, thus * terminating the loop. */ AWS_STATIC_IMPL bool aws_linked_list_is_valid_deep(const struct aws_linked_list *list); /** * Initializes the list. List will be empty after this call. */ AWS_STATIC_IMPL void aws_linked_list_init(struct aws_linked_list *list); /** * Returns an iteration pointer for the first element in the list. */ AWS_STATIC_IMPL struct aws_linked_list_node *aws_linked_list_begin(const struct aws_linked_list *list); /** * Returns an iteration pointer for one past the last element in the list. */ AWS_STATIC_IMPL const struct aws_linked_list_node *aws_linked_list_end(const struct aws_linked_list *list); /** * Returns a pointer for the last element in the list. * Used to begin iterating the list in reverse. Ex: * for (i = aws_linked_list_rbegin(list); i != aws_linked_list_rend(list); i = aws_linked_list_prev(i)) {...} */ AWS_STATIC_IMPL struct aws_linked_list_node *aws_linked_list_rbegin(const struct aws_linked_list *list); /** * Returns the pointer to one before the first element in the list. * Used to end iterating the list in reverse. */ AWS_STATIC_IMPL const struct aws_linked_list_node *aws_linked_list_rend(const struct aws_linked_list *list); /** * Returns the next element in the list. */ AWS_STATIC_IMPL struct aws_linked_list_node *aws_linked_list_next(const struct aws_linked_list_node *node); /** * Returns the previous element in the list. */ AWS_STATIC_IMPL struct aws_linked_list_node *aws_linked_list_prev(const struct aws_linked_list_node *node); /** * Inserts to_add immediately after after. */ AWS_STATIC_IMPL void aws_linked_list_insert_after( struct aws_linked_list_node *after, struct aws_linked_list_node *to_add); /** * Swaps the order two nodes in the linked list. */ AWS_STATIC_IMPL void aws_linked_list_swap_nodes(struct aws_linked_list_node *a, struct aws_linked_list_node *b); /** * Inserts to_add immediately before before. */ AWS_STATIC_IMPL void aws_linked_list_insert_before( struct aws_linked_list_node *before, struct aws_linked_list_node *to_add); /** * Removes the specified node from the list (prev/next point to each other) and * returns the next node in the list. */ AWS_STATIC_IMPL void aws_linked_list_remove(struct aws_linked_list_node *node); /** * Append new_node. */ AWS_STATIC_IMPL void aws_linked_list_push_back(struct aws_linked_list *list, struct aws_linked_list_node *node); /** * Returns the element in the back of the list. */ AWS_STATIC_IMPL struct aws_linked_list_node *aws_linked_list_back(const struct aws_linked_list *list); /** * Returns the element in the back of the list and removes it */ AWS_STATIC_IMPL struct aws_linked_list_node *aws_linked_list_pop_back(struct aws_linked_list *list); /** * Prepend new_node. */ AWS_STATIC_IMPL void aws_linked_list_push_front(struct aws_linked_list *list, struct aws_linked_list_node *node); /** * Returns the element in the front of the list. */ AWS_STATIC_IMPL struct aws_linked_list_node *aws_linked_list_front(const struct aws_linked_list *list); /** * Returns the element in the front of the list and removes it */ AWS_STATIC_IMPL struct aws_linked_list_node *aws_linked_list_pop_front(struct aws_linked_list *list); AWS_STATIC_IMPL void aws_linked_list_swap_contents( struct aws_linked_list *AWS_RESTRICT a, struct aws_linked_list *AWS_RESTRICT b); /** * Remove all nodes from one list, and add them to the back of another. * * Example: if dst={1,2} and src={3,4}, they become dst={1,2,3,4} and src={} */ AWS_STATIC_IMPL void aws_linked_list_move_all_back( struct aws_linked_list *AWS_RESTRICT dst, struct aws_linked_list *AWS_RESTRICT src); /** * Remove all nodes from one list, and add them to the front of another. * * Example: if dst={2,1} and src={4,3}, they become dst={4,3,2,1} and src={} */ AWS_STATIC_IMPL void aws_linked_list_move_all_front( struct aws_linked_list *AWS_RESTRICT dst, struct aws_linked_list *AWS_RESTRICT src); #ifndef AWS_NO_STATIC_IMPL # include #endif /* AWS_NO_STATIC_IMPL */ AWS_EXTERN_C_END #endif /* AWS_COMMON_LINKED_LIST_H */