#include #include #include #include #include #include akerr_ErrorContext AKERR_NOIGNORE *aksl_malloc(size_t size, void **dst) { PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, dst, AKERR_NULLPOINTER, "NULL"); *dst = malloc(size); FAIL_ZERO_RETURN(e, *dst, errno, "%ld bytes", size); SUCCEED_RETURN(e); } akerr_ErrorContext AKERR_NOIGNORE *aksl_free(void *ptr) { PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, ptr, AKERR_NULLPOINTER, "NULL"); free(ptr); SUCCEED_RETURN(e); } akerr_ErrorContext AKERR_NOIGNORE *aksl_memset(void *s, int c, size_t n) { PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, s, AKERR_NULLPOINTER, "s=%p", s); FAIL_ZERO_RETURN(e, memset(s, c, n), errno, "Failed to memset"); SUCCEED_RETURN(e); } akerr_ErrorContext AKERR_NOIGNORE *aksl_memcpy(void *d, void *s, size_t n) { PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, d, AKERR_NULLPOINTER, "d=%p, s=%p", d, s); FAIL_ZERO_RETURN(e, s, AKERR_NULLPOINTER, "d=%p, s=%p", d, s); FAIL_ZERO_RETURN(e, (memcpy(d, s, n) == d), errno, "Failed to memcpy"); SUCCEED_RETURN(e); } akerr_ErrorContext AKERR_NOIGNORE *aksl_fopen( char *pathname, char *mode, FILE **fp) { PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, fp, AKERR_NULLPOINTER, "NULL"); *fp = fopen(pathname, mode); FAIL_ZERO_RETURN(e, *fp, errno, "%s", pathname); SUCCEED_RETURN(e); } akerr_ErrorContext AKERR_NOIGNORE *aksl_fread( void *ptr, size_t size, size_t nmemb, FILE *fp) { size_t nmemr; PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, fp, AKERR_NULLPOINTER, "NULL"); nmemr = fread(ptr, size, nmemb, fp); if ( nmemr != nmemb ) { FAIL_NONZERO_RETURN(e, feof(fp), AKERR_EOF, "EOF reached"); FAIL_NONZERO_RETURN(e, ferror(fp), AKERR_IO, "Error reading file"); } SUCCEED_RETURN(e); } akerr_ErrorContext AKERR_NOIGNORE *aksl_fwrite( void *ptr, size_t size, size_t nmemb, FILE *fp) { size_t nmemw; PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, fp, AKERR_NULLPOINTER, "NULL argument"); nmemw = fwrite(ptr, size, nmemb, fp); if ( nmemw != nmemb ) { FAIL_NONZERO_RETURN(e, feof(fp), AKERR_EOF, "EOF reached"); FAIL_NONZERO_RETURN(e, ferror(fp), AKERR_IO, "Error reading file"); } SUCCEED_RETURN(e); } akerr_ErrorContext AKERR_NOIGNORE *aksl_fclose(FILE *stream) { PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, stream, AKERR_NULLPOINTER, "NULL"); FAIL_NONZERO_RETURN(e, fclose(stream), errno, "Failed to fclose"); SUCCEED_RETURN(e); } akerr_ErrorContext AKERR_NOIGNORE *aksl_printf(int *count, const char *restrict format, ...) { va_list args; PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, count, AKERR_NULLPOINTER, "count=%p, format=%p", (void *)count, (void *)format); FAIL_ZERO_RETURN(e, format, AKERR_NULLPOINTER, "count=%p, format=%p", (void *)count, (void *)format); va_start(args, format); *count = vprintf(format, args); FAIL_NONZERO_RETURN(e, (*count == -1), errno, "Short write"); SUCCEED_RETURN(e); } akerr_ErrorContext AKERR_NOIGNORE *aksl_fprintf(int *count, FILE *restrict stream, const char *restrict format, ...) { va_list args; PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, count, AKERR_NULLPOINTER, "count=%p, stream=%p, format=%p", (void *)count, (void *)stream, (void *)format); FAIL_ZERO_RETURN(e, stream, AKERR_NULLPOINTER, "count=%p, stream=%p, format=%p", (void *)count, (void *)stream, (void *)format); FAIL_ZERO_RETURN(e, format, AKERR_NULLPOINTER, "count=%p, stream=%p, format=%p", (void *)count, (void *)stream, (void *)format); va_start(args, format); *count = vfprintf(stream, format, args); FAIL_NONZERO_RETURN(e, (*count == -1), errno, "Short write"); SUCCEED_RETURN(e); } akerr_ErrorContext AKERR_NOIGNORE *aksl_sprintf(int *count, char *restrict str, const char *restrict format, ...) { va_list args; PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, count, AKERR_NULLPOINTER, "count=%p, str=%p, format=%p", (void *)count, (void *)str, (void *)format); FAIL_ZERO_RETURN(e, str, AKERR_NULLPOINTER, "count=%p, str=%p, format=%p", (void *)count, (void *)str, (void *)format); FAIL_ZERO_RETURN(e, format, AKERR_NULLPOINTER, "count=%p, str=%p, format=%p", (void *)count, (void *)str, (void *)format); va_start(args, format); *count = vsprintf(str, format, args); FAIL_NONZERO_RETURN(e, (*count == -1), errno, "Short write"); SUCCEED_RETURN(e); } akerr_ErrorContext AKERR_NOIGNORE *aksl_atoi(const char *nptr, int *dest) { PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, nptr, AKERR_NULLPOINTER, "nptr=%p, dest=%p", (void *)nptr, (void *)dest); FAIL_ZERO_RETURN(e, dest, AKERR_NULLPOINTER, "nptr=%p, dest=%p", (void *)nptr, (void *)dest); *dest = atoi(nptr); SUCCEED_RETURN(e); } akerr_ErrorContext AKERR_NOIGNORE *aksl_atol(const char *nptr, long *dest) { PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, nptr, AKERR_NULLPOINTER, "nptr=%p, dest=%p", (void *)nptr, (void *)dest); FAIL_ZERO_RETURN(e, dest, AKERR_NULLPOINTER, "nptr=%p, dest=%p", (void *)nptr, (void *)dest); *dest = atol(nptr); SUCCEED_RETURN(e); } akerr_ErrorContext AKERR_NOIGNORE *aksl_atoll(const char *nptr, long long *dest) { PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, nptr, AKERR_NULLPOINTER, "nptr=%p, dest=%p", (void *)nptr, (void *)dest); FAIL_ZERO_RETURN(e, dest, AKERR_NULLPOINTER, "nptr=%p, dest=%p", (void *)nptr, (void *)dest); *dest = atoll(nptr); SUCCEED_RETURN(e); } akerr_ErrorContext AKERR_NOIGNORE *aksl_atof(const char *nptr, double *dest) { PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, nptr, AKERR_NULLPOINTER, "nptr=%p, dest=%p", (void *)nptr, (void *)dest); FAIL_ZERO_RETURN(e, dest, AKERR_NULLPOINTER, "nptr=%p, dest=%p", (void *)nptr, (void *)dest); *dest = atof(nptr); SUCCEED_RETURN(e); } akerr_ErrorContext AKERR_NOIGNORE *aksl_realpath(const char *restrict path, char *restrict resolved_path) { char *result = NULL; PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, path, AKERR_NULLPOINTER, "path=%p, dest=%p", (void *)path, (void *)resolved_path); result = realpath(path, resolved_path); 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; aksl_ListNode *tail = list; do { if ( fast != NULL && fast->next != NULL ) { fast = fast->next->next; } tail = slow; slow = slow->next; if ( fast != NULL && fast == slow) { FAIL(e, AKERR_CIRCULAR_REFERENCE, "%p", list); } } while ( slow != NULL || (fast != NULL && fast->next != NULL) ); tail->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"); if ( node->prev != NULL ) { node->prev->next = node->next; } if ( node->next != NULL ) { node->next->prev = node->prev; } node->next = NULL; node->prev = NULL; SUCCEED_RETURN(e); } /** * @brief Iterates over a tree structure in breadth or depth first order, executing a callback function on each node. * * This function recursively calls itself to traverse a binary tree datastructure. * * @param[in] root The tree structure to search * @param[in] iter An aksl_TreeNodeIterator function which will be called for each node found * @param[in] lalloc An aksl_AllocFunc function which will be used to allocate aksl_ListNode elements for the search, or NULL to use the default allocator (aksl_malloc) * @param[in] lfree An aksl_FreeFunc function which will be used to free the elements procured with lalloc, or NULL to use the default free function (aksl_free) * @param[in] searchmode One of the AKSL_TREE_SEARCH_BFS* defines * @param[in] data Any user data that should be provided when the iterator is called * @param[in] queue The linked list node to use as the head of the queue. The caller should pass NULL here. * * @throws AKERR_NULLPOINTER On null pointer inputs * @return akerr_ErrorContext */ akerr_ErrorContext AKERR_NOIGNORE *aksl_tree_iterate( aksl_TreeNode *root, aksl_TreeNodeIterator iter, aksl_AllocFunc lalloc, aksl_FreeFunc lfree, uint8_t searchmode, void *data, aksl_ListNode *queue) { PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, root, AKERR_NULLPOINTER, "root"); FAIL_ZERO_RETURN(e, iter, AKERR_NULLPOINTER, "iter"); if ( lalloc == NULL ) { lalloc = &aksl_malloc; } if ( lfree == NULL ) { lfree = &aksl_free; } switch ( searchmode ) { case AKSL_TREE_SEARCH_DFS_PREORDER: PASS(e, iter(root, data)); if ( root->left != NULL ) { PASS(e, aksl_tree_iterate(root->left, iter, lalloc, lfree, searchmode, data, NULL)); } if ( root-> right != NULL ) { PASS(e, aksl_tree_iterate(root->right, iter, lalloc, lfree, searchmode, data, NULL)); } break; case AKSL_TREE_SEARCH_DFS_POSTORDER: if ( root->left != NULL ) { PASS(e, aksl_tree_iterate(root->left, iter, lalloc, lfree, searchmode, data, NULL)); } if ( root-> right != NULL ) { PASS(e, aksl_tree_iterate(root->right, iter, lalloc, lfree, searchmode, data, NULL)); } PASS(e, iter(root, data)); break; case AKSL_TREE_SEARCH_DFS_INORDER: if ( root->left != NULL ) { PASS(e, aksl_tree_iterate(root->left, iter, lalloc, lfree, searchmode, data, NULL)); } PASS(e, iter(root, data)); if ( root-> right != NULL ) { PASS(e, aksl_tree_iterate(root->right, iter, lalloc, lfree, searchmode, data, NULL)); } break; case AKSL_TREE_SEARCH_BFS: case AKSL_TREE_SEARCH_BFS_RIGHT: FAIL_RETURN(e, AKERR_NOT_IMPLEMENTED, "Searchmode %d", searchmode); break; } SUCCEED_RETURN(e); } /** * @brief Iterates over a linked list and execute a callback function on each node * * @param[in] list The linked list to iterate * @param[in] iter An aksl_ListNodeIterator function which will be called for each node found * @param[in] data Any user data that should be provided when the iterator is called * * @throws AKERR_NULLPOINTER on null pointer inputs * @throws AKERR_CIRCULAR_REFERENCE when the linked list contains a circular reference * * @return akerr_ErrorContext */ akerr_ErrorContext AKERR_NOIGNORE *aksl_list_iterate(aksl_ListNode *list, aksl_ListNodeIterator iter, void *data) { 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; aksl_ListNode *tail = list; do { if ( fast != NULL && fast->next != NULL ) { fast = fast->next->next; } PASS(e, iter(slow, data)); slow = slow->next; if ( fast != NULL && fast == slow) { FAIL(e, AKERR_CIRCULAR_REFERENCE, "%p", list); } } while ( slow != NULL || (fast != NULL && fast->next != NULL) ); SUCCEED_RETURN(e); }