diff --git a/list.c b/list.c new file mode 100644 index 0000000..ff6f5bb --- /dev/null +++ b/list.c @@ -0,0 +1,125 @@ +#include +#include +#include +#define TYPE int +//A list is one of: +// - (make-note element next) +// - '() -> NULL + +struct node { + TYPE element; + struct node* prev; + struct node* next; +}; + +typedef struct node node_t; + +typedef struct { + node* first; +} list_t; + +size_t list_length(const list_t* self) { + size_t length = 0; + node_t* i = self->first; + + while (i != NULL) { + length++; + i = self->next; + } + + return length; +} + +node_t* list_ith(const list_t* self, const size_t position) { + size_t found; + node_t* elem = list_ith_or_last(self, position, &found); + return found != position ? NULL : elem; +} + +node_t* list_ith_or_last(const list_t* self, const size_t position, + const size_t* returned) { + node_t* to_reach = self->first; + size_t i; + for (i = 0; i < position && to_reach->next != NULL; i++) { + to_reach = to_reach->next; + } + *returned = i; + return to_reach; +} + +node_t* make_node(TYPE element) { + node_t* node = malloc(sizeof(node)); + node->element = element; + node->next = NULL; + node->prev = NULL; +} + +void free_list(const list_t* list) { + while(list->first != NULL) { + free(list_remove(self, 0)); + } +} + +size_t list_copy_slice(const list_t* self, const list_t* destination, + const size_t from, const size_t to) { + if (from >= to) { + return 0; + } + free_list(destination); + size_t start, i; + node_t* to_copy = list_ith_or_last(self, to, &start); + if (to_copy == NULL) { + return 0; + } + + for(i = start; i > from; i--) { + node_t* copied = malloc(sizeof(node_t)); + memcpy(copied, src, sizeof(node_t)); + list_insert(destination, 0, copied); + } + + return start - from; +} + +int list_insert(const list_t* self, const size_t position, const node_t* node) { + if (self->first == NULL) { + return 1; + } + + if (position == 0) { + node->next = self->first; + node->prev = NULL; + self->first = node; + return 0; + } + + node_t* to_reach = list_ith(self, position - 1); + + if (to_reach == NULL) { + return 2; + } + + to_reach->next->prev = node; + node->next = to_reach->next; + node->prev = to_reach; + to_reach->next = node; + return 0; +} + +node_t* list_remove(const list_t* self, const size_t position) { + if(position == 0) { + node_t* to_remove = self->first; + self->first = to_remove->next; + return to_remove; + } + + node_t* to_reach = list_ith(self, position - 1); + if (to_reach == NULL || to_reach->next == NULL) { + return NULL; + } + + node_t* to_remove = to_reach->next; + to_reach->next = to_reach->next->next; + to_reach->next->prev = to_reach; + return to_remove; +}