diff --git a/src/lib/data-types.h b/src/lib/data-types.h index 434cc97..4c625a4 100644 --- a/src/lib/data-types.h +++ b/src/lib/data-types.h @@ -10,13 +10,10 @@ #ifndef DATA_TYPES_h #define DATA_TYPES_h + #include #include #include #include "data-types/linked-list.h" - #define bool _Bool - #define true ((bool)1) - #define false ((bool)0) - #endif diff --git a/src/lib/data-types/linked-list.c b/src/lib/data-types/linked-list.c index ec14c1e..9528132 100644 --- a/src/lib/data-types/linked-list.c +++ b/src/lib/data-types/linked-list.c @@ -1,5 +1,10 @@ /* ---------------------------------------------------------------------------- * linked list + * + * Notes: + * - When 'position' is used, it referes to the position of the node in the + * list, not the node's offset. E.g. the node with position == 1 is the + * first node in the list. * ---------------------------------------------------------------------------- * Copyright (c) 2012 Ben Blazak * Released under The MIT License (MIT) (see "license.md") @@ -13,13 +18,22 @@ #include "linked-list.h" -// convenience macros (undefined later) -#define _NEW_STRUCT_POINTER(type, name) \ - struct type * name = (struct type *) malloc(sizeof(struct type)) +// local macros (undefined later) +#define _NEW_POINTER(type, name) type * name = (type *) malloc(sizeof(type)) +#define _list_t linked_list_t +#define _node_t linked_list_node_t +#define _data_t LINKED_LIST_DATA_TYPE -struct linked_list * linked_list_new(void) { - _NEW_STRUCT_POINTER(linked_list, list); +/* + * new() + * + * Returns + * - success: a pointer to a new linked list + * - failure: NULL + */ +_list_t * linked_list_new(void) { + _NEW_POINTER(_list_t, list); if (!list) return NULL; list->head = NULL; @@ -29,11 +43,15 @@ struct linked_list * linked_list_new(void) { return list; } -struct linked_list * linked_list_add_head( - struct linked_list * list, - LINKED_LIST_DATA_TYPE data ) { - - _NEW_STRUCT_POINTER(linked_list_node, node); +/* + * add_head() + * + * Returns + * - success: the pointer to the list that was passed + * - failure: NULL + */ +_list_t * linked_list_add_head(_list_t * list, _data_t data) { + _NEW_POINTER(_node_t, node); if (!node) return NULL; node->data = data; @@ -46,11 +64,15 @@ struct linked_list * linked_list_add_head( return list; } -struct linked_list * linked_list_add_tail( - struct linked_list * list, - LINKED_LIST_DATA_TYPE data ) { - - _NEW_STRUCT_POINTER(linked_list_node, node); +/* + * add_tail() + * + * Returns + * - success: the pointer to the list that was passed + * - failure: NULL + */ +_list_t * linked_list_add_tail(_list_t * list, _data_t data) { + _NEW_POINTER(_node_t, node); if (!node) return NULL; node->data = data; @@ -65,11 +87,18 @@ struct linked_list * linked_list_add_tail( return list; } -LINKED_LIST_DATA_TYPE linked_list_pop_head(struct linked_list * list) { +/* + * pop_head() + * + * Returns + * - success: the data element of the first node of the list + * - failure: (_data_t) 0 + */ +_data_t linked_list_pop_head(_list_t * list) { if (list->number_of_elements == 0) - return 0; + return (_data_t) 0; - struct linked_list_node node = { + _node_t node = { .data = list->head->data, .next = list->head->next }; @@ -87,15 +116,24 @@ LINKED_LIST_DATA_TYPE linked_list_pop_head(struct linked_list * list) { return node.data; } -// note: this function is inefficient for singly linked lists: it has O(n) time -// instead of O(1) time like most of the other functions. but it's not needed -// for implementing stacks or queues, so i don't anticipate it being used all -// that much. it's here for completeness. -LINKED_LIST_DATA_TYPE linked_list_pop_tail(struct linked_list * list) { +/* + * pop_tail() + * + * Returns + * - success: the data element of the last node of the list + * - failure: (_data_t) 0 + * + * Note + * - This function is inefficient for singly linked lists: it has O(n) time + * instead of O(1) time like most of the other functions. But it's not + * needed for implementing stacks or queues, so i don't anticipate it being + * used all that much. It's here for completeness. + */ +_data_t linked_list_pop_tail(_list_t * list) { if (list->number_of_elements == 0) - return 0; + return (_data_t) 0; - struct linked_list_node node = { + _node_t node = { .data = list->tail->data, .next = list->tail->next }; @@ -116,22 +154,62 @@ LINKED_LIST_DATA_TYPE linked_list_pop_tail(struct linked_list * list) { return node.data; } -LINKED_LIST_DATA_TYPE linked_list_read( - struct linked_list * list, - uint8_t position ) { - +/* + * read() + * + * Returns + * - success: the data element at the given position + * - failure: (_data_t) 0 + */ +_data_t linked_list_read(_list_t * list, uint8_t position) { if (position < 1 || position > (list->number_of_elements)) - return 0; + return (_data_t) 0; - struct linked_list_node * node = list->head; + _node_t * node = list->head; for (uint8_t i=1; inext; return node->data; } -struct linked_list * linked_list_copy(struct linked_list * list) { - _NEW_STRUCT_POINTER(linked_list, copy); +/* + * insert() + * - Insert a new node containing the given data such that it occupies the + * given position in the list. + * + * Returns + * - success: the pointer to the list that was passed + * - failure: NULL + */ +_list_t * linked_list_insert(_list_t * list, _data_t data, uint8_t position) { + if (position < 1 || position > (list->number_of_elements)+1) + return NULL; + + _NEW_POINTER(_node_t, new); + if (!new) return NULL; + + _node_t * prev = list->head; + for (uint8_t i=0; inext; + + new->data = data; + new->next = prev->next; + prev->next = new; + + list->number_of_elements++; + return list; +} + +/* + * copy() + * + * Returns + * - success: a new pointer to a copy of the list who's pointer was passed + * - failure: NULL + */ +_list_t * linked_list_copy(_list_t * list) { + _NEW_POINTER(_list_t, copy); + if (!copy) return NULL; for (uint8_t i=1; i<=(list->number_of_elements); i++) linked_list_add_tail(copy, linked_list_read(list, i)); @@ -139,18 +217,102 @@ struct linked_list * linked_list_copy(struct linked_list * list) { return copy; } - -// note: this is implemented inefficiently (using ...pop_head(), which does -// extra work). but that makes things simpler, and i don't anticipate using it -// all that often. -void linked_list_free(struct linked_list * list) { +/* + * free() + * - Free the memory allocated to all the nodes, then free the memory allocated + * to the list. + * + * Note + * - This is implemented inefficiently (using pop_head(), which does extra + * work). But that makes things simpler, and i don't anticipate using it all + * that often. + */ +void linked_list_free(_list_t * list) { while ((list->number_of_elements) > 0) linked_list_pop_head(list); free(list); } +/* + * slice_copy() + * - Return the (copied) sublist + * + * Arguments + * - start_position: + * - the position of the first element to include in the slice + * - or '0' for the beginning of the list + * - end_position: + * - the position of the last element to include in the slice + * - or '0' for the end of the list + * + * Returns + * - success: a copy of the portion of the list indicated + * - failure: NULL + */ +_list_t * linked_list_slice_copy ( + _list_t * list, + uint8_t start_position, + uint8_t end_position ) { -// convenience macros (undefined here) -#undef _NEW_STRUCT_POINTER + if ( start_position > end_position || + end_position > (list->number_of_elements) ) + return NULL; + + if (start_position == 0) + start_position = 1; + if (end_position == 0) + end_position = list->number_of_elements; + + _NEW_POINTER(_list_t, shallow_slice); + if (!shallow_slice) return NULL; + + shallow_slice->number_of_elements = end_position - start_position + 1; + shallow_slice->head = list->head; + for (uint8_t i=1; ihead = shallow_slice->head->next; + shallow_slice->tail = shallow_slice->head; + for (uint8_t i=1; i<(shallow_slice->number_of_elements); i++) + shallow_slice->tail = shallow_slice->tail->next; + + return linked_list_copy(shallow_slice); +} + +/* + * slice() + */ +_list_t * linked_list_slice ( + _list_t * list, + uint8_t start_position, + uint8_t end_position ) { + // TODO +} + +/* + * remove() + */ +_list_t * linked_list_remove(_list_t * list, uint8_t position) { + // TODO +} + +/* + * find_first() + */ +uint8_t linked_list_find_first(_list_t * list, _data_t data) { + // TODO +} + +/* + * reverse() + */ +_list_t * linked_list_reverse(_list_t * list) { + // TODO +} + + +// local macros (undefined here) +#undef _NEW_POINTER +#undef _list_t +#undef _node_t +#undef _data_t diff --git a/src/lib/data-types/linked-list.h b/src/lib/data-types/linked-list.h index 9a918e7..56bcb88 100644 --- a/src/lib/data-types/linked-list.h +++ b/src/lib/data-types/linked-list.h @@ -1,7 +1,5 @@ /* ---------------------------------------------------------------------------- * linked list : exports - * - * Includes aliases to treat the list as a queue or stack. * ---------------------------------------------------------------------------- * Copyright (c) 2012 Ben Blazak * Released under The MIT License (MIT) (see "license.md") @@ -15,7 +13,7 @@ #include "lib/data-types.h" - // default list data type + // default data type for the list #ifndef LINKED_LIST_DATA_TYPE #define LINKED_LIST_DATA_TYPE uint8_t #endif @@ -27,60 +25,42 @@ struct linked_list_node * next; }; - struct linked_list{ + struct linked_list { uint8_t number_of_elements; struct linked_list_node * head; struct linked_list_node * tail; }; + // typedefs + typedef struct linked_list linked_list_t; + typedef struct linked_list_node linked_list_node_t; + // functions - struct linked_list * linked_list_new(void); - struct linked_list * linked_list_add_head( - struct linked_list * list, - LINKED_LIST_DATA_TYPE data ); - struct linked_list * linked_list_add_tail( - struct linked_list * list, - LINKED_LIST_DATA_TYPE data ); - LINKED_LIST_DATA_TYPE linked_list_pop_head(struct linked_list * list); - LINKED_LIST_DATA_TYPE linked_list_pop_tail(struct linked_list * list); - LINKED_LIST_DATA_TYPE linked_list_read( - struct linked_list * list, - uint8_t position ); - struct linked_list * linked_list_copy(struct linked_list * list); - void linked_list_free(struct linked_list * list); - - - // typedefs, for user code - typedef struct linked_list * linked_list_t; - typedef struct linked_list_node * linked_list_node_t; - - // aliases, for user code - #define list_t linked_list_t - #define list_new linked_list_new - #define list_push linked_list_add_head - #define list_append linked_list_add_tail - #define list_pop linked_list_pop_head - #define list_pop_tail linked_list_pop_tail - #define list_read linked_list_read - #define list_copy linked_list_copy - #define list_free linked_list_free - - #define queue_t list_t - #define queue_new list_new - #define queue_append list_append - #define queue_pop list_pop - #define queue_read list_read - #define queue_copy list_copy - #define queue_free list_free - - #define stack_t list_t - #define stack_new list_new - #define stack_push list_push - #define stack_pop list_pop - #define stack_read list_read - #define stack_copy list_copy - #define stack_free list_free + #define _list_t linked_list_t + #define _data_t LINKED_LIST_DATA_TYPE + _list_t * linked_list_new (void); + _list_t * linked_list_add_head (_list_t * list, _data_t data); + _list_t * linked_list_add_tail (_list_t * list, _data_t data); + _data_t linked_list_pop_head (_list_t * list); + _data_t linked_list_pop_tail (_list_t * list); + _data_t linked_list_read (_list_t * list, uint8_t position); + _list_t * linked_list_insert ( _list_t * list, + uint8_t position, + _data_t data ); + _list_t * linked_list_copy (_list_t * list); + void linked_list_free (_list_t * list); + _list_t * linked_list_slice_copy ( _list_t * list, + uint8_t start_position, + uint8_t end_position ); + _list_t * linked_list_slice ( _list_t * list, + uint8_t start_position, + uint8_t end_position ); + _list_t * linked_list_remove (_list_t * list, uint8_t position); + uint8_t linked_list_find_first (_list_t * list, _data_t data); + _list_t * linked_list_reverse (_list_t * list); + #undef _list_t + #undef _data_t #endif