data-structures-c
Loading...
Searching...
No Matches
fstack_template.h
Go to the documentation of this file.
1// Copyright (c) 2026 abxh
2// SPDX-License-Identifier: MIT
3
8
13
14#ifdef __cplusplus
15#ifdef __GNUC__
16#define restrict __restrict__
17#else
18#define restrict
19#endif
20extern "C" {
21#endif
22
23#include <stdbool.h>
24#include <stddef.h>
25#include <stdint.h>
26
27// macro definitions: {{{
28
33#ifndef PASTE
34#define PASTE(a, b) a##b
35#endif
36
41#ifndef XPASTE
42#define XPASTE(a, b) PASTE(a, b)
43#endif
44
49#ifndef JOIN
50#define JOIN(a, b) XPASTE(a, XPASTE(_, b))
51#endif
52
63#ifndef FSTACK_FOR_EACH
64#define FSTACK_FOR_EACH(self, index, value) \
65 for ((index) = (self)->count; (index) > 0 && ((value) = (self)->values[(index) - 1], true); (index)--)
66#endif
67
78#ifndef FSTACK_FOR_EACH_REVERSE
79#define FSTACK_FOR_EACH_REVERSE(self, index, value) \
80 for ((index) = 0; (index) < (self)->count && ((value) = (self)->values[(index)], true); (index)++)
81#endif
82
93#ifndef FSTACK_CALC_SIZEOF
94#define FSTACK_CALC_SIZEOF(fstack_name, capacity) \
95 (uint32_t)(offsetof(struct fstack_name, values) + capacity * sizeof(((struct fstack_name *)0)->values[0]))
96#endif
97
108#ifndef FSTACK_CALC_SIZEOF_OVERFLOWS
109#define FSTACK_CALC_SIZEOF_OVERFLOWS(fstack_name, capacity) \
110 (capacity > (UINT32_MAX - offsetof(struct fstack_name, values)) / sizeof(((struct fstack_name *)0)->values[0]))
111#endif
112
120#ifndef NAME
121#error "Must define NAME."
122#define FUNCTION_DEFINITIONS
123#define TYPE_DEFINITIONS
124#else
125#define FSTACK_NAME NAME
126#endif
127
135#ifndef VALUE_TYPE
136#define VALUE_TYPE int
137#error "Must define VALUE_TYPE."
138#endif
139
144#ifndef FUNCTION_LINKAGE
145#define FUNCTION_LINKAGE
146#endif
147
149#define FSTACK_TYPE struct FSTACK_NAME
150#define FSTACK_IS_EMPTY JOIN(FSTACK_NAME, is_empty)
151#define FSTACK_IS_FULL JOIN(FSTACK_NAME, is_full)
152#define FSTACK_INIT JOIN(FSTACK_NAME, init)
154
155// }}}
156
157// type definitions: {{{
158
159struct FSTACK_NAME;
160
165#ifdef TYPE_DEFINITIONS
166
170struct FSTACK_NAME {
171 uint32_t count;
172 uint32_t capacity;
174};
175
176#endif
177
178// }}}
179
180// function declarations: {{{
181
188FUNCTION_LINKAGE FSTACK_TYPE *JOIN(FSTACK_NAME, init)(FSTACK_TYPE *self, const uint32_t capacity);
189
202FUNCTION_LINKAGE FSTACK_TYPE *JOIN(FSTACK_NAME,
203 create_custom)(const uint32_t capacity, void *context_ptr,
204 void *(*allocate)(void *context_ptr, size_t alignment, size_t size));
205
216FUNCTION_LINKAGE FSTACK_TYPE *JOIN(FSTACK_NAME, create)(const uint32_t capacity);
217
225FUNCTION_LINKAGE void JOIN(FSTACK_NAME, destroy_custom)(FSTACK_TYPE *self, void *context_ptr,
226 void (*deallocate)(void *context_ptr, void *mem));
227
235FUNCTION_LINKAGE void JOIN(FSTACK_NAME, destroy)(FSTACK_TYPE *self);
236
244FUNCTION_LINKAGE bool JOIN(FSTACK_NAME, is_empty)(const FSTACK_TYPE *self);
245
253FUNCTION_LINKAGE bool JOIN(FSTACK_NAME, is_full)(const FSTACK_TYPE *self);
254
266FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, at)(const FSTACK_TYPE *self, const uint32_t index);
267
275FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, get_top)(const FSTACK_TYPE *self);
276
284FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, get_bottom)(const FSTACK_TYPE *self);
285
293FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, peek)(const FSTACK_TYPE *self);
294
301FUNCTION_LINKAGE void JOIN(FSTACK_NAME, push)(FSTACK_TYPE *self, const VALUE_TYPE value);
302
310FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, pop)(FSTACK_TYPE *self);
311
317FUNCTION_LINKAGE void JOIN(FSTACK_NAME, clear)(FSTACK_TYPE *self);
318
325FUNCTION_LINKAGE void JOIN(FSTACK_NAME, copy)(FSTACK_TYPE *restrict dest_ptr, const FSTACK_TYPE *restrict src_ptr);
326
327// }}}
328
329// function definitions: {{{
330
335#ifdef FUNCTION_DEFINITIONS
336
337#include <assert.h>
338#include <stdalign.h>
339#include <stdlib.h>
340#include <string.h>
341
342FUNCTION_LINKAGE FSTACK_TYPE *JOIN(FSTACK_NAME, init)(FSTACK_TYPE *self, const uint32_t capacity)
343{
344 assert(self);
345
346 self->count = 0;
347 self->capacity = capacity;
348
349 return self;
350}
351
352FUNCTION_LINKAGE FSTACK_TYPE *JOIN(FSTACK_NAME,
353 create_custom)(const uint32_t capacity, void *context_ptr,
354 void *(*allocate)(void *context_ptr, size_t alignment, size_t size))
355{
356 if (capacity == 0 || FSTACK_CALC_SIZEOF_OVERFLOWS(FSTACK_NAME, capacity)) {
357 return NULL;
358 }
359
360 const uint32_t size = FSTACK_CALC_SIZEOF(FSTACK_NAME, capacity);
361
362 FSTACK_TYPE *self = (FSTACK_TYPE *)allocate(context_ptr, alignof(FSTACK_TYPE), size);
363
364 if (!self) {
365 return NULL;
366 }
367
368 memset(self, 0, size);
369 FSTACK_INIT(self, capacity);
370
371 return self;
372}
373
375static inline void *JOIN(internal, JOIN(FSTACK_NAME, allocate))(void *context_ptr, size_t alignment, size_t size)
376{
377 (void)context_ptr;
378 (void)alignment;
379 return malloc(size);
380}
382
383FUNCTION_LINKAGE FSTACK_TYPE *JOIN(FSTACK_NAME, create)(const uint32_t capacity)
384{
385 return JOIN(FSTACK_NAME, create_custom)(capacity, NULL, JOIN(internal, JOIN(FSTACK_NAME, allocate)));
386}
387
388FUNCTION_LINKAGE void JOIN(FSTACK_NAME, destroy_custom)(FSTACK_TYPE *self, void *context_ptr,
389 void (*deallocate)(void *context_ptr, void *mem))
390{
391 assert(self != NULL);
392
393 deallocate(context_ptr, self);
394}
395
397static inline void JOIN(internal, JOIN(FSTACK_NAME, deallocate))(void *context_ptr, void *mem)
398{
399 (void)context_ptr;
400 free(mem);
401}
403
404FUNCTION_LINKAGE void JOIN(FSTACK_NAME, destroy)(FSTACK_TYPE *self)
405{
406 assert(self != NULL);
407
408 JOIN(FSTACK_NAME, destroy_custom)(self, NULL, JOIN(internal, JOIN(FSTACK_NAME, deallocate)));
409}
410
411FUNCTION_LINKAGE bool JOIN(FSTACK_NAME, is_empty)(const FSTACK_TYPE *self)
412{
413 assert(self != NULL);
414
415 return self->count == 0;
416}
417
418FUNCTION_LINKAGE bool JOIN(FSTACK_NAME, is_full)(const FSTACK_TYPE *self)
419{
420 assert(self != NULL);
421
422 return self->count == self->capacity;
423}
424
425FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, at)(const FSTACK_TYPE *self, const uint32_t index)
426{
427 assert(self != NULL);
428 assert(index < self->count);
429
430 return self->values[self->count - 1 - index];
431}
432
433FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, get_top)(const FSTACK_TYPE *self)
434{
435 assert(self != NULL);
436 assert(FSTACK_IS_EMPTY(self) == false);
437
438 return self->values[self->count - 1];
439}
440
441FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, get_bottom)(const FSTACK_TYPE *self)
442{
443 assert(self != NULL);
444 assert(FSTACK_IS_EMPTY(self) == false);
445
446 return self->values[0];
447}
448
449FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, peek)(const FSTACK_TYPE *self)
450{
451 return JOIN(FSTACK_NAME, get_top)(self);
452}
453
454FUNCTION_LINKAGE void JOIN(FSTACK_NAME, push)(FSTACK_TYPE *self, const VALUE_TYPE value)
455{
456 assert(self != NULL);
457 assert(FSTACK_IS_FULL(self) == false);
458
459 self->values[self->count++] = value;
460}
461
462FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, pop)(FSTACK_TYPE *self)
463{
464 assert(self != NULL);
465 assert(FSTACK_IS_EMPTY(self) == false);
466
467 return self->values[--self->count];
468}
469
470FUNCTION_LINKAGE void JOIN(FSTACK_NAME, clear)(FSTACK_TYPE *self)
471{
472 assert(self != NULL);
473 self->count = 0;
474}
475
476FUNCTION_LINKAGE void JOIN(FSTACK_NAME, copy)(FSTACK_TYPE *restrict dest_ptr, const FSTACK_TYPE *restrict src_ptr)
477{
478 assert(src_ptr != NULL);
479 assert(dest_ptr != NULL);
480 assert(src_ptr->count <= dest_ptr->capacity);
481 assert(FSTACK_IS_EMPTY(dest_ptr));
482
483 for (uint32_t i = 0; i < src_ptr->count; i++) {
484 dest_ptr->values[i] = src_ptr->values[i];
485 }
486 dest_ptr->count = src_ptr->count;
487}
488
489#endif
490
491// }}}
492
493// macro undefs: {{{
494#undef NAME
495#undef VALUE_TYPE
496#undef FUNCTION_LINKAGE
497#undef FUNCTION_DEFINITIONS
498#undef TYPE_DEFINITIONS
499
500#undef FSTACK_NAME
501#undef FSTACK_TYPE
502#undef FSTACK_IS_EMPTY
503#undef FSTACK_IS_FULL
504#undef FSTACK_INIT
505
506// }}}
507
508#ifdef __cplusplus
509}
510#endif
511
512// vim: ft=c fdm=marker
#define FUNCTION_LINKAGE
Specify function linkage e.g. static inline.
Definition fstack_template.h:145
#define JOIN(a, b)
First expand tokens, then paste them together with a _ in between.
Definition fstack_template.h:50
#define VALUE_TYPE
Stack value type. This must be manually defined before including this header file.
Definition fstack_template.h:136
#define FSTACK_CALC_SIZEOF(fstack_name, capacity)
Calculate the size of the stack struct. No overflow checks.
Definition fstack_template.h:94
#define FSTACK_CALC_SIZEOF_OVERFLOWS(fstack_name, capacity)
Check for a given capacity, if the equivalent size of the stack struct overflows.
Definition fstack_template.h:109
uint32_t capacity
maximum number of values allocated for.
Definition fstack_template.h:172
VALUE_TYPE values[]
array of values.
Definition fstack_template.h:173
uint32_t count
number of values.
Definition fstack_template.h:171