xref: /freebsd-src/contrib/bc/include/vector.h (revision a970610a3af63b3f4df5b69d91c6b4093a00ed8f)
1252884aeSStefan Eßer /*
2252884aeSStefan Eßer  * *****************************************************************************
3252884aeSStefan Eßer  *
43aa99676SStefan Eßer  * SPDX-License-Identifier: BSD-2-Clause
5252884aeSStefan Eßer  *
6*a970610aSStefan Eßer  * Copyright (c) 2018-2024 Gavin D. Howard and contributors.
7252884aeSStefan Eßer  *
8252884aeSStefan Eßer  * Redistribution and use in source and binary forms, with or without
9252884aeSStefan Eßer  * modification, are permitted provided that the following conditions are met:
10252884aeSStefan Eßer  *
11252884aeSStefan Eßer  * * Redistributions of source code must retain the above copyright notice, this
12252884aeSStefan Eßer  *   list of conditions and the following disclaimer.
13252884aeSStefan Eßer  *
14252884aeSStefan Eßer  * * Redistributions in binary form must reproduce the above copyright notice,
15252884aeSStefan Eßer  *   this list of conditions and the following disclaimer in the documentation
16252884aeSStefan Eßer  *   and/or other materials provided with the distribution.
17252884aeSStefan Eßer  *
18252884aeSStefan Eßer  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19252884aeSStefan Eßer  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20252884aeSStefan Eßer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21252884aeSStefan Eßer  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22252884aeSStefan Eßer  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23252884aeSStefan Eßer  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24252884aeSStefan Eßer  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25252884aeSStefan Eßer  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26252884aeSStefan Eßer  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27252884aeSStefan Eßer  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28252884aeSStefan Eßer  * POSSIBILITY OF SUCH DAMAGE.
29252884aeSStefan Eßer  *
30252884aeSStefan Eßer  * *****************************************************************************
31252884aeSStefan Eßer  *
32252884aeSStefan Eßer  * Definitions for bc vectors (resizable arrays).
33252884aeSStefan Eßer  *
34252884aeSStefan Eßer  */
35252884aeSStefan Eßer 
36252884aeSStefan Eßer #ifndef BC_VECTOR_H
37252884aeSStefan Eßer #define BC_VECTOR_H
38252884aeSStefan Eßer 
39252884aeSStefan Eßer #include <stdbool.h>
40252884aeSStefan Eßer #include <stddef.h>
41252884aeSStefan Eßer #include <stdint.h>
42252884aeSStefan Eßer 
43252884aeSStefan Eßer #include <status.h>
44252884aeSStefan Eßer 
4544d4804dSStefan Eßer /// An invalid index for a map to mark when an item does not exist.
46252884aeSStefan Eßer #define BC_VEC_INVALID_IDX (SIZE_MAX)
4744d4804dSStefan Eßer 
4844d4804dSStefan Eßer /// The starting capacity for vectors. This is based on the minimum allocation
4944d4804dSStefan Eßer /// for 64-bit systems.
50252884aeSStefan Eßer #define BC_VEC_START_CAP (UINTMAX_C(1) << 5)
51252884aeSStefan Eßer 
5244d4804dSStefan Eßer /// An alias.
53252884aeSStefan Eßer typedef unsigned char uchar;
54252884aeSStefan Eßer 
5544d4804dSStefan Eßer /**
5644d4804dSStefan Eßer  * A destructor. Frees the object that @a ptr points to. This is used by vectors
5744d4804dSStefan Eßer  * to free the memory they own.
5844d4804dSStefan Eßer  * @param ptr  Pointer to the data to free.
5944d4804dSStefan Eßer  */
6044d4804dSStefan Eßer typedef void (*BcVecFree)(void* ptr);
61252884aeSStefan Eßer 
6244d4804dSStefan Eßer #if BC_LONG_BIT >= 64
6344d4804dSStefan Eßer 
6444d4804dSStefan Eßer /// An integer to shrink the size of a vector by using these instead of size_t.
6544d4804dSStefan Eßer typedef uint32_t BcSize;
6644d4804dSStefan Eßer 
6744d4804dSStefan Eßer #else // BC_LONG_BIT >= 64
6844d4804dSStefan Eßer 
6944d4804dSStefan Eßer /// An integer to shrink the size of a vector by using these instead of size_t.
7044d4804dSStefan Eßer typedef uint16_t BcSize;
7144d4804dSStefan Eßer 
7244d4804dSStefan Eßer #endif // BC_LONG_BIT >= 64
7344d4804dSStefan Eßer 
7444d4804dSStefan Eßer /// An enum of all of the destructors. We use an enum to save space.
7578bc019dSStefan Eßer typedef enum BcDtorType
7678bc019dSStefan Eßer {
7744d4804dSStefan Eßer 	/// No destructor needed.
7844d4804dSStefan Eßer 	BC_DTOR_NONE,
7944d4804dSStefan Eßer 
8044d4804dSStefan Eßer 	/// Vector destructor.
8144d4804dSStefan Eßer 	BC_DTOR_VEC,
8244d4804dSStefan Eßer 
8344d4804dSStefan Eßer 	/// BcNum destructor.
8444d4804dSStefan Eßer 	BC_DTOR_NUM,
8544d4804dSStefan Eßer 
8644d4804dSStefan Eßer #if !BC_ENABLE_LIBRARY
8744d4804dSStefan Eßer 
88103d7cdfSStefan Eßer #if BC_DEBUG
8944d4804dSStefan Eßer 
9044d4804dSStefan Eßer 	/// BcFunc destructor.
9144d4804dSStefan Eßer 	BC_DTOR_FUNC,
9244d4804dSStefan Eßer 
93103d7cdfSStefan Eßer #endif // BC_DEBUG
9444d4804dSStefan Eßer 
9544d4804dSStefan Eßer 	/// BcSlab destructor.
9644d4804dSStefan Eßer 	BC_DTOR_SLAB,
9744d4804dSStefan Eßer 
9844d4804dSStefan Eßer 	/// BcConst destructor.
9944d4804dSStefan Eßer 	BC_DTOR_CONST,
10044d4804dSStefan Eßer 
10144d4804dSStefan Eßer 	/// BcResult destructor.
10244d4804dSStefan Eßer 	BC_DTOR_RESULT,
10344d4804dSStefan Eßer 
10444d4804dSStefan Eßer #if BC_ENABLE_HISTORY
10544d4804dSStefan Eßer 
10644d4804dSStefan Eßer 	/// String destructor for history, which is *special*.
10744d4804dSStefan Eßer 	BC_DTOR_HISTORY_STRING,
10844d4804dSStefan Eßer 
10944d4804dSStefan Eßer #endif // BC_ENABLE_HISTORY
11044d4804dSStefan Eßer #else // !BC_ENABLE_LIBRARY
11144d4804dSStefan Eßer 
11244d4804dSStefan Eßer 	/// Destructor for bcl numbers.
11344d4804dSStefan Eßer 	BC_DTOR_BCL_NUM,
11444d4804dSStefan Eßer 
11544d4804dSStefan Eßer #endif // !BC_ENABLE_LIBRARY
11644d4804dSStefan Eßer 
11744d4804dSStefan Eßer } BcDtorType;
11844d4804dSStefan Eßer 
11944d4804dSStefan Eßer /// The actual vector struct.
12078bc019dSStefan Eßer typedef struct BcVec
12178bc019dSStefan Eßer {
12244d4804dSStefan Eßer 	/// The vector array itself. This uses a char* because it is compatible with
12344d4804dSStefan Eßer 	/// pointers of all other types, and I can do pointer arithmetic on it.
12444d4804dSStefan Eßer 	char* restrict v;
12544d4804dSStefan Eßer 
12644d4804dSStefan Eßer 	/// The length of the vector, which is how many items actually exist.
127252884aeSStefan Eßer 	size_t len;
12844d4804dSStefan Eßer 
12944d4804dSStefan Eßer 	/// The capacity of the vector, which is how many items can fit in the
13044d4804dSStefan Eßer 	/// current allocation.
131252884aeSStefan Eßer 	size_t cap;
13244d4804dSStefan Eßer 
13344d4804dSStefan Eßer 	/// The size of the items in the vector, as returned by sizeof().
13444d4804dSStefan Eßer 	BcSize size;
13544d4804dSStefan Eßer 
13644d4804dSStefan Eßer 	/// The destructor as a BcDtorType enum.
13744d4804dSStefan Eßer 	BcSize dtor;
13844d4804dSStefan Eßer 
139252884aeSStefan Eßer } BcVec;
140252884aeSStefan Eßer 
14144d4804dSStefan Eßer /**
14244d4804dSStefan Eßer  * Initializes a vector.
14344d4804dSStefan Eßer  * @param v      The vector to initialize.
14444d4804dSStefan Eßer  * @param esize  The size of the elements, as returned by sizeof().
14544d4804dSStefan Eßer  * @param dtor   The destructor of the elements, as a BcDtorType enum.
14644d4804dSStefan Eßer  */
14778bc019dSStefan Eßer void
14878bc019dSStefan Eßer bc_vec_init(BcVec* restrict v, size_t esize, BcDtorType dtor);
14944d4804dSStefan Eßer 
15044d4804dSStefan Eßer /**
15144d4804dSStefan Eßer  * Expands the vector to have a capacity of @a req items, if it doesn't have
15244d4804dSStefan Eßer  * enough already.
15344d4804dSStefan Eßer  * @param v    The vector to expand.
15444d4804dSStefan Eßer  * @param req  The requested capacity.
15544d4804dSStefan Eßer  */
15678bc019dSStefan Eßer void
15778bc019dSStefan Eßer bc_vec_expand(BcVec* restrict v, size_t req);
15844d4804dSStefan Eßer 
15944d4804dSStefan Eßer /**
16044d4804dSStefan Eßer  * Grow a vector by at least @a n elements.
16144d4804dSStefan Eßer  * @param v  The vector to grow.
16244d4804dSStefan Eßer  * @param n  The number of elements to grow the vector by.
16344d4804dSStefan Eßer  */
16478bc019dSStefan Eßer void
16578bc019dSStefan Eßer bc_vec_grow(BcVec* restrict v, size_t n);
166252884aeSStefan Eßer 
16744d4804dSStefan Eßer /**
16844d4804dSStefan Eßer  * Pops @a n items off the back of the vector. The vector must have at least
16944d4804dSStefan Eßer  * @a n elements.
17044d4804dSStefan Eßer  * @param v  The vector to pop off of.
17144d4804dSStefan Eßer  * @param n  The number of elements to pop off.
17244d4804dSStefan Eßer  */
17378bc019dSStefan Eßer void
17478bc019dSStefan Eßer bc_vec_npop(BcVec* restrict v, size_t n);
17544d4804dSStefan Eßer 
17644d4804dSStefan Eßer /**
17744d4804dSStefan Eßer  * Pops @a n items, starting at index @a idx, off the vector. The vector must
17844d4804dSStefan Eßer  * have at least @a n elements after the @a idx index. Any remaining elements at
17944d4804dSStefan Eßer  * the end are moved up to fill the hole.
18044d4804dSStefan Eßer  * @param v  The vector to pop off of.
18144d4804dSStefan Eßer  * @param n  The number of elements to pop off.
18244d4804dSStefan Eßer  * @param idx  The index to start popping at.
18344d4804dSStefan Eßer  */
18478bc019dSStefan Eßer void
18578bc019dSStefan Eßer bc_vec_npopAt(BcVec* restrict v, size_t n, size_t idx);
186252884aeSStefan Eßer 
18744d4804dSStefan Eßer /**
18844d4804dSStefan Eßer  * Pushes one item on the back of the vector. It does a memcpy(), but it assumes
18944d4804dSStefan Eßer  * that the vector takes ownership of the data.
19044d4804dSStefan Eßer  * @param v     The vector to push onto.
19144d4804dSStefan Eßer  * @param data  A pointer to the data to push.
19244d4804dSStefan Eßer  */
19378bc019dSStefan Eßer void
19478bc019dSStefan Eßer bc_vec_push(BcVec* restrict v, const void* data);
19544d4804dSStefan Eßer 
19644d4804dSStefan Eßer /**
19744d4804dSStefan Eßer  * Pushes @a n items on the back of the vector. It does a memcpy(), but it
19844d4804dSStefan Eßer  * assumes that the vector takes ownership of the data.
19944d4804dSStefan Eßer  * @param v     The vector to push onto.
20044d4804dSStefan Eßer  * @param data  A pointer to the elements of data to push.
20144d4804dSStefan Eßer  */
20278bc019dSStefan Eßer void
20378bc019dSStefan Eßer bc_vec_npush(BcVec* restrict v, size_t n, const void* data);
20444d4804dSStefan Eßer 
20544d4804dSStefan Eßer /**
20644d4804dSStefan Eßer  * Push an empty element and return a pointer to it. This is done as an
20744d4804dSStefan Eßer  * optimization where initializing an item needs a pointer anyway. It removes an
20844d4804dSStefan Eßer  * extra memcpy().
20944d4804dSStefan Eßer  * @param v  The vector to push onto.
21044d4804dSStefan Eßer  * @return   A pointer to the newly-pushed element.
21144d4804dSStefan Eßer  */
21278bc019dSStefan Eßer void*
21378bc019dSStefan Eßer bc_vec_pushEmpty(BcVec* restrict v);
21444d4804dSStefan Eßer 
21544d4804dSStefan Eßer /**
21644d4804dSStefan Eßer  * Pushes a byte onto a bytecode vector. This is a convenience function for the
21744d4804dSStefan Eßer  * parsers pushing instructions. The vector must be a bytecode vector.
21844d4804dSStefan Eßer  * @param v     The vector to push onto.
21944d4804dSStefan Eßer  * @param data  The byte to push.
22044d4804dSStefan Eßer  */
22178bc019dSStefan Eßer void
22278bc019dSStefan Eßer bc_vec_pushByte(BcVec* restrict v, uchar data);
22344d4804dSStefan Eßer 
22444d4804dSStefan Eßer /**
22544d4804dSStefan Eßer  * Pushes and index onto a bytecode vector. The vector must be a bytecode
22644d4804dSStefan Eßer  * vector. For more info about why and how this is done, see the development
22744d4804dSStefan Eßer  * manual (manuals/development#bytecode-indices).
22844d4804dSStefan Eßer  * @param v    The vector to push onto.
22944d4804dSStefan Eßer  * @param idx  The index to push.
23044d4804dSStefan Eßer  */
23178bc019dSStefan Eßer void
23278bc019dSStefan Eßer bc_vec_pushIndex(BcVec* restrict v, size_t idx);
23344d4804dSStefan Eßer 
23444d4804dSStefan Eßer /**
23544d4804dSStefan Eßer  * Push an item onto the vector at a certain index. The index must be valid
23644d4804dSStefan Eßer  * (either exists or is equal to the length of the vector). The elements at that
23744d4804dSStefan Eßer  * index and after are moved back one element and kept in the same order. This
23844d4804dSStefan Eßer  * is how the map vectors are kept sorted.
23944d4804dSStefan Eßer  * @param v     The vector to push onto.
24044d4804dSStefan Eßer  * @param data  A pointer to the data to push.
24144d4804dSStefan Eßer  * @param idx   The index to push at.
24244d4804dSStefan Eßer  */
24378bc019dSStefan Eßer void
24478bc019dSStefan Eßer bc_vec_pushAt(BcVec* restrict v, const void* data, size_t idx);
24544d4804dSStefan Eßer 
24644d4804dSStefan Eßer /**
24744d4804dSStefan Eßer  * Empties the vector and sets it to the string. The vector must be a valid
24844d4804dSStefan Eßer  * vector and must have chars as its elements.
24944d4804dSStefan Eßer  * @param v    The vector to set to the string.
25044d4804dSStefan Eßer  * @param len  The length of the string. This can be less than the actual length
25144d4804dSStefan Eßer  *             of the string, but must never be more.
25244d4804dSStefan Eßer  * @param str  The string to push.
25344d4804dSStefan Eßer  */
25478bc019dSStefan Eßer void
25578bc019dSStefan Eßer bc_vec_string(BcVec* restrict v, size_t len, const char* restrict str);
25644d4804dSStefan Eßer 
25744d4804dSStefan Eßer /**
25844d4804dSStefan Eßer  * Appends the string to the end of the vector, which must be holding a string
25944d4804dSStefan Eßer  * (nul byte-terminated) already.
26044d4804dSStefan Eßer  * @param v    The vector to append to.
26144d4804dSStefan Eßer  * @param str  The string to append (by copying).
26244d4804dSStefan Eßer  */
26378bc019dSStefan Eßer void
26478bc019dSStefan Eßer bc_vec_concat(BcVec* restrict v, const char* restrict str);
26544d4804dSStefan Eßer 
26644d4804dSStefan Eßer /**
26744d4804dSStefan Eßer  * Empties a vector and pushes a nul-byte at the first index. The vector must be
26844d4804dSStefan Eßer  * a char vector.
26944d4804dSStefan Eßer  */
27078bc019dSStefan Eßer void
27178bc019dSStefan Eßer bc_vec_empty(BcVec* restrict v);
272252884aeSStefan Eßer 
273252884aeSStefan Eßer #if BC_ENABLE_HISTORY
27444d4804dSStefan Eßer 
27544d4804dSStefan Eßer /**
27644d4804dSStefan Eßer  * Replaces an item at a particular index. No elements are moved. The index must
27744d4804dSStefan Eßer  * exist.
27844d4804dSStefan Eßer  * @param v     The vector to replace an item on.
27944d4804dSStefan Eßer  * @param idx   The index of the item to replace.
28044d4804dSStefan Eßer  * @param data  The data to replace the item with.
28144d4804dSStefan Eßer  */
28278bc019dSStefan Eßer void
28378bc019dSStefan Eßer bc_vec_replaceAt(BcVec* restrict v, size_t idx, const void* data);
28444d4804dSStefan Eßer 
285252884aeSStefan Eßer #endif // BC_ENABLE_HISTORY
286252884aeSStefan Eßer 
28744d4804dSStefan Eßer /**
28844d4804dSStefan Eßer  * Returns a pointer to the item in the vector at the index. This is the key
28944d4804dSStefan Eßer  * function for vectors. The index must exist.
29044d4804dSStefan Eßer  * @param v    The vector.
29144d4804dSStefan Eßer  * @param idx  The index to the item to get a pointer to.
29244d4804dSStefan Eßer  * @return     A pointer to the item at @a idx.
29344d4804dSStefan Eßer  */
29478bc019dSStefan Eßer void*
29578bc019dSStefan Eßer bc_vec_item(const BcVec* restrict v, size_t idx);
29644d4804dSStefan Eßer 
29744d4804dSStefan Eßer /**
29844d4804dSStefan Eßer  * Returns a pointer to the item in the vector at the index, reversed. This is
29944d4804dSStefan Eßer  * another key function for vectors. The index must exist.
30044d4804dSStefan Eßer  * @param v    The vector.
30144d4804dSStefan Eßer  * @param idx  The index to the item to get a pointer to.
30244d4804dSStefan Eßer  * @return     A pointer to the item at len - @a idx - 1.
30344d4804dSStefan Eßer  */
30478bc019dSStefan Eßer void*
30578bc019dSStefan Eßer bc_vec_item_rev(const BcVec* restrict v, size_t idx);
306252884aeSStefan Eßer 
30744d4804dSStefan Eßer /**
30844d4804dSStefan Eßer  * Zeros a vector. The vector must not be allocated.
30944d4804dSStefan Eßer  * @param v  The vector to clear.
31044d4804dSStefan Eßer  */
31178bc019dSStefan Eßer void
31278bc019dSStefan Eßer bc_vec_clear(BcVec* restrict v);
313252884aeSStefan Eßer 
31444d4804dSStefan Eßer /**
31544d4804dSStefan Eßer  * Frees a vector and its elements. This is a destructor.
31644d4804dSStefan Eßer  * @param vec  A vector as a void pointer.
31744d4804dSStefan Eßer  */
31878bc019dSStefan Eßer void
31978bc019dSStefan Eßer bc_vec_free(void* vec);
320252884aeSStefan Eßer 
32144d4804dSStefan Eßer /**
322d101cdd6SStefan Eßer  * Attempts to insert an ID into a map and returns true if it succeeded, false
32344d4804dSStefan Eßer  * if the item already exists.
32444d4804dSStefan Eßer  * @param v     The map vector to insert into.
32544d4804dSStefan Eßer  * @param name  The name of the item to insert. This name is assumed to be owned
32644d4804dSStefan Eßer  *              by another entity.
32744d4804dSStefan Eßer  * @param idx   The index of the partner array where the actual item is.
32844d4804dSStefan Eßer  * @param i     A pointer to an index that will be set to the index of the item
32944d4804dSStefan Eßer  *              in the map.
33044d4804dSStefan Eßer  * @return      True if the item was inserted, false if the item already exists.
33144d4804dSStefan Eßer  */
33278bc019dSStefan Eßer bool
33378bc019dSStefan Eßer bc_map_insert(BcVec* restrict v, const char* name, size_t idx,
33478bc019dSStefan Eßer               size_t* restrict i);
33544d4804dSStefan Eßer 
33644d4804dSStefan Eßer /**
33744d4804dSStefan Eßer  * Returns the index of the item with @a name in the map, or BC_VEC_INVALID_IDX
33844d4804dSStefan Eßer  * if it doesn't exist.
33944d4804dSStefan Eßer  * @param v     The map vector.
34044d4804dSStefan Eßer  * @param name  The name of the item to find.
34144d4804dSStefan Eßer  * @return      The index in the map of the item with @a name, or
34244d4804dSStefan Eßer  *              BC_VEC_INVALID_IDX if the item does not exist.
34344d4804dSStefan Eßer  */
34478bc019dSStefan Eßer size_t
34578bc019dSStefan Eßer bc_map_index(const BcVec* restrict v, const char* name);
346252884aeSStefan Eßer 
34744d4804dSStefan Eßer #if DC_ENABLED
34844d4804dSStefan Eßer 
34944d4804dSStefan Eßer /**
35044d4804dSStefan Eßer  * Returns the name of the item at index @a idx in the map.
35144d4804dSStefan Eßer  * @param v    The map vector.
35244d4804dSStefan Eßer  * @param idx  The index.
35344d4804dSStefan Eßer  * @return     The name of the item at @a idx.
35444d4804dSStefan Eßer  */
35578bc019dSStefan Eßer const char*
35678bc019dSStefan Eßer bc_map_name(const BcVec* restrict v, size_t idx);
35744d4804dSStefan Eßer 
35844d4804dSStefan Eßer #endif // DC_ENABLED
35944d4804dSStefan Eßer 
36044d4804dSStefan Eßer /**
36144d4804dSStefan Eßer  * Pops one item off of the vector.
36244d4804dSStefan Eßer  * @param v  The vector to pop one item off of.
36344d4804dSStefan Eßer  */
364252884aeSStefan Eßer #define bc_vec_pop(v) (bc_vec_npop((v), 1))
36544d4804dSStefan Eßer 
36644d4804dSStefan Eßer /**
36744d4804dSStefan Eßer  * Pops all items off of the vector.
36844d4804dSStefan Eßer  * @param v  The vector to pop all items off of.
36944d4804dSStefan Eßer  */
37010328f8bSStefan Eßer #define bc_vec_popAll(v) (bc_vec_npop((v), (v)->len))
37144d4804dSStefan Eßer 
37244d4804dSStefan Eßer /**
37344d4804dSStefan Eßer  * Return a pointer to the last item in the vector, or first if it's being
37444d4804dSStefan Eßer  * treated as a stack.
37544d4804dSStefan Eßer  * @param v  The vector to get the top of stack of.
37644d4804dSStefan Eßer  */
377252884aeSStefan Eßer #define bc_vec_top(v) (bc_vec_item_rev((v), 0))
378252884aeSStefan Eßer 
37944d4804dSStefan Eßer /**
38044d4804dSStefan Eßer  * Initializes a vector to serve as a map.
38144d4804dSStefan Eßer  * @param v  The vector to initialize.
38244d4804dSStefan Eßer  */
38344d4804dSStefan Eßer #define bc_map_init(v) (bc_vec_init((v), sizeof(BcId), BC_DTOR_NONE))
38444d4804dSStefan Eßer 
38544d4804dSStefan Eßer /// A reference to the array of destructors.
38644d4804dSStefan Eßer extern const BcVecFree bc_vec_dtors[];
38744d4804dSStefan Eßer 
38844d4804dSStefan Eßer #if !BC_ENABLE_LIBRARY
38944d4804dSStefan Eßer 
39044d4804dSStefan Eßer /// The allocated size of slabs.
39144d4804dSStefan Eßer #define BC_SLAB_SIZE (4096)
39244d4804dSStefan Eßer 
39344d4804dSStefan Eßer /// A slab for allocating strings.
39478bc019dSStefan Eßer typedef struct BcSlab
39578bc019dSStefan Eßer {
39644d4804dSStefan Eßer 	/// The actual allocation.
39744d4804dSStefan Eßer 	char* s;
39844d4804dSStefan Eßer 
39944d4804dSStefan Eßer 	/// How many bytes of the slab are taken.
40044d4804dSStefan Eßer 	size_t len;
40144d4804dSStefan Eßer 
40244d4804dSStefan Eßer } BcSlab;
40344d4804dSStefan Eßer 
40444d4804dSStefan Eßer /**
40544d4804dSStefan Eßer  * Frees a slab. This is a destructor.
40644d4804dSStefan Eßer  * @param slab  The slab as a void pointer.
40744d4804dSStefan Eßer  */
40878bc019dSStefan Eßer void
40978bc019dSStefan Eßer bc_slab_free(void* slab);
41044d4804dSStefan Eßer 
41144d4804dSStefan Eßer /**
41244d4804dSStefan Eßer  * Initializes a slab vector.
41344d4804dSStefan Eßer  * @param v  The vector to initialize.
41444d4804dSStefan Eßer  */
41578bc019dSStefan Eßer void
41678bc019dSStefan Eßer bc_slabvec_init(BcVec* restrict v);
41744d4804dSStefan Eßer 
41844d4804dSStefan Eßer /**
41944d4804dSStefan Eßer  * Duplicates the string using slabs in the slab vector.
42044d4804dSStefan Eßer  * @param v    The slab vector.
42144d4804dSStefan Eßer  * @param str  The string to duplicate.
42244d4804dSStefan Eßer  * @return     A pointer to the duplicated string, owned by the slab vector.
42344d4804dSStefan Eßer  */
42478bc019dSStefan Eßer char*
42578bc019dSStefan Eßer bc_slabvec_strdup(BcVec* restrict v, const char* str);
42644d4804dSStefan Eßer 
42744d4804dSStefan Eßer /**
42844d4804dSStefan Eßer  * Clears a slab vector. This deallocates all but the first slab and clears the
42944d4804dSStefan Eßer  * first slab.
43044d4804dSStefan Eßer  * @param v  The slab vector to clear.
43144d4804dSStefan Eßer  */
43278bc019dSStefan Eßer void
43378bc019dSStefan Eßer bc_slabvec_clear(BcVec* restrict v);
43444d4804dSStefan Eßer 
43544d4804dSStefan Eßer #if BC_DEBUG_CODE
43644d4804dSStefan Eßer 
43744d4804dSStefan Eßer /**
43844d4804dSStefan Eßer  * Prints all of the items in a slab vector, in order.
43944d4804dSStefan Eßer  * @param v  The vector whose items will be printed.
44044d4804dSStefan Eßer  */
44178bc019dSStefan Eßer void
44278bc019dSStefan Eßer bc_slabvec_print(BcVec* v, const char* func);
44344d4804dSStefan Eßer 
44444d4804dSStefan Eßer #endif // BC_DEBUG_CODE
44544d4804dSStefan Eßer 
44644d4804dSStefan Eßer /// A convenience macro for freeing a vector of slabs.
44744d4804dSStefan Eßer #define bc_slabvec_free bc_vec_free
44844d4804dSStefan Eßer 
44944d4804dSStefan Eßer #ifndef _WIN32
45044d4804dSStefan Eßer 
45144d4804dSStefan Eßer /**
45244d4804dSStefan Eßer  * A macro to get rid of a warning on Windows.
45344d4804dSStefan Eßer  * @param d  The destination string.
45444d4804dSStefan Eßer  * @param l  The length of the destination string. This has to be big enough to
45544d4804dSStefan Eßer  *           contain @a s.
45644d4804dSStefan Eßer  * @param s  The source string.
45744d4804dSStefan Eßer  */
458662087dfSStefan Eßer #define bc_strcpy(d, l, s) strcpy(d, s)
45944d4804dSStefan Eßer 
46044d4804dSStefan Eßer #else // _WIN32
46144d4804dSStefan Eßer 
46244d4804dSStefan Eßer /**
46344d4804dSStefan Eßer  * A macro to get rid of a warning on Windows.
46444d4804dSStefan Eßer  * @param d  The destination string.
46544d4804dSStefan Eßer  * @param l  The length of the destination string. This has to be big enough to
46644d4804dSStefan Eßer  *           contain @a s.
46744d4804dSStefan Eßer  * @param s  The source string.
46844d4804dSStefan Eßer  */
469662087dfSStefan Eßer #define bc_strcpy(d, l, s) strcpy_s(d, l, s)
47044d4804dSStefan Eßer 
47144d4804dSStefan Eßer #endif // _WIN32
47244d4804dSStefan Eßer 
47344d4804dSStefan Eßer #endif // !BC_ENABLE_LIBRARY
474252884aeSStefan Eßer 
475252884aeSStefan Eßer #endif // BC_VECTOR_H
476