197 lines
6.3 KiB
C
197 lines
6.3 KiB
C
#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 <aws/common/common.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
AWS_PUSH_SANE_WARNING_LEVEL
|
|
|
|
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);
|
|
|
|
/**
|
|
* Returns true if the node is currently in a list, false otherwise.
|
|
*/
|
|
AWS_STATIC_IMPL bool aws_linked_list_node_is_in_list(struct aws_linked_list_node *node);
|
|
AWS_EXTERN_C_END
|
|
|
|
#ifndef AWS_NO_STATIC_IMPL
|
|
# include <aws/common/linked_list.inl>
|
|
#endif /* AWS_NO_STATIC_IMPL */
|
|
AWS_POP_SANE_WARNING_LEVEL
|
|
|
|
#endif /* AWS_COMMON_LINKED_LIST_H */
|