create a_regress_simple_evar
[liba.git] / src / que.c
blobc52e4ff03622804760158e17c7e5dd0abbf62778
1 #include "a/que.h"
3 static a_list *a_que_new_(a_que *ctx)
5 a_list *node;
6 if (ctx->cur_ == 0)
8 node = (a_list *)a_alloc(A_NULL, sizeof(a_list) + ctx->siz_);
9 if (A_UNLIKELY(!node)) { return node; }
11 else
13 node = ctx->ptr_[--ctx->cur_];
15 ++ctx->num_;
16 return node;
19 static int a_que_die_(a_que *ctx, a_list *node)
21 if (A_UNLIKELY(!node)) { return A_INVALID; }
22 if (ctx->mem_ <= ctx->cur_)
24 a_size const mem = ctx->mem_ + (ctx->mem_ >> 1) + 1;
25 a_list **const ptr = (a_list **)a_alloc((void *)ctx->ptr_, sizeof(void *) * mem);
26 if (A_UNLIKELY(!ptr)) { return A_FAILURE; }
27 ctx->ptr_ = ptr;
28 ctx->mem_ = mem;
30 ctx->ptr_[ctx->cur_++] = node;
31 --ctx->num_;
32 return A_SUCCESS;
35 a_que *a_que_new(a_size size)
37 a_que *const ctx = (a_que *)a_alloc(A_NULL, sizeof(a_que));
38 if (ctx) { a_que_ctor(ctx, size); }
39 return ctx;
42 void a_que_die(a_que *ctx, void (*dtor)(void *))
44 if (ctx)
46 a_que_dtor(ctx, dtor);
47 a_alloc(ctx, 0);
51 void a_que_ctor(a_que *ctx, a_size size)
53 if (!size) { size = sizeof(void *); }
54 a_list_ctor(&ctx->head_);
55 ctx->ptr_ = A_NULL;
56 ctx->siz_ = size;
57 ctx->num_ = 0;
58 ctx->cur_ = 0;
59 ctx->mem_ = 0;
62 void a_que_dtor(a_que *ctx, void (*dtor)(void *))
64 if (dtor)
66 for (a_list **node = ctx->ptr_; ctx->cur_; --ctx->cur_)
68 dtor(*node + 1);
69 a_alloc(*node++, 0);
71 a_list_forsafe_next(node, next, &ctx->head_)
73 dtor(node + 1);
74 a_alloc(node, 0);
77 else
79 for (a_list **node = ctx->ptr_; ctx->cur_; --ctx->cur_)
81 a_alloc(*node++, 0);
83 a_list_forsafe_next(node, next, &ctx->head_)
85 a_alloc(node, 0);
88 a_alloc((void *)ctx->ptr_, 0);
89 ctx->ptr_ = A_NULL;
90 ctx->siz_ = 0;
91 ctx->mem_ = 0;
94 void a_que_move(a_que *ctx, a_que *obj)
96 a_copy(ctx, obj, sizeof(*obj));
97 a_zero(obj, sizeof(*obj));
100 void *a_que_at(a_que const *ctx, a_diff idx)
102 a_diff cur = 0;
103 if (idx >= 0)
105 a_list_foreach_next(it, &ctx->head_)
107 if (cur++ == idx) { return it + 1; }
110 else
112 a_list_foreach_prev(it, &ctx->head_)
114 if (--cur == idx) { return it + 1; }
117 return A_NULL;
120 int a_que_drop(a_que *ctx, void (*dtor)(void *))
122 a_list *const head = &ctx->head_;
123 for (a_list *node = head->next; node != head; node = head->next)
125 if (a_que_die_(ctx, node) == A_SUCCESS)
127 a_list_del_node(node);
128 a_list_dtor(node);
130 else { return A_FAILURE; }
132 if (dtor)
134 a_size cur = ctx->cur_;
135 a_list **node = ctx->ptr_;
136 for (; cur; ++node, --cur)
138 dtor(*node + 1);
141 return A_SUCCESS;
144 int a_que_edit(a_que *ctx, a_size size, void (*dtor)(void *))
146 int ok = a_que_drop(ctx, dtor);
147 if (ok == A_SUCCESS)
149 if (!size) { size = sizeof(void *); }
150 if (size > ctx->siz_)
152 a_size cur = ctx->cur_;
153 a_list **node = ctx->ptr_;
154 for (; cur; ++node, --cur)
156 void *const ptr = a_alloc(*node, sizeof(a_list) + size);
157 if (A_UNLIKELY(!ptr)) { return A_FAILURE; }
158 *node = (a_list *)ptr;
161 ctx->siz_ = size;
163 return ok;
166 int a_que_swap(a_que const *ctx, a_size lhs, a_size rhs)
168 a_size cur = 0;
169 int ok = A_FAILURE;
170 a_list *at = A_NULL;
171 a_size const num = ctx->num_ - 1;
172 lhs = lhs < ctx->num_ ? lhs : num;
173 rhs = rhs < ctx->num_ ? rhs : num;
174 if (lhs == rhs) { return A_SUCCESS; }
175 a_list_foreach_next(it, &ctx->head_)
177 if (cur == lhs || cur == rhs)
179 if (at)
181 a_list_swap_node(it, at);
182 ok = A_SUCCESS;
183 break;
185 else { at = it; }
187 ++cur;
189 return ok;
192 void a_que_sort_fore(a_que const *ctx, int (*cmp)(void const *, void const *))
194 if (ctx->num_ > 1)
196 a_list *const it = ctx->head_.next;
197 a_list *at = it->next;
198 do {
199 if (cmp(it + 1, at + 1) <= 0) { break; }
200 at = at->next;
201 } while (at != &ctx->head_);
202 if (at != it->next)
204 at = at->prev; // a-it-b-at-a => a-b-at-it-a
205 a_list_link(it->prev, it->next); // a-b
206 a_list_link(it, at->next); // it-a
207 a_list_link(at, it); // at-it
212 void a_que_sort_back(a_que const *ctx, int (*cmp)(void const *, void const *))
214 if (ctx->num_ > 1)
216 a_list *const it = ctx->head_.prev;
217 a_list *at = it->prev;
218 do {
219 if (cmp(at + 1, it + 1) <= 0) { break; }
220 at = at->prev;
221 } while (at != &ctx->head_);
222 if (at != it->prev)
224 at = at->next; // a-at-b-it-a => a-it-at-b-a
225 a_list_link(it->prev, it->next); // b-a
226 a_list_link(at->prev, it); // a-it
227 a_list_link(it, at); // it-at
232 void *a_que_push_sort(a_que *ctx, void const *key, int (*cmp)(void const *, void const *))
234 a_list *it = ctx->head_.prev;
235 a_list *const node = a_que_new_(ctx);
236 if (A_UNLIKELY(!node)) { return node; }
237 if (ctx->num_ > 1)
239 do {
240 if (cmp(it + 1, key) <= 0) { break; }
241 it = it->prev;
242 } while (it != &ctx->head_);
244 a_list_link(node, it->next);
245 a_list_link(it, node);
246 return node + 1;
249 void *a_que_push_fore(a_que *ctx)
251 a_list *const node = a_que_new_(ctx);
252 if (A_UNLIKELY(!node)) { return node; }
253 a_list_add_next(&ctx->head_, node);
254 return node + 1;
257 void *a_que_push_back(a_que *ctx)
259 a_list *const node = a_que_new_(ctx);
260 if (A_UNLIKELY(!node)) { return node; }
261 a_list_add_prev(&ctx->head_, node);
262 return node + 1;
265 void *a_que_pull_fore(a_que *ctx)
267 if (ctx->head_.next != &ctx->head_)
269 a_list *const node = (a_list *)ctx->head_.next;
270 if (a_que_die_(ctx, node) == A_SUCCESS)
272 a_list_del_node(node);
273 a_list_dtor(node);
274 return node + 1;
277 return A_NULL;
280 void *a_que_pull_back(a_que *ctx)
282 if (ctx->head_.prev != &ctx->head_)
284 a_list *const node = (a_list *)ctx->head_.prev;
285 if (a_que_die_(ctx, node) == A_SUCCESS)
287 a_list_del_node(node);
288 a_list_dtor(node);
289 return node + 1;
292 return A_NULL;
295 void *a_que_insert(a_que *ctx, a_size idx)
297 if (idx < ctx->num_)
299 a_size cur = 0;
300 a_list *const node = a_que_new_(ctx);
301 if (node)
303 a_list_foreach_next(it, &ctx->head_)
305 if (cur++ == idx)
307 a_list_add_prev(it, node);
308 break;
311 return node + 1;
313 return A_NULL;
315 return a_que_push_back(ctx);
318 void *a_que_remove(a_que *ctx, a_size idx)
320 if (idx < ctx->num_)
322 a_size cur = 0;
323 a_list *node = A_NULL;
324 a_list_foreach_next(it, &ctx->head_)
326 if (cur++ == idx)
328 node = it;
329 break;
332 if (a_que_die_(ctx, node) == A_SUCCESS)
334 a_list_del_node(node);
335 a_list_dtor(node);
336 return node + 1;
338 return A_NULL;
340 return a_que_pull_back(ctx);