update the command to install the latest liba via luarocks
[liba.git] / src / vec.c
blob6e5df0217f3ae6976f3e5adc99a0c9c401a3425c
1 #include "a/vec.h"
2 #include <stdlib.h>
4 #undef a_vec_at
5 #undef a_vec_at_
6 #undef a_vec_idx
7 #undef a_vec_ptr
8 #undef a_vec_end
9 #undef a_vec_top
10 #undef a_vec_end_
11 #undef a_vec_top_
12 #undef a_vec_push
13 #undef a_vec_pull
14 #undef a_vec_search
15 #undef a_vec_insert
16 #undef a_vec_remove
17 #undef a_vec_push_fore
18 #undef a_vec_push_back
19 #undef a_vec_pull_fore
20 #undef a_vec_pull_back
22 static A_INLINE void *a_vec_inc_(a_vec *ctx)
24 return (a_byte *)ctx->ptr_ + ctx->siz_ * ctx->num_++;
27 static A_INLINE void *a_vec_dec_(a_vec *ctx)
29 return (a_byte *)ctx->ptr_ + ctx->siz_ * --ctx->num_;
32 static void a_vec_drop_(a_vec *ctx, a_size bot, void (*dtor)(void *))
34 if (dtor)
36 while (ctx->num_ > bot) { dtor(a_vec_dec_(ctx)); }
38 ctx->num_ = bot;
41 static int a_vec_alloc(a_vec *ctx, a_size num)
43 if (ctx->mem_ <= num)
45 a_size mem = ctx->mem_;
46 do {
47 mem += (mem >> 1) + 1;
48 } while (mem < num);
49 a_size const siz = a_size_up(sizeof(void *), ctx->siz_ * mem);
50 void *ptr = a_alloc(ctx->ptr_, siz);
51 if (a_unlikely(!ptr)) { return A_FAILURE; }
52 ctx->ptr_ = ptr;
53 ctx->mem_ = mem;
55 return A_SUCCESS;
58 a_vec *a_vec_new(a_size size)
60 a_vec *const ctx = (a_vec *)a_alloc(A_NULL, sizeof(a_vec));
61 if (ctx) { a_vec_ctor(ctx, size); }
62 return ctx;
65 void a_vec_die(a_vec *ctx, void (*dtor)(void *))
67 if (ctx)
69 a_vec_dtor(ctx, dtor);
70 a_alloc(ctx, 0);
74 void a_vec_ctor(a_vec *ctx, a_size size)
76 ctx->siz_ = size ? size : sizeof(a_cast);
77 ctx->ptr_ = A_NULL;
78 ctx->num_ = 0;
79 ctx->mem_ = 0;
82 void a_vec_dtor(a_vec *ctx, void (*dtor)(void *))
84 if (ctx->ptr_)
86 a_vec_drop_(ctx, 0, dtor);
87 ctx->ptr_ = a_alloc(ctx->ptr_, 0);
89 ctx->siz_ = 0;
90 ctx->mem_ = 0;
93 int a_vec_copy(a_vec *ctx, a_vec const *obj, int (*dup)(void *, void const *))
95 ctx->ptr_ = a_alloc(A_NULL, obj->mem_ * obj->siz_);
96 if (a_unlikely(!ctx->ptr_)) { return A_FAILURE; }
97 ctx->num_ = obj->num_;
98 ctx->mem_ = obj->mem_;
99 ctx->siz_ = obj->siz_;
100 if (dup)
102 a_byte *dst = (a_byte *)ctx->ptr_;
103 a_byte *src = (a_byte *)obj->ptr_;
104 for (a_size num = obj->num_; num; --num)
106 dup(dst, src);
107 dst += ctx->siz_;
108 src += ctx->siz_;
111 else
113 a_copy(ctx->ptr_, obj->ptr_, obj->num_ * obj->siz_);
115 return A_SUCCESS;
118 void a_vec_move(a_vec *ctx, a_vec *obj)
120 a_copy(ctx, obj, sizeof(*obj));
121 a_zero(obj, sizeof(*obj));
124 void a_vec_edit(a_vec *ctx, a_size size, void (*dtor)(void *))
126 size = size ? size : sizeof(a_cast);
127 a_vec_drop_(ctx, 0, dtor);
128 ctx->mem_ = ctx->mem_ * ctx->siz_ / size;
129 ctx->siz_ = size;
132 int a_vec_make(a_vec *ctx, a_size num, void (*dtor)(void *))
134 if (a_unlikely(a_vec_alloc(ctx, num))) { return A_FAILURE; }
135 a_vec_drop_(ctx, num, dtor);
136 return A_SUCCESS;
139 void a_vec_drop(a_vec *ctx, void (*dtor)(void *))
141 a_vec_drop_(ctx, 0, dtor);
144 void a_vec_swap(a_vec const *ctx, a_size lhs, a_size rhs)
146 a_size const num = ctx->num_ - 1;
147 lhs = lhs < ctx->num_ ? lhs : num;
148 rhs = rhs < ctx->num_ ? rhs : num;
149 if (lhs != rhs)
151 a_swap((a_byte *)ctx->ptr_ + lhs * ctx->siz_,
152 (a_byte *)ctx->ptr_ + rhs * ctx->siz_,
153 ctx->siz_);
157 void a_vec_sort(a_vec const *ctx, int (*cmp)(void const *, void const *))
159 qsort(ctx->ptr_, ctx->num_, ctx->siz_, cmp);
162 void a_vec_sort_fore(a_vec const *ctx, int (*cmp)(void const *, void const *))
164 if (ctx->num_ > 1)
166 a_byte *ptr = (a_byte *)ctx->ptr_;
167 a_byte *const end = (a_byte *)ctx->ptr_ + ctx->siz_ * ctx->num_ - ctx->siz_;
168 do {
169 a_byte *const cur = ptr + ctx->siz_;
170 if (cmp(ptr, cur) > 0)
172 a_swap(cur, ptr, ctx->siz_);
174 else { break; }
175 ptr = cur;
176 } while (ptr != end);
180 void a_vec_sort_back(a_vec const *ctx, int (*cmp)(void const *, void const *))
182 if (ctx->num_ > 1)
184 a_byte *ptr = (a_byte *)ctx->ptr_ + ctx->siz_ * ctx->num_ - ctx->siz_;
185 do {
186 a_byte *const cur = ptr - ctx->siz_;
187 if (cmp(cur, ptr) > 0)
189 a_swap(cur, ptr, ctx->siz_);
191 else { break; }
192 ptr = cur;
193 } while (ptr != ctx->ptr_);
197 void *a_vec_search(a_vec const *ctx, void const *obj, int (*cmp)(void const *, void const *))
199 return bsearch(obj, ctx->ptr_, ctx->num_, ctx->siz_, cmp);
202 void *a_vec_insert(a_vec *ctx, a_size idx)
204 if (a_unlikely(a_vec_alloc(ctx, ctx->num_))) { return A_NULL; }
205 if (idx < ctx->num_)
207 a_byte *const src = (a_byte *)ctx->ptr_ + ctx->siz_ * (idx + 0);
208 a_byte *const dst = (a_byte *)ctx->ptr_ + ctx->siz_ * (idx + 1);
209 a_move(dst, src, (ctx->num_ - idx) * ctx->siz_);
210 ++ctx->num_;
211 return src;
213 return a_vec_inc_(ctx);
216 void *a_vec_push_fore(a_vec *ctx) { return a_vec_insert(ctx, 0); }
218 void *a_vec_push_back(a_vec *ctx)
220 if (a_unlikely(a_vec_alloc(ctx, ctx->num_))) { return A_NULL; }
221 return a_vec_inc_(ctx);
224 void *a_vec_remove(a_vec *ctx, a_size idx)
226 if (ctx->num_ && idx < ctx->num_ - 1)
228 if (a_unlikely(a_vec_alloc(ctx, ctx->num_))) { return A_NULL; }
229 a_byte *const ptr = (a_byte *)ctx->ptr_ + ctx->siz_ * ctx->num_;
230 a_byte *const dst = (a_byte *)ctx->ptr_ + ctx->siz_ * (idx + 0);
231 a_byte *const src = (a_byte *)ctx->ptr_ + ctx->siz_ * (idx + 1);
232 a_copy(ptr, dst, ctx->siz_);
233 a_move(dst, src, (a_size)(ptr - src));
234 --ctx->num_;
235 return ptr;
237 return a_likely(ctx->num_) ? a_vec_dec_(ctx) : A_NULL;
240 void *a_vec_pull_fore(a_vec *ctx) { return a_vec_remove(ctx, 0); }
242 void *a_vec_pull_back(a_vec *ctx)
244 return a_likely(ctx->num_) ? a_vec_dec_(ctx) : A_NULL;