1
0
Fork 0
C_lib/linked_lists/double_linked_list.c

782 lines
24 KiB
C

/*
* C_lib Copyright (C) 2021 Wael Karram.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/* This file contains the function implementations for a double-linked-list. */
/* Include guard + includes. */
#include <stdlib.h>
#ifndef DOUBLE_LINKED_LIST_C
#define DOUBLE_LINKED_LIST_C
#include "double_linked_list.h"
#endif /* DOUBLE_LINKED_LIST_C */
/* Function implementations. */
/* This function initializes a new double-linked list, returns NULL on failure. */
double_linked_list_t* initialize_double_linked_list() {
/* Local variables. */
double_linked_list_t* list;
/* Attempt to allocate. */
list = (double_linked_list_t*) malloc(sizeof(double_linked_list_t));
/* Check if the allocation failed. */
if (list == NULL)
return NULL;
/* Initialize the internal fields. */
list->length = 0;
list->head = NULL;
list->tail = NULL;
/* return the result. */
return list;
}
/* This function appends a node to the given linked list. */
/* Returns SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
int append_node_double_linked_list(double_linked_list_t *list, double_node_t *node){
/* Sanity check - make sure input is not NULL and list state is defined! */
if (list == NULL || node == NULL || (list->head != NULL && list->tail == NULL) || (list->head == NULL && list->tail != NULL))
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Set the next node to NULL. */
node->next = NULL;
/* The data is in a defined state, append. */
/* Split cases according to if this is the first node or not. */
if (list->head == NULL) {
/* Set the previous node to NULL. */
node->previous = NULL;
/* Attach. */
list->head = node;
list->tail = node;
list->length = 1;
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* Connect the nodes and update the tail. */
list->tail->next = node;
node->previous = list->tail;
list->tail = node;
list->length = list->length + 1;
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* This function prepends a node the the given linked list. */
/* Returns SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
int prepend_node_double_linked_list(double_linked_list_t *list, double_node_t *node){
/* Sanity check - make sure input is not NULL and list state is defined! */
if (list == NULL || node == NULL || (list->head != NULL && list->tail == NULL) || (list->head == NULL && list->tail != NULL))
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Set the previous node to NULL. */
node->previous = NULL;
/* The data is in a defined state, prepend. */
/* Split cases according to if this is the first node or not. */
if (list->head == NULL) {
/* Set the next node to NULL. */
node->next = NULL;
/* Attach. */
list->head = node;
list->tail = node;
list->length = 1;
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* Connect the nodes and update the head. */
list->head->previous = node;
node->next = list->head;
list->tail = node;
list->length = list->length + 1;
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* This function creates and appends a node to the given linked list. */
/* Returns SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
int append_node_data_double_linked_list(double_linked_list_t *list, void *data){
/* Sanity check - make sure input is not NULL and list state is defined! */
if (list == NULL || (list->head != NULL && list->tail == NULL) || (list->head == NULL && list->tail != NULL))
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Local variables. */
double_node_t* node;
/* Attempt to allocate the node. */
node = (double_node_t*) malloc(sizeof(double_node_t));
/* Check for allocation failure. */
if (node == NULL)
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Store the value. */
node->data = data;
/* Delegate. */
return append_node_double_linked_list(list, node);
}
/* This function creates and prepends a node to the given linked list. */
/* Returns SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
int prepend_node_data_double_linked_list(double_linked_list_t *list, void *data){
/* Sanity check - make sure input is not NULL and list state is defined! */
if (list == NULL || (list->head != NULL && list->tail == NULL) || (list->head == NULL && list->tail != NULL))
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Local variables. */
double_node_t* node;
/* Attempt to allocate the node. */
node = (double_node_t*) malloc(sizeof(double_node_t));
/* Check for allocation failure. */
if (node == NULL)
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Store the value. */
node->data = data;
/* Delegate. */
return prepend_node_double_linked_list(list, node);
}
/* This function inserts a node at the ith place. */
/* Returns SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
int add_node_i_double_linked_list(double_linked_list_t *list, double_node_t *node, int i) {
/* Sanity check - make sure input is not NULL, list state is defined and index is valid. */
if (list == NULL || node == NULL || (list->head != NULL && list->tail == NULL) || (list->head == NULL && list->tail != NULL) || i < 0 || i > list->length)
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Deal with special "easy" cases. */
if (i == 0)
return prepend_node_double_linked_list(list, node);
if (i == list->length)
return append_node_double_linked_list(list, node);
/* Local variables. */
int index;
double_node_t* current;
/* Loop until we get to the desired node. */
current = list->head;
for (index = 0; index < i; index++)
current = current->next;
/* Insert before current. */
node->previous = current->previous;
node->next = current;
current->previous->next = node;
current->previous = node;
/* Increase the length. */
list->length = list->length + 1;
/* Inserted. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* This function creates and inserts a node at the ith place. */
/* Returns SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
int add_node_data_i_double_linked_list(double_linked_list_t *list, void *data, int i) {
/* Sanity check - make sure list state is defined and index is valid. */
if (list == NULL || (list->head != NULL && list->tail == NULL) || (list->head == NULL && list->tail != NULL) || i < 0 || i > list->length)
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Local variables. */
double_node_t* node;
/* Attempt to allocate the node. */
node = (double_node_t*) malloc(sizeof(double_node_t));
/* Check for allocation failure. */
if (node == NULL)
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Store the data. */
node->data = data;
/* Delegate. */
return add_node_i_double_linked_list(list, node, i);
}
/* This function reads the data at the ith node. */
/* Returns NULL on failure! (Even if NULL can be a legitimate value). */
/* Sets error to SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
void* read_node_i_double_linked_list(double_linked_list_t *list, int i, int *error) {
/* Sanity check - make sure list state is defined and index is valid. */
if (error == NULL)
return NULL;
if (list == NULL || (list->head != NULL && list->tail == NULL) || (list->head == NULL && list->tail != NULL) || i < 0 || i > list->length) {
*error = FAILURE_CODE_DOUBLE_LINKED_LIST_C;
return NULL;
}
/* Local variables. */
int index;
double_node_t* current;
/* Loop until we get to the desired node. */
current = list->head;
for (index = 0; index < i; index++)
current = current->next;
/* Set the error code. */
*error = SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
/* Return the data. */
return current->data;
}
/* This function retrieves a pointer to the ith node. */
/* Returns NULL on failure! */
/* Sets error to SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
double_node_t* get_node_i_double_linked_list(double_linked_list_t *list, int i, int *error) {
/* Sanity check - make sure list state is defined and index is valid. */
if (error == NULL)
return NULL;
if (list == NULL || (list->head != NULL && list->tail == NULL) || (list->head == NULL && list->tail != NULL) || i < 0 || i > list->length) {
*error = FAILURE_CODE_DOUBLE_LINKED_LIST_C;
return NULL;
}
/* Local variables. */
int index;
double_node_t* current;
/* Loop till we get to the desired node. */
current = list->head;
for (index = 0; index < i; index++)
current = current->next;
/* Set the error code. */
*error = SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
/* Return the node pointer. */
return current;
}
/* This function attempts to find the index of a given node, by pointer. */
/* Returns INDEX_NOT_FOUND_CODE_DOUBLE_LINKED_LIST_C on failure. */
int get_node_index_pointer_double_linked_list(double_linked_list_t *list, double_node_t *node) {
/* Sanity check. */
if (list == NULL || (list->head != NULL && list->tail == NULL) || (list->head == NULL && list->tail != NULL) || node == NULL)
return INDEX_NOT_FOUND_CODE_DOUBLE_LINKED_LIST_C;
/* Local variables. */
int index = 0;
double_node_t* current = list->head;
/* Loop and look for it. */
while (current != node && current != NULL) {
current = current->next;
index++;
}
/* Return according to if found or not. */
return (current != NULL) ? index : INDEX_NOT_FOUND_CODE_DOUBLE_LINKED_LIST_C;
}
/* This function deletes the ith node, leaves the data AS IS! */
/* Returns SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
int remove_node_i_double_linked_list(double_linked_list_t *list, int i) {
/* Sanity check - make sure list state is defined and index is valid. */
if (list == NULL || (list->head != NULL && list->tail == NULL) || (list->head == NULL && list->tail != NULL) || i < 0 || i > list->length)
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Local variables. */
double_node_t* current;
int index;
/* Special case of an empty list. */
if (list->length == 0) {
/* Done nothing. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* Special case of a list with a single node. */
if (list->length == 1) {
/* Clear the node. */
free(list->head);
/* "Relink" */
list->head = NULL;
list->tail = NULL;
list->length = 0;
/* Done. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* Loop till we get to the desired node. */
while (index < i) {
/* Increment. */
index++;
current = current->next;
}
/* Try to remove the node. */
/* Check if head or tail. */
if (current->previous == NULL) {
/* Update head. */
list->head = current->next;
list->head->previous = NULL;
/* Free node struct. */
free(current);
current = NULL;
/* Update length. */
list->length = list->length - 1;
/* Done. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
if (current->next == NULL) {
/* Update tail. */
list->tail = current->previous;
current->previous->next = NULL;
/* Free node struct. */
free(current);
current = NULL;
/* Update length. */
list->length = list->length - 1;
/* Done. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* General (middle) case. */
/* Update preceding and following nodes. */
current->previous->next = current->next;
current->next->previous = current->previous;
/* Free node struct. */
free(current);
current = NULL;
/* Update length. */
list->length = list->length - 1;
/* Done. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* This function deletes the ith node and the data stored within. */
/* Returns SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
/* If free_function is NULL, will use the stdlib's free(). */
int remove_node_i_data_double_linked_list(double_linked_list_t *list, int i, void (*free_function)(const void*)) {
/* Sanity check - make sure list state is defined and index is valid. */
if (list == NULL || (list->head != NULL && list->tail == NULL) || (list->head == NULL && list->tail != NULL) || i < 0 || i > list->length)
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Local variables. */
double_node_t* current;
int index;
/* Special case of an empty list. */
if (list->length == 0) {
/* Done nothing. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* Special case of a list with a single node. */
if (list->length == 1) {
/* Free the data within the node. */
if (free_function == NULL)
free(list->head->data);
else
free_function(list->head->data);
/* Clear the node. */
free(list->head);
/* "Relink" */
list->head = NULL;
list->tail = NULL;
list->length = 0;
/* Done. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* Loop till we get to the desired node. */
while (index < i) {
/* Increment. */
index++;
current = current->next;
}
/* Try to remove the node. */
/* Check if head or tail. */
if (current->previous == NULL) {
/* Update head. */
list->head = current->next;
current->next->previous = NULL;
/* Free node struct and the data within it. */
if (free_function != NULL)
free_function(current->data);
else
free(current->data);
free(current);
current = NULL;
/* Update length. */
list->length = list->length - 1;
/* Done. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
if (current->next == NULL) {
/* Update tail. */
list->tail = current->previous;
current->previous->next = NULL;
/* Free node struct and the data within it. */
if (free_function != NULL)
free_function(current->data);
else
free(current->data);
free(current);
current = NULL;
/* Update length. */
list->length = list->length - 1;
/* Done. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* General (middle) case. */
/* Update preceding and following nodes. */
current->previous->next = current->next;
current->next->previous = current->previous;
/* Free node struct and the data within it. */
if (free_function != NULL)
free_function(current->data);
else
free(current->data);
free(current);
current = NULL;
/* Update length. */
list->length = list->length - 1;
/* Done. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* This function reads the data at the first node. */
/* Returns NULL on error or empty list. */
void* read_node_head_double_linked_list(double_linked_list_t *list) {
/* Sanity check. */
if (list == NULL || list->length == 0 || list->head == NULL)
return NULL;
/* Return the data. */
return list->head->data;
}
/* This function retrieves the first node. */
/* Returns NULL on error or empty list. */
double_node_t* get_node_head_double_linked_list(double_linked_list_t *list) {
/* Sanity check. */
if (list == NULL || list->length == 0)
return NULL;
/* Return the data. */
return list->head;
}
/* This function deletes the first node. */
/* Returns SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
int remove_node_head_double_linked_list(double_linked_list_t *list) {
/* Sanity check. */
if (list == NULL || (list->head != NULL && list->tail == NULL) || (list->head == NULL && list->tail != NULL))
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Check if we have to do anything at all. */
if (list->head == NULL)
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
/* Split into cases. */
if (list->length == 1) {
/* Clear the only node. */
free(list->head);
/* Set the list to be empty again. */
list->head = NULL;
list->tail = NULL;
list->length = 0;
/* Done. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* Length over one. */
/* Local variables. */
double_node_t* tmp = list->head;
/* Reconnect. */
list->head = list->head->next;
list->head->previous = NULL;
/* Free the node. */
free(tmp);
/* Change the length. */
list->length = list->length - 1;
/* Done. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* This function deletes the first node and the data thereof. */
/* Returns SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
/* If free_function is NULL, will use the stdlib's free(). */
int remove_node_head_data_double_linked_list(double_linked_list_t *list, void (*free_function)(const void*)) {
/* Sanity check. */
if (list == NULL || (list->head != NULL && list->tail == NULL) || (list->head == NULL && list->tail != NULL))
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Check if we have to do anything at all. */
if (list->head == NULL)
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
/* Split into cases. */
if (list->length == 1) {
/* Clear the only node and the data therof. */
if (free_function == NULL)
free(list->head->data);
else
free_function(list->head->data);
free(list->head);
/* Set the list to be empty again. */
list->head = NULL;
list->tail = NULL;
list->length = 0;
/* Done. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* Length over one. */
/* Local variables. */
double_node_t* tmp = list->head;
/* Reconnect. */
list->head = list->head->next;
list->head->previous = NULL;
/* Free the node and data thereof. */
if (free_function == NULL)
free(list->head->data);
else
free_function(list->head->data);
free(tmp);
/* Change the length. */
list->length = list->length - 1;
/* Done. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* This function reads the data at the last node. */
/* Returns NULL on error or empty list. */
void* read_node_tail_double_linked_list(double_linked_list_t *list) {
/* Sanity check. */
if (list == NULL || list->length == 0 || list->tail == NULL)
return NULL;
/* Return the data. */
return list->tail->data;
}
/* This function retrieves the last node. */
/* Returns NULL on error or empty list. */
double_node_t* get_node_tail_double_linked_list(double_linked_list_t *list) {
/* Sanity check. */
if (list == NULL || list->length == 0)
return NULL;
/* Return the data. */
return list->tail;
}
/* This function deletes the last node. */
/* Returns SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
/* Failure is also when the list state isn't properly defined! */
int remove_node_tail_double_linked_list(double_linked_list_t *list) {
/* Sanity check. */
if (list == NULL || list->length == 0 || (list->head != NULL && list->tail == NULL) || (list->head == NULL && list->tail != NULL))
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Local variables. */
double_node_t *current;
/* Split cases. */
/* Single node case. */
if (list->length == 1) {
free(list->tail);
list->head = NULL;
list->tail = NULL;
list->length = 0;
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* General case. */
/* Save the pointer to the node to be deleted. */
current = list->tail;
/* Relink the tail. */
list->tail = current->previous;
free(current);
list->length = list->length - 1;
/* Done. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* This function deletes the last node and the data thereof. */
/* Returns SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
/* If free_function is NULL, will use the stdlib's free(). */
int remove_node_tail_data_double_linked_list(double_linked_list_t *list, void (*free_function)(const void*)) {
/* Sanity check. */
if (list == NULL || list->length == 0 || (list->head != NULL && list->tail == NULL) || (list->head == NULL && list->tail != NULL))
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Local variables. */
double_node_t *current;
/* Split cases. */
/* Single node case. */
if (list->length == 1) {
/* Free the data. */
if (free_function == NULL)
free(list->tail->data);
else
free_function(list->tail->data);
/* Free the node and clean up. */
free(list->tail);
list->head = NULL;
list->tail = NULL;
list->length = 0;
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* General case. */
/* Save the pointer to the node to be deleted. */
current = list->tail;
/* Free the data. */
if (free_function == NULL)
free(list->tail->data);
else
free_function(list->tail->data);
/* Free the node and clean up. */
/* Relink the tail. */
list->tail = current->previous;
free(current);
list->length = list->length - 1;
/* Done. */
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* This function deletes all the nodes of the given list and the list itself. */
/* Returns SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
int clear_list_double_linked_list(double_linked_list_t **list) {
/* Sanity check. */
if (list == NULL || *list == NULL)
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
/* Invalid state. */
if (((*list)->head != NULL && (*list)->tail == NULL) || ((*list)->head == NULL && (*list)->tail != NULL))
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Variables. */
double_node_t *current, *next;
/* Special case. */
if ((*list)->length == 0) {
/* Free the list, and set the pointer. */
free(*list);
*list = NULL;
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* General case, free all nodes then the list. */
current = (*list)->head;
while (current != NULL) {
/* Save the next pointer. */
next = current->next;
/* Free the current node. */
free(current);
/* Advance by one node. */
current = next;
}
/* Free the list, and set the pointer. */
free(*list);
*list = NULL;
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* This function deletes all the nodes and data stored within of the given list and the list itself. */
/* Returns SUCCESS_CODE_DOUBLE_LINKED_LIST_C on success, and FAILURE_CODE_DOUBLE_LINKED_LIST_C on failure. */
/* If free_function is NULL, will use the stdlib's free(). */
int clear_list_data_double_linked_list(double_linked_list_t **list, void (*free_function)(const void*)) {
/* Sanity check. */
if (list == NULL || *list == NULL)
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
/* Invalid state. */
if (((*list)->head != NULL && (*list)->tail == NULL) || ((*list)->head == NULL && (*list)->tail != NULL))
return FAILURE_CODE_DOUBLE_LINKED_LIST_C;
/* Variables. */
double_node_t *current, *next;
/* Special case. */
if ((*list)->length == 0) {
/* Free the list, and set the pointer. */
free(*list);
*list = NULL;
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* General case, free all nodes then the list. */
current = (*list)->head;
while (current != NULL) {
/* Save the next pointer. */
next = current->next;
/* Free the current node's data. */
if (free_function == NULL)
free(current->data);
else
free_function(current->data);
/* Free the current node. */
free(current);
/* Advance by one node. */
current = next;
}
/* Free the list, and set the pointer. */
free(*list);
*list = NULL;
return SUCCESS_CODE_DOUBLE_LINKED_LIST_C;
}
/* This function attempts to serialize a doubly-linked list into an array. */
/* The function will allocate and return a pointer to said array on success, NULL on failure. */
/* The length of the array is sent through the length pointer, and set to -1 on failure. */
void **serialize_double_linked_list(double_linked_list_t *list, int *length) {
/* Local variables. */
void **array;
double_node_t *current;
int i;
/* Sanity check. */
if (list == NULL || list->head == NULL || length == NULL || list->length <= 0)
return NULL;
/* Set the length. */
*length = list->length;
/* Attempt to allocate the array. */
array = (void**) (malloc(list->length * sizeof(void*)));
if (array == NULL) {
*length = -1;
return NULL;
}
/* Loop and add the elements. */
current = list->head;
for (i = 0; i < *length; i++) {
array[i] = current->data;
current = current->next;
}
/* Return the filled array. */
return array;
}