From 9d35ddb703d7ba22bdd6cdbaaf3b5c992ec79025 Mon Sep 17 00:00:00 2001 From: sanine Date: Fri, 24 Oct 2025 15:14:07 -0500 Subject: add list copy --- lichen.c | 32 +++++++++++++++++++++++++------- lichen.h | 6 +++--- lichen.test.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/lichen.c b/lichen.c index b0b0684..d7f0f82 100644 --- a/lichen.c +++ b/lichen.c @@ -77,10 +77,10 @@ void li_free_ll(struct li_ll_t *list, void (*free_data)(void*)) { } -void li_ll_append(struct li_ll_t *list, void *data) { +int li_ll_append(struct li_ll_t *list, void *data) { li_llnode_t *n = li_alloc_llnode(); if (n == NULL) { - return; + return 1; } n->data = data; if (list->end != NULL) { @@ -91,13 +91,14 @@ void li_ll_append(struct li_ll_t *list, void *data) { list->end = n; } list->count += 1; + return 0; } -void li_ll_prepend(struct li_ll_t *list, void *data) { +int li_ll_prepend(struct li_ll_t *list, void *data) { li_llnode_t *n = li_alloc_llnode(); if (n == NULL) { - return; + return 1; } n->data = data; if (list->head != NULL) { @@ -108,10 +109,27 @@ void li_ll_prepend(struct li_ll_t *list, void *data) { list->end = n; } list->count += 1; + return 0; } -struct li_ll_t * li_copy_list(struct li_ll_t *list) { - list = list; - return NULL; +int li_copy_list(struct li_ll_t **dst, struct li_ll_t *src, void *(*copy_data)(void*)) { + *dst = li_alloc_ll(); + if (*dst == NULL) { + return 1; + } + + (*dst)->tag = src->tag; + + for (li_llnode_t *n = src->head; n != NULL; n = n->next) { + void *dup = copy_data(n->data); + if (dup == NULL) { + return 1; + } + if (li_ll_append(*dst, dup) != 0) { + return 1; + } + } + + return 0; } diff --git a/lichen.h b/lichen.h index 4bcd608..5f13e85 100644 --- a/lichen.h +++ b/lichen.h @@ -49,9 +49,9 @@ typedef struct li_ll_t { struct li_ll_t * li_alloc_ll(); // free a linked list void li_free_ll(struct li_ll_t *list, void (*free_data)(void*)); -void li_ll_append(struct li_ll_t *list, void *data); -void li_ll_prepend(struct li_ll_t *list, void *data); -struct li_ll_t * li_copy_list(struct li_ll_t *list); +int li_ll_append(struct li_ll_t *list, void *data); +int li_ll_prepend(struct li_ll_t *list, void *data); +int li_copy_list(struct li_ll_t **dst, struct li_ll_t *src, void *(*copy_data)(void*)); diff --git a/lichen.test.c b/lichen.test.c index 622f480..946e0be 100644 --- a/lichen.test.c +++ b/lichen.test.c @@ -146,6 +146,35 @@ LILY_TEST("mix prepends and appends") { #include LILY_PUSH_TEST() +void * copy_int(void *n) { + int *copy = malloc(sizeof(int)); + *copy = *((int*)n); + return copy; +} +LILY_TEST("copy a list") { + struct li_ll_t *list_a = li_alloc_ll(); + list_a->tag = 8; + int a = 1; int b = 2; int c = 3; + li_ll_append(list_a, &a); + li_ll_append(list_a, &b); + li_ll_append(list_a, &c); + + struct li_ll_t *list_b; + li_copy_list(&list_b, list_a, copy_int); + li_free_ll(list_a, do_nothing); + + REQUIRE_NEQ(list_b, NULL, "%p"); + CHECK_EQ(list_b->tag, 8, "%d"); + CHECK_EQ(list_b->count, 3, "%d"); + CHECK_EQ(*((int*)list_b->head->data), a, "%d"); + CHECK_EQ(*((int*)list_b->head->next->data), b, "%d"); + CHECK_EQ(*((int*)list_b->head->next->next->data), c, "%d"); + + li_free_ll(list_b, free); +} +#include LILY_PUSH_TEST() + + #define LILY_FILE_END #include LILY_REGISTER_TESTS() -- cgit v1.2.1