2 * *****************************************************************************
4 * SPDX-License-Identifier: BSD-2-Clause
6 * Copyright (c) 2018-2021 Gavin D. Howard and contributors.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * * Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
30 * *****************************************************************************
32 * Definitions for bc vectors (resizable arrays).
45 /// An invalid index for a map to mark when an item does not exist.
46 #define BC_VEC_INVALID_IDX (SIZE_MAX)
48 /// The starting capacity for vectors. This is based on the minimum allocation
49 /// for 64-bit systems.
50 #define BC_VEC_START_CAP (UINTMAX_C(1)<<5)
53 typedef unsigned char uchar;
56 * A destructor. Frees the object that @a ptr points to. This is used by vectors
57 * to free the memory they own.
58 * @param ptr Pointer to the data to free.
60 typedef void (*BcVecFree)(void *ptr);
62 // Forward declaration.
67 /// An integer to shrink the size of a vector by using these instead of size_t.
68 typedef uint32_t BcSize;
70 #else // BC_LONG_BIT >= 64
72 /// An integer to shrink the size of a vector by using these instead of size_t.
73 typedef uint16_t BcSize;
75 #endif // BC_LONG_BIT >= 64
77 /// An enum of all of the destructors. We use an enum to save space.
78 typedef enum BcDtorType {
80 /// No destructor needed.
83 /// Vector destructor.
89 #if !BC_ENABLE_LIBRARY
93 /// BcFunc destructor.
98 /// BcSlab destructor.
101 /// BcConst destructor.
104 /// BcResult destructor.
107 #if BC_ENABLE_HISTORY
109 /// String destructor for history, which is *special*.
110 BC_DTOR_HISTORY_STRING,
112 #endif // BC_ENABLE_HISTORY
113 #else // !BC_ENABLE_LIBRARY
115 /// Destructor for bcl numbers.
118 #endif // !BC_ENABLE_LIBRARY
122 /// The actual vector struct.
123 typedef struct BcVec {
125 /// The vector array itself. This uses a char* because it is compatible with
126 /// pointers of all other types, and I can do pointer arithmetic on it.
129 /// The length of the vector, which is how many items actually exist.
132 /// The capacity of the vector, which is how many items can fit in the
133 /// current allocation.
136 /// The size of the items in the vector, as returned by sizeof().
139 /// The destructor as a BcDtorType enum.
145 * Initializes a vector.
146 * @param v The vector to initialize.
147 * @param esize The size of the elements, as returned by sizeof().
148 * @param dtor The destructor of the elements, as a BcDtorType enum.
150 void bc_vec_init(BcVec *restrict v, size_t esize, BcDtorType dtor);
153 * Expands the vector to have a capacity of @a req items, if it doesn't have
155 * @param v The vector to expand.
156 * @param req The requested capacity.
158 void bc_vec_expand(BcVec *restrict v, size_t req);
161 * Grow a vector by at least @a n elements.
162 * @param v The vector to grow.
163 * @param n The number of elements to grow the vector by.
165 void bc_vec_grow(BcVec *restrict v, size_t n);
168 * Pops @a n items off the back of the vector. The vector must have at least
170 * @param v The vector to pop off of.
171 * @param n The number of elements to pop off.
173 void bc_vec_npop(BcVec *restrict v, size_t n);
176 * Pops @a n items, starting at index @a idx, off the vector. The vector must
177 * have at least @a n elements after the @a idx index. Any remaining elements at
178 * the end are moved up to fill the hole.
179 * @param v The vector to pop off of.
180 * @param n The number of elements to pop off.
181 * @param idx The index to start popping at.
183 void bc_vec_npopAt(BcVec *restrict v, size_t n, size_t idx);
186 * Pushes one item on the back of the vector. It does a memcpy(), but it assumes
187 * that the vector takes ownership of the data.
188 * @param v The vector to push onto.
189 * @param data A pointer to the data to push.
191 void bc_vec_push(BcVec *restrict v, const void *data);
194 * Pushes @a n items on the back of the vector. It does a memcpy(), but it
195 * assumes that the vector takes ownership of the data.
196 * @param v The vector to push onto.
197 * @param data A pointer to the elements of data to push.
199 void bc_vec_npush(BcVec *restrict v, size_t n, const void *data);
202 * Push an empty element and return a pointer to it. This is done as an
203 * optimization where initializing an item needs a pointer anyway. It removes an
205 * @param v The vector to push onto.
206 * @return A pointer to the newly-pushed element.
208 void* bc_vec_pushEmpty(BcVec *restrict v);
211 * Pushes a byte onto a bytecode vector. This is a convenience function for the
212 * parsers pushing instructions. The vector must be a bytecode vector.
213 * @param v The vector to push onto.
214 * @param data The byte to push.
216 void bc_vec_pushByte(BcVec *restrict v, uchar data);
219 * Pushes and index onto a bytecode vector. The vector must be a bytecode
220 * vector. For more info about why and how this is done, see the development
221 * manual (manuals/development#bytecode-indices).
222 * @param v The vector to push onto.
223 * @param idx The index to push.
225 void bc_vec_pushIndex(BcVec *restrict v, size_t idx);
228 * Push an item onto the vector at a certain index. The index must be valid
229 * (either exists or is equal to the length of the vector). The elements at that
230 * index and after are moved back one element and kept in the same order. This
231 * is how the map vectors are kept sorted.
232 * @param v The vector to push onto.
233 * @param data A pointer to the data to push.
234 * @param idx The index to push at.
236 void bc_vec_pushAt(BcVec *restrict v, const void *data, size_t idx);
239 * Empties the vector and sets it to the string. The vector must be a valid
240 * vector and must have chars as its elements.
241 * @param v The vector to set to the string.
242 * @param len The length of the string. This can be less than the actual length
243 * of the string, but must never be more.
244 * @param str The string to push.
246 void bc_vec_string(BcVec *restrict v, size_t len, const char *restrict str);
249 * Appends the string to the end of the vector, which must be holding a string
250 * (nul byte-terminated) already.
251 * @param v The vector to append to.
252 * @param str The string to append (by copying).
254 void bc_vec_concat(BcVec *restrict v, const char *restrict str);
257 * Empties a vector and pushes a nul-byte at the first index. The vector must be
260 void bc_vec_empty(BcVec *restrict v);
262 #if BC_ENABLE_HISTORY
265 * Replaces an item at a particular index. No elements are moved. The index must
267 * @param v The vector to replace an item on.
268 * @param idx The index of the item to replace.
269 * @param data The data to replace the item with.
271 void bc_vec_replaceAt(BcVec *restrict v, size_t idx, const void *data);
273 #endif // BC_ENABLE_HISTORY
276 * Returns a pointer to the item in the vector at the index. This is the key
277 * function for vectors. The index must exist.
278 * @param v The vector.
279 * @param idx The index to the item to get a pointer to.
280 * @return A pointer to the item at @a idx.
282 void* bc_vec_item(const BcVec *restrict v, size_t idx);
285 * Returns a pointer to the item in the vector at the index, reversed. This is
286 * another key function for vectors. The index must exist.
287 * @param v The vector.
288 * @param idx The index to the item to get a pointer to.
289 * @return A pointer to the item at len - @a idx - 1.
291 void* bc_vec_item_rev(const BcVec *restrict v, size_t idx);
294 * Zeros a vector. The vector must not be allocated.
295 * @param v The vector to clear.
297 void bc_vec_clear(BcVec *restrict v);
300 * Frees a vector and its elements. This is a destructor.
301 * @param vec A vector as a void pointer.
303 void bc_vec_free(void *vec);
306 * Attempts to insert an item into a map and returns true if it succeeded, false
307 * if the item already exists.
308 * @param v The map vector to insert into.
309 * @param name The name of the item to insert. This name is assumed to be owned
311 * @param idx The index of the partner array where the actual item is.
312 * @param i A pointer to an index that will be set to the index of the item
314 * @return True if the item was inserted, false if the item already exists.
316 bool bc_map_insert(BcVec *restrict v, const char *name,
317 size_t idx, size_t *restrict i);
320 * Returns the index of the item with @a name in the map, or BC_VEC_INVALID_IDX
321 * if it doesn't exist.
322 * @param v The map vector.
323 * @param name The name of the item to find.
324 * @return The index in the map of the item with @a name, or
325 * BC_VEC_INVALID_IDX if the item does not exist.
327 size_t bc_map_index(const BcVec *restrict v, const char *name);
332 * Returns the name of the item at index @a idx in the map.
333 * @param v The map vector.
334 * @param idx The index.
335 * @return The name of the item at @a idx.
337 const char* bc_map_name(const BcVec *restrict v, size_t idx);
342 * Pops one item off of the vector.
343 * @param v The vector to pop one item off of.
345 #define bc_vec_pop(v) (bc_vec_npop((v), 1))
348 * Pops all items off of the vector.
349 * @param v The vector to pop all items off of.
351 #define bc_vec_popAll(v) (bc_vec_npop((v), (v)->len))
354 * Return a pointer to the last item in the vector, or first if it's being
355 * treated as a stack.
356 * @param v The vector to get the top of stack of.
358 #define bc_vec_top(v) (bc_vec_item_rev((v), 0))
361 * Initializes a vector to serve as a map.
362 * @param v The vector to initialize.
364 #define bc_map_init(v) (bc_vec_init((v), sizeof(BcId), BC_DTOR_NONE))
366 /// A reference to the array of destructors.
367 extern const BcVecFree bc_vec_dtors[];
369 #if !BC_ENABLE_LIBRARY
371 /// The allocated size of slabs.
372 #define BC_SLAB_SIZE (4096)
374 /// A slab for allocating strings.
375 typedef struct BcSlab {
377 /// The actual allocation.
380 /// How many bytes of the slab are taken.
386 * Frees a slab. This is a destructor.
387 * @param slab The slab as a void pointer.
389 void bc_slab_free(void *slab);
392 * Initializes a slab vector.
393 * @param v The vector to initialize.
395 void bc_slabvec_init(BcVec *restrict v);
398 * Duplicates the string using slabs in the slab vector.
399 * @param v The slab vector.
400 * @param str The string to duplicate.
401 * @return A pointer to the duplicated string, owned by the slab vector.
403 char* bc_slabvec_strdup(BcVec *restrict v, const char *str);
408 * Undoes the last allocation on the slab vector. This allows bc to have a
409 * heap-based stacks for strings. This is used by the bc parser.
411 void bc_slabvec_undo(BcVec *restrict v, size_t len);
416 * Clears a slab vector. This deallocates all but the first slab and clears the
418 * @param v The slab vector to clear.
420 void bc_slabvec_clear(BcVec *restrict v);
425 * Prints all of the items in a slab vector, in order.
426 * @param v The vector whose items will be printed.
428 void bc_slabvec_print(BcVec *v, const char *func);
430 #endif // BC_DEBUG_CODE
432 /// A convenience macro for freeing a vector of slabs.
433 #define bc_slabvec_free bc_vec_free
438 * A macro to get rid of a warning on Windows.
439 * @param d The destination string.
440 * @param l The length of the destination string. This has to be big enough to
442 * @param s The source string.
444 #define bc_strcpy(d, l, s) strcpy(d, s)
449 * A macro to get rid of a warning on Windows.
450 * @param d The destination string.
451 * @param l The length of the destination string. This has to be big enough to
453 * @param s The source string.
455 #define bc_strcpy(d, l, s) strcpy_s(d, l, s)
459 #endif // !BC_ENABLE_LIBRARY
461 #endif // BC_VECTOR_H