diff --git a/list.c b/list.c index 11309fd..8122d4b 100644 --- a/list.c +++ b/list.c @@ -1,136 +1,229 @@ - #include #include #include "util.h" #include "list.h" - void list_init(list *l) { - assert(l); - memset(l, 0, sizeof(*l)); + assert(l); + memset(l, 0, sizeof(*l)); } static inline list_node * list_node_orphan(list_node *li) { - li->next = NULL; - li->prev = NULL; - return li; + li->next = NULL; + li->prev = NULL; + return li; } -//NOTE: Можем ли мы расчитывать на то, что node->next валидно после вызова list_free_cb??? void list_clear(list *l, list_free_cb cb) { - assert(l); - // + assert(l); + list_node *current = l->head; + while (current != NULL) { + list_node *next = current->next; + if (cb) { + cb(current); + } + current = next; + } + l->head = NULL; + l->tail = NULL; } void list_push_front(list *l, list_node *item) { - assert(l && item); - // + assert(l && item); + item->prev = NULL; + item->next = l->head; + + if (l->head != NULL) { + l->head->prev = item; + } else { + l->tail = item; + } + l->head = item; } void list_push_back(list *l, list_node *item) { - assert(l && item); - // + assert(l && item); + item->next = NULL; + item->prev = l->tail; + + if (l->tail != NULL) { + l->tail->next = item; + } else { + l->head = item; + } + l->tail = item; } list_node * list_first(list *l) { - assert(l); - return l->head; + assert(l); + return l->head; } list_node * list_last(list *l) { - assert(l); - return l->tail; + assert(l); + return l->tail; } size_t list_len(list *l) { - assert(l); - // - return 0; + assert(l); + size_t count = 0; + list_node *current = l->head; + while (current != NULL) { + count++; + current = current->next; + } + return count; } list_node * list_get(list *l, int idx) { - assert(l); - // - return NULL; + assert(l); + if (idx < 0) return NULL; + + list_node *current = l->head; + int i = 0; + while (current != NULL && i < idx) { + current = current->next; + i++; + } + return current; } void list_insert(list *l, list_node *item, int idx) { - assert(l && item); - // + assert(l && item); + if (idx == 0) { + list_push_front(l, item); + return; + } + + list_node *current = list_get(l, idx); + if (current == NULL) { + list_push_back(l, item); + return; + } + + item->next = current; + item->prev = current->prev; + current->prev->next = item; + current->prev = item; } list_node * list_pop_front(list *l) { - assert(l); - // - return NULL; + assert(l); + if (l->head == NULL) return NULL; + + list_node *front = l->head; + l->head = front->next; + if (l->head != NULL) { + l->head->prev = NULL; + } else { + l->tail = NULL; + } + return list_node_orphan(front); } list_node * list_pop_back(list *l) { - assert(l); - // - return NULL; + assert(l); + if (l->tail == NULL) return NULL; + + list_node *back = l->tail; + l->tail = back->prev; + if (l->tail != NULL) { + l->tail->next = NULL; + } else { + l->head = NULL; + } + return list_node_orphan(back); } int list_index(list *l, list_node *n) { - assert(l && n); - list_node *tmp; - int i = 0; - for (tmp = l->head; tmp != NULL; tmp = tmp->next) { - if (tmp == n) - return i; - i++; - } - return -1; + assert(l && n); + list_node *tmp; + int i = 0; + for (tmp = l->head; tmp != NULL; tmp = tmp->next) { + if (tmp == n) + return i; + i++; + } + return -1; } list_node * list_remove(list *l, int idx) { - assert(l); - // - return NULL; + assert(l); + if (idx < 0) return NULL; + + list_node *node = list_get(l, idx); + if (node == NULL) return NULL; + + if (node->prev != NULL) { + node->prev->next = node->next; + } else { + l->head = node->next; + } + + if (node->next != NULL) { + node->next->prev = node->prev; + } else { + l->tail = node->prev; + } + + return list_node_orphan(node); } void list_reverse(list *l) { - assert(l); - // + assert(l); + list_node *current = l->head; + list_node *temp = NULL; + + while (current != NULL) { + temp = current->prev; + current->prev = current->next; + current->next = temp; + current = current->prev; + } + + if (temp != NULL) { + l->tail = l->head; + l->head = temp->prev; + } } - void list_pass(list *l, list_pass_cb cb, void *opaq) { - struct list_node *iter; - list_for_each(iter, l) { - cb(iter, opaq); - } -} \ No newline at end of file + struct list_node *iter; + list_for_each(iter, l) { + cb(iter, opaq); + } +} +