Optimized and slimmed down single linked lists, similar work to follow. Allows for better debugging flow too.
This commit is contained in:
parent
77b9e2e264
commit
cf57df8f27
|
@ -22,7 +22,7 @@
|
|||
#endif /* SINGLE_LINKED_LIST_C */
|
||||
|
||||
/* This function initializes a new linked list, returns NULL on failure. */
|
||||
linked_list_t* initialize_single_linked_list() {
|
||||
static inline linked_list_t* initialize_single_linked_list() {
|
||||
/* Variables. */
|
||||
linked_list_t *result;
|
||||
|
||||
|
@ -41,18 +41,18 @@ linked_list_t* initialize_single_linked_list() {
|
|||
return result;
|
||||
}
|
||||
|
||||
/* This function appends a node to the given linked list, returns 1 on success and 0 on failure. */
|
||||
int append_node_single_linked_list(linked_list_t *list, node_t *node) {
|
||||
/* This function appends a node to the given linked list. */
|
||||
static inline void append_node_single_linked_list(linked_list_t *list, node_t *node) {
|
||||
/* Input sanity check. */
|
||||
if (!list || !node)
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
assert(list && node);
|
||||
|
||||
/* Set the next to NULL. */
|
||||
node->next = NULL;
|
||||
/* Check if we can append at the start. */
|
||||
if (!(list->head)) {
|
||||
list->head = node;
|
||||
(list->length)++;
|
||||
return SUCCESS_CODE_SIGNLE_LINKED_LIST_C;
|
||||
return;
|
||||
}
|
||||
/* Loop till we get to the end. */
|
||||
node_t *current = list->head;
|
||||
|
@ -62,63 +62,62 @@ int append_node_single_linked_list(linked_list_t *list, node_t *node) {
|
|||
/* Got to the end, append and add. */
|
||||
current->next = node;
|
||||
(list->length)++;
|
||||
return SUCCESS_CODE_SIGNLE_LINKED_LIST_C;
|
||||
}
|
||||
|
||||
/* This function prepends a node to the given linked list, returns 1 on success and 0 on failure. */
|
||||
int prepend_node_single_linked_list(linked_list_t *list, node_t *node) {
|
||||
/* This function prepends a node to the given linked list. */
|
||||
static inline void prepend_node_single_linked_list(linked_list_t *list, node_t *node) {
|
||||
/* Input sanity check. */
|
||||
if (!list || !node)
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
assert(list && node);
|
||||
|
||||
/* Check if we can prepend at the start. */
|
||||
if (!(list->head)) {
|
||||
list->head = node;
|
||||
(list->length)++;
|
||||
return SUCCESS_CODE_SIGNLE_LINKED_LIST_C;
|
||||
return;
|
||||
}
|
||||
/* Set the node's next to the current head, and swap. */
|
||||
node->next = list->head;
|
||||
list->head = node;
|
||||
(list->length)++;
|
||||
return SUCCESS_CODE_SIGNLE_LINKED_LIST_C;
|
||||
}
|
||||
|
||||
/* This function creates and appends a node to the given linked list, returns 1 on success and 0 on failure. */
|
||||
int append_node_data_single_linked_list(linked_list_t *list, void *data) {
|
||||
static inline int append_node_data_single_linked_list(linked_list_t *list, void *data) {
|
||||
/* Input sanity check. */
|
||||
if (!list || !data)
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
assert(list && data);
|
||||
|
||||
/* Attempt to create a node. */
|
||||
node_t *node = (node_t*) malloc(sizeof(node_t));
|
||||
if (!node)
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
return FAILURE_CODE_SINGLE_LINKED_LIST_C;
|
||||
/* Insert the data. */
|
||||
node->data = data;
|
||||
/* Delegate the work. */
|
||||
return append_node_single_linked_list(list, node);
|
||||
append_node_single_linked_list(list, node);
|
||||
return SUCCESS_CODE_SINGLE_LINKED_LIST_C;
|
||||
}
|
||||
|
||||
/* This function creates and prepends a node to the given linked list, returns 1 on success and 0 on failure. */
|
||||
int prepend_node_data_single_linked_list(linked_list_t *list, void *data) {
|
||||
static inline int prepend_node_data_single_linked_list(linked_list_t *list, void *data) {
|
||||
/* Input sanity check. */
|
||||
if (!list || !data)
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
assert(list && data);
|
||||
|
||||
/* Attempt to create a node. */
|
||||
node_t *node = (node_t*) malloc(sizeof(node_t));
|
||||
if (!node)
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
return FAILURE_CODE_SINGLE_LINKED_LIST_C;
|
||||
/* Insert the data. */
|
||||
node->data = data;
|
||||
/* Delegate the work. */
|
||||
return prepend_node_single_linked_list(list, node);
|
||||
prepend_node_single_linked_list(list, node);
|
||||
return SUCCESS_CODE_SINGLE_LINKED_LIST_C;
|
||||
}
|
||||
|
||||
/* This function inserts a node at the ith place, returns 1 on success and 0 on failure. */
|
||||
int add_node_i_single_linked_list(linked_list_t *list, node_t *node, size_t i) {
|
||||
/* This function inserts a node at the ith place. */
|
||||
static inline void add_node_i_single_linked_list(linked_list_t *list, node_t *node, size_t i) {
|
||||
/* Input sanity check. */
|
||||
if (!list || !node || list->length <= i)
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
assert(list && node && list->length > i);
|
||||
|
||||
/* Set the next to NULL. */
|
||||
node->next = NULL;
|
||||
/* Deal with special case of head. */
|
||||
|
@ -126,7 +125,7 @@ int add_node_i_single_linked_list(linked_list_t *list, node_t *node, size_t i) {
|
|||
node->next = list->head;
|
||||
list->head = node;
|
||||
(list->length)++;
|
||||
return SUCCESS_CODE_SIGNLE_LINKED_LIST_C;
|
||||
return;
|
||||
}
|
||||
/* Loop till we get to the right place. */
|
||||
node_t *current = list->head;
|
||||
|
@ -136,34 +135,28 @@ int add_node_i_single_linked_list(linked_list_t *list, node_t *node, size_t i) {
|
|||
node->next = current->next;
|
||||
current->next = node;
|
||||
(list->length)++;
|
||||
return SUCCESS_CODE_SIGNLE_LINKED_LIST_C;
|
||||
}
|
||||
|
||||
/* This function creates and inserts a node at the ith place, returns 1 in success and 0 on failure. */
|
||||
int add_node_data_i_single_linked_list(linked_list_t *list, void *data, size_t i) {
|
||||
static inline int add_node_data_i_single_linked_list(linked_list_t *list, void *data, size_t i) {
|
||||
/* Input sanity check. */
|
||||
if (!list || list->length <= i)
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
assert(list && list->length >= i);
|
||||
|
||||
/* Attempt to create a node. */
|
||||
node_t *node = (node_t*) malloc(sizeof(node_t));
|
||||
if (!node)
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
return FAILURE_CODE_SINGLE_LINKED_LIST_C;
|
||||
/* Insert the data. */
|
||||
node->data = data;
|
||||
/* Delegate. */
|
||||
return add_node_i_single_linked_list(list, node, i);
|
||||
add_node_i_single_linked_list(list, node, i);
|
||||
return SUCCESS_CODE_SINGLE_LINKED_LIST_C;
|
||||
}
|
||||
|
||||
/* This function reads the data at the ith node, returns NULL on failure or NULL data! */
|
||||
/* Sets the error code in error (instead of returning it). */
|
||||
void* read_node_i_single_linked_list(linked_list_t *list, size_t i, int *error) {
|
||||
static inline void* read_node_i_single_linked_list(linked_list_t *list, size_t i) {
|
||||
/* Input sanity check. */
|
||||
if (!error)
|
||||
return NULL;
|
||||
if (!list || list->length <= i) {
|
||||
*error = FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
return NULL;
|
||||
}
|
||||
assert(list && list->length > i);
|
||||
|
||||
/* Check if dealing with the head. */
|
||||
if (!i)
|
||||
|
@ -174,23 +167,14 @@ void* read_node_i_single_linked_list(linked_list_t *list, size_t i, int *error)
|
|||
for (; i > 0; i--)
|
||||
current = current->next;
|
||||
|
||||
/* Set the error code. */
|
||||
*error = SUCCESS_CODE_SIGNLE_LINKED_LIST_C;
|
||||
|
||||
/* Got to the requested node, return the stored data. */
|
||||
return current->data;
|
||||
}
|
||||
|
||||
/* This function retrieves a pointer to the ith node, returns NULL on failure. */
|
||||
/* Sets the error code in error (instead of returning it). */
|
||||
node_t* get_node_i_single_linked_list(linked_list_t *list, size_t i, int *error) {
|
||||
static inline node_t* get_node_i_single_linked_list(linked_list_t *list, size_t i) {
|
||||
/* Input sanity check */
|
||||
if (!error)
|
||||
return NULL;
|
||||
if (!list || list->length <= i) {
|
||||
*error = FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
return NULL;
|
||||
}
|
||||
assert(list && list->length > i);
|
||||
|
||||
/* Check if dealing with the head. */
|
||||
if (!i)
|
||||
|
@ -201,23 +185,20 @@ node_t* get_node_i_single_linked_list(linked_list_t *list, size_t i, int *error)
|
|||
for (; i > 0; i--)
|
||||
current = current->next;
|
||||
|
||||
/* Set the error code. */
|
||||
*error = SUCCESS_CODE_SIGNLE_LINKED_LIST_C;
|
||||
|
||||
/* Got to the requested node, return the pointer. */
|
||||
return current;
|
||||
}
|
||||
|
||||
/* This function attempts to find the index of a given node, by pointer. */
|
||||
/* Returns -2 on invalid input, and -1 when not found. */
|
||||
size_t get_node_index_pointer_single_linked_list(linked_list_t *list, node_t *node){
|
||||
/* Returns -1 when not found. */
|
||||
static inline size_t get_node_index_pointer_single_linked_list(linked_list_t *list, node_t *node){
|
||||
/* Sanity check. */
|
||||
if (!list || !node)
|
||||
return INVALID_INPUT_CODE_SINGLE_LINKED_LIST_C;
|
||||
assert(list && node);
|
||||
|
||||
/* Local variables. */
|
||||
node_t *current;
|
||||
size_t i = 0L;
|
||||
|
||||
/* Attempt to search. */
|
||||
if (!(list->head))
|
||||
return INDEX_NOT_FOUND_CODE_SINGLE_LINKED_LIST_C;
|
||||
|
@ -226,16 +207,16 @@ size_t get_node_index_pointer_single_linked_list(linked_list_t *list, node_t *no
|
|||
current = current->next;
|
||||
i++;
|
||||
}
|
||||
/* Check if we found it or not. */
|
||||
|
||||
/* Check if found or not. */
|
||||
return (i >= list->length) ? INDEX_NOT_FOUND_CODE_SINGLE_LINKED_LIST_C : i;
|
||||
}
|
||||
|
||||
/* This function attempts to find the index of a given node, by data. */
|
||||
/* Returns -2 on invalid input, and -1 when not found. */
|
||||
size_t get_node_index_data_single_linked_list(linked_list_t *list, void *data, int (*comparison_function)(const void*, const void*)) {
|
||||
/* Returns -1 when not found. */
|
||||
static inline size_t get_node_index_data_single_linked_list(linked_list_t *list, void *data, int (*comparison_function)(const void*, const void*)) {
|
||||
/* Sanity check. */
|
||||
if (list == NULL || comparison_function == NULL)
|
||||
return INVALID_INPUT_CODE_SINGLE_LINKED_LIST_C;
|
||||
assert(list && comparison_function);
|
||||
|
||||
/* Local variables. */
|
||||
node_t *current;
|
||||
|
@ -255,21 +236,21 @@ size_t get_node_index_data_single_linked_list(linked_list_t *list, void *data, i
|
|||
return (i >= list->length) ? INDEX_NOT_FOUND_CODE_SINGLE_LINKED_LIST_C : i;
|
||||
}
|
||||
|
||||
/* This function deletes the ith node, returns 1 on success and 0 on failure. */
|
||||
int remove_node_i_single_linked_list(linked_list_t *list, size_t i) {
|
||||
/* This function deletes the ith node. */
|
||||
static inline void remove_node_i_single_linked_list(linked_list_t *list, size_t i) {
|
||||
/* Input sanity check */
|
||||
if (!list || list->length <= i)
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
assert(list && list->length > i);
|
||||
|
||||
/* Deal with the special case of the head node. */
|
||||
if (!i) {
|
||||
if (!(list->head))
|
||||
return SUCCESS_CODE_SIGNLE_LINKED_LIST_C;
|
||||
return;
|
||||
node_t *tmp = list->head;
|
||||
list->head = tmp->next;
|
||||
tmp->next = NULL;
|
||||
free(tmp);
|
||||
(list->length)--;
|
||||
return SUCCESS_CODE_SIGNLE_LINKED_LIST_C;
|
||||
return;
|
||||
}
|
||||
/* Loop. */
|
||||
node_t *current = list->head;
|
||||
|
@ -281,19 +262,17 @@ int remove_node_i_single_linked_list(linked_list_t *list, size_t i) {
|
|||
tmp->next = NULL;
|
||||
free(tmp);
|
||||
(list->length)--;
|
||||
return SUCCESS_CODE_SIGNLE_LINKED_LIST_C;
|
||||
}
|
||||
|
||||
/* This function deletes the ith node with the data stored within it, returns 1 on success and 0 on failure. */
|
||||
/* A free function pointer of NULL value causes the use of the internal stdlib free(). */
|
||||
int remove_node_i_data_single_linked_list(linked_list_t *list, size_t i, void (*free_function)(void*)) {
|
||||
/* This function deletes the ith node with the data stored within it. */
|
||||
static inline void remove_node_i_data_single_linked_list(linked_list_t *list, size_t i, void (*free_function)(void*)) {
|
||||
/* Input sanity check */
|
||||
if (!list || list->length <= i)
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
assert(list && list->length > i);
|
||||
|
||||
/* Deal with the special case of the head node. */
|
||||
if (!i) {
|
||||
if (!(list->head))
|
||||
return SUCCESS_CODE_SIGNLE_LINKED_LIST_C;
|
||||
return;
|
||||
node_t *tmp = list->head;
|
||||
list->head = tmp->next;
|
||||
tmp->next = NULL;
|
||||
|
@ -303,9 +282,10 @@ int remove_node_i_data_single_linked_list(linked_list_t *list, size_t i, void (*
|
|||
free_function(tmp->data);
|
||||
free(tmp);
|
||||
(list->length)--;
|
||||
return SUCCESS_CODE_SIGNLE_LINKED_LIST_C;
|
||||
return;
|
||||
}
|
||||
/* Loop. */
|
||||
|
||||
/* Loop to the correct location. */
|
||||
node_t *current = list->head;
|
||||
for (; i > 0; i--)
|
||||
current = current->next;
|
||||
|
@ -319,75 +299,77 @@ int remove_node_i_data_single_linked_list(linked_list_t *list, size_t i, void (*
|
|||
free_function(tmp->data);
|
||||
free(tmp);
|
||||
(list->length)--;
|
||||
return SUCCESS_CODE_SIGNLE_LINKED_LIST_C;
|
||||
}
|
||||
|
||||
/* This function reads the data at the first node, note that it will return NULL on invalid input or first node being NULL. */
|
||||
/* Sets the error code in error (instead of returning it). */
|
||||
void* read_node_head_single_linked_list(linked_list_t *list, int *error) {
|
||||
static inline void* read_node_head_single_linked_list(linked_list_t *list) {
|
||||
/* Sanity check. */
|
||||
assert(list);
|
||||
|
||||
/* Delegate. */
|
||||
return read_node_i_single_linked_list(list, INDEX_HEAD_SINGLE_LINKED_LIST_C, error);
|
||||
return read_node_i_single_linked_list(list, INDEX_HEAD_SINGLE_LINKED_LIST_C);
|
||||
}
|
||||
|
||||
/* This function retrieves the first node, note that it will return NULL on invalid input or first node being NULL. */
|
||||
/* Sets the error code in error (instead of returning it). */
|
||||
node_t* get_node_head_single_linked_list(linked_list_t *list, int *error) {
|
||||
static inline node_t* get_node_head_single_linked_list(linked_list_t *list) {
|
||||
/* Sanity check. */
|
||||
assert(list);
|
||||
|
||||
/* Delegate. */
|
||||
return get_node_i_single_linked_list(list, INDEX_HEAD_SINGLE_LINKED_LIST_C, error);
|
||||
return get_node_i_single_linked_list(list, INDEX_HEAD_SINGLE_LINKED_LIST_C);
|
||||
}
|
||||
|
||||
/* This function deletes the first node, returns 1 on success and 0 on failure. */
|
||||
int remove_node_head_single_linked_list(linked_list_t *list) {
|
||||
static inline void remove_node_head_single_linked_list(linked_list_t *list) {
|
||||
/* Sanity check. */
|
||||
assert(list);
|
||||
|
||||
/* Delegate. */
|
||||
return remove_node_i_single_linked_list(list, INDEX_HEAD_SINGLE_LINKED_LIST_C);
|
||||
}
|
||||
|
||||
/* This function deletes the first node and the contents thereof, returns 1 on success and 0 on failure. */
|
||||
/* If the free_function is NULL, will use stdlib's free() instead. */
|
||||
int remove_node_head_data_single_linked_list(linked_list_t *list, void (*free_function)(void*)) {
|
||||
/* This function deletes the first node and the contents thereof. */
|
||||
static inline void remove_node_head_data_single_linked_list(linked_list_t *list, void (*free_function)(void*)) {
|
||||
/* Sanity check. */
|
||||
assert(list && free_function);
|
||||
|
||||
/* Delegate. */
|
||||
return remove_node_i_data_single_linked_list(list, INDEX_HEAD_SINGLE_LINKED_LIST_C, free_function);
|
||||
}
|
||||
|
||||
/* This function reads the data at the last node, will return NULL on invalid input or first node being NULL. */
|
||||
/* Sets the error code in error (instead of returning it). */
|
||||
void* read_node_tail_single_linked_list(linked_list_t *list, int *error) {
|
||||
static inline void* read_node_tail_single_linked_list(linked_list_t *list) {
|
||||
/* Sanity check. */
|
||||
if (!error)
|
||||
return NULL;
|
||||
if (!list || !(list->head))
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
assert(list && (list->head));
|
||||
|
||||
/* Delegate. */
|
||||
return read_node_i_single_linked_list(list, list->length - 1, error);
|
||||
return read_node_i_single_linked_list(list, list->length - 1);
|
||||
}
|
||||
|
||||
/* This function retrieves the last node, will return NULL on invalid input or the first node being NULL. */
|
||||
/* Sets the error code in error (instead of returning it). */
|
||||
node_t* get_node_tail_single_linked_list(linked_list_t *list, int *error) {
|
||||
static inline node_t* get_node_tail_single_linked_list(linked_list_t *list) {
|
||||
/* Sanity check. */
|
||||
if (!error)
|
||||
return NULL;
|
||||
if (!list || !(list->head))
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
assert(list && (list->head));
|
||||
|
||||
/* Delegate. */
|
||||
return get_node_i_single_linked_list(list, list->length - 1, error);
|
||||
return get_node_i_single_linked_list(list, list->length - 1);
|
||||
}
|
||||
|
||||
/* This function deletes the last node, returns 1 on success and 0 on failure. */
|
||||
int remove_node_tail_single_linked_list(linked_list_t *list) {
|
||||
/* This function deletes the last node. */
|
||||
static inline void remove_node_tail_single_linked_list(linked_list_t *list) {
|
||||
/* Sanity check. */
|
||||
if (!list || !(list->head))
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
assert(list && (list->head));
|
||||
|
||||
/* Delegate. */
|
||||
return remove_node_i_single_linked_list(list, list->length - 1);
|
||||
}
|
||||
|
||||
/* This function deletes the last node and the data thereof, returns 1 on success and 0 on failure. */
|
||||
/* If the free_function is NULL, will use stdlib's free() instead. */
|
||||
int remove_node_tail_data_single_linked_list(linked_list_t *list, void (*free_function)(void*)) {
|
||||
/* This function deletes the last node and the data thereof. */
|
||||
static inline void remove_node_tail_data_single_linked_list(linked_list_t *list, void (*free_function)(void*)) {
|
||||
/* Sanity check. */
|
||||
if (!list || !(list->head))
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
assert(list && (list->head));
|
||||
|
||||
/* Delegate. */
|
||||
return remove_node_i_data_single_linked_list(list, list->length - 1, free_function);
|
||||
}
|
||||
|
@ -395,10 +377,10 @@ int remove_node_tail_data_single_linked_list(linked_list_t *list, void (*free_fu
|
|||
/* This function deletes all the nodes of the given list and the list itself. */
|
||||
/* Note that it doesn't touch the data, returns 1 on success and 0 on failure - failure is potentially undefined behavior! */
|
||||
/* Will return -1 when the list was freed successfully but it was initially malformed. */
|
||||
int clear_list_single_linked_list(linked_list_t **list) {
|
||||
static inline int clear_list_single_linked_list(linked_list_t **list) {
|
||||
/* Sanity check. */
|
||||
if (!list || !(*list))
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
assert(list && *list);
|
||||
|
||||
/* Local variables. */
|
||||
node_t *current = (*list)->head, *tmp;
|
||||
size_t length, count = 0;
|
||||
|
@ -415,16 +397,16 @@ int clear_list_single_linked_list(linked_list_t **list) {
|
|||
/* Should all be freed by now, free the list and return. */
|
||||
free(*list);
|
||||
*list = NULL;
|
||||
return (count == length) ? SUCCESS_CODE_SIGNLE_LINKED_LIST_C : CODE_FREE_SUCCESS_MALFORMED_SINGLE_LINKED_LIST_C;
|
||||
return (count == length) ? SUCCESS_CODE_SINGLE_LINKED_LIST_C : CODE_FREE_SUCCESS_MALFORMED_SINGLE_LINKED_LIST_C;
|
||||
}
|
||||
|
||||
/* This function deletes all the nodes and data stored within of the given list and the list itself. */
|
||||
/* Returns 1 on success and 0 on failure, undefined behavior in the latter. Will return -1 when the list was freed successfully but was initially malformed. */
|
||||
/* If free_function is NULL will use STDLIB free instead. */
|
||||
int clear_list_data_single_linked_list(linked_list_t **list, void (*free_function)(void*)) {
|
||||
static inline int clear_list_data_single_linked_list(linked_list_t **list, void (*free_function)(void*)) {
|
||||
/* Sanity check. */
|
||||
if (!list || !(*list))
|
||||
return FAILURE_CODE_SIGNLE_LINKED_LIST_C;
|
||||
assert(list && *list);
|
||||
|
||||
/* Local variables. */
|
||||
node_t *current = (*list)->head, *tmp;
|
||||
size_t length, count = 0;
|
||||
|
@ -446,20 +428,19 @@ int clear_list_data_single_linked_list(linked_list_t **list, void (*free_functio
|
|||
/* Should all be freed by now, free the list and return. */
|
||||
free(*list);
|
||||
*list = NULL;
|
||||
return (count == length) ? SUCCESS_CODE_SIGNLE_LINKED_LIST_C : CODE_FREE_SUCCESS_MALFORMED_SINGLE_LINKED_LIST_C;
|
||||
return (count == length) ? SUCCESS_CODE_SINGLE_LINKED_LIST_C : CODE_FREE_SUCCESS_MALFORMED_SINGLE_LINKED_LIST_C;
|
||||
}
|
||||
|
||||
/* This function attetmps to serialize a linked list into an array. */
|
||||
/* Note that the array has to be allocated by the caller. */
|
||||
/* The array setting function is used to set the values at an index, takes the pointer to the array, index, and value to put. */
|
||||
void *serialize_linked_list(linked_list_t *list, void (*array_setting_function)(void*, size_t, void*), void *array) {
|
||||
static inline void *serialize_linked_list(linked_list_t *list, void (*array_setting_function)(void*, size_t, void*), void *array) {
|
||||
/* Local variables. */
|
||||
node_t *current;
|
||||
size_t i = 0L;
|
||||
|
||||
/* Sanity check. */
|
||||
if (!list || !(list->head) || list->length <= 0 || !array || !array_setting_function)
|
||||
return NULL;
|
||||
assert(list && (list->head) && list->length >= 0 && array && array_setting_function);
|
||||
|
||||
/* Fill the array. */
|
||||
for (current = list->head; current; i++) {
|
||||
|
|
|
@ -20,12 +20,17 @@
|
|||
#ifndef SINGLE_LINKED_LIST_H
|
||||
#define SINGLE_LINKED_LIST_H
|
||||
#include "../nodes/single_node.h"
|
||||
/* Include assert.h to allow code generation, but only run with debug flag. */
|
||||
#ifndef DEBUG
|
||||
#define NDEBUG
|
||||
#endif /* DEBUG. */
|
||||
#include <assert.h>
|
||||
|
||||
/* Constants. */
|
||||
/* Function error/return code on success. */
|
||||
#define SUCCESS_CODE_SIGNLE_LINKED_LIST_C 1
|
||||
#define SUCCESS_CODE_SINGLE_LINKED_LIST_C 1
|
||||
/* Function error/return code on failure. */
|
||||
#define FAILURE_CODE_SIGNLE_LINKED_LIST_C 0
|
||||
#define FAILURE_CODE_SINGLE_LINKED_LIST_C 0
|
||||
/* Function error/return code on failure to find index. */
|
||||
#define INDEX_NOT_FOUND_CODE_SINGLE_LINKED_LIST_C -1
|
||||
/* Function error/return code on invalid input. */
|
||||
|
@ -44,51 +49,51 @@ typedef struct linked_list {
|
|||
} linked_list_t;
|
||||
|
||||
/* This function initializes a new linked list. */
|
||||
linked_list_t* initialize_single_linked_list();
|
||||
static inline linked_list_t* initialize_single_linked_list();
|
||||
/* This function appends a node to the given linked list. */
|
||||
int append_node_single_linked_list(linked_list_t *list, node_t *node);
|
||||
static inline void append_node_single_linked_list(linked_list_t *list, node_t *node);
|
||||
/* This function prepends a node to the given linked list. */
|
||||
int prepend_node_single_linked_list(linked_list_t *list, node_t *node);
|
||||
static inline void prepend_node_single_linked_list(linked_list_t *list, node_t *node);
|
||||
/* This function creates and appends a node to the given linked list. */
|
||||
int append_node_data_single_linked_list(linked_list_t *list, void *data);
|
||||
static inline int append_node_data_single_linked_list(linked_list_t *list, void *data);
|
||||
/* This function creates and prepends a node to the given linked list. */
|
||||
int prepend_node_data_single_linked_list(linked_list_t *list, void *data);
|
||||
static inline int prepend_node_data_single_linked_list(linked_list_t *list, void *data);
|
||||
/* This function inserts a node at the ith place. */
|
||||
int add_node_i_single_linked_list(linked_list_t *list, node_t *node, size_t i);
|
||||
static inline void add_node_i_single_linked_list(linked_list_t *list, node_t *node, size_t i);
|
||||
/* This function creates and inserts a node at the ith place. */
|
||||
int add_node_data_i_single_linked_list(linked_list_t *list, void *data, size_t i);
|
||||
static inline int add_node_data_i_single_linked_list(linked_list_t *list, void *data, size_t i);
|
||||
/* This function reads the data at the ith node. */
|
||||
void* read_node_i_single_linked_list(linked_list_t *list, size_t i, int *error);
|
||||
static inline void* read_node_i_single_linked_list(linked_list_t *list, size_t i);
|
||||
/* This function retrieves a pointer to the ith node. */
|
||||
node_t* get_node_i_single_linked_list(linked_list_t *list, size_t i, int *error);
|
||||
static inline node_t* get_node_i_single_linked_list(linked_list_t *list, size_t i);
|
||||
/* This function attempts to find the index of a given node, by pointer. */
|
||||
size_t get_node_index_pointer_single_linked_list(linked_list_t *list, node_t *node);
|
||||
static inline size_t get_node_index_pointer_single_linked_list(linked_list_t *list, node_t *node);
|
||||
/* This function attempts to find the index of a given node, by data. */
|
||||
size_t get_node_index_data_single_linked_list(linked_list_t *list, void *data, int (*comparison_function)(const void*, const void*));
|
||||
static inline size_t get_node_index_data_single_linked_list(linked_list_t *list, void *data, int (*comparison_function)(const void*, const void*));
|
||||
/* This function deletes the ith node. */
|
||||
int remove_node_i_single_linked_list(linked_list_t *list, size_t i);
|
||||
static inline void remove_node_i_single_linked_list(linked_list_t *list, size_t i);
|
||||
/* This function deletes the ith node and the data stored within. */
|
||||
int remove_node_i_data_single_linked_list(linked_list_t *list, size_t i, void (*free_function)(void*));
|
||||
static inline void remove_node_i_data_single_linked_list(linked_list_t *list, size_t i, void (*free_function)(void*));
|
||||
/* This function reads the data at the first node. */
|
||||
void* read_node_head_single_linked_list(linked_list_t *list, int *error);
|
||||
static inline void* read_node_head_single_linked_list(linked_list_t *list);
|
||||
/* This function retrieves the first node. */
|
||||
node_t* get_node_head_single_linked_list(linked_list_t *list, int *error);
|
||||
static inline node_t* get_node_head_single_linked_list(linked_list_t *list);
|
||||
/* This function deletes the first node. */
|
||||
int remove_node_head_single_linked_list(linked_list_t *list);
|
||||
static inline void remove_node_head_single_linked_list(linked_list_t *list);
|
||||
/* This function deletes the first node and the data thereof. */
|
||||
int remove_node_head_data_single_linked_list(linked_list_t *list, void (*free_function)(void*));
|
||||
static inline void remove_node_head_data_single_linked_list(linked_list_t *list, void (*free_function)(void*));
|
||||
/* This function reads the data at the last node. */
|
||||
void* read_node_tail_single_linked_list(linked_list_t *list, int *error);
|
||||
static inline void* read_node_tail_single_linked_list(linked_list_t *list);
|
||||
/* This function retrieves the last node. */
|
||||
node_t* get_node_tail_single_linked_list(linked_list_t *list, int *error);
|
||||
static inline node_t* get_node_tail_single_linked_list(linked_list_t *list);
|
||||
/* This function deletes the last node. */
|
||||
int remove_node_tail_single_linked_list(linked_list_t *list);
|
||||
static inline void remove_node_tail_single_linked_list(linked_list_t *list);
|
||||
/* This function deletes the last node and the data thereof. */
|
||||
int remove_node_tail_data_single_linked_list(linked_list_t *list, void (*free_function)(void*));
|
||||
static inline void remove_node_tail_data_single_linked_list(linked_list_t *list, void (*free_function)(void*));
|
||||
/* This function deletes all the nodes of the given list and the list itself. */
|
||||
int clear_list_single_linked_list(linked_list_t **list);
|
||||
static inline int clear_list_single_linked_list(linked_list_t **list);
|
||||
/* This function deletes all the nodes and data stored within of the given list and the list itself. */
|
||||
int clear_list_data_single_linked_list(linked_list_t **list, void (*free_function)(void*));
|
||||
static inline int clear_list_data_single_linked_list(linked_list_t **list, void (*free_function)(void*));
|
||||
/* This function attempts to serialize a linked list into an array, it relies on an array setting function and an allocated buffer. */
|
||||
void *serialize_linked_list(linked_list_t *list, void (*array_setting_function)(void*, size_t, void*), void *array);
|
||||
static inline void *serialize_linked_list(linked_list_t *list, void (*array_setting_function)(void*, size_t, void*), void *array);
|
||||
#endif /* SINGLE_LINKED_LIST_H */
|
||||
|
|
|
@ -61,6 +61,7 @@ linked_list_t* generate_long_random_list(int length) {
|
|||
/* Sanity check. */
|
||||
if (length <= 0)
|
||||
return NULL;
|
||||
|
||||
/* Variables. */
|
||||
linked_list_t *list;
|
||||
node_t *current;
|
||||
|
@ -68,35 +69,26 @@ linked_list_t* generate_long_random_list(int length) {
|
|||
|
||||
/* Allocate the list. */
|
||||
list = initialize_single_linked_list();
|
||||
if (list == NULL)
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
/* Fill the list with random nodes. */
|
||||
/* First node. */
|
||||
current = generate_random_node();
|
||||
if (current == NULL) {
|
||||
if (!current) {
|
||||
free(list);
|
||||
return NULL;
|
||||
}
|
||||
/* Attempt to append. */
|
||||
if (!append_node_single_linked_list(list, current)) {
|
||||
free(current->data);
|
||||
free(current);
|
||||
free(list);
|
||||
return NULL;
|
||||
}
|
||||
append_node_single_linked_list(list, current);
|
||||
|
||||
/* Loop and add the rest. */
|
||||
for (i = 1; i < length; i++) {
|
||||
/* Generate and attempt to append. */
|
||||
current = generate_random_node();
|
||||
if (!append_node_single_linked_list(list, current)) {
|
||||
/* Abort. */
|
||||
free(current->data);
|
||||
free(current);
|
||||
clear_list_data_single_linked_list(&list, NULL);
|
||||
return NULL;
|
||||
}
|
||||
if (!current)
|
||||
break;
|
||||
append_node_single_linked_list(list, current);
|
||||
}
|
||||
|
||||
/* Return the result. */
|
||||
|
@ -202,7 +194,6 @@ int test_linked_lists() {
|
|||
/* Local variables. */
|
||||
linked_list_t *list;
|
||||
node_t *node, *tail;
|
||||
int error;
|
||||
|
||||
/* Initialize an empty list. */
|
||||
list = initialize_single_linked_list();
|
||||
|
@ -219,7 +210,7 @@ int test_linked_lists() {
|
|||
/* Check that the list grew and the head got set. */
|
||||
assert(list->length == LIST_LENGTH_ONE);
|
||||
assert(list->head != NULL && list->head == node);
|
||||
assert(get_node_i_single_linked_list(list, 0, &error) == node);
|
||||
assert(get_node_i_single_linked_list(list, 0) == node);
|
||||
assert(get_node_index_pointer_single_linked_list(list, node) == 0);
|
||||
|
||||
/* Attempt to free the nodes and then the list. */
|
||||
|
@ -239,8 +230,8 @@ int test_linked_lists() {
|
|||
assert(list->length == LIST_LENGTH_LONG_TEST);
|
||||
assert(list->length == list_count_length(list));
|
||||
/* Test the get head/tail functions. */
|
||||
assert(get_node_head_single_linked_list(list, &error) == list->head);
|
||||
tail = get_node_tail_single_linked_list(list, &error);
|
||||
assert(get_node_head_single_linked_list(list) == list->head);
|
||||
tail = get_node_tail_single_linked_list(list);
|
||||
assert(tail != NULL && tail->next == NULL);
|
||||
/* Test the indexer functions. */
|
||||
assert(get_node_index_pointer_single_linked_list(list, tail) == (list->length - 1));
|
||||
|
|
Loading…
Reference in New Issue