summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2025-10-24 15:14:07 -0500
committersanine <sanine.not@pm.me>2025-10-24 15:14:07 -0500
commit9d35ddb703d7ba22bdd6cdbaaf3b5c992ec79025 (patch)
treeedc09566743454fad659cd5d47ebfda2e4282907
parent4167860e015a779f83a17bc8754c7070bdfba336 (diff)
add list copy
-rw-r--r--lichen.c32
-rw-r--r--lichen.h6
-rw-r--r--lichen.test.c29
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()