diff --git a/include/patty/list.h b/include/patty/list.h new file mode 100644 index 0000000..6e67f72 --- /dev/null +++ b/include/patty/list.h @@ -0,0 +1,64 @@ +#ifndef _PATTY_LIST_H +#define _PATTY_LIST_H + +#include +#include + +typedef struct _patty_list_item { + struct _patty_list_item * prev; + struct _patty_list_item * next; + + void * value; +} patty_list_item; + +typedef struct _patty_list { + uint64_t size; + uint64_t length; + + patty_list_item * first; + patty_list_item * last; +} patty_list; + +typedef struct _patty_list_iterator { + patty_list *list; + + size_t index; + patty_list_item * item; +} patty_list_iterator; + +typedef void (*patty_list_callback)(void *item, void *ctx); + +patty_list *patty_list_new(); + +void patty_list_destroy(patty_list *list); + +size_t patty_list_length(patty_list *list); + +void *patty_list_set(patty_list *list, off_t index, void *item); + +void *patty_list_append(patty_list *list, void *item); + +void *patty_list_prepend(patty_list *list, void *item); + +void *patty_list_last(patty_list *list); + +void *patty_list_pop(patty_list *list); + +void *patty_list_insert(patty_list *list, off_t index); + +void *patty_list_index(patty_list *list, off_t index); + +patty_list_iterator *patty_list_start(patty_list *list); + +void *patty_list_next(patty_list_iterator *iterator); + +void patty_list_reset(patty_list_iterator *iterator); + +void patty_list_finish(patty_list_iterator *iterator); + +void patty_list_each( + patty_list * list, + patty_list_callback callback, + void * ctx); + +#endif /* _PATTY_LIST_H */ diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000..da7146b --- /dev/null +++ b/src/list.c @@ -0,0 +1,183 @@ +#include +#include +#include + +#include + +patty_list *patty_list_new() { + patty_list *list; + + if ((list = malloc(sizeof(*list))) == NULL) { + goto error_malloc_list; + } + + list->length = 0; + list->size = 0; + list->first = NULL; + list->last = NULL; + + return list; + +error_malloc_list: + return NULL; +} + +void patty_list_destroy(patty_list *list) { + patty_list_item *item = list->first; + + while (item != NULL) { + patty_list_item *next = (patty_list_item *)item->next; + + free(item); + + item = next; + } + + free(list); +} + +size_t patty_list_length(patty_list *list) { + return list->length; +} + +void *patty_list_set(patty_list *list, off_t index, void *value) { + patty_list_item *item = list->first; + size_t i = 0; + + while (item != NULL) { + if (i++ == index) { + return item->value = value; + } + + item = item->next; + } + + return NULL; +} + +void *patty_list_append(patty_list *list, void *value) { + patty_list_item *item = list->first; + patty_list_item *new; + + if ((new = malloc(sizeof(*new))) == NULL) { + goto error_malloc_item; + } + + new->value = value; + + if (list->first == NULL) { + list->first = new; + } else { + for (item = list->first; item->next != NULL; item = item->next); + + item->next = new; + } + + list->length++; + + return value; + +error_malloc_item: + return NULL; +} + +void *patty_list_last(patty_list *list) { + patty_list_item *item = list->first; + + while (item->next != NULL) { + item = item->next; + } + + return item->value; +} + +void *patty_list_pop(patty_list *list) { + patty_list_item *item = list->first; + patty_list_item *last = NULL; + + while (item != NULL) { + if (item->next == NULL) { + void *ret = item->value; + + if (last == NULL) { + list->first = NULL; + } else { + last->next = NULL; + } + + free(item); + + return ret; + } + + last = item; + item = item->next; + } + + return NULL; +} + +void *patty_list_index(patty_list *list, off_t index) { + patty_list_item *item = list->first; + size_t i = 0; + + if (index < 0) { + index += list->length; + + } + + if (index >= list->length || index < 0) { + return NULL; + } + + while (i < index && item->next != NULL) { + item = item->next; + i++; + } + + return item->value; +} + +patty_list_iterator *patty_list_start(patty_list *list) { + patty_list_iterator *iterator; + + if ((iterator = malloc(sizeof(patty_list_iterator))) == NULL) { + goto error_malloc; + } + + iterator->list = list; + iterator->item = list->first; + + return iterator; + +error_malloc: + return NULL; +} + +void *patty_list_next(patty_list_iterator *iterator) { + void *value = NULL; + + if (iterator->item) { + value = iterator->item->value; + + iterator->item = iterator->item->next; + } + + return value; +} + +void patty_list_reset(patty_list_iterator *iterator) { + iterator->item = iterator->list->first; +} + +void patty_list_finish(patty_list_iterator *iterator) { + free(iterator); +} + +void patty_list_each(patty_list *list, patty_list_callback callback, void *ctx) { + patty_list_item *item; + + for (item = list->first; item != NULL; item = item->next) { + callback(item->value, ctx); + } +}