#ifndef LIST_H # define LIST_H #include #include #include #include #include #include #include typedef struct node_s { void *data; struct node_s *next; } node_t; typedef struct { int size; node_t *first; node_t *last; } list_t; typedef struct { node_t *current; } list_iter_t; list_t *ListInit(list_t *lst); void ListInsert(list_t *lst, size_t idx, void *data); void ListPushBack(list_t *lst, void *data); list_iter_t ListGetIter(const list_t *lst); void *ListAdvance(list_iter_t *it); void *ListPeek(const list_iter_t *it); void *ListPeekNext(const list_iter_t *it); bool ListAtEnd(const list_iter_t *it); void ListReset(list_iter_t *it, const list_t *lst); void ListFree(list_t *lst, void (*free_func)(void*)); void *ListPeekK(const list_iter_t *it, size_t k); void ListRestore(list_iter_t *it, const list_iter_t checkpoint); bool ListMatch(list_iter_t *it, bool (*predicate)(void*, void*), void *target); # ifdef LIST_IMPLEMENTATION list_t *ListInit(list_t *lst) { if (!lst) { lst = (list_t *)malloc(sizeof(list_t)); } lst->first = NULL; lst->last = NULL; lst->size = 0; return (lst); } void ListInsert(list_t *lst, size_t idx, void *data) { node_t *node = (node_t *)malloc(sizeof(node_t)); node->data = data; node->next = 0; if (lst->size == 0) { lst->first = lst->last = node; } else if (idx == 0) { node->next = lst->first; lst->first = node; } else { node_t *prev = lst->first; for (int i = 0; i < idx - 1 && prev->next; i++) { prev = prev->next; } node->next = prev->next; prev->next = node; if (node->next == NULL) { lst->last = node; } } lst->size++; } void ListPushBack(list_t *lst, void *data) { node_t *node = (node_t *)malloc(sizeof(node_t)); node->data = data; node->next = NULL; if (!lst->first) { lst->first = node; } else { lst->last->next = node; } lst->last = node; lst->size++; } list_iter_t ListGetIter(const list_t *lst) { return ((list_iter_t){.current = lst->first}); } void *ListAdvance(list_iter_t *it) { if (!it->current) return NULL; void *data = it->current->data; it->current = it->current->next; return (data); } void *ListPeek(const list_iter_t *it) { return (it->current ? it->current->data : NULL); } void *ListPeekNext(const list_iter_t *it) { return (it->current ? (it->current->next ? it->current->next->data : NULL) : NULL); } bool ListAtEnd(const list_iter_t *it) { return (it->current == NULL); } void ListReset(list_iter_t *it, const list_t *lst) { it->current = lst->first; } void ListFree(list_t *lst, void (*free_func)(void*)) { node_t *current = lst->first; while (current) { node_t *next = current->next; if (free_func) free_func(current->data); free(current); current = next; } lst->size = 0; lst->first = lst->last = NULL; } void *ListPeekK(const list_iter_t *it, size_t k) { node_t *current = it->current; for (size_t i = 0; i < k && current; i++) { current = current->next; } return (current ? current->data : NULL); } void ListRestore(list_iter_t *it, const list_iter_t checkpoint) { it->current = checkpoint.current; } bool ListMatch(list_iter_t *it, bool (*predicate)(void*, void*), void *target) { if (it->current && predicate(it->current->data, target)) { ListAdvance(it); return true; } return false; } # endif #endif