fix bugprone-multi-level-implicit-pointer-conversio
[liba.git] / src / vec.c
blob927161856f2383e9b6d0f8256eb56820f44a4349
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 if (!size) { size = sizeof(a_cast); }
77 ctx->ptr_ = A_NULL;
78 ctx->siz_ = size;
79 ctx->num_ = 0;
80 ctx->mem_ = 0;
83 void a_vec_dtor(a_vec *ctx, void (*dtor)(void *))
85 if (ctx->ptr_)
87 a_vec_drop_(ctx, 0, dtor);
88 ctx->ptr_ = a_alloc(ctx->ptr_, 0);
90 ctx->siz_ = 0;
91 ctx->mem_ = 0;
94 int a_vec_copy(a_vec *ctx, a_vec const *obj, int (*dup)(void *, void const *))
96 ctx->ptr_ = a_alloc(A_NULL, obj->mem_ * obj->siz_);
97 if (a_unlikely(!ctx->ptr_)) { return A_FAILURE; }
98 ctx->num_ = obj->num_;
99 ctx->mem_ = obj->mem_;
100 ctx->siz_ = obj->siz_;
101 if (dup)
103 a_byte *dst = (a_byte *)ctx->ptr_;
104 a_byte *src = (a_byte *)obj->ptr_;
105 for (a_size num = obj->num_; num; --num)
107 dup(dst, src);
108 dst += ctx->siz_;
109 src += ctx->siz_;
112 else
114 a_copy(ctx->ptr_, obj->ptr_, obj->num_ * obj->siz_);
116 return A_SUCCESS;
119 void a_vec_move(a_vec *ctx, a_vec *obj)
121 a_copy(ctx, obj, sizeof(*obj));
122 a_zero(obj, sizeof(*obj));
125 void a_vec_edit(a_vec *ctx, a_size size, void (*dtor)(void *))
127 if (!size) { size = sizeof(a_cast); }
128 a_vec_drop_(ctx, 0, dtor);
129 ctx->mem_ = ctx->mem_ * ctx->siz_ / size;
130 ctx->siz_ = size;
133 int a_vec_make(a_vec *ctx, a_size num, void (*dtor)(void *))
135 if (a_unlikely(a_vec_alloc(ctx, num))) { return A_FAILURE; }
136 a_vec_drop_(ctx, num, dtor);
137 return A_SUCCESS;
140 void a_vec_drop(a_vec *ctx, void (*dtor)(void *))
142 a_vec_drop_(ctx, 0, dtor);
145 void a_vec_swap(a_vec const *ctx, a_size lhs, a_size rhs)
147 a_size const num = ctx->num_ - 1;
148 lhs = lhs < ctx->num_ ? lhs : num;
149 rhs = rhs < ctx->num_ ? rhs : num;
150 if (lhs != rhs)
152 a_swap((a_byte *)ctx->ptr_ + lhs * ctx->siz_,
153 (a_byte *)ctx->ptr_ + rhs * ctx->siz_,
154 ctx->siz_);
158 void a_vec_sort(a_vec const *ctx, int (*cmp)(void const *, void const *))
160 qsort(ctx->ptr_, ctx->num_, ctx->siz_, cmp);
163 void a_vec_sort_fore(a_vec const *ctx, int (*cmp)(void const *, void const *))
165 if (ctx->num_ > 1)
167 a_byte *ptr = (a_byte *)ctx->ptr_;
168 a_byte *const end = (a_byte *)ctx->ptr_ + ctx->siz_ * ctx->num_ - ctx->siz_;
169 do {
170 a_byte *const cur = ptr + ctx->siz_;
171 if (cmp(ptr, cur) > 0)
173 a_swap(cur, ptr, ctx->siz_);
175 else { break; }
176 ptr = cur;
177 } while (ptr != end);
181 void a_vec_sort_back(a_vec const *ctx, int (*cmp)(void const *, void const *))
183 if (ctx->num_ > 1)
185 a_byte *ptr = (a_byte *)ctx->ptr_ + ctx->siz_ * ctx->num_ - ctx->siz_;
186 do {
187 a_byte *const cur = ptr - ctx->siz_;
188 if (cmp(cur, ptr) > 0)
190 a_swap(cur, ptr, ctx->siz_);
192 else { break; }
193 ptr = cur;
194 } while (ptr != ctx->ptr_);
198 void *a_vec_search(a_vec const *ctx, void const *obj, int (*cmp)(void const *, void const *))
200 return bsearch(obj, ctx->ptr_, ctx->num_, ctx->siz_, cmp);
203 void *a_vec_insert(a_vec *ctx, a_size idx)
205 if (a_unlikely(a_vec_alloc(ctx, ctx->num_))) { return A_NULL; }
206 if (idx < ctx->num_)
208 a_byte *const src = (a_byte *)ctx->ptr_ + ctx->siz_ * (idx + 0);
209 a_byte *const dst = (a_byte *)ctx->ptr_ + ctx->siz_ * (idx + 1);
210 a_move(dst, src, (ctx->num_ - idx) * ctx->siz_);
211 ++ctx->num_;
212 return src;
214 return a_vec_inc_(ctx);
217 void *a_vec_push_fore(a_vec *ctx) { return a_vec_insert(ctx, 0); }
219 void *a_vec_push_back(a_vec *ctx)
221 if (a_unlikely(a_vec_alloc(ctx, ctx->num_))) { return A_NULL; }
222 return a_vec_inc_(ctx);
225 void *a_vec_remove(a_vec *ctx, a_size idx)
227 if (ctx->num_ && idx < ctx->num_ - 1)
229 if (a_unlikely(a_vec_alloc(ctx, ctx->num_))) { return A_NULL; }
230 a_byte *const ptr = (a_byte *)ctx->ptr_ + ctx->siz_ * ctx->num_;
231 a_byte *const dst = (a_byte *)ctx->ptr_ + ctx->siz_ * (idx + 0);
232 a_byte *const src = (a_byte *)ctx->ptr_ + ctx->siz_ * (idx + 1);
233 a_copy(ptr, dst, ctx->siz_);
234 a_move(dst, src, (a_size)(ptr - src));
235 --ctx->num_;
236 return ptr;
238 return a_likely(ctx->num_) ? a_vec_dec_(ctx) : A_NULL;
241 void *a_vec_pull_fore(a_vec *ctx) { return a_vec_remove(ctx, 0); }
243 void *a_vec_pull_back(a_vec *ctx)
245 return a_likely(ctx->num_) ? a_vec_dec_(ctx) : A_NULL;