#include <stdio.h>
#include <stdlib.h>
typedef struct Item_ {
unsigned id;
void *data; // Pointer to custom data container.
void (*deleter)(void *); // Custom deleter for `data`, defaults to `free()`.
struct Item_ *next;
} Item;
Item **endOfList_(Item **const begin) {
Item **item = begin;
for (; *item; item = &(*item)->next);
return item;
}
Item **findItem_(Item **const begin, unsigned const id) {
Item **item = begin;
for (; *item && (*item)->id != id; item = &(*item)->next);
return item;
}
void spliceItem_(Item **const reference, Item *const item) {
Item *next = *reference;
*reference = item;
(*reference)->next = next;
}
Item *newItem(
unsigned const id, void *const data, void (*const deleter)(void *)) {
Item *item = malloc(sizeof(Item));
item->id = id;
item->data = data;
item->deleter = deleter;
item->next = NULL;
return item;
}
void deleteItem(Item *const item) {
if (item->deleter) {
item->deleter(item->data);
}
else {
free(item->data);
}
free(item);
}
void appendItem(Item **const begin, Item *const item) {
Item **reference = endOfList_(begin);
*reference = item;
}
void prependItem(Item **const begin, Item *const item) {
spliceItem_(begin, item);
}
Item *findItem(Item **const begin, unsigned const id) {
return *findItem_(begin, id);
}
void insertAfter(Item **const begin, unsigned const id, Item *const item) {
Item **reference = findItem_(begin, id);
if (!*reference) {
return;
}
spliceItem_(&(*reference)->next, item);
}
void insertBefore(Item **const begin, unsigned const id, Item *const item) {
Item **reference = findItem_(begin, id);
if (!*reference) {
return;
}
spliceItem_(reference, item);
}
void removeItem(Item **const begin, unsigned const id) {
Item **item = findItem_(begin, id);
if (!*item) {
return;
}
Item *item_ = *item;
(*item) = (*item)->next;
deleteItem(item_);
}
void destroyList(Item **const begin) {
for (Item *item = *begin; item;) {
Item *item_ = item;
item = item->next;
deleteItem(item_);
}
}
void printList(Item **const begin) {
for (Item *item = *begin; item; item = item->next) {
printf("%i ", item->id);
}
printf("\n");
}
/* Usage example. */
typedef struct {
int x;
int y;
} Data;
Data *newData(int const x, int const y) {
Data *data = malloc(sizeof(Data));
data->x = x;
data->y = y;
return data;
}
void deleteData(void *data) {
printf("Custom deleter called.\n");
free(data);
}
void printItem(Item *const item) {
printf("item: %u, ", item->id);
Data *data = item->data;
if (data) {
printf("data: (x: %i, y: %i)\n", data->x, data->y);
}
else {
printf("no data\n");
}
}
int main(void) {
Item *list = {NULL};
Data *data = newData(10, 20);
appendItem(&list, newItem(1, data, NULL));
appendItem(&list, newItem(2, NULL, deleteData));
printList(&list); // 1, 2
prependItem(&list, newItem(0, NULL, deleteData));
printList(&list); // 0, 1, 2
insertAfter(&list, 0, newItem(4, NULL, NULL));
printList(&list); // 0, 4, 1, 2
insertBefore(&list, 0, newItem(5, NULL, NULL));
printList(&list); // 5, 0, 4, 1, 2
insertBefore(&list, 4, newItem(6, NULL, NULL));
printList(&list); // 5, 0, 6, 4, 1, 2
removeItem(&list, 4);
printList(&list); // 5, 0, 6, 1, 2
removeItem(&list, 2);
printList(&list); // 5, 0, 6, 1
printItem(findItem(&list, 1));
printItem(findItem(&list, 6));
destroyList(&list);
}Add a code snippet to your website: www.paste.org