====== linkedlist ======
A dual sided linked list structure. Used as the foundation for many other modules in ''%%libflint%%''
===== Usage =====
Create the list. The user is responsible for memory management of the ''%%List%%'' struct.
List *list = malloc(sizeof(List));
After the tree is created, init it. The second argument on ''%%bintree_init()%%'' is an optional memory freeing function pointer with signature ''%%void (*destroy)(void *data)%%''. Use ''%%free()%%'' from the stdlib if you are creating the data with ''%%malloc()%%''. If allocation of your data is more complex, you can pass your own memory deallocation function as long as it fits the signature.
In this example, we are passing ''%%NULL%%'' because all memory will be stack allocated.
ll_init(list, NULL);
int i = 1;
int j = 2;
int k = 4;
Next, insert data into the list. Data can be inserted from either side of a node.
ll_ins_next(list, list->head, (void *) &i);
ll_ins_next(list, list->tail, (void *) &j);
ll_ins_next(list, list->tail, (void *) &k);
/* List is now 1 2 4 */
Lists can have a node removed by either targeting the node directly or removing a node pointed to by the head or tail of another node. The user is responsible for the memory management of the data inside the node, which is why a ''%%void*%%'' must be supplied to hold the data. Since in this example our memory is stack allocated, we don’t need to worry about freeing the ''%%void*%%'' but one must still be supplied for the function to work.
/* List is 1 2 4 */
/* node is the 2nd node in the list with value 2 */
ListNode *node = list->head;
/* void pointer to the data inside of the node */
void *data;
ll_remove(list, node, &data);
/* List is now 1 4 */
printf("Removed: %d\n", *((int *) data));
/* Prints "2" */
Here is an alternative example using ''%%ll_remove_next()%%'' instead of ''%%ll_remove()%%''
/* node is the 2nd node in the list with value 2 */
ListNode *node = list->head;
void *data; /* void pointer to the data inside of the node */
ll_remove_next(list, node, &data);
/* List is now 1 2 */
printf("Removed: %d\n", *((int *) data));
/* Prints "4" */
To destroy the list, first call ''%%ll_destroy()%%'' to free the nodes in the list and optionally run the destroy function against the data stored in the list. Since this example is stack allocated and we passed ''%%NULL%%'' when creating the list, no destroy function is run against the memory in the nodes. The list itself must be deleted with ''%%free()%%''
ll_destroy(list);
free(list);
Complete example:
List *list = malloc(sizeof(List));
ll_init(list, NULL);
int i = 1;
int j = 2;
int k = 4;
ll_ins_next(list, list->head, (void *) &i);
ll_ins_next(list, list->tail, (void *) &j);
ll_ins_next(list, list->tail, (void *) &k);
printf("List: ");
print_ll(list);
void *data;
ll_remove_next(list, list->head, &data);
printf("List: ");
print_ll(list);
printf("Removed: %d\n", *((int *) data));
ll_destroy(list);
free(list);
===== Structs =====
==== List ====
Double ended linked list struct
typedef struct {
size_t size;
void (*destroy)(void *data);
int (*match)(const void *a, const void *b);
struct ListNode *head;
struct ListNode *tail;
} List;
Members:
* ''%%size%%'': How many nodes are in the list
* ''%%destroy%%'': Optional deallocation function for member data. Use ''%%NULL%%'' if data is stack allocated
* ''%%match%%'': Comparison function between data inside two nodes. This is not used by ''%%List%%'' itself, but is used in structures built on top of ''%%List%%''
* ''%%head%%'': Pointer to the ''%%ListNode%%'' at the head of the list
* ''%%tail%%'': Pointer to the ''%%ListNode%%'' at the tail of the list
==== ListNode ====
Node of the list
typedef struct ListNode {
void *data;
struct ListNode *next;
struct ListNode *prev;
} ListNode;
Members:
* ''%%data%%'': void pointer to the member data in the node
* ''%%next%%'': Pointer to the ''%%ListNode%%'' before this node in the list
* ''%%prev%%'': Pointer to the ''%%ListNode%%'' after this node in the list
===== Functions =====
==== ll_init ====
Initialize the list. User is responsible for creating the initial ''%%List%%'' structure and freeing memory with ''%%ll_destroy()%%''. ''%%destroy%%'' is a deallocation function for the members of ''%%List%%'', pass ''%%NULL%%'' if the memory is stack-allocated
void ll_init(List *list, void (*destroy)(void *data));
/* Usage */
List *list = malloc(sizeof(Stack));
// Pass NULL for stack-allocated memory
ll_init(list, NULL);
// Pass free or a custom freeing function for heap allocated memory
ll_init(list, free);
==== ll_destroy ====
Destroys the nodes inside a list and calls the deallocation funciton on the data if one was provided. Does not destroy the list itself, that is left up to the user.
void ll_destroy(List *list);
==== ll_ins_next ====
Creates a new node containing ''%%data%%'' and inserts it after ''%%node%%''.
int ll_ins_next(List *list, ListNode *node, const void *data);
==== ll_ins_prev ====
Creates a new node containing ''%%data%%'' and inserts it before ''%%node%%''.
int ll_ins_prev(List *list, ListNode *node, const void *data);
==== ll_remove ====
Removes and deallocates the node pointed to by ''%%node%%''. The user is responsible for managing the contained data’s memory, as such the ''%%destroy%%'' function is **not** run by ''%%ll_remove()%%''
int ll_remove(List *list, ListNode *node, void **data);
==== ll_remove_next ====
Removes and deallocates the node pointed to by ''%%node%%''’s ''%%tail%%'' pointer. The user is responsible for managing the contained data’s memory, as such the ''%%destroy%%'' function is **not** run by ''%%ll_remove_next()%%''
int ll_remove_next(List *list, ListNode *node, void **data);
==== ll_remove_prev ====
Removes and deallocates the node pointed to by ''%%node%%''’s ''%%head%%'' pointer. The user is responsible for managing the contained data’s memory, as such the ''%%destroy%%'' function is **not** run by ''%%ll_remove_prev()%%''
int ll_remove_prev(List *list, ListNode *node, void **data);
===== Macros =====
==== LL_ITER ====
A utility macro that helps with iterating over an entire list. A ''%%ListNode%%'' pointer named ''%%node%%'' is created as part of this macro and can be used to access the current node in the iteration, so be careful your own variable naming if you intend to use ''%%LL_ITER%%''.
#define LL_ITER(list) for(ListNode *node = (list)->head; node != NULL; node = node->next)
/* Example with list of strings */
for LL_ITER(list) {
printf("%s\n", (char *)(node->data));
}