e910aee184
* Finish clang-format on lists
262 lines
6.4 KiB
C
262 lines
6.4 KiB
C
/** @file list.h
|
|
*
|
|
* @brief A doubly-linked list
|
|
*
|
|
* List Implementation
|
|
* ===================
|
|
*
|
|
* - This @ref List operates as a linked list @ref ListNodes. It operates as a regular doubly-linked list
|
|
* but doesn't allocate memory and rather gets @ref ListNodes from a pool.
|
|
*/
|
|
#ifndef LIST_H
|
|
#define LIST_H
|
|
|
|
#include <stdbool.h>
|
|
|
|
#define MAX_LIST_NODES 128
|
|
|
|
typedef struct ListNode ListNode;
|
|
|
|
/**
|
|
* @brief A single entry in a @ref List
|
|
*/
|
|
struct ListNode
|
|
{
|
|
/**
|
|
* @brief The previous @ref ListNode in the associated @ref List, NULL if at the `head` of the list
|
|
*/
|
|
ListNode* prev;
|
|
|
|
/**
|
|
* @brief The next @ref ListNode in the associated @ref List, NULL if at the `tail` of the list
|
|
*/
|
|
ListNode* next;
|
|
|
|
/**
|
|
* @brief Pointer to generic data stored in this node
|
|
*/
|
|
void* data;
|
|
};
|
|
|
|
/**
|
|
* @brief A doubly-linked list
|
|
*/
|
|
typedef struct List
|
|
{
|
|
/**
|
|
* @brief The first entry in the list
|
|
*/
|
|
ListNode* head;
|
|
|
|
/**
|
|
* @brief The last entry in the list
|
|
*/
|
|
ListNode* tail;
|
|
|
|
/**
|
|
* @brief Number of elements in list
|
|
*/
|
|
int len;
|
|
} List;
|
|
|
|
/**
|
|
* @brief @ref ListItr direction
|
|
*/
|
|
enum ListItrDirection
|
|
{
|
|
LIST_ITR_FORWARD,
|
|
LIST_ITR_REVERSE,
|
|
};
|
|
|
|
/**
|
|
* @brief An iterator into a list
|
|
*/
|
|
typedef struct
|
|
{
|
|
/**
|
|
* @brief A pointer to the @ref List this is iterating through
|
|
*/
|
|
List* list;
|
|
|
|
/**
|
|
* @brief The next node in the list
|
|
*/
|
|
ListNode* next_node;
|
|
|
|
/**
|
|
* @brief The current node in the list iterator
|
|
*
|
|
* The node of the most recently returned data from @ref list_itr_next() .
|
|
*/
|
|
ListNode* current_node;
|
|
|
|
/**
|
|
* @brief The direction of the iterator
|
|
*/
|
|
enum ListItrDirection direction;
|
|
} ListItr;
|
|
|
|
/**
|
|
* Create a list.
|
|
*
|
|
* While this function does not allocate memory for the list itself, the list does allocate memory for each element.
|
|
* So every created list must be freed with @ref list_clear to ensure the list's nodes are deleted properly.
|
|
*
|
|
* @return A @ref List with head and tail reset.
|
|
*/
|
|
List list_create(void);
|
|
|
|
/**
|
|
* Clear a list.
|
|
*
|
|
* Go through the list and free each node and set the `head` and `tail` to `NULL`.
|
|
* Note, it doesn't "free" the data at the node.
|
|
*
|
|
* @param list pointer to a @ref List to clear
|
|
*/
|
|
void list_clear(List* list);
|
|
|
|
/**
|
|
* Check if a list is empty
|
|
*
|
|
* @param list pointer to a @ref List
|
|
*
|
|
* @return `true` if the `list` is empty, `false` otherwise.
|
|
*/
|
|
bool list_is_empty(const List* list);
|
|
|
|
/**
|
|
* Prepend an entry to the `head` of a @ref list
|
|
*
|
|
* @param list pointer to a @ref List
|
|
* @param data pointer to data to put into the @ref List
|
|
*/
|
|
void list_push_front(List* list, void* data);
|
|
|
|
/**
|
|
* Append an entry to the `tail` of a @ref list
|
|
*
|
|
* @param list pointer to a @ref List
|
|
* @param data pointer to data to put into the @ref List
|
|
*/
|
|
void list_push_back(List* list, void* data);
|
|
|
|
/**
|
|
* Insert data into a @ref List a specific index
|
|
*
|
|
* If the index specified is larger than the length of the list
|
|
* it will @ref list_push_back() the data instead;
|
|
*
|
|
* Performs the following operation:
|
|
*
|
|
* ┌─────┐
|
|
* │ node│
|
|
* └─────┘
|
|
* ┌─────┐ ┌─────┐ ┌─────┐
|
|
* │idx-1│◄─►│ idx │◄─►│idx+1│
|
|
* └─────┘ └─────┘ └─────┘
|
|
*
|
|
* 1. Set new `node` `prev` to the node at idx - 1
|
|
* 2. Set new `node` `next` to the node at idx
|
|
* 3. Set node at idx - 1 `next` to new `node`
|
|
* 4. Set node at idx `prev` to the new `node`
|
|
*
|
|
* Result:
|
|
*
|
|
* ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐
|
|
* │idx-1│◄─►│ node│◄─►│ idx │◄─►│idx+1│
|
|
* └─────┘ └─────┘ └─────┘ └─────┘
|
|
*
|
|
* Finally, the list is now updated with new `node` now at the labeled idx:
|
|
*
|
|
* ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐
|
|
* │idx-1│◄─►│ idx │◄─►│idx+1│◄─►│idx+2│
|
|
* └─────┘ └─────┘ └─────┘ └─────┘
|
|
*
|
|
* @param list pointer to a @ref List
|
|
* @param data pointer to data to put into the @ref List
|
|
* @param idx desired index to insert
|
|
*/
|
|
void list_insert(List* list, void* data, unsigned int idx);
|
|
|
|
/**
|
|
* Swap the data pointers at the specified indices of a @ref List
|
|
*
|
|
* If either indices are larger than the length of the list, return false.
|
|
*
|
|
* @param list pointer to a @ref List
|
|
* @param idx_a desired index to swap with idx_b
|
|
* @param idx_b desired index to swap with idx_a
|
|
*
|
|
* @return true if successful, false otherwise
|
|
*/
|
|
bool list_swap(List* list, unsigned int idx_a, unsigned int idx_b);
|
|
|
|
/**
|
|
* Get a List's node at the specified index
|
|
*
|
|
* @param list pointer to a @ref List
|
|
* @param idx index of the desired @ref ListNode in the list
|
|
*
|
|
* @return a pointer to the data at the index of the list, or NULL if out-of-bounds
|
|
*/
|
|
void* list_get_at_idx(List* list, unsigned int idx);
|
|
|
|
/**
|
|
* Remove a List's node at the specified index
|
|
*
|
|
* @param list pointer to a @ref List
|
|
* @param idx index of the desired @ref ListNode in the list
|
|
*
|
|
* @return `true` if successfully removed, `false` if out-of-bounds
|
|
*/
|
|
bool list_remove_at_idx(List* list, unsigned int idx);
|
|
|
|
/**
|
|
* Get the number of elements in a @ref List
|
|
*
|
|
* @param list pointer to a @ref List
|
|
*
|
|
* @return The number of elements in the list
|
|
*/
|
|
int list_get_len(const List* list);
|
|
|
|
/**
|
|
* Declare a @ref ListItr
|
|
*
|
|
* @param list pointer to a @ref List
|
|
*
|
|
* @return A new @ref ListItr
|
|
*/
|
|
ListItr list_itr_create(List* list);
|
|
|
|
/**
|
|
* Declare a reverse @ref ListItr
|
|
*
|
|
* @param list pointer to a @ref List
|
|
*
|
|
* @return A new reverse @ref ListItr
|
|
*/
|
|
ListItr rev_list_itr_create(List* list);
|
|
|
|
/**
|
|
* Get the next data entry in a @ref ListItr
|
|
*
|
|
* @param itr pointer to the @ref ListItr
|
|
*
|
|
* @return A pointer to the data pointer at the next @ref ListNode if valid, otherwise return NULL.
|
|
*/
|
|
void* list_itr_next(ListItr* itr);
|
|
|
|
/**
|
|
* Remove the current @ref ListNode from the iterator.
|
|
*
|
|
* The "current node" corresponds to the list node associated with the
|
|
* most recently returned valu from @ref list_itr_next()
|
|
*
|
|
* @param itr pointer to the @ref ListItr
|
|
*/
|
|
void list_itr_remove_current_node(ListItr* itr);
|
|
|
|
#endif
|