list.c (4072B)
1#include "list.h" 2 3void 4list_init(struct list *list) 5{ 6 LIST_ABORT_ON_ARGS(!list); 7 8 list->head.prev = NULL; 9 list->head.next = &list->tail; 10 list->tail.prev = &list->head; 11 list->tail.next = NULL; 12} 13 14void 15list_clear(struct list *list) 16{ 17 LIST_ABORT_ON_ARGS(!list); 18 19 while (!list_empty(list)) 20 list_pop_back(list); 21} 22 23void 24list_free_items(struct list *list, list_item_free_fn free_item, size_t offset) 25{ 26 struct list_link *item; 27 28 LIST_ABORT_ON_ARGS(!list || !free_item); 29 30 while (!list_empty(list)) { 31 item = list_link_pop(list->head.next); 32 free_item(((void *) item) - offset); 33 } 34} 35 36size_t 37list_len(const struct list *list) 38{ 39 const struct list_link *link; 40 size_t len; 41 42 LIST_ABORT_ON_ARGS(!list); 43 44 len = 0; 45 for (LIST_ITER(list, link)) 46 len += 1; 47 48 return len; 49} 50 51ssize_t 52list_index(const struct list *list, const struct list_link *target) 53{ 54 struct list_link *link; 55 ssize_t index; 56 57 LIST_ABORT_ON_ARGS(!list || !target); 58 59 index = 0; 60 for (LIST_ITER(list, link)) { 61 if (link == target) 62 return index; 63 index++; 64 } 65 66 return -1; 67} 68 69struct list_link * 70list_at(struct list *list, size_t n) 71{ 72 struct list_link *link; 73 74 LIST_ABORT_ON_ARGS(!list); 75 76 link = list_iter_fwd(list->head.next, n); 77 78 return LIST_INNER(link) ? link : NULL; 79} 80 81struct list_link * 82list_at_back(struct list *list, size_t n) 83{ 84 struct list_link *link; 85 86 LIST_ABORT_ON_ARGS(!list); 87 88 link = list_iter_bwd(&list->tail, n); 89 90 return LIST_INNER(link) ? link : NULL; 91} 92 93void 94list_insert_sorted(struct list *list, struct list_link *insert, 95 bool reverse, list_sort_order_fn in_order, size_t offset, void *user) 96{ 97 struct list_link *link; 98 void *link_item, *insert_item; 99 100 LIST_ABORT_ON_ARGS(!list || !insert || !in_order); 101 102 insert_item = ((void *) insert) - offset; 103 for (LIST_ITER(list, link)) { 104 link_item = ((void *) link) - offset; 105 if (in_order(insert_item, link_item, user) == !reverse) { 106 list_link_prepend(link, insert); 107 return; 108 } 109 } 110 111 list_insert_back(list, insert); 112} 113 114void 115list_insert_sorted_bwd(struct list *list, struct list_link *insert, 116 bool reverse, list_sort_order_fn in_order, size_t offset, void *user) 117{ 118 struct list_link *link; 119 void *link_item, *insert_item; 120 121 LIST_ABORT_ON_ARGS(!list || !insert || !in_order); 122 123 insert_item = ((void *) insert) - offset; 124 for (LIST_ITER_BWD(list, link)) { 125 link_item = ((void *) link) - offset; 126 if (in_order(link_item, insert_item, user) == !reverse) { 127 list_link_append(link, insert); 128 return; 129 } 130 } 131 132 list_insert_front(list, insert); 133} 134 135void 136list_insertion_sort(struct list *list, bool reverse, 137 list_sort_order_fn in_order, size_t offset, void *user) 138{ 139 struct list_link *link, *cmp, *next; 140 void *link_item, *cmp_item; 141 142 LIST_ABORT_ON_ARGS(!list || !in_order); 143 144 link = list->head.next; 145 while (LIST_INNER(link)) { 146 next = link->next; 147 cmp = link->prev; 148 link_item = ((void *) link) - offset; 149 while (LIST_INNER(cmp)) { 150 cmp_item = ((void *) cmp) - offset; 151 if (in_order(cmp_item, link_item, user) == !reverse) 152 break; 153 cmp = cmp->prev; 154 } 155 if (cmp != link->prev) 156 list_link_append(cmp, list_link_pop(link)); 157 link = next; 158 } 159} 160 161struct list_link * 162list_pop_front(struct list *list) 163{ 164 LIST_ABORT_ON_ARGS(!list); 165 166 if (list_empty(list)) return NULL; 167 168 return list_link_pop(list->head.next); 169} 170 171struct list_link * 172list_pop_back(struct list *list) 173{ 174 LIST_ABORT_ON_ARGS(!list); 175 176 if (list_empty(list)) return NULL; 177 178 return list_link_pop(list->tail.prev); 179} 180 181struct list_link * 182list_link_pop(struct list_link *link) 183{ 184 LIST_ABORT_ON_ARGS(!link); 185 186 if (link->prev) 187 link->prev->next = link->next; 188 if (link->next) 189 link->next->prev = link->prev; 190 *link = LIST_LINK_INIT; 191 192 return link; 193} 194 195struct list_link * 196list_iter_fwd(struct list_link *link, size_t n) 197{ 198 size_t i; 199 200 LIST_ABORT_ON_ARGS(!link); 201 202 for (i = 0; i < n; i++) { 203 if (!link) return NULL; 204 link = link->next; 205 } 206 207 return link; 208} 209 210struct list_link * 211list_iter_bwd(struct list_link *link, size_t n) 212{ 213 size_t i; 214 215 LIST_ABORT_ON_ARGS(!link); 216 217 for (i = 0; i < n; i++) { 218 if (!link) return NULL; 219 link = link->prev; 220 } 221 222 return link; 223} 224