|
C Container Collection (CCC)
|
The Doubly Linked List Interface. More...


Go to the source code of this file.
The Doubly Linked List Interface.
A doubly linked list offers efficient push, pop, extract, and erase operations for elements stored in the list. For single elements, the list can offer O(1) push front/back, pop front/back, and removal of elements in arbitrary positions in the list. The cost of this efficiency is higher memory footprint.
This container offers pointer stability. Also, if the container is not permitted to allocate all insertion code assumes that the user has allocated memory appropriately for the element to be inserted; it will not allocate or free in this case. If allocation is permitted upon initialization the container will manage the memory as expected on insert or erase operations as defined by the interface; memory is allocated for insertions and freed for removals.
To shorten names in the interface, define the following preprocessor directive at the top of your file.
All types and functions can then be written without the CCC_ prefix.
Initialization Interface | |
Initialize the container with memory, callbacks, and permissions. | |
| #define | CCC_doubly_linked_list_initialize(struct_name, type_intruder_field, compare, allocate, context_data) |
| Initialize a doubly linked list with its l-value name, type containing the Doubly_linked_list elems, the field of the doubly_linked_list elem, allocation function, compare function and any context data needed for comparison, printing, or destructors. | |
| #define | CCC_doubly_linked_list_from(type_intruder_field, compare, allocate, destroy, context_data, compound_literal_array...) |
| Initialize a doubly linked list at runtime from a compound literal array. | |
Insert and Remove Interface | |
Add or remove elements from the doubly linked list. | |
| #define | CCC_doubly_linked_list_emplace_back(list_pointer, type_compound_literal...) |
| writes contents of type initializer directly to allocated memory at the back of the list. O(1). | |
| #define | CCC_doubly_linked_list_emplace_front(list_pointer, type_compound_literal...) |
| writes contents of type initializer directly to allocated memory at the front of the list. O(1). | |
| void * | CCC_doubly_linked_list_push_front (CCC_Doubly_linked_list *list, CCC_Doubly_linked_list_node *type_intruder) |
| Push user type wrapping type_intruder to the front of the list. O(1). | |
| void * | CCC_doubly_linked_list_push_back (CCC_Doubly_linked_list *list, CCC_Doubly_linked_list_node *type_intruder) |
| Push user type wrapping type_intruder to the back of the list. O(1). | |
| void * | CCC_doubly_linked_list_insert (CCC_Doubly_linked_list *list, CCC_Doubly_linked_list_node *position_node, CCC_Doubly_linked_list_node *type_intruder) |
| Insert user type wrapping type_intruder before position_node. O(1). | |
| CCC_Result | CCC_doubly_linked_list_pop_front (CCC_Doubly_linked_list *list) |
| Pop the user type at the front of the list. O(1). | |
| CCC_Result | CCC_doubly_linked_list_pop_back (CCC_Doubly_linked_list *list) |
| Pop the user type at the back of the list. O(1). | |
| void * | CCC_doubly_linked_list_extract (CCC_Doubly_linked_list *list, CCC_Doubly_linked_list_node *type_intruder) |
| Returns the element following an extracted element from the list without deallocating regardless of allocation permission provided to the container. O(1). | |
| void * | CCC_doubly_linked_list_erase (CCC_Doubly_linked_list *list, CCC_Doubly_linked_list_node *type_intruder) |
| Returns the element following an erased element from the list. O(1). | |
| void * | CCC_doubly_linked_list_erase_range (CCC_Doubly_linked_list *list, CCC_Doubly_linked_list_node *type_intruder_begin, CCC_Doubly_linked_list_node *type_intruder_end) |
| Returns the element following an extracted range of elements from the list. O(N). | |
| void * | CCC_doubly_linked_list_extract_range (CCC_Doubly_linked_list *list, CCC_Doubly_linked_list_node *type_intruder_begin, CCC_Doubly_linked_list_node *type_intruder_end) |
| Returns the element following an extracted range of elements from the list without deallocating regardless of allocation permission provided to the container. O(N). | |
| CCC_Result | CCC_doubly_linked_list_splice (CCC_Doubly_linked_list *position_doubly_linked_list, CCC_Doubly_linked_list_node *type_intruder_position, CCC_Doubly_linked_list *to_cut_doubly_linked_list, CCC_Doubly_linked_list_node *type_intruder_to_cut) |
| Repositions to_cut before pos. Only list pointers are modified. O(1). | |
| CCC_Result | CCC_doubly_linked_list_splice_range (CCC_Doubly_linked_list *position_doubly_linked_list, CCC_Doubly_linked_list_node *type_intruder_position, CCC_Doubly_linked_list *to_cut_doubly_linked_list, CCC_Doubly_linked_list_node *type_intruder_to_cut_begin, CCC_Doubly_linked_list_node *type_intruder_to_cut_exclusive_end) |
| Splices the list to cut before the specified position. The range being cut is exclusive from [start, end), meaning the final element provided is not move. This is an O(N) operation. | |
Container Types | |
Types available in the container interface. | |
| typedef struct CCC_Doubly_linked_list | CCC_Doubly_linked_list |
| A container offering bidirectional, insert, removal, and iteration. | |
| typedef struct CCC_Doubly_linked_list_node | CCC_Doubly_linked_list_node |
| A doubly linked list intrusive element to embedded in a user type. | |
Sorting Interface | |
Sort the container. | |
| CCC_Result | CCC_doubly_linked_list_sort (CCC_Doubly_linked_list *doubly_linked_list) |
Sorts the doubly linked list in non-decreasing order as defined by the provided comparison function. O(N * log(N)) time, O(1) space. | |
| void * | CCC_doubly_linked_list_insert_sorted (CCC_Doubly_linked_list *doubly_linked_list, CCC_Doubly_linked_list_node *type_intruder) |
Inserts type_intruder in sorted position according to the non-decreasing order of the list determined by the user provided comparison function. O(1). | |
| CCC_Tribool | CCC_doubly_linked_list_is_sorted (CCC_Doubly_linked_list const *doubly_linked_list) |
| Returns true if the list is sorted in non-decreasing order according to the user provided comparison function. | |
Deallocation Interface | |
Deallocate the container. | |
| CCC_Result | CCC_doubly_linked_list_clear (CCC_Doubly_linked_list *list, CCC_Type_destructor *destroy) |
| Clear the contents of the list freeing elements, if given allocation permission. O(N). | |
Iteration Interface | |
Iterate through the doubly linked list. | |
| void * | CCC_doubly_linked_list_begin (CCC_Doubly_linked_list const *list) |
| Return the user type at the start of the list or NULL if empty. O(1). | |
| void * | CCC_doubly_linked_list_reverse_begin (CCC_Doubly_linked_list const *list) |
| Return the user type at the end of the list or NULL if empty. O(1). | |
| void * | CCC_doubly_linked_list_next (CCC_Doubly_linked_list const *list, CCC_Doubly_linked_list_node const *type_intruder) |
| Return the user type following the element known to be in the list. O(1). | |
| void * | CCC_doubly_linked_list_reverse_next (CCC_Doubly_linked_list const *list, CCC_Doubly_linked_list_node const *type_intruder) |
| Return the user type following the element known to be in the list moving from back to front. O(1). | |
| void * | CCC_doubly_linked_list_end (CCC_Doubly_linked_list const *list) |
| Return the end sentinel with no accessible fields. O(1). | |
| void * | CCC_doubly_linked_list_reverse_end (CCC_Doubly_linked_list const *list) |
| Return the start sentinel with no accessible fields. O(1). | |
State Interface | |
Obtain state from the doubly linked list. | |
| void * | CCC_doubly_linked_list_front (CCC_Doubly_linked_list const *list) |
| Returns the user type at the front of the list. O(1). | |
| void * | CCC_doubly_linked_list_back (CCC_Doubly_linked_list const *list) |
| Returns the user type at the back of the list. O(1). | |
| CCC_Doubly_linked_list_node * | CCC_doubly_linked_list_node_begin (CCC_Doubly_linked_list const *list) |
| Return a handle to the list element at the front of the list which may be the sentinel. O(1). | |
| CCC_Count | CCC_doubly_linked_list_count (CCC_Doubly_linked_list const *list) |
| Return the count of elements in the list. O(1). | |
| CCC_Tribool | CCC_doubly_linked_list_is_empty (CCC_Doubly_linked_list const *list) |
| Return if the size of the list is equal to 0. O(1). | |
| CCC_Tribool | CCC_doubly_linked_list_validate (CCC_Doubly_linked_list const *list) |
| Validates internal state of the list. | |
| #define CCC_doubly_linked_list_emplace_back | ( | list_pointer, | |
| type_compound_literal... | |||
| ) |
writes contents of type initializer directly to allocated memory at the back of the list. O(1).
| [in] | list_pointer | the address of the doubly linked list. |
| [in] | type_compound_literal | the r-value initializer of the type to be inserted in the list. This should match the type containing Doubly_linked_list elements as a struct member for this list. |
Note that it does not make sense to use this method if the list has been initialized without an allocation function. If the user does not allow allocation, the contents of new elements to be inserted has been determined by the user prior to any inserts into the list.
| #define CCC_doubly_linked_list_emplace_front | ( | list_pointer, | |
| type_compound_literal... | |||
| ) |
writes contents of type initializer directly to allocated memory at the front of the list. O(1).
| [in] | list_pointer | the address of the doubly linked list. |
| [in] | type_compound_literal | the r-value initializer of the type to be inserted in the list. This should match the type containing Doubly_linked_list elements as a struct member for this list. |
Note that it does not make sense to use this method if the list has been initialized without an allocation function. If the user does not allow allocation, the contents of new elements to be inserted has been determined by the user prior to any inserts into the list.
| #define CCC_doubly_linked_list_from | ( | type_intruder_field, | |
| compare, | |||
| allocate, | |||
| destroy, | |||
| context_data, | |||
| compound_literal_array... | |||
| ) |
Initialize a doubly linked list at runtime from a compound literal array.
| [in] | type_intruder_field | the name of the field intruding on user's type. |
| [in] | compare | the comparison function for the user type. |
| [in] | allocate | the allocation function required for construction. |
| [in] | destroy | the optional destructor to run if insertion fails. |
| [in] | context_data | context data needed for comparison or destruction. |
| [in] | compound_literal_array | the array of user types to insert into the map (e.g. (struct My_type[]){ {.val = 1}, {.val = 2}}). |
| #define CCC_doubly_linked_list_initialize | ( | struct_name, | |
| type_intruder_field, | |||
| compare, | |||
| allocate, | |||
| context_data | |||
| ) |
Initialize a doubly linked list with its l-value name, type containing the Doubly_linked_list elems, the field of the doubly_linked_list elem, allocation function, compare function and any context data needed for comparison, printing, or destructors.
| [in] | struct_name | the type containing the intrusive doubly_linked_list element. |
| [in] | type_intruder_field | name of the Doubly_linked_list element in the containing type. |
| [in] | compare | the CCC_Type_comparator used to compare list elements. |
| [in] | context_data | any context data that will be needed for comparison, printing, or destruction of elements. |
| [in] | allocate | the optional allocation function or NULL. |
| typedef struct CCC_Doubly_linked_list CCC_Doubly_linked_list |
A container offering bidirectional, insert, removal, and iteration.
A doubly linked list may be stored in the stack, heap, or data segment. Once initialized it is passed by reference to all functions. A doubly linked list can be initialized at compile time or runtime.
| typedef struct CCC_Doubly_linked_list_node CCC_Doubly_linked_list_node |
A doubly linked list intrusive element to embedded in a user type.
It can be used in an allocating or non allocating container. If allocation is prohibited the container assumes the element is wrapped in pre-allocated memory with the appropriate lifetime and scope for the user's needs; the container does not allocate or free in this case. If allocation is allowed the container will handle copying the data wrapping the element to allocations and deallocating when necessary.
| void * CCC_doubly_linked_list_back | ( | CCC_Doubly_linked_list const * | list | ) |
Returns the user type at the back of the list. O(1).
| [in] | list | a pointer to the doubly linked list. |
| void * CCC_doubly_linked_list_begin | ( | CCC_Doubly_linked_list const * | list | ) |
Return the user type at the start of the list or NULL if empty. O(1).
| [in] | list | a pointer to the doubly linked list. |
| CCC_Result CCC_doubly_linked_list_clear | ( | CCC_Doubly_linked_list * | list, |
| CCC_Type_destructor * | destroy | ||
| ) |
Clear the contents of the list freeing elements, if given allocation permission. O(N).
| [in] | list | a pointer to the doubly linked list. |
| [in] | destroy | a destructor function to run on each element. |
Note that if the list is initialized with allocation permission it will free elements for the user and the destructor function should only perform context cleanup, otherwise a double free will occur.
If the list has not been given allocation permission the user should free the list elements with the destructor if they wish to do so. The implementation ensures the function is called after the element is removed. Otherwise, the user must manage their elements at their discretion after the list is emptied in this function.
| CCC_Count CCC_doubly_linked_list_count | ( | CCC_Doubly_linked_list const * | list | ) |
Return the count of elements in the list. O(1).
| [in] | list | a pointer to the doubly linked list. |
| void * CCC_doubly_linked_list_end | ( | CCC_Doubly_linked_list const * | list | ) |
Return the end sentinel with no accessible fields. O(1).
| [in] | list | a pointer to the doubly linked list. |
| void * CCC_doubly_linked_list_erase | ( | CCC_Doubly_linked_list * | list, |
| CCC_Doubly_linked_list_node * | type_intruder | ||
| ) |
Returns the element following an erased element from the list. O(1).
| [in] | list | a pointer to the doubly linked list. |
| [in] | type_intruder | the handle of an element known to be in the list. |
| void * CCC_doubly_linked_list_erase_range | ( | CCC_Doubly_linked_list * | list, |
| CCC_Doubly_linked_list_node * | type_intruder_begin, | ||
| CCC_Doubly_linked_list_node * | type_intruder_end | ||
| ) |
Returns the element following an extracted range of elements from the list. O(N).
| [in] | list | a pointer to the doubly linked list. |
| [in] | type_intruder_begin | the handle of an element known to be in the list at the start of the range. |
| [in] | type_intruder_end | the handle of an element known to be in the list at the end of the range following type_intruder_begin. |
Note that if the user does not permit the container to allocate they may iterate through the extracted range in the same way one iterates through a normal list using the iterator function. If allocation is allowed, all elements from type_intruder_begin to type_intruder_end will be erased and references invalidated.
| void * CCC_doubly_linked_list_extract | ( | CCC_Doubly_linked_list * | list, |
| CCC_Doubly_linked_list_node * | type_intruder | ||
| ) |
Returns the element following an extracted element from the list without deallocating regardless of allocation permission provided to the container. O(1).
| [in] | list | a pointer to the doubly linked list. |
| [in] | type_intruder | the handle of an element known to be in the list. |
| void * CCC_doubly_linked_list_extract_range | ( | CCC_Doubly_linked_list * | list, |
| CCC_Doubly_linked_list_node * | type_intruder_begin, | ||
| CCC_Doubly_linked_list_node * | type_intruder_end | ||
| ) |
Returns the element following an extracted range of elements from the list without deallocating regardless of allocation permission provided to the container. O(N).
| [in] | list | a pointer to the doubly linked list. |
| [in] | type_intruder_begin | the handle of an element known to be in the list at the start of the range. |
| [in] | type_intruder_end | the handle of an element known to be in the list at the end of the range following type_intruder_begin. |
Note that the user may iterate through the extracted range in the same way one iterates through a normal list using the iterator function.
| void * CCC_doubly_linked_list_front | ( | CCC_Doubly_linked_list const * | list | ) |
Returns the user type at the front of the list. O(1).
| [in] | list | a pointer to the doubly linked list. |
| void * CCC_doubly_linked_list_insert | ( | CCC_Doubly_linked_list * | list, |
| CCC_Doubly_linked_list_node * | position_node, | ||
| CCC_Doubly_linked_list_node * | type_intruder | ||
| ) |
Insert user type wrapping type_intruder before position_node. O(1).
| [in] | list | a pointer to the doubly linked list. |
| [in] | position_node | a pointer to the list element before which type_intruder inserts. |
| [in] | type_intruder | a pointer to the list element. |
| void * CCC_doubly_linked_list_insert_sorted | ( | CCC_Doubly_linked_list * | doubly_linked_list, |
| CCC_Doubly_linked_list_node * | type_intruder | ||
| ) |
Inserts type_intruder in sorted position according to the non-decreasing order of the list determined by the user provided comparison function. O(1).
| [in] | doubly_linked_list | a pointer to the doubly linked list. |
| [in] | type_intruder | a pointer to the element to be inserted in order. |
If a non-increasing order is desired, return opposite results from the user comparison function. If an element is CCC_ORDER_LESSERERS return CCC_ORDER_GREATER and vice versa. If elements are equal, return CCC_ORDER_EQUAL.
| CCC_Tribool CCC_doubly_linked_list_is_empty | ( | CCC_Doubly_linked_list const * | list | ) |
Return if the size of the list is equal to 0. O(1).
| [in] | list | a pointer to the doubly linked list. |
| CCC_Tribool CCC_doubly_linked_list_is_sorted | ( | CCC_Doubly_linked_list const * | doubly_linked_list | ) |
Returns true if the list is sorted in non-decreasing order according to the user provided comparison function.
| [in] | doubly_linked_list | a pointer to the singly linked list. |
If a non-increasing order is desired, return opposite results from the user comparison function. If an element is CCC_ORDER_LESSER return CCC_ORDER_GREATER and vice versa. If elements are equal, return CCC_ORDER_EQUAL.
| void * CCC_doubly_linked_list_next | ( | CCC_Doubly_linked_list const * | list, |
| CCC_Doubly_linked_list_node const * | type_intruder | ||
| ) |
Return the user type following the element known to be in the list. O(1).
| [in] | list | a pointer to the doubly linked list. |
| [in] | type_intruder | a handle to the list element known to be in the list. |
| CCC_Doubly_linked_list_node * CCC_doubly_linked_list_node_begin | ( | CCC_Doubly_linked_list const * | list | ) |
Return a handle to the list element at the front of the list which may be the sentinel. O(1).
| [in] | list | a pointer to the doubly linked list. |
| CCC_Result CCC_doubly_linked_list_pop_back | ( | CCC_Doubly_linked_list * | list | ) |
Pop the user type at the back of the list. O(1).
| [in] | list | a pointer to the doubly linked list. |
| CCC_Result CCC_doubly_linked_list_pop_front | ( | CCC_Doubly_linked_list * | list | ) |
Pop the user type at the front of the list. O(1).
| [in] | list | a pointer to the doubly linked list. |
| void * CCC_doubly_linked_list_push_back | ( | CCC_Doubly_linked_list * | list, |
| CCC_Doubly_linked_list_node * | type_intruder | ||
| ) |
Push user type wrapping type_intruder to the back of the list. O(1).
| [in] | list | a pointer to the doubly linked list. |
| [in] | type_intruder | a pointer to the list element. |
| void * CCC_doubly_linked_list_push_front | ( | CCC_Doubly_linked_list * | list, |
| CCC_Doubly_linked_list_node * | type_intruder | ||
| ) |
Push user type wrapping type_intruder to the front of the list. O(1).
| [in] | list | a pointer to the doubly linked list. |
| [in] | type_intruder | a pointer to the list element. |
| void * CCC_doubly_linked_list_reverse_begin | ( | CCC_Doubly_linked_list const * | list | ) |
Return the user type at the end of the list or NULL if empty. O(1).
| [in] | list | a pointer to the doubly linked list. |
| void * CCC_doubly_linked_list_reverse_end | ( | CCC_Doubly_linked_list const * | list | ) |
Return the start sentinel with no accessible fields. O(1).
| [in] | list | a pointer to the doubly linked list. |
| void * CCC_doubly_linked_list_reverse_next | ( | CCC_Doubly_linked_list const * | list, |
| CCC_Doubly_linked_list_node const * | type_intruder | ||
| ) |
Return the user type following the element known to be in the list moving from back to front. O(1).
| [in] | list | a pointer to the doubly linked list. |
| [in] | type_intruder | a handle to the list element known to be in the list. |
| CCC_Result CCC_doubly_linked_list_sort | ( | CCC_Doubly_linked_list * | doubly_linked_list | ) |
Sorts the doubly linked list in non-decreasing order as defined by the provided comparison function. O(N * log(N)) time, O(1) space.
| [in] | doubly_linked_list | a pointer to the doubly linked list to sort. |
| CCC_Result CCC_doubly_linked_list_splice | ( | CCC_Doubly_linked_list * | position_doubly_linked_list, |
| CCC_Doubly_linked_list_node * | type_intruder_position, | ||
| CCC_Doubly_linked_list * | to_cut_doubly_linked_list, | ||
| CCC_Doubly_linked_list_node * | type_intruder_to_cut | ||
| ) |
Repositions to_cut before pos. Only list pointers are modified. O(1).
| [in] | position_doubly_linked_list | the list to which position belongs. |
| [in] | type_intruder_position | the position before which to_cut will be moved. |
| [in] | to_cut_doubly_linked_list | the list to which to_cut belongs. |
| [in] | type_intruder_to_cut | the element to cut. |
| CCC_Result CCC_doubly_linked_list_splice_range | ( | CCC_Doubly_linked_list * | position_doubly_linked_list, |
| CCC_Doubly_linked_list_node * | type_intruder_position, | ||
| CCC_Doubly_linked_list * | to_cut_doubly_linked_list, | ||
| CCC_Doubly_linked_list_node * | type_intruder_to_cut_begin, | ||
| CCC_Doubly_linked_list_node * | type_intruder_to_cut_exclusive_end | ||
| ) |
Splices the list to cut before the specified position. The range being cut is exclusive from [start, end), meaning the final element provided is not move. This is an O(N) operation.
| [in] | position_doubly_linked_list | the list to which position belongs. |
| [in] | type_intruder_position | the position before which the list is moved. |
| [in] | to_cut_doubly_linked_list | the list to which the range belongs. |
| [in] | type_intruder_to_cut_begin | the start of the list to splice. |
| [in] | type_intruder_to_cut_exclusive_end | the exclusive end of the list to splice, not included in the splice operation. |
| CCC_Tribool CCC_doubly_linked_list_validate | ( | CCC_Doubly_linked_list const * | list | ) |
Validates internal state of the list.
| [in] | list | a pointer to the doubly linked list. |