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#define NAME fstack
122#error "Must define NAME."
123#else
124#define FSTACK_NAME NAME
125#endif
126
134#ifndef VALUE_TYPE
135#define VALUE_TYPE int
136#define FUNCTION_DEFINITIONS
137#define TYPE_DEFINITIONS
138#error "Must define VALUE_TYPE."
139#endif
140
145#ifndef FUNCTION_LINKAGE
146#define FUNCTION_LINKAGE
147#endif
148
150#define FSTACK_TYPE struct FSTACK_NAME
151#define FSTACK_IS_EMPTY JOIN(FSTACK_NAME, is_empty)
152#define FSTACK_IS_FULL JOIN(FSTACK_NAME, is_full)
153#define FSTACK_INIT JOIN(FSTACK_NAME, init)
155
156// }}}
157
158// type definitions: {{{
159
160struct FSTACK_NAME;
161
166#ifdef TYPE_DEFINITIONS
167
171struct FSTACK_NAME {
172 uint32_t count;
173 uint32_t capacity;
175};
176
177#endif
178
179// }}}
180
181// function declarations: {{{
182
189FUNCTION_LINKAGE FSTACK_TYPE *JOIN(FSTACK_NAME, init)(FSTACK_TYPE *self, const uint32_t capacity);
190
203FUNCTION_LINKAGE FSTACK_TYPE *JOIN(FSTACK_NAME,
204 create_custom)(const uint32_t capacity, void *context_ptr,
205 void *(*allocate)(void *context_ptr, size_t alignment, size_t size));
206
217FUNCTION_LINKAGE FSTACK_TYPE *JOIN(FSTACK_NAME, create)(const uint32_t capacity);
218
226FUNCTION_LINKAGE void JOIN(FSTACK_NAME, destroy_custom)(FSTACK_TYPE *self, void *context_ptr,
227 void (*deallocate)(void *context_ptr, void *mem));
228
236FUNCTION_LINKAGE void JOIN(FSTACK_NAME, destroy)(FSTACK_TYPE *self);
237
245FUNCTION_LINKAGE bool JOIN(FSTACK_NAME, is_empty)(const FSTACK_TYPE *self);
246
254FUNCTION_LINKAGE bool JOIN(FSTACK_NAME, is_full)(const FSTACK_TYPE *self);
255
267FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, at)(const FSTACK_TYPE *self, const uint32_t index);
268
276FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, get_top)(const FSTACK_TYPE *self);
277
285FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, get_bottom)(const FSTACK_TYPE *self);
286
294FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, peek)(const FSTACK_TYPE *self);
295
302FUNCTION_LINKAGE void JOIN(FSTACK_NAME, push)(FSTACK_TYPE *self, const VALUE_TYPE value);
303
311FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, pop)(FSTACK_TYPE *self);
312
318FUNCTION_LINKAGE void JOIN(FSTACK_NAME, clear)(FSTACK_TYPE *self);
319
326FUNCTION_LINKAGE void JOIN(FSTACK_NAME, copy)(FSTACK_TYPE *restrict dest_ptr, const FSTACK_TYPE *restrict src_ptr);
327
328// }}}
329
330// function definitions: {{{
331
336#ifdef FUNCTION_DEFINITIONS
337
338#include <assert.h>
339#include <stdalign.h>
340#include <stdlib.h>
341#include <string.h>
342
343FUNCTION_LINKAGE FSTACK_TYPE *JOIN(FSTACK_NAME, init)(FSTACK_TYPE *self, const uint32_t capacity)
344{
345 assert(self);
346
347 self->count = 0;
348 self->capacity = capacity;
349
350 return self;
351}
352
353FUNCTION_LINKAGE FSTACK_TYPE *JOIN(FSTACK_NAME,
354 create_custom)(const uint32_t capacity, void *context_ptr,
355 void *(*allocate)(void *context_ptr, size_t alignment, size_t size))
356{
357 if (capacity == 0 || FSTACK_CALC_SIZEOF_OVERFLOWS(FSTACK_NAME, capacity)) {
358 return NULL;
359 }
360
361 const uint32_t size = FSTACK_CALC_SIZEOF(FSTACK_NAME, capacity);
362
363 FSTACK_TYPE *self = (FSTACK_TYPE *)allocate(context_ptr, alignof(FSTACK_TYPE), size);
364
365 if (!self) {
366 return NULL;
367 }
368
369 memset(self, 0, size);
370 FSTACK_INIT(self, capacity);
371
372 return self;
373}
374
376static inline void *JOIN(internal, JOIN(FSTACK_NAME, allocate))(void *context_ptr, size_t alignment, size_t size)
377{
378 (void)context_ptr;
379 (void)alignment;
380 return malloc(size);
381}
383
384FUNCTION_LINKAGE FSTACK_TYPE *JOIN(FSTACK_NAME, create)(const uint32_t capacity)
385{
386 return JOIN(FSTACK_NAME, create_custom)(capacity, NULL, JOIN(internal, JOIN(FSTACK_NAME, allocate)));
387}
388
389FUNCTION_LINKAGE void JOIN(FSTACK_NAME, destroy_custom)(FSTACK_TYPE *self, void *context_ptr,
390 void (*deallocate)(void *context_ptr, void *mem))
391{
392 assert(self != NULL);
393
394 deallocate(context_ptr, self);
395}
396
398static inline void JOIN(internal, JOIN(FSTACK_NAME, deallocate))(void *context_ptr, void *mem)
399{
400 (void)context_ptr;
401 free(mem);
402}
404
405FUNCTION_LINKAGE void JOIN(FSTACK_NAME, destroy)(FSTACK_TYPE *self)
406{
407 assert(self != NULL);
408
409 JOIN(FSTACK_NAME, destroy_custom)(self, NULL, JOIN(internal, JOIN(FSTACK_NAME, deallocate)));
410}
411
412FUNCTION_LINKAGE bool JOIN(FSTACK_NAME, is_empty)(const FSTACK_TYPE *self)
413{
414 assert(self != NULL);
415
416 return self->count == 0;
417}
418
419FUNCTION_LINKAGE bool JOIN(FSTACK_NAME, is_full)(const FSTACK_TYPE *self)
420{
421 assert(self != NULL);
422
423 return self->count == self->capacity;
424}
425
426FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, at)(const FSTACK_TYPE *self, const uint32_t index)
427{
428 assert(self != NULL);
429 assert(index < self->count);
430
431 return self->values[self->count - 1 - index];
432}
433
434FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, get_top)(const FSTACK_TYPE *self)
435{
436 assert(self != NULL);
437 assert(FSTACK_IS_EMPTY(self) == false);
438
439 return self->values[self->count - 1];
440}
441
442FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, get_bottom)(const FSTACK_TYPE *self)
443{
444 assert(self != NULL);
445 assert(FSTACK_IS_EMPTY(self) == false);
446
447 return self->values[0];
448}
449
450FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, peek)(const FSTACK_TYPE *self)
451{
452 return JOIN(FSTACK_NAME, get_top)(self);
453}
454
455FUNCTION_LINKAGE void JOIN(FSTACK_NAME, push)(FSTACK_TYPE *self, const VALUE_TYPE value)
456{
457 assert(self != NULL);
458 assert(FSTACK_IS_FULL(self) == false);
459
460 self->values[self->count++] = value;
461}
462
463FUNCTION_LINKAGE VALUE_TYPE JOIN(FSTACK_NAME, pop)(FSTACK_TYPE *self)
464{
465 assert(self != NULL);
466 assert(FSTACK_IS_EMPTY(self) == false);
467
468 return self->values[--self->count];
469}
470
471FUNCTION_LINKAGE void JOIN(FSTACK_NAME, clear)(FSTACK_TYPE *self)
472{
473 assert(self != NULL);
474 self->count = 0;
475}
476
477FUNCTION_LINKAGE void JOIN(FSTACK_NAME, copy)(FSTACK_TYPE *restrict dest_ptr, const FSTACK_TYPE *restrict src_ptr)
478{
479 assert(src_ptr != NULL);
480 assert(dest_ptr != NULL);
481 assert(src_ptr->count <= dest_ptr->capacity);
482 assert(FSTACK_IS_EMPTY(dest_ptr));
483
484 for (uint32_t i = 0; i < src_ptr->count; i++) {
485 dest_ptr->values[i] = src_ptr->values[i];
486 }
487 dest_ptr->count = src_ptr->count;
488}
489
490#endif
491
492// }}}
493
494// macro undefs: {{{
495#undef NAME
496#undef VALUE_TYPE
497#undef FUNCTION_LINKAGE
498#undef FUNCTION_DEFINITIONS
499#undef TYPE_DEFINITIONS
500
501#undef FSTACK_NAME
502#undef FSTACK_TYPE
503#undef FSTACK_IS_EMPTY
504#undef FSTACK_IS_FULL
505#undef FSTACK_INIT
506
507// }}}
508
509#ifdef __cplusplus
510}
511#endif
512
513// vim: ft=c fdm=marker
#define FUNCTION_LINKAGE
Specify function linkage e.g. static inline.
Definition fstack_template.h:146
#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:135
#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:173
VALUE_TYPE values[]
array of values.
Definition fstack_template.h:174
uint32_t count
number of values.
Definition fstack_template.h:172