#include #include #include "util.h" #include "list.h" void list_init(list *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; } //NOTE: Можем ли мы расчитывать на то, что node->next валидно после вызова list_free_cb??? void list_clear(list *l, list_free_cb cb) { assert(l); list_node *cur = l->head; while (cur) { list_node *next_node = cur->next; if (cb) cb(cur); cur = next_node; } l->head = NULL; l->tail = NULL; } void list_push_front(list *l, list_node *item) { assert(l && item); item->prev = NULL; item->next = l->head; if (l->head) l->head->prev = item; else l->tail = item; l->head = item; } void list_push_back(list *l, list_node *item) { assert(l && item); item->next = NULL; item->prev = l->tail; if (l->tail) l->tail->next = item; else l->head = item; l->tail = item; } list_node * list_first(list *l) { assert(l); return l->head; } list_node * list_last(list *l) { assert(l); return l->tail; } size_t list_len(list *l) { assert(l); size_t cnt = 0; for (list_node *cur = l->head; cur; cur = cur->next) cnt++; return cnt; } list_node * list_get(list *l, int idx) { assert(l); if (idx < 0) return NULL; int i = 0; for (list_node *cur = l->head; cur; cur = cur->next, i++) if (i == idx) return cur; return NULL; } void list_insert(list *l, list_node *item, int idx) { assert(l && item); int len = (int)list_len(l); if (idx < 0 || idx > len) xerror(1, "index out of range\n"); if (idx == 0) { list_push_front(l, item); return; } if (idx == len) { list_push_back(l, item); return; } list_node *pos = list_get(l, idx); assert(pos); item->prev = pos->prev; item->next = pos; pos->prev->next = item; pos->prev = item; } list_node * list_pop_front(list *l) { assert(l); if (!l->head) return NULL; list_node *res = l->head; l->head = res->next; if (l->head) l->head->prev = NULL; else l->tail = NULL; return list_node_orphan(res); } list_node * list_pop_back(list *l) { assert(l); if (!l->tail) return NULL; list_node *res = l->tail; l->tail = res->prev; if (l->tail) l->tail->next = NULL; else l->head = NULL; return list_node_orphan(res); } int list_index(list *l, list_node *n) { assert(l && n); int i = 0; for (list_node *cur = l->head; cur; cur = cur->next, i++) if (cur == n) return i; return -1; } list_node * list_remove(list *l, int idx) { assert(l); list_node *cur = list_get(l, idx); if (!cur) return NULL; if (cur->prev) cur->prev->next = cur->next; else l->head = cur->next; if (cur->next) cur->next->prev = cur->prev; else l->tail = cur->prev; return list_node_orphan(cur); } void list_reverse(list *l) { assert(l); list_node *cur = l->head; list_node *tmp = NULL; while (cur) { tmp = cur->next; cur->next = cur->prev; cur->prev = tmp; cur = tmp; } tmp = l->head; l->head = l->tail; l->tail = tmp; }