From 22414addd3d983cca65d060741370a87fa19828c Mon Sep 17 00:00:00 2001 From: Andrew Kesterson Date: Tue, 2 Jun 2026 12:42:21 -0400 Subject: [PATCH] WIP --- include/akstdlib.h | 19 +++++++++++++++++ src/stdlib.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/include/akstdlib.h b/include/akstdlib.h index 90ce834..e160a19 100644 --- a/include/akstdlib.h +++ b/include/akstdlib.h @@ -6,6 +6,20 @@ #include #include +typedef struct aksl_ListNode { + void *data; + struct aksl_ListNode *next; + struct aksl_ListNode *prev; +} aksl_ListNode; + +typedef akerr_ErrorContext AKERR_NOIGNORE *(*aksl_ListNodeIterator)(aksl_ListNode *node); + +typedef struct aksl_TreeNode { + struct aksl_TreeNode *left; + struct aksl_TreeNode *right; + void *leaf; +} + akerr_ErrorContext AKERR_NOIGNORE *aksl_fopen(char *pathname, char *mode, FILE **fp); akerr_ErrorContext AKERR_NOIGNORE *aksl_fread(void *ptr, size_t size, size_t nmemb, FILE *stream); akerr_ErrorContext AKERR_NOIGNORE *aksl_fwrite(void *ptr, size_t size, size_t nmemb, FILE *fp); @@ -28,4 +42,9 @@ akerr_ErrorContext AKERR_NOIGNORE *aksl_atof(const char *nptr, double *dest); akerr_ErrorContext AKERR_NOIGNORE *aksl_realpath(const char *restrict path, char *restrict resolved_path); +// Linked list functions +akerr_ErrorContext AKERR_NOIGNORE *aksl_list_push(aksl_ListNode *list, aksl_ListNode *obj); +akerr_ErrorContext AKERR_NOIGNORE *aksl_list_pop(aksl_ListNode *node); +akerr_ErrorContext AKERR_NOIGNORE *aksl_list_iterate(aksl_ListNode *list, aksl_ListNodeIterator iter); + #endif diff --git a/src/stdlib.c b/src/stdlib.c index b6cc060..e46a4db 100644 --- a/src/stdlib.c +++ b/src/stdlib.c @@ -174,3 +174,54 @@ akerr_ErrorContext AKERR_NOIGNORE *aksl_realpath(const char *restrict path, char FAIL_ZERO_RETURN(e, result, errno, "path=%s, dest=%s", path, resolved_path); SUCCEED_RETURN(e); } + +akerr_ErrorContext AKERR_NOIGNORE *aksl_list_push(aksl_ListNode *list, aksl_ListNode *obj) +{ + PREPARE_ERROR(e); + FAIL_ZERO_RETURN(e, list, AKERR_NULLPOINTER, "list"); + FAIL_ZERO_RETURN(e, obj, AKERR_NULLPOINTER, "obj"); + aksl_ListNode *slow = list; + aksl_ListNode *fast = list; + while ( slow->next != NULL || fast->next != NULL ) { + if ( fast->next != NULL ) { + fast = fast->next->next; + } + slow = slow->next; + if ( fast == slow ) { + FAIL(e, AKERR_CIRCULAR_REFERENCE, "%p", list); + } + } + slow->next = obj; + obj->next = NULL; + obj->prev = slow; + SUCCEED_RETURN(e); +} + +akerr_ErrorContext AKERR_NOIGNORE *aksl_list_pop(aksl_ListNode *node) +{ + PREPARE_ERROR(e); + FAIL_ZERO_RETURN(e, node, AKERR_NULLPOINTER, "node"); + FAIL_ZERO_RETURN(e, node->prev, AKERR_NULLPOINTER, "node->prev"); + node->prev->next = node->next; + SUCCEED_RETURN(e); +} + +akerr_ErrorContext AKERR_NOIGNORE *aksl_list_iterate(aksl_ListNode *list, aksl_ListNodeIterator iter) +{ + PREPARE_ERROR(e); + FAIL_ZERO_RETURN(e, list, AKERR_NULLPOINTER, "list"); + FAIL_ZERO_RETURN(e, iter, AKERR_NULLPOINTER, "iter"); + aksl_ListNode *slow = list; + aksl_ListNode *fast = list; + while ( slow->next != NULL || fast->next != NULL ) { + if ( fast->next != NULL ) { + fast = fast->next->next; + } + slow = slow->next; + if ( fast == slow ) { + FAIL(e, AKERR_CIRCULAR_LIST, "%p", list); + } + PASS(e, iter(slow)); + } + SUCCEED_RETURN(e); +}