Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/bc/include/vector.h
39534 views
1
/*
2
* *****************************************************************************
3
*
4
* SPDX-License-Identifier: BSD-2-Clause
5
*
6
* Copyright (c) 2018-2025 Gavin D. Howard and contributors.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions are met:
10
*
11
* * Redistributions of source code must retain the above copyright notice, this
12
* list of conditions and the following disclaimer.
13
*
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.
17
*
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.
29
*
30
* *****************************************************************************
31
*
32
* Definitions for bc vectors (resizable arrays).
33
*
34
*/
35
36
#ifndef BC_VECTOR_H
37
#define BC_VECTOR_H
38
39
#include <stdbool.h>
40
#include <stddef.h>
41
#include <stdint.h>
42
43
#include <status.h>
44
45
/// An invalid index for a map to mark when an item does not exist.
46
#define BC_VEC_INVALID_IDX (SIZE_MAX)
47
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)
51
52
/// An alias.
53
typedef unsigned char uchar;
54
55
/**
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.
59
*/
60
typedef void (*BcVecFree)(void* ptr);
61
62
#if BC_LONG_BIT >= 64
63
64
/// An integer to shrink the size of a vector by using these instead of size_t.
65
typedef uint32_t BcSize;
66
67
#else // BC_LONG_BIT >= 64
68
69
/// An integer to shrink the size of a vector by using these instead of size_t.
70
typedef uint16_t BcSize;
71
72
#endif // BC_LONG_BIT >= 64
73
74
/// An enum of all of the destructors. We use an enum to save space.
75
typedef enum BcDtorType
76
{
77
/// No destructor needed.
78
BC_DTOR_NONE,
79
80
/// Vector destructor.
81
BC_DTOR_VEC,
82
83
/// BcNum destructor.
84
BC_DTOR_NUM,
85
86
#if !BC_ENABLE_LIBRARY
87
88
#if BC_DEBUG
89
90
/// BcFunc destructor.
91
BC_DTOR_FUNC,
92
93
#endif // BC_DEBUG
94
95
/// BcSlab destructor.
96
BC_DTOR_SLAB,
97
98
/// BcConst destructor.
99
BC_DTOR_CONST,
100
101
/// BcResult destructor.
102
BC_DTOR_RESULT,
103
104
#if BC_ENABLE_HISTORY
105
106
/// String destructor for history, which is *special*.
107
BC_DTOR_HISTORY_STRING,
108
109
#endif // BC_ENABLE_HISTORY
110
#else // !BC_ENABLE_LIBRARY
111
112
/// Destructor for bcl numbers.
113
BC_DTOR_BCL_NUM,
114
115
#endif // !BC_ENABLE_LIBRARY
116
117
} BcDtorType;
118
119
/// The actual vector struct.
120
typedef struct BcVec
121
{
122
/// The vector array itself. This uses a char* because it is compatible with
123
/// pointers of all other types, and I can do pointer arithmetic on it.
124
char* restrict v;
125
126
/// The length of the vector, which is how many items actually exist.
127
size_t len;
128
129
/// The capacity of the vector, which is how many items can fit in the
130
/// current allocation.
131
size_t cap;
132
133
/// The size of the items in the vector, as returned by sizeof().
134
BcSize size;
135
136
/// The destructor as a BcDtorType enum.
137
BcSize dtor;
138
139
} BcVec;
140
141
/**
142
* Initializes a vector.
143
* @param v The vector to initialize.
144
* @param esize The size of the elements, as returned by sizeof().
145
* @param dtor The destructor of the elements, as a BcDtorType enum.
146
*/
147
void
148
bc_vec_init(BcVec* restrict v, size_t esize, BcDtorType dtor);
149
150
/**
151
* Expands the vector to have a capacity of @a req items, if it doesn't have
152
* enough already.
153
* @param v The vector to expand.
154
* @param req The requested capacity.
155
*/
156
void
157
bc_vec_expand(BcVec* restrict v, size_t req);
158
159
/**
160
* Grow a vector by at least @a n elements.
161
* @param v The vector to grow.
162
* @param n The number of elements to grow the vector by.
163
*/
164
void
165
bc_vec_grow(BcVec* restrict v, size_t n);
166
167
/**
168
* Pops @a n items off the back of the vector. The vector must have at least
169
* @a n elements.
170
* @param v The vector to pop off of.
171
* @param n The number of elements to pop off.
172
*/
173
void
174
bc_vec_npop(BcVec* restrict v, size_t n);
175
176
/**
177
* Pops @a n items, starting at index @a idx, off the vector. The vector must
178
* have at least @a n elements after the @a idx index. Any remaining elements at
179
* the end are moved up to fill the hole.
180
* @param v The vector to pop off of.
181
* @param n The number of elements to pop off.
182
* @param idx The index to start popping at.
183
*/
184
void
185
bc_vec_npopAt(BcVec* restrict v, size_t n, size_t idx);
186
187
/**
188
* Pushes one item on the back of the vector. It does a memcpy(), but it assumes
189
* that the vector takes ownership of the data.
190
* @param v The vector to push onto.
191
* @param data A pointer to the data to push.
192
*/
193
void
194
bc_vec_push(BcVec* restrict v, const void* data);
195
196
/**
197
* Pushes @a n items on the back of the vector. It does a memcpy(), but it
198
* assumes that the vector takes ownership of the data.
199
* @param v The vector to push onto.
200
* @param data A pointer to the elements of data to push.
201
*/
202
void
203
bc_vec_npush(BcVec* restrict v, size_t n, const void* data);
204
205
/**
206
* Push an empty element and return a pointer to it. This is done as an
207
* optimization where initializing an item needs a pointer anyway. It removes an
208
* extra memcpy().
209
* @param v The vector to push onto.
210
* @return A pointer to the newly-pushed element.
211
*/
212
void*
213
bc_vec_pushEmpty(BcVec* restrict v);
214
215
/**
216
* Pushes a byte onto a bytecode vector. This is a convenience function for the
217
* parsers pushing instructions. The vector must be a bytecode vector.
218
* @param v The vector to push onto.
219
* @param data The byte to push.
220
*/
221
void
222
bc_vec_pushByte(BcVec* restrict v, uchar data);
223
224
/**
225
* Pushes and index onto a bytecode vector. The vector must be a bytecode
226
* vector. For more info about why and how this is done, see the development
227
* manual (manuals/development#bytecode-indices).
228
* @param v The vector to push onto.
229
* @param idx The index to push.
230
*/
231
void
232
bc_vec_pushIndex(BcVec* restrict v, size_t idx);
233
234
/**
235
* Push an item onto the vector at a certain index. The index must be valid
236
* (either exists or is equal to the length of the vector). The elements at that
237
* index and after are moved back one element and kept in the same order. This
238
* is how the map vectors are kept sorted.
239
* @param v The vector to push onto.
240
* @param data A pointer to the data to push.
241
* @param idx The index to push at.
242
*/
243
void
244
bc_vec_pushAt(BcVec* restrict v, const void* data, size_t idx);
245
246
/**
247
* Empties the vector and sets it to the string. The vector must be a valid
248
* vector and must have chars as its elements.
249
* @param v The vector to set to the string.
250
* @param len The length of the string. This can be less than the actual length
251
* of the string, but must never be more.
252
* @param str The string to push.
253
*/
254
void
255
bc_vec_string(BcVec* restrict v, size_t len, const char* restrict str);
256
257
/**
258
* Appends the string to the end of the vector, which must be holding a string
259
* (nul byte-terminated) already.
260
* @param v The vector to append to.
261
* @param str The string to append (by copying).
262
*/
263
void
264
bc_vec_concat(BcVec* restrict v, const char* restrict str);
265
266
/**
267
* Empties a vector and pushes a nul-byte at the first index. The vector must be
268
* a char vector.
269
*/
270
void
271
bc_vec_empty(BcVec* restrict v);
272
273
#if BC_ENABLE_HISTORY
274
275
/**
276
* Replaces an item at a particular index. No elements are moved. The index must
277
* exist.
278
* @param v The vector to replace an item on.
279
* @param idx The index of the item to replace.
280
* @param data The data to replace the item with.
281
*/
282
void
283
bc_vec_replaceAt(BcVec* restrict v, size_t idx, const void* data);
284
285
#endif // BC_ENABLE_HISTORY
286
287
/**
288
* Returns a pointer to the item in the vector at the index. This is the key
289
* function for vectors. The index must exist.
290
* @param v The vector.
291
* @param idx The index to the item to get a pointer to.
292
* @return A pointer to the item at @a idx.
293
*/
294
void*
295
bc_vec_item(const BcVec* restrict v, size_t idx);
296
297
/**
298
* Returns a pointer to the item in the vector at the index, reversed. This is
299
* another key function for vectors. The index must exist.
300
* @param v The vector.
301
* @param idx The index to the item to get a pointer to.
302
* @return A pointer to the item at len - @a idx - 1.
303
*/
304
void*
305
bc_vec_item_rev(const BcVec* restrict v, size_t idx);
306
307
/**
308
* Zeros a vector. The vector must not be allocated.
309
* @param v The vector to clear.
310
*/
311
void
312
bc_vec_clear(BcVec* restrict v);
313
314
/**
315
* Frees a vector and its elements. This is a destructor.
316
* @param vec A vector as a void pointer.
317
*/
318
void
319
bc_vec_free(void* vec);
320
321
/**
322
* Attempts to insert an ID into a map and returns true if it succeeded, false
323
* if the item already exists.
324
* @param v The map vector to insert into.
325
* @param name The name of the item to insert. This name is assumed to be owned
326
* by another entity.
327
* @param idx The index of the partner array where the actual item is.
328
* @param i A pointer to an index that will be set to the index of the item
329
* in the map.
330
* @return True if the item was inserted, false if the item already exists.
331
*/
332
bool
333
bc_map_insert(BcVec* restrict v, const char* name, size_t idx,
334
size_t* restrict i);
335
336
/**
337
* Returns the index of the item with @a name in the map, or BC_VEC_INVALID_IDX
338
* if it doesn't exist.
339
* @param v The map vector.
340
* @param name The name of the item to find.
341
* @return The index in the map of the item with @a name, or
342
* BC_VEC_INVALID_IDX if the item does not exist.
343
*/
344
size_t
345
bc_map_index(const BcVec* restrict v, const char* name);
346
347
#if DC_ENABLED
348
349
/**
350
* Returns the name of the item at index @a idx in the map.
351
* @param v The map vector.
352
* @param idx The index.
353
* @return The name of the item at @a idx.
354
*/
355
const char*
356
bc_map_name(const BcVec* restrict v, size_t idx);
357
358
#endif // DC_ENABLED
359
360
/**
361
* Pops one item off of the vector.
362
* @param v The vector to pop one item off of.
363
*/
364
#define bc_vec_pop(v) (bc_vec_npop((v), 1))
365
366
/**
367
* Pops all items off of the vector.
368
* @param v The vector to pop all items off of.
369
*/
370
#define bc_vec_popAll(v) (bc_vec_npop((v), (v)->len))
371
372
/**
373
* Return a pointer to the last item in the vector, or first if it's being
374
* treated as a stack.
375
* @param v The vector to get the top of stack of.
376
*/
377
#define bc_vec_top(v) (bc_vec_item_rev((v), 0))
378
379
/**
380
* Initializes a vector to serve as a map.
381
* @param v The vector to initialize.
382
*/
383
#define bc_map_init(v) (bc_vec_init((v), sizeof(BcId), BC_DTOR_NONE))
384
385
/// A reference to the array of destructors.
386
extern const BcVecFree bc_vec_dtors[];
387
388
#if !BC_ENABLE_LIBRARY
389
390
/// The allocated size of slabs.
391
#define BC_SLAB_SIZE (4096)
392
393
/// A slab for allocating strings.
394
typedef struct BcSlab
395
{
396
/// The actual allocation.
397
char* s;
398
399
/// How many bytes of the slab are taken.
400
size_t len;
401
402
} BcSlab;
403
404
/**
405
* Frees a slab. This is a destructor.
406
* @param slab The slab as a void pointer.
407
*/
408
void
409
bc_slab_free(void* slab);
410
411
/**
412
* Initializes a slab vector.
413
* @param v The vector to initialize.
414
*/
415
void
416
bc_slabvec_init(BcVec* restrict v);
417
418
/**
419
* Duplicates the string using slabs in the slab vector.
420
* @param v The slab vector.
421
* @param str The string to duplicate.
422
* @return A pointer to the duplicated string, owned by the slab vector.
423
*/
424
char*
425
bc_slabvec_strdup(BcVec* restrict v, const char* str);
426
427
/**
428
* Clears a slab vector. This deallocates all but the first slab and clears the
429
* first slab.
430
* @param v The slab vector to clear.
431
*/
432
void
433
bc_slabvec_clear(BcVec* restrict v);
434
435
#if BC_DEBUG_CODE
436
437
/**
438
* Prints all of the items in a slab vector, in order.
439
* @param v The vector whose items will be printed.
440
*/
441
void
442
bc_slabvec_print(BcVec* v, const char* func);
443
444
#endif // BC_DEBUG_CODE
445
446
/// A convenience macro for freeing a vector of slabs.
447
#define bc_slabvec_free bc_vec_free
448
449
#ifndef _WIN32
450
451
/**
452
* A macro to get rid of a warning on Windows.
453
* @param d The destination string.
454
* @param l The length of the destination string. This has to be big enough to
455
* contain @a s.
456
* @param s The source string.
457
*/
458
#define bc_strcpy(d, l, s) strcpy(d, s)
459
460
#else // _WIN32
461
462
/**
463
* A macro to get rid of a warning on Windows.
464
* @param d The destination string.
465
* @param l The length of the destination string. This has to be big enough to
466
* contain @a s.
467
* @param s The source string.
468
*/
469
#define bc_strcpy(d, l, s) strcpy_s(d, l, s)
470
471
#endif // _WIN32
472
473
#endif // !BC_ENABLE_LIBRARY
474
475
#endif // BC_VECTOR_H
476
477