1*5a6e8488SAndroid Build Coastguard Worker /*
2*5a6e8488SAndroid Build Coastguard Worker * *****************************************************************************
3*5a6e8488SAndroid Build Coastguard Worker *
4*5a6e8488SAndroid Build Coastguard Worker * SPDX-License-Identifier: BSD-2-Clause
5*5a6e8488SAndroid Build Coastguard Worker *
6*5a6e8488SAndroid Build Coastguard Worker * Copyright (c) 2018-2024 Gavin D. Howard and contributors.
7*5a6e8488SAndroid Build Coastguard Worker *
8*5a6e8488SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
9*5a6e8488SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met:
10*5a6e8488SAndroid Build Coastguard Worker *
11*5a6e8488SAndroid Build Coastguard Worker * * Redistributions of source code must retain the above copyright notice, this
12*5a6e8488SAndroid Build Coastguard Worker * list of conditions and the following disclaimer.
13*5a6e8488SAndroid Build Coastguard Worker *
14*5a6e8488SAndroid Build Coastguard Worker * * Redistributions in binary form must reproduce the above copyright notice,
15*5a6e8488SAndroid Build Coastguard Worker * this list of conditions and the following disclaimer in the documentation
16*5a6e8488SAndroid Build Coastguard Worker * and/or other materials provided with the distribution.
17*5a6e8488SAndroid Build Coastguard Worker *
18*5a6e8488SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19*5a6e8488SAndroid Build Coastguard Worker * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*5a6e8488SAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*5a6e8488SAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22*5a6e8488SAndroid Build Coastguard Worker * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*5a6e8488SAndroid Build Coastguard Worker * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*5a6e8488SAndroid Build Coastguard Worker * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*5a6e8488SAndroid Build Coastguard Worker * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*5a6e8488SAndroid Build Coastguard Worker * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*5a6e8488SAndroid Build Coastguard Worker * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*5a6e8488SAndroid Build Coastguard Worker * POSSIBILITY OF SUCH DAMAGE.
29*5a6e8488SAndroid Build Coastguard Worker *
30*5a6e8488SAndroid Build Coastguard Worker * *****************************************************************************
31*5a6e8488SAndroid Build Coastguard Worker *
32*5a6e8488SAndroid Build Coastguard Worker * Code to manipulate vectors (resizable arrays).
33*5a6e8488SAndroid Build Coastguard Worker *
34*5a6e8488SAndroid Build Coastguard Worker */
35*5a6e8488SAndroid Build Coastguard Worker
36*5a6e8488SAndroid Build Coastguard Worker #include <assert.h>
37*5a6e8488SAndroid Build Coastguard Worker #include <stdlib.h>
38*5a6e8488SAndroid Build Coastguard Worker #include <string.h>
39*5a6e8488SAndroid Build Coastguard Worker #include <stdbool.h>
40*5a6e8488SAndroid Build Coastguard Worker
41*5a6e8488SAndroid Build Coastguard Worker #include <vector.h>
42*5a6e8488SAndroid Build Coastguard Worker #include <lang.h>
43*5a6e8488SAndroid Build Coastguard Worker #include <vm.h>
44*5a6e8488SAndroid Build Coastguard Worker
45*5a6e8488SAndroid Build Coastguard Worker void
bc_vec_grow(BcVec * restrict v,size_t n)46*5a6e8488SAndroid Build Coastguard Worker bc_vec_grow(BcVec* restrict v, size_t n)
47*5a6e8488SAndroid Build Coastguard Worker {
48*5a6e8488SAndroid Build Coastguard Worker size_t cap, len;
49*5a6e8488SAndroid Build Coastguard Worker #if !BC_ENABLE_LIBRARY
50*5a6e8488SAndroid Build Coastguard Worker sig_atomic_t lock;
51*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_ENABLE_LIBRARY
52*5a6e8488SAndroid Build Coastguard Worker
53*5a6e8488SAndroid Build Coastguard Worker cap = v->cap;
54*5a6e8488SAndroid Build Coastguard Worker len = v->len + n;
55*5a6e8488SAndroid Build Coastguard Worker
56*5a6e8488SAndroid Build Coastguard Worker // If this is true, we might overflow.
57*5a6e8488SAndroid Build Coastguard Worker if (len > SIZE_MAX / 2) cap = len;
58*5a6e8488SAndroid Build Coastguard Worker else
59*5a6e8488SAndroid Build Coastguard Worker {
60*5a6e8488SAndroid Build Coastguard Worker // Keep doubling until larger.
61*5a6e8488SAndroid Build Coastguard Worker while (cap < len)
62*5a6e8488SAndroid Build Coastguard Worker {
63*5a6e8488SAndroid Build Coastguard Worker cap += cap;
64*5a6e8488SAndroid Build Coastguard Worker }
65*5a6e8488SAndroid Build Coastguard Worker }
66*5a6e8488SAndroid Build Coastguard Worker
67*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYLOCK(lock);
68*5a6e8488SAndroid Build Coastguard Worker
69*5a6e8488SAndroid Build Coastguard Worker v->v = bc_vm_realloc(v->v, bc_vm_arraySize(cap, v->size));
70*5a6e8488SAndroid Build Coastguard Worker v->cap = cap;
71*5a6e8488SAndroid Build Coastguard Worker
72*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYUNLOCK(lock);
73*5a6e8488SAndroid Build Coastguard Worker }
74*5a6e8488SAndroid Build Coastguard Worker
75*5a6e8488SAndroid Build Coastguard Worker void
bc_vec_init(BcVec * restrict v,size_t esize,BcDtorType dtor)76*5a6e8488SAndroid Build Coastguard Worker bc_vec_init(BcVec* restrict v, size_t esize, BcDtorType dtor)
77*5a6e8488SAndroid Build Coastguard Worker {
78*5a6e8488SAndroid Build Coastguard Worker BC_SIG_ASSERT_LOCKED;
79*5a6e8488SAndroid Build Coastguard Worker
80*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL && esize);
81*5a6e8488SAndroid Build Coastguard Worker
82*5a6e8488SAndroid Build Coastguard Worker v->v = bc_vm_malloc(bc_vm_arraySize(BC_VEC_START_CAP, esize));
83*5a6e8488SAndroid Build Coastguard Worker
84*5a6e8488SAndroid Build Coastguard Worker v->size = (BcSize) esize;
85*5a6e8488SAndroid Build Coastguard Worker v->cap = BC_VEC_START_CAP;
86*5a6e8488SAndroid Build Coastguard Worker v->len = 0;
87*5a6e8488SAndroid Build Coastguard Worker v->dtor = (BcSize) dtor;
88*5a6e8488SAndroid Build Coastguard Worker }
89*5a6e8488SAndroid Build Coastguard Worker
90*5a6e8488SAndroid Build Coastguard Worker void
bc_vec_expand(BcVec * restrict v,size_t req)91*5a6e8488SAndroid Build Coastguard Worker bc_vec_expand(BcVec* restrict v, size_t req)
92*5a6e8488SAndroid Build Coastguard Worker {
93*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL);
94*5a6e8488SAndroid Build Coastguard Worker
95*5a6e8488SAndroid Build Coastguard Worker // Only expand if necessary.
96*5a6e8488SAndroid Build Coastguard Worker if (v->cap < req)
97*5a6e8488SAndroid Build Coastguard Worker {
98*5a6e8488SAndroid Build Coastguard Worker #if !BC_ENABLE_LIBRARY
99*5a6e8488SAndroid Build Coastguard Worker sig_atomic_t lock;
100*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_ENABLE_LIBRARY
101*5a6e8488SAndroid Build Coastguard Worker
102*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYLOCK(lock);
103*5a6e8488SAndroid Build Coastguard Worker
104*5a6e8488SAndroid Build Coastguard Worker v->v = bc_vm_realloc(v->v, bc_vm_arraySize(req, v->size));
105*5a6e8488SAndroid Build Coastguard Worker v->cap = req;
106*5a6e8488SAndroid Build Coastguard Worker
107*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYUNLOCK(lock);
108*5a6e8488SAndroid Build Coastguard Worker }
109*5a6e8488SAndroid Build Coastguard Worker }
110*5a6e8488SAndroid Build Coastguard Worker
111*5a6e8488SAndroid Build Coastguard Worker void
bc_vec_npop(BcVec * restrict v,size_t n)112*5a6e8488SAndroid Build Coastguard Worker bc_vec_npop(BcVec* restrict v, size_t n)
113*5a6e8488SAndroid Build Coastguard Worker {
114*5a6e8488SAndroid Build Coastguard Worker #if !BC_ENABLE_LIBRARY
115*5a6e8488SAndroid Build Coastguard Worker sig_atomic_t lock;
116*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_ENABLE_LIBRARY
117*5a6e8488SAndroid Build Coastguard Worker
118*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL && n <= v->len);
119*5a6e8488SAndroid Build Coastguard Worker
120*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYLOCK(lock);
121*5a6e8488SAndroid Build Coastguard Worker
122*5a6e8488SAndroid Build Coastguard Worker if (!v->dtor) v->len -= n;
123*5a6e8488SAndroid Build Coastguard Worker else
124*5a6e8488SAndroid Build Coastguard Worker {
125*5a6e8488SAndroid Build Coastguard Worker const BcVecFree d = bc_vec_dtors[v->dtor];
126*5a6e8488SAndroid Build Coastguard Worker size_t esize = v->size;
127*5a6e8488SAndroid Build Coastguard Worker size_t len = v->len - n;
128*5a6e8488SAndroid Build Coastguard Worker
129*5a6e8488SAndroid Build Coastguard Worker // Loop through and manually destruct every element.
130*5a6e8488SAndroid Build Coastguard Worker while (v->len > len)
131*5a6e8488SAndroid Build Coastguard Worker {
132*5a6e8488SAndroid Build Coastguard Worker d(v->v + (esize * --v->len));
133*5a6e8488SAndroid Build Coastguard Worker }
134*5a6e8488SAndroid Build Coastguard Worker }
135*5a6e8488SAndroid Build Coastguard Worker
136*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYUNLOCK(lock);
137*5a6e8488SAndroid Build Coastguard Worker }
138*5a6e8488SAndroid Build Coastguard Worker
139*5a6e8488SAndroid Build Coastguard Worker void
bc_vec_npopAt(BcVec * restrict v,size_t n,size_t idx)140*5a6e8488SAndroid Build Coastguard Worker bc_vec_npopAt(BcVec* restrict v, size_t n, size_t idx)
141*5a6e8488SAndroid Build Coastguard Worker {
142*5a6e8488SAndroid Build Coastguard Worker char* ptr;
143*5a6e8488SAndroid Build Coastguard Worker char* data;
144*5a6e8488SAndroid Build Coastguard Worker #if !BC_ENABLE_LIBRARY
145*5a6e8488SAndroid Build Coastguard Worker sig_atomic_t lock;
146*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_ENABLE_LIBRARY
147*5a6e8488SAndroid Build Coastguard Worker
148*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL);
149*5a6e8488SAndroid Build Coastguard Worker assert(idx + n < v->len);
150*5a6e8488SAndroid Build Coastguard Worker
151*5a6e8488SAndroid Build Coastguard Worker // Grab start and end pointers.
152*5a6e8488SAndroid Build Coastguard Worker ptr = bc_vec_item(v, idx);
153*5a6e8488SAndroid Build Coastguard Worker data = bc_vec_item(v, idx + n);
154*5a6e8488SAndroid Build Coastguard Worker
155*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYLOCK(lock);
156*5a6e8488SAndroid Build Coastguard Worker
157*5a6e8488SAndroid Build Coastguard Worker if (v->dtor)
158*5a6e8488SAndroid Build Coastguard Worker {
159*5a6e8488SAndroid Build Coastguard Worker size_t i;
160*5a6e8488SAndroid Build Coastguard Worker const BcVecFree d = bc_vec_dtors[v->dtor];
161*5a6e8488SAndroid Build Coastguard Worker
162*5a6e8488SAndroid Build Coastguard Worker // Destroy every popped item.
163*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < n; ++i)
164*5a6e8488SAndroid Build Coastguard Worker {
165*5a6e8488SAndroid Build Coastguard Worker d(bc_vec_item(v, idx + i));
166*5a6e8488SAndroid Build Coastguard Worker }
167*5a6e8488SAndroid Build Coastguard Worker }
168*5a6e8488SAndroid Build Coastguard Worker
169*5a6e8488SAndroid Build Coastguard Worker v->len -= n;
170*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
171*5a6e8488SAndroid Build Coastguard Worker memmove(ptr, data, (v->len - idx) * v->size);
172*5a6e8488SAndroid Build Coastguard Worker
173*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYUNLOCK(lock);
174*5a6e8488SAndroid Build Coastguard Worker }
175*5a6e8488SAndroid Build Coastguard Worker
176*5a6e8488SAndroid Build Coastguard Worker void
bc_vec_npush(BcVec * restrict v,size_t n,const void * data)177*5a6e8488SAndroid Build Coastguard Worker bc_vec_npush(BcVec* restrict v, size_t n, const void* data)
178*5a6e8488SAndroid Build Coastguard Worker {
179*5a6e8488SAndroid Build Coastguard Worker #if !BC_ENABLE_LIBRARY
180*5a6e8488SAndroid Build Coastguard Worker sig_atomic_t lock;
181*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_ENABLE_LIBRARY
182*5a6e8488SAndroid Build Coastguard Worker size_t esize;
183*5a6e8488SAndroid Build Coastguard Worker
184*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL && data != NULL);
185*5a6e8488SAndroid Build Coastguard Worker
186*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYLOCK(lock);
187*5a6e8488SAndroid Build Coastguard Worker
188*5a6e8488SAndroid Build Coastguard Worker // Grow if necessary.
189*5a6e8488SAndroid Build Coastguard Worker if (v->len + n > v->cap) bc_vec_grow(v, n);
190*5a6e8488SAndroid Build Coastguard Worker
191*5a6e8488SAndroid Build Coastguard Worker esize = v->size;
192*5a6e8488SAndroid Build Coastguard Worker
193*5a6e8488SAndroid Build Coastguard Worker // Copy the elements in.
194*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
195*5a6e8488SAndroid Build Coastguard Worker memcpy(v->v + (esize * v->len), data, esize * n);
196*5a6e8488SAndroid Build Coastguard Worker v->len += n;
197*5a6e8488SAndroid Build Coastguard Worker
198*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYUNLOCK(lock);
199*5a6e8488SAndroid Build Coastguard Worker }
200*5a6e8488SAndroid Build Coastguard Worker
201*5a6e8488SAndroid Build Coastguard Worker inline void
bc_vec_push(BcVec * restrict v,const void * data)202*5a6e8488SAndroid Build Coastguard Worker bc_vec_push(BcVec* restrict v, const void* data)
203*5a6e8488SAndroid Build Coastguard Worker {
204*5a6e8488SAndroid Build Coastguard Worker bc_vec_npush(v, 1, data);
205*5a6e8488SAndroid Build Coastguard Worker }
206*5a6e8488SAndroid Build Coastguard Worker
207*5a6e8488SAndroid Build Coastguard Worker void*
bc_vec_pushEmpty(BcVec * restrict v)208*5a6e8488SAndroid Build Coastguard Worker bc_vec_pushEmpty(BcVec* restrict v)
209*5a6e8488SAndroid Build Coastguard Worker {
210*5a6e8488SAndroid Build Coastguard Worker #if !BC_ENABLE_LIBRARY
211*5a6e8488SAndroid Build Coastguard Worker sig_atomic_t lock;
212*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_ENABLE_LIBRARY
213*5a6e8488SAndroid Build Coastguard Worker void* ptr;
214*5a6e8488SAndroid Build Coastguard Worker
215*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL);
216*5a6e8488SAndroid Build Coastguard Worker
217*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYLOCK(lock);
218*5a6e8488SAndroid Build Coastguard Worker
219*5a6e8488SAndroid Build Coastguard Worker // Grow if necessary.
220*5a6e8488SAndroid Build Coastguard Worker if (v->len + 1 > v->cap) bc_vec_grow(v, 1);
221*5a6e8488SAndroid Build Coastguard Worker
222*5a6e8488SAndroid Build Coastguard Worker ptr = v->v + v->size * v->len;
223*5a6e8488SAndroid Build Coastguard Worker v->len += 1;
224*5a6e8488SAndroid Build Coastguard Worker
225*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYUNLOCK(lock);
226*5a6e8488SAndroid Build Coastguard Worker
227*5a6e8488SAndroid Build Coastguard Worker return ptr;
228*5a6e8488SAndroid Build Coastguard Worker }
229*5a6e8488SAndroid Build Coastguard Worker
230*5a6e8488SAndroid Build Coastguard Worker inline void
bc_vec_pushByte(BcVec * restrict v,uchar data)231*5a6e8488SAndroid Build Coastguard Worker bc_vec_pushByte(BcVec* restrict v, uchar data)
232*5a6e8488SAndroid Build Coastguard Worker {
233*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL && v->size == sizeof(uchar));
234*5a6e8488SAndroid Build Coastguard Worker bc_vec_npush(v, 1, &data);
235*5a6e8488SAndroid Build Coastguard Worker }
236*5a6e8488SAndroid Build Coastguard Worker
237*5a6e8488SAndroid Build Coastguard Worker void
bc_vec_pushIndex(BcVec * restrict v,size_t idx)238*5a6e8488SAndroid Build Coastguard Worker bc_vec_pushIndex(BcVec* restrict v, size_t idx)
239*5a6e8488SAndroid Build Coastguard Worker {
240*5a6e8488SAndroid Build Coastguard Worker uchar amt, nums[sizeof(size_t) + 1];
241*5a6e8488SAndroid Build Coastguard Worker
242*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL);
243*5a6e8488SAndroid Build Coastguard Worker assert(v->size == sizeof(uchar));
244*5a6e8488SAndroid Build Coastguard Worker
245*5a6e8488SAndroid Build Coastguard Worker // Encode the index.
246*5a6e8488SAndroid Build Coastguard Worker for (amt = 0; idx; ++amt)
247*5a6e8488SAndroid Build Coastguard Worker {
248*5a6e8488SAndroid Build Coastguard Worker nums[amt + 1] = (uchar) idx;
249*5a6e8488SAndroid Build Coastguard Worker idx &= ((size_t) ~(UCHAR_MAX));
250*5a6e8488SAndroid Build Coastguard Worker idx >>= sizeof(uchar) * CHAR_BIT;
251*5a6e8488SAndroid Build Coastguard Worker }
252*5a6e8488SAndroid Build Coastguard Worker
253*5a6e8488SAndroid Build Coastguard Worker nums[0] = amt;
254*5a6e8488SAndroid Build Coastguard Worker
255*5a6e8488SAndroid Build Coastguard Worker // Push the index onto the vector.
256*5a6e8488SAndroid Build Coastguard Worker bc_vec_npush(v, amt + 1, nums);
257*5a6e8488SAndroid Build Coastguard Worker }
258*5a6e8488SAndroid Build Coastguard Worker
259*5a6e8488SAndroid Build Coastguard Worker void
bc_vec_pushAt(BcVec * restrict v,const void * data,size_t idx)260*5a6e8488SAndroid Build Coastguard Worker bc_vec_pushAt(BcVec* restrict v, const void* data, size_t idx)
261*5a6e8488SAndroid Build Coastguard Worker {
262*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL && data != NULL && idx <= v->len);
263*5a6e8488SAndroid Build Coastguard Worker
264*5a6e8488SAndroid Build Coastguard Worker BC_SIG_ASSERT_LOCKED;
265*5a6e8488SAndroid Build Coastguard Worker
266*5a6e8488SAndroid Build Coastguard Worker // Do the easy case.
267*5a6e8488SAndroid Build Coastguard Worker if (idx == v->len) bc_vec_push(v, data);
268*5a6e8488SAndroid Build Coastguard Worker else
269*5a6e8488SAndroid Build Coastguard Worker {
270*5a6e8488SAndroid Build Coastguard Worker char* ptr;
271*5a6e8488SAndroid Build Coastguard Worker size_t esize;
272*5a6e8488SAndroid Build Coastguard Worker
273*5a6e8488SAndroid Build Coastguard Worker // Grow if necessary.
274*5a6e8488SAndroid Build Coastguard Worker if (v->len == v->cap) bc_vec_grow(v, 1);
275*5a6e8488SAndroid Build Coastguard Worker
276*5a6e8488SAndroid Build Coastguard Worker esize = v->size;
277*5a6e8488SAndroid Build Coastguard Worker
278*5a6e8488SAndroid Build Coastguard Worker ptr = v->v + esize * idx;
279*5a6e8488SAndroid Build Coastguard Worker
280*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
281*5a6e8488SAndroid Build Coastguard Worker memmove(ptr + esize, ptr, esize * (v->len++ - idx));
282*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
283*5a6e8488SAndroid Build Coastguard Worker memcpy(ptr, data, esize);
284*5a6e8488SAndroid Build Coastguard Worker }
285*5a6e8488SAndroid Build Coastguard Worker }
286*5a6e8488SAndroid Build Coastguard Worker
287*5a6e8488SAndroid Build Coastguard Worker void
bc_vec_string(BcVec * restrict v,size_t len,const char * restrict str)288*5a6e8488SAndroid Build Coastguard Worker bc_vec_string(BcVec* restrict v, size_t len, const char* restrict str)
289*5a6e8488SAndroid Build Coastguard Worker {
290*5a6e8488SAndroid Build Coastguard Worker #if !BC_ENABLE_LIBRARY
291*5a6e8488SAndroid Build Coastguard Worker sig_atomic_t lock;
292*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_ENABLE_LIBRARY
293*5a6e8488SAndroid Build Coastguard Worker
294*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL && v->size == sizeof(char));
295*5a6e8488SAndroid Build Coastguard Worker assert(!v->dtor);
296*5a6e8488SAndroid Build Coastguard Worker assert(!v->len || !v->v[v->len - 1]);
297*5a6e8488SAndroid Build Coastguard Worker assert(v->v != str);
298*5a6e8488SAndroid Build Coastguard Worker
299*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYLOCK(lock);
300*5a6e8488SAndroid Build Coastguard Worker
301*5a6e8488SAndroid Build Coastguard Worker bc_vec_popAll(v);
302*5a6e8488SAndroid Build Coastguard Worker bc_vec_expand(v, bc_vm_growSize(len, 1));
303*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
304*5a6e8488SAndroid Build Coastguard Worker memcpy(v->v, str, len);
305*5a6e8488SAndroid Build Coastguard Worker v->len = len;
306*5a6e8488SAndroid Build Coastguard Worker
307*5a6e8488SAndroid Build Coastguard Worker bc_vec_pushByte(v, '\0');
308*5a6e8488SAndroid Build Coastguard Worker
309*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYUNLOCK(lock);
310*5a6e8488SAndroid Build Coastguard Worker }
311*5a6e8488SAndroid Build Coastguard Worker
312*5a6e8488SAndroid Build Coastguard Worker void
bc_vec_concat(BcVec * restrict v,const char * restrict str)313*5a6e8488SAndroid Build Coastguard Worker bc_vec_concat(BcVec* restrict v, const char* restrict str)
314*5a6e8488SAndroid Build Coastguard Worker {
315*5a6e8488SAndroid Build Coastguard Worker #if !BC_ENABLE_LIBRARY
316*5a6e8488SAndroid Build Coastguard Worker sig_atomic_t lock;
317*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_ENABLE_LIBRARY
318*5a6e8488SAndroid Build Coastguard Worker
319*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL && v->size == sizeof(char));
320*5a6e8488SAndroid Build Coastguard Worker assert(!v->dtor);
321*5a6e8488SAndroid Build Coastguard Worker assert(!v->len || !v->v[v->len - 1]);
322*5a6e8488SAndroid Build Coastguard Worker assert(v->v != str);
323*5a6e8488SAndroid Build Coastguard Worker
324*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYLOCK(lock);
325*5a6e8488SAndroid Build Coastguard Worker
326*5a6e8488SAndroid Build Coastguard Worker // If there is already a string, erase its nul byte.
327*5a6e8488SAndroid Build Coastguard Worker if (v->len) v->len -= 1;
328*5a6e8488SAndroid Build Coastguard Worker
329*5a6e8488SAndroid Build Coastguard Worker bc_vec_npush(v, strlen(str) + 1, str);
330*5a6e8488SAndroid Build Coastguard Worker
331*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYUNLOCK(lock);
332*5a6e8488SAndroid Build Coastguard Worker }
333*5a6e8488SAndroid Build Coastguard Worker
334*5a6e8488SAndroid Build Coastguard Worker void
bc_vec_empty(BcVec * restrict v)335*5a6e8488SAndroid Build Coastguard Worker bc_vec_empty(BcVec* restrict v)
336*5a6e8488SAndroid Build Coastguard Worker {
337*5a6e8488SAndroid Build Coastguard Worker #if !BC_ENABLE_LIBRARY
338*5a6e8488SAndroid Build Coastguard Worker sig_atomic_t lock;
339*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_ENABLE_LIBRARY
340*5a6e8488SAndroid Build Coastguard Worker
341*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL && v->size == sizeof(char));
342*5a6e8488SAndroid Build Coastguard Worker assert(!v->dtor);
343*5a6e8488SAndroid Build Coastguard Worker
344*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYLOCK(lock);
345*5a6e8488SAndroid Build Coastguard Worker
346*5a6e8488SAndroid Build Coastguard Worker bc_vec_popAll(v);
347*5a6e8488SAndroid Build Coastguard Worker bc_vec_pushByte(v, '\0');
348*5a6e8488SAndroid Build Coastguard Worker
349*5a6e8488SAndroid Build Coastguard Worker BC_SIG_TRYUNLOCK(lock);
350*5a6e8488SAndroid Build Coastguard Worker }
351*5a6e8488SAndroid Build Coastguard Worker
352*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_HISTORY
353*5a6e8488SAndroid Build Coastguard Worker void
bc_vec_replaceAt(BcVec * restrict v,size_t idx,const void * data)354*5a6e8488SAndroid Build Coastguard Worker bc_vec_replaceAt(BcVec* restrict v, size_t idx, const void* data)
355*5a6e8488SAndroid Build Coastguard Worker {
356*5a6e8488SAndroid Build Coastguard Worker char* ptr;
357*5a6e8488SAndroid Build Coastguard Worker
358*5a6e8488SAndroid Build Coastguard Worker BC_SIG_ASSERT_LOCKED;
359*5a6e8488SAndroid Build Coastguard Worker
360*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL);
361*5a6e8488SAndroid Build Coastguard Worker
362*5a6e8488SAndroid Build Coastguard Worker ptr = bc_vec_item(v, idx);
363*5a6e8488SAndroid Build Coastguard Worker
364*5a6e8488SAndroid Build Coastguard Worker if (v->dtor) bc_vec_dtors[v->dtor](ptr);
365*5a6e8488SAndroid Build Coastguard Worker
366*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
367*5a6e8488SAndroid Build Coastguard Worker memcpy(ptr, data, v->size);
368*5a6e8488SAndroid Build Coastguard Worker }
369*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_HISTORY
370*5a6e8488SAndroid Build Coastguard Worker
371*5a6e8488SAndroid Build Coastguard Worker inline void*
bc_vec_item(const BcVec * restrict v,size_t idx)372*5a6e8488SAndroid Build Coastguard Worker bc_vec_item(const BcVec* restrict v, size_t idx)
373*5a6e8488SAndroid Build Coastguard Worker {
374*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL && v->len && idx < v->len);
375*5a6e8488SAndroid Build Coastguard Worker return v->v + v->size * idx;
376*5a6e8488SAndroid Build Coastguard Worker }
377*5a6e8488SAndroid Build Coastguard Worker
378*5a6e8488SAndroid Build Coastguard Worker inline void*
bc_vec_item_rev(const BcVec * restrict v,size_t idx)379*5a6e8488SAndroid Build Coastguard Worker bc_vec_item_rev(const BcVec* restrict v, size_t idx)
380*5a6e8488SAndroid Build Coastguard Worker {
381*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL && v->len && idx < v->len);
382*5a6e8488SAndroid Build Coastguard Worker return v->v + v->size * (v->len - idx - 1);
383*5a6e8488SAndroid Build Coastguard Worker }
384*5a6e8488SAndroid Build Coastguard Worker
385*5a6e8488SAndroid Build Coastguard Worker inline void
bc_vec_clear(BcVec * restrict v)386*5a6e8488SAndroid Build Coastguard Worker bc_vec_clear(BcVec* restrict v)
387*5a6e8488SAndroid Build Coastguard Worker {
388*5a6e8488SAndroid Build Coastguard Worker BC_SIG_ASSERT_LOCKED;
389*5a6e8488SAndroid Build Coastguard Worker v->v = NULL;
390*5a6e8488SAndroid Build Coastguard Worker v->len = 0;
391*5a6e8488SAndroid Build Coastguard Worker v->dtor = BC_DTOR_NONE;
392*5a6e8488SAndroid Build Coastguard Worker }
393*5a6e8488SAndroid Build Coastguard Worker
394*5a6e8488SAndroid Build Coastguard Worker void
bc_vec_free(void * vec)395*5a6e8488SAndroid Build Coastguard Worker bc_vec_free(void* vec)
396*5a6e8488SAndroid Build Coastguard Worker {
397*5a6e8488SAndroid Build Coastguard Worker BcVec* v = (BcVec*) vec;
398*5a6e8488SAndroid Build Coastguard Worker BC_SIG_ASSERT_LOCKED;
399*5a6e8488SAndroid Build Coastguard Worker bc_vec_popAll(v);
400*5a6e8488SAndroid Build Coastguard Worker free(v->v);
401*5a6e8488SAndroid Build Coastguard Worker }
402*5a6e8488SAndroid Build Coastguard Worker
403*5a6e8488SAndroid Build Coastguard Worker #if !BC_ENABLE_LIBRARY
404*5a6e8488SAndroid Build Coastguard Worker
405*5a6e8488SAndroid Build Coastguard Worker /**
406*5a6e8488SAndroid Build Coastguard Worker * Finds a name in a map by binary search. Returns the index where the item
407*5a6e8488SAndroid Build Coastguard Worker * *would* be if it doesn't exist. Callers are responsible for checking that the
408*5a6e8488SAndroid Build Coastguard Worker * item exists at the index.
409*5a6e8488SAndroid Build Coastguard Worker * @param v The map.
410*5a6e8488SAndroid Build Coastguard Worker * @param name The name to find.
411*5a6e8488SAndroid Build Coastguard Worker * @return The index of the item with @a name, or where the item would be
412*5a6e8488SAndroid Build Coastguard Worker * if it does not exist.
413*5a6e8488SAndroid Build Coastguard Worker */
414*5a6e8488SAndroid Build Coastguard Worker static size_t
bc_map_find(const BcVec * restrict v,const char * name)415*5a6e8488SAndroid Build Coastguard Worker bc_map_find(const BcVec* restrict v, const char* name)
416*5a6e8488SAndroid Build Coastguard Worker {
417*5a6e8488SAndroid Build Coastguard Worker size_t low = 0, high = v->len;
418*5a6e8488SAndroid Build Coastguard Worker
419*5a6e8488SAndroid Build Coastguard Worker while (low < high)
420*5a6e8488SAndroid Build Coastguard Worker {
421*5a6e8488SAndroid Build Coastguard Worker size_t mid = low + (high - low) / 2;
422*5a6e8488SAndroid Build Coastguard Worker const BcId* id = bc_vec_item(v, mid);
423*5a6e8488SAndroid Build Coastguard Worker int result = strcmp(name, id->name);
424*5a6e8488SAndroid Build Coastguard Worker
425*5a6e8488SAndroid Build Coastguard Worker if (!result) return mid;
426*5a6e8488SAndroid Build Coastguard Worker else if (result < 0) high = mid;
427*5a6e8488SAndroid Build Coastguard Worker else low = mid + 1;
428*5a6e8488SAndroid Build Coastguard Worker }
429*5a6e8488SAndroid Build Coastguard Worker
430*5a6e8488SAndroid Build Coastguard Worker return low;
431*5a6e8488SAndroid Build Coastguard Worker }
432*5a6e8488SAndroid Build Coastguard Worker
433*5a6e8488SAndroid Build Coastguard Worker bool
bc_map_insert(BcVec * restrict v,const char * name,size_t idx,size_t * restrict i)434*5a6e8488SAndroid Build Coastguard Worker bc_map_insert(BcVec* restrict v, const char* name, size_t idx,
435*5a6e8488SAndroid Build Coastguard Worker size_t* restrict i)
436*5a6e8488SAndroid Build Coastguard Worker {
437*5a6e8488SAndroid Build Coastguard Worker BcId id;
438*5a6e8488SAndroid Build Coastguard Worker
439*5a6e8488SAndroid Build Coastguard Worker BC_SIG_ASSERT_LOCKED;
440*5a6e8488SAndroid Build Coastguard Worker
441*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL && name != NULL && i != NULL);
442*5a6e8488SAndroid Build Coastguard Worker
443*5a6e8488SAndroid Build Coastguard Worker *i = bc_map_find(v, name);
444*5a6e8488SAndroid Build Coastguard Worker
445*5a6e8488SAndroid Build Coastguard Worker assert(*i <= v->len);
446*5a6e8488SAndroid Build Coastguard Worker
447*5a6e8488SAndroid Build Coastguard Worker if (*i != v->len && !strcmp(name, ((BcId*) bc_vec_item(v, *i))->name))
448*5a6e8488SAndroid Build Coastguard Worker {
449*5a6e8488SAndroid Build Coastguard Worker return false;
450*5a6e8488SAndroid Build Coastguard Worker }
451*5a6e8488SAndroid Build Coastguard Worker
452*5a6e8488SAndroid Build Coastguard Worker id.name = bc_slabvec_strdup(&vm->slabs, name);
453*5a6e8488SAndroid Build Coastguard Worker id.idx = idx;
454*5a6e8488SAndroid Build Coastguard Worker
455*5a6e8488SAndroid Build Coastguard Worker bc_vec_pushAt(v, &id, *i);
456*5a6e8488SAndroid Build Coastguard Worker
457*5a6e8488SAndroid Build Coastguard Worker return true;
458*5a6e8488SAndroid Build Coastguard Worker }
459*5a6e8488SAndroid Build Coastguard Worker
460*5a6e8488SAndroid Build Coastguard Worker size_t
bc_map_index(const BcVec * restrict v,const char * name)461*5a6e8488SAndroid Build Coastguard Worker bc_map_index(const BcVec* restrict v, const char* name)
462*5a6e8488SAndroid Build Coastguard Worker {
463*5a6e8488SAndroid Build Coastguard Worker size_t i;
464*5a6e8488SAndroid Build Coastguard Worker BcId* id;
465*5a6e8488SAndroid Build Coastguard Worker
466*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL && name != NULL);
467*5a6e8488SAndroid Build Coastguard Worker
468*5a6e8488SAndroid Build Coastguard Worker i = bc_map_find(v, name);
469*5a6e8488SAndroid Build Coastguard Worker
470*5a6e8488SAndroid Build Coastguard Worker // If out of range, return invalid.
471*5a6e8488SAndroid Build Coastguard Worker if (i >= v->len) return BC_VEC_INVALID_IDX;
472*5a6e8488SAndroid Build Coastguard Worker
473*5a6e8488SAndroid Build Coastguard Worker id = (BcId*) bc_vec_item(v, i);
474*5a6e8488SAndroid Build Coastguard Worker
475*5a6e8488SAndroid Build Coastguard Worker // Make sure the item exists and return appropriately.
476*5a6e8488SAndroid Build Coastguard Worker return strcmp(name, id->name) ? BC_VEC_INVALID_IDX : i;
477*5a6e8488SAndroid Build Coastguard Worker }
478*5a6e8488SAndroid Build Coastguard Worker
479*5a6e8488SAndroid Build Coastguard Worker #if DC_ENABLED
480*5a6e8488SAndroid Build Coastguard Worker const char*
bc_map_name(const BcVec * restrict v,size_t idx)481*5a6e8488SAndroid Build Coastguard Worker bc_map_name(const BcVec* restrict v, size_t idx)
482*5a6e8488SAndroid Build Coastguard Worker {
483*5a6e8488SAndroid Build Coastguard Worker size_t i, len = v->len;
484*5a6e8488SAndroid Build Coastguard Worker
485*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < len; ++i)
486*5a6e8488SAndroid Build Coastguard Worker {
487*5a6e8488SAndroid Build Coastguard Worker BcId* id = (BcId*) bc_vec_item(v, i);
488*5a6e8488SAndroid Build Coastguard Worker if (id->idx == idx) return id->name;
489*5a6e8488SAndroid Build Coastguard Worker }
490*5a6e8488SAndroid Build Coastguard Worker
491*5a6e8488SAndroid Build Coastguard Worker BC_UNREACHABLE
492*5a6e8488SAndroid Build Coastguard Worker
493*5a6e8488SAndroid Build Coastguard Worker #if !BC_CLANG
494*5a6e8488SAndroid Build Coastguard Worker return "";
495*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_CLANG
496*5a6e8488SAndroid Build Coastguard Worker }
497*5a6e8488SAndroid Build Coastguard Worker #endif // DC_ENABLED
498*5a6e8488SAndroid Build Coastguard Worker
499*5a6e8488SAndroid Build Coastguard Worker /**
500*5a6e8488SAndroid Build Coastguard Worker * Initializes a single slab.
501*5a6e8488SAndroid Build Coastguard Worker * @param s The slab to initialize.
502*5a6e8488SAndroid Build Coastguard Worker */
503*5a6e8488SAndroid Build Coastguard Worker static void
bc_slab_init(BcSlab * s)504*5a6e8488SAndroid Build Coastguard Worker bc_slab_init(BcSlab* s)
505*5a6e8488SAndroid Build Coastguard Worker {
506*5a6e8488SAndroid Build Coastguard Worker s->s = bc_vm_malloc(BC_SLAB_SIZE);
507*5a6e8488SAndroid Build Coastguard Worker s->len = 0;
508*5a6e8488SAndroid Build Coastguard Worker }
509*5a6e8488SAndroid Build Coastguard Worker
510*5a6e8488SAndroid Build Coastguard Worker /**
511*5a6e8488SAndroid Build Coastguard Worker * Adds a string to a slab and returns a pointer to it, or NULL if it could not
512*5a6e8488SAndroid Build Coastguard Worker * be added.
513*5a6e8488SAndroid Build Coastguard Worker * @param s The slab to add to.
514*5a6e8488SAndroid Build Coastguard Worker * @param str The string to add.
515*5a6e8488SAndroid Build Coastguard Worker * @param len The length of the string, including its nul byte.
516*5a6e8488SAndroid Build Coastguard Worker * @return A pointer to the new string in the slab, or NULL if it could not
517*5a6e8488SAndroid Build Coastguard Worker * be added.
518*5a6e8488SAndroid Build Coastguard Worker */
519*5a6e8488SAndroid Build Coastguard Worker static char*
bc_slab_add(BcSlab * s,const char * str,size_t len)520*5a6e8488SAndroid Build Coastguard Worker bc_slab_add(BcSlab* s, const char* str, size_t len)
521*5a6e8488SAndroid Build Coastguard Worker {
522*5a6e8488SAndroid Build Coastguard Worker char* ptr;
523*5a6e8488SAndroid Build Coastguard Worker
524*5a6e8488SAndroid Build Coastguard Worker assert(s != NULL);
525*5a6e8488SAndroid Build Coastguard Worker assert(str != NULL);
526*5a6e8488SAndroid Build Coastguard Worker assert(len == strlen(str) + 1);
527*5a6e8488SAndroid Build Coastguard Worker
528*5a6e8488SAndroid Build Coastguard Worker if (s->len + len > BC_SLAB_SIZE) return NULL;
529*5a6e8488SAndroid Build Coastguard Worker
530*5a6e8488SAndroid Build Coastguard Worker ptr = (char*) (s->s + s->len);
531*5a6e8488SAndroid Build Coastguard Worker
532*5a6e8488SAndroid Build Coastguard Worker // NOLINTNEXTLINE
533*5a6e8488SAndroid Build Coastguard Worker bc_strcpy(ptr, len, str);
534*5a6e8488SAndroid Build Coastguard Worker
535*5a6e8488SAndroid Build Coastguard Worker s->len += len;
536*5a6e8488SAndroid Build Coastguard Worker
537*5a6e8488SAndroid Build Coastguard Worker return ptr;
538*5a6e8488SAndroid Build Coastguard Worker }
539*5a6e8488SAndroid Build Coastguard Worker
540*5a6e8488SAndroid Build Coastguard Worker void
bc_slab_free(void * slab)541*5a6e8488SAndroid Build Coastguard Worker bc_slab_free(void* slab)
542*5a6e8488SAndroid Build Coastguard Worker {
543*5a6e8488SAndroid Build Coastguard Worker free(((BcSlab*) slab)->s);
544*5a6e8488SAndroid Build Coastguard Worker }
545*5a6e8488SAndroid Build Coastguard Worker
546*5a6e8488SAndroid Build Coastguard Worker void
bc_slabvec_init(BcVec * v)547*5a6e8488SAndroid Build Coastguard Worker bc_slabvec_init(BcVec* v)
548*5a6e8488SAndroid Build Coastguard Worker {
549*5a6e8488SAndroid Build Coastguard Worker BcSlab* slab;
550*5a6e8488SAndroid Build Coastguard Worker
551*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL);
552*5a6e8488SAndroid Build Coastguard Worker
553*5a6e8488SAndroid Build Coastguard Worker bc_vec_init(v, sizeof(BcSlab), BC_DTOR_SLAB);
554*5a6e8488SAndroid Build Coastguard Worker
555*5a6e8488SAndroid Build Coastguard Worker // We always want to have at least one slab.
556*5a6e8488SAndroid Build Coastguard Worker slab = bc_vec_pushEmpty(v);
557*5a6e8488SAndroid Build Coastguard Worker bc_slab_init(slab);
558*5a6e8488SAndroid Build Coastguard Worker }
559*5a6e8488SAndroid Build Coastguard Worker
560*5a6e8488SAndroid Build Coastguard Worker char*
bc_slabvec_strdup(BcVec * v,const char * str)561*5a6e8488SAndroid Build Coastguard Worker bc_slabvec_strdup(BcVec* v, const char* str)
562*5a6e8488SAndroid Build Coastguard Worker {
563*5a6e8488SAndroid Build Coastguard Worker char* s;
564*5a6e8488SAndroid Build Coastguard Worker size_t len;
565*5a6e8488SAndroid Build Coastguard Worker BcSlab slab;
566*5a6e8488SAndroid Build Coastguard Worker BcSlab* slab_ptr;
567*5a6e8488SAndroid Build Coastguard Worker
568*5a6e8488SAndroid Build Coastguard Worker BC_SIG_ASSERT_LOCKED;
569*5a6e8488SAndroid Build Coastguard Worker
570*5a6e8488SAndroid Build Coastguard Worker assert(v != NULL && v->len);
571*5a6e8488SAndroid Build Coastguard Worker
572*5a6e8488SAndroid Build Coastguard Worker assert(str != NULL);
573*5a6e8488SAndroid Build Coastguard Worker
574*5a6e8488SAndroid Build Coastguard Worker len = strlen(str) + 1;
575*5a6e8488SAndroid Build Coastguard Worker
576*5a6e8488SAndroid Build Coastguard Worker // If the len is greater than 128, then just allocate it with malloc.
577*5a6e8488SAndroid Build Coastguard Worker if (BC_UNLIKELY(len >= BC_SLAB_SIZE))
578*5a6e8488SAndroid Build Coastguard Worker {
579*5a6e8488SAndroid Build Coastguard Worker // SIZE_MAX is a marker for these standalone allocations.
580*5a6e8488SAndroid Build Coastguard Worker slab.len = SIZE_MAX;
581*5a6e8488SAndroid Build Coastguard Worker slab.s = bc_vm_strdup(str);
582*5a6e8488SAndroid Build Coastguard Worker
583*5a6e8488SAndroid Build Coastguard Worker // Push the standalone slab.
584*5a6e8488SAndroid Build Coastguard Worker bc_vec_pushAt(v, &slab, v->len - 1);
585*5a6e8488SAndroid Build Coastguard Worker
586*5a6e8488SAndroid Build Coastguard Worker return slab.s;
587*5a6e8488SAndroid Build Coastguard Worker }
588*5a6e8488SAndroid Build Coastguard Worker
589*5a6e8488SAndroid Build Coastguard Worker // Add to a slab.
590*5a6e8488SAndroid Build Coastguard Worker slab_ptr = bc_vec_top(v);
591*5a6e8488SAndroid Build Coastguard Worker s = bc_slab_add(slab_ptr, str, len);
592*5a6e8488SAndroid Build Coastguard Worker
593*5a6e8488SAndroid Build Coastguard Worker // If it couldn't be added, add a slab and try again.
594*5a6e8488SAndroid Build Coastguard Worker if (BC_UNLIKELY(s == NULL))
595*5a6e8488SAndroid Build Coastguard Worker {
596*5a6e8488SAndroid Build Coastguard Worker slab_ptr = bc_vec_pushEmpty(v);
597*5a6e8488SAndroid Build Coastguard Worker bc_slab_init(slab_ptr);
598*5a6e8488SAndroid Build Coastguard Worker
599*5a6e8488SAndroid Build Coastguard Worker s = bc_slab_add(slab_ptr, str, len);
600*5a6e8488SAndroid Build Coastguard Worker
601*5a6e8488SAndroid Build Coastguard Worker assert(s != NULL);
602*5a6e8488SAndroid Build Coastguard Worker }
603*5a6e8488SAndroid Build Coastguard Worker
604*5a6e8488SAndroid Build Coastguard Worker return s;
605*5a6e8488SAndroid Build Coastguard Worker }
606*5a6e8488SAndroid Build Coastguard Worker
607*5a6e8488SAndroid Build Coastguard Worker void
bc_slabvec_clear(BcVec * v)608*5a6e8488SAndroid Build Coastguard Worker bc_slabvec_clear(BcVec* v)
609*5a6e8488SAndroid Build Coastguard Worker {
610*5a6e8488SAndroid Build Coastguard Worker BcSlab* s;
611*5a6e8488SAndroid Build Coastguard Worker bool again;
612*5a6e8488SAndroid Build Coastguard Worker
613*5a6e8488SAndroid Build Coastguard Worker // This complicated loop exists because of standalone allocations over 128
614*5a6e8488SAndroid Build Coastguard Worker // bytes.
615*5a6e8488SAndroid Build Coastguard Worker do
616*5a6e8488SAndroid Build Coastguard Worker {
617*5a6e8488SAndroid Build Coastguard Worker // Get the first slab.
618*5a6e8488SAndroid Build Coastguard Worker s = bc_vec_item(v, 0);
619*5a6e8488SAndroid Build Coastguard Worker
620*5a6e8488SAndroid Build Coastguard Worker // Either the slab must be valid (not standalone), or there must be
621*5a6e8488SAndroid Build Coastguard Worker // another slab.
622*5a6e8488SAndroid Build Coastguard Worker assert(s->len != SIZE_MAX || v->len > 1);
623*5a6e8488SAndroid Build Coastguard Worker
624*5a6e8488SAndroid Build Coastguard Worker // Do we have to loop again? We do if it's a standalone allocation.
625*5a6e8488SAndroid Build Coastguard Worker again = (s->len == SIZE_MAX);
626*5a6e8488SAndroid Build Coastguard Worker
627*5a6e8488SAndroid Build Coastguard Worker // Pop the standalone allocation, not the one after it.
628*5a6e8488SAndroid Build Coastguard Worker if (again) bc_vec_npopAt(v, 1, 0);
629*5a6e8488SAndroid Build Coastguard Worker }
630*5a6e8488SAndroid Build Coastguard Worker while (again);
631*5a6e8488SAndroid Build Coastguard Worker
632*5a6e8488SAndroid Build Coastguard Worker // If we get here, we know that the first slab is a valid slab. We want to
633*5a6e8488SAndroid Build Coastguard Worker // pop all of the other slabs.
634*5a6e8488SAndroid Build Coastguard Worker if (v->len > 1) bc_vec_npop(v, v->len - 1);
635*5a6e8488SAndroid Build Coastguard Worker
636*5a6e8488SAndroid Build Coastguard Worker // Empty the first slab.
637*5a6e8488SAndroid Build Coastguard Worker s->len = 0;
638*5a6e8488SAndroid Build Coastguard Worker }
639*5a6e8488SAndroid Build Coastguard Worker #endif // !BC_ENABLE_LIBRARY
640*5a6e8488SAndroid Build Coastguard Worker
641*5a6e8488SAndroid Build Coastguard Worker #if BC_DEBUG_CODE
642*5a6e8488SAndroid Build Coastguard Worker
643*5a6e8488SAndroid Build Coastguard Worker void
bc_slabvec_print(BcVec * v,const char * func)644*5a6e8488SAndroid Build Coastguard Worker bc_slabvec_print(BcVec* v, const char* func)
645*5a6e8488SAndroid Build Coastguard Worker {
646*5a6e8488SAndroid Build Coastguard Worker size_t i;
647*5a6e8488SAndroid Build Coastguard Worker BcSlab* s;
648*5a6e8488SAndroid Build Coastguard Worker
649*5a6e8488SAndroid Build Coastguard Worker bc_file_printf(&vm->ferr, "%s\n", func);
650*5a6e8488SAndroid Build Coastguard Worker
651*5a6e8488SAndroid Build Coastguard Worker for (i = 0; i < v->len; ++i)
652*5a6e8488SAndroid Build Coastguard Worker {
653*5a6e8488SAndroid Build Coastguard Worker s = bc_vec_item(v, i);
654*5a6e8488SAndroid Build Coastguard Worker bc_file_printf(&vm->ferr, "%zu { s = %zu, len = %zu }\n", i,
655*5a6e8488SAndroid Build Coastguard Worker (uintptr_t) s->s, s->len);
656*5a6e8488SAndroid Build Coastguard Worker }
657*5a6e8488SAndroid Build Coastguard Worker
658*5a6e8488SAndroid Build Coastguard Worker bc_file_puts(&vm->ferr, bc_flush_none, "\n");
659*5a6e8488SAndroid Build Coastguard Worker bc_file_flush(&vm->ferr, bc_flush_none);
660*5a6e8488SAndroid Build Coastguard Worker }
661*5a6e8488SAndroid Build Coastguard Worker
662*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEBUG_CODE
663