/* Standard Includes */ #include /* Local Includes */ #include "std_list.h" /** * A node in the linked list. */ struct std_list_node { /** * The data stored in the node. */ void *data; /** * The next node in the list, or NULL. */ struct std_list_node *next; /** * The previous node in the list, or NULL. */ struct std_list_node *prev; }; /** * The doubly linked list context. * * This stores the begin and end (one past last node) of the list, * and can store any state data associated with a list context. */ struct std_list { /** * A pointer to the first node in the list. * * If the list is empty, this points to end. */ struct std_list_node *begin; /** * A pointer to the node after the last node in the list. * If the list is empty, this points to an empty node. */ struct std_list_node *end; /** * The size of the list. */ int length; /** * A destroy function used to free the user's data before a list * item is free'd. */ STDDestroyNotify destroy_func; }; /* Functions */ /* --------- */ /** * Allocate a single std_list_node. * * @return * A new list on success, or NULL on error */ static struct std_list_node* std_list_node_create (void) { struct std_list_node *list_node; list_node = malloc ( sizeof ( struct std_list_node )); if ( !list_node ) return NULL; list_node->data = NULL; list_node->next = NULL; list_node->prev = NULL; return list_node; } /** * Destroy a single std_list_node. * * @return * 0 on success, or -1 on error. */ static int std_list_node_destroy ( struct std_list_node *list_node, STDDestroyNotify destroy_func ) { if ( !list_node ) return -1; if ( destroy_func ) destroy_func ( list_node->data ); list_node->data = NULL; list_node->next = NULL; list_node->prev = NULL; free ( list_node ); list_node = NULL; return 0; } /** * Allocate for a new list. * * @return * A new list on success, or NULL on error */ struct std_list* std_list_create ( STDDestroyNotify destroy_func ) { struct std_list *list; list = malloc ( sizeof ( struct std_list )); if ( !list ) return NULL; list->begin = std_list_node_create (); if ( !list->begin ) return NULL; list->end = list->begin; list->length = 0; list->destroy_func = destroy_func; return list; } int std_list_remove_all ( struct std_list *list ) { std_list_iterator iter; /* Traverse the list and free the data members */ for ( iter = std_list_begin ( list ); iter != std_list_end ( list ); ){ iter = std_list_remove ( list, iter ); if (!iter ) return -1; } return 0; } int std_list_destroy ( struct std_list *list ) { if ( !list ) return -1; if ( std_list_remove_all ( list ) == -1 ) return -1; /* Free the dummy node (remove won't do this) */ std_list_node_destroy(list->end, list->destroy_func); /* Free the list structure */ free(list); return 0; } int std_list_append ( struct std_list *list, void *data ) { if ( !list ) return -1; if ( std_list_insert ( list, list->end, data ) == -1 ) return -1; return 0; } int std_list_prepend ( struct std_list *list, void *data ) { if ( !list ) return -1; if ( std_list_insert ( list, list->begin, data ) == -1 ) return -1; return 0; } int std_list_insert ( struct std_list *list, const std_list_iterator iter, void *data) { std_list_iterator new_node; if ( !list ) return -1; if ( !iter ) return -1; new_node = std_list_node_create (); if ( !new_node ) return -1; new_node->data = data; if ( iter == list->begin ) { new_node->next = iter; iter->prev = new_node; list->begin = new_node; } else { std_list_iterator before; before = iter->prev; new_node->next = iter; before->next = new_node; new_node->prev = before; iter->prev = new_node; } list->length = list->length + 1; return 0; } int std_list_insert_sorted ( struct std_list *list, void *data, const STDCompareFunc func) { std_list_iterator current; void *current_data; if ( !list ) return -1; if ( !func ) return -1; /* Seek to the corrent position to insert new item */ for (current = std_list_begin(list); current != std_list_end(list); current = std_list_next(current)) { if (std_list_get_data(current, ¤t_data) != 0){ return -2; } /* If the new data is <= data at this node, stop looping and * insert the data into the list before the current. */ if (func(data, current_data) <= 0){ break; } } /* Insert the item before the current iterator now. */ return std_list_insert(list, current, data); } std_list_iterator std_list_remove ( struct std_list *list, std_list_iterator iter ) { std_list_iterator after; if ( !list ) return NULL; if ( !iter ) return NULL; /* remove the iterator */ if ( iter == list->end ) return NULL; if ( iter == list->begin ) { after = iter->next; list->begin = after; list->begin->prev = NULL; } else { std_list_iterator before; before = iter->prev; after = iter->next; before->next = after; after->prev = before; } if ( std_list_node_destroy ( iter, list->destroy_func ) == -1 ) return NULL; list->length -= 1; return after; } std_list_iterator std_list_find ( const struct std_list *list, const void *data, const STDCompareFunc func ) { std_list_iterator iter; std_list_iterator found; if ( !list ) return NULL; if ( !func ) return NULL; found = std_list_end ( list ); /* Find the item */ for ( iter = std_list_begin ( list ); iter != std_list_end ( list ); iter = std_list_next ( iter ) ){ void *iter_data; if ( std_list_get_data ( iter, &iter_data ) == -1 ) return NULL; if ( func ( iter_data, data ) == 0 ) { found = iter; break; } } return iter; } std_list_iterator std_list_begin ( const struct std_list *list ) { if ( !list ) return NULL; return list->begin; } std_list_iterator std_list_end ( const struct std_list *list ) { if ( !list ) return NULL; return list->end; } std_list_iterator std_list_next ( const std_list_iterator iter ){ if ( !iter ) return NULL; return iter->next; } std_list_iterator std_list_previous ( const std_list_iterator iter ){ if ( !iter ) return NULL; return iter->prev; } int std_list_length ( struct std_list *list ) { if ( !list ) return -1; return list->length; } int std_list_foreach ( const struct std_list *list, const STDFunc func, void *user_data ) { std_list_iterator iter; if ( !list ) return -1; if ( !func ) return -1; /* do the foreach */ for ( iter = std_list_begin ( list ); iter != std_list_end ( list ); iter = std_list_next ( iter ) ){ void *data; if ( std_list_get_data ( iter, &data ) == -1 ) return -1; if ( func ( data, user_data ) == 0 ) break; } return 0; } int std_list_sort ( struct std_list *list, STDCompareFunc compare_func ) { if ( !list ) return -1; if ( !compare_func ) return -1; /* sort the list */ return 0; } int std_list_sort_with_data ( struct std_list *list, STDCompareDataFunc compare_func, void *user_data ) { if ( !list ) return -1; if ( !compare_func ) return -1; /* sort the list */ return 0; } int std_list_get_data ( std_list_iterator iter, void *data ) { if ( !iter ) return -1; /* Copy the pointer */ memcpy(data, &iter->data, sizeof(void *)); return 0; }