A generic implementation of LinkedList in C
Example
#include "list.h"
typedef struct IntElem {
int data;
struct IntElem *next;
} IntElem_t;
int main(int argc, char const *argv[])
{
LinkedList *list = LinkedListInit();
IntElem_t *iter, *rm;
for (int i = 0; i < 10; ++i) {
IntElem_t *item = malloc(sizeof(IntElem_t));
item->data = i;
if (i == 5) rm = item;
LinkedListAppend(struct IntElem, list, item);
}
LinkedListForEach(IntElem_t, list, iter, {
printf("%d\n", iter->data);
})
LinkedListRemove(IntElem_t, list, rm);
LinkedListForEach(IntElem_t, list, iter, {
printf("%d\n", iter->data);
})
return 0;
}
in file linked_list.h
typedef struct {
void *elem_head;
void *elem_tail;
size_t sz;
void (*dealloc)(void *elem);
} LinkedList;
LinkedList *LinkedListInit();
uint8_t __LinkedListAppend(LinkedList *list, void *elem, uint64_t offset);
uint8_t __LinkedListRemove(LinkedList *list, void *elem, uint64_t offset);
void __LinkedListDestroy(LinkedList *list, uint64_t offset, uint8_t free_elem);
void *__LinkedListGet(LinkedList *list, size_t idx, uint64_t offset);
void LinkedListSetDealloc(LinkedList *list, void (*dealloc)(void *elem));
#define LinkedListAppend(typename, list, elem) { \
uint64_t offset = offsetof(typename, next); \
if ((__LinkedListAppend(list, elem, offset))) { \
fatalf("LinkedList at <0x%x>append failed", list); \
}; \
} while (0); \
#define LinkedListRemove(typename, list, elem) { \
uint64_t offset = offsetof(typename, next); \
__LinkedListRemove(list, elem, offset); \
} while (0); \
#define LinkedListDestroy(typename, list, free_elem) { \
uint64_t offset = offsetof(typename, next); \
__LinkedListDestroy(list, offset, free_elem); \
} while (0); \
#define LinkedListGet(typename, list, elem) { \
uint64_t offset = offsetof(typename, next); \
__LinkedListGet(list, offset, free_elem); \
} while (0); \
#define LinkedListForEach(typename, list, vvar, code) { \
uint64_t offset = offsetof(typename, next); \
vvar = (typename *) list->elem_head; \
while (vvar) { \
code; \
vvar = (typename *)(*(void **)((void *)vvar + offset)); \
} \
} \
in file linked_list.c
LinkedList *LinkedListInit()
{
LinkedList *list = malloc(sizeof(LinkedList));
memset(list, 0, sizeof(LinkedList));
return list;
}
uint8_t __LinkedListAppend(LinkedList *list, void *elem, uint64_t offset)
{
void *curr, **next;
if (list->elem_head == NULL) {
list->elem_head = list->elem_tail = elem;
list->sz = 1;
return 0;
} else {
next = (list->elem_tail + offset);
*next = elem;
list->elem_tail = elem;
list->sz++;
return 0;
}
return 1;
}
uint8_t __LinkedListRemove(LinkedList *list, void *elem, uint64_t offset)
{
void **curr = &list->elem_head;
while ((*curr) != elem) {
curr = (void **)(*curr + offset);
}
*curr = (*(void **)(elem + offset));
}
void __LinkedListDestroy(LinkedList *list, uint64_t offset, uint8_t free_elem)
{
if (free_elem && list->sz > 0) {
if (!list->dealloc) {
fatalf("deallocation function should be set");
}
void *curr = list->elem_head, *next;
while (curr != list->elem_tail) {
next = (*(void **)(curr + offset));
free(curr);
curr = next;
}
free(curr);
}
free(list);
}
void *__LinkedListGet(LinkedList *list, size_t idx, uint64_t offset)
{
void *curr = list->elem_head;
size_t i = 0;
while (i < idx) {
curr = (*(void **)(curr + offset));
i++;
}
return curr;
}
void LinkedListSetDealloc(LinkedList *list, void (*dealloc)(void *elem))
{
list->dealloc = dealloc;
}