data-structures-c
Loading...
Searching...
No Matches
fstack.h
Go to the documentation of this file.
1/* fstack.h
2 *
3 * Copyright (C) 2023 abxh
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 * See the file LICENSE included with this distribution for more
10 * information. */
11
26// macro definitions: {{{
27
28#ifndef FSTACK_H
29#define FSTACK_H
30
31#include "paste.h" // PASTE, XPASTE, JOIN
32
33#include <assert.h>
34#include <stdbool.h>
35#include <stddef.h>
36#include <stdint.h>
37#include <stdio.h>
38#include <stdlib.h>
39
50#define fstack_for_each(self, index, value) \
51 for ((index) = (self)->count; (index) > 0 && ((value) = (self)->values[(index) - 1], true); (index)--)
52
63#define fstack_for_each_reverse(self, index, value) \
64 for ((index) = 0; (index) < (self)->count && ((value) = (self)->values[(index)], true); (index)++)
65
76#define fstack_calc_sizeof(fstack_name, capacity) \
77 (uint32_t)(offsetof(struct fstack_name, values) + capacity * sizeof(((struct fstack_name *)0)->values[0]))
78
89#define fstack_calc_sizeof_overflows(fstack_name, capacity) \
90 (capacity > (UINT32_MAX - offsetof(struct fstack_name, values)) / sizeof(((struct fstack_name *)0)->values[0]))
91
92#endif // FSTACK_H
93
101#ifndef NAME
102#define NAME fstack
103#error "Must define NAME."
104#else
105#define FSTACK_NAME NAME
106#endif
107
115#ifndef VALUE_TYPE
116#define VALUE_TYPE int
117#error "Must define VALUE_TYPE."
118#endif
119
121#define FSTACK_TYPE struct FSTACK_NAME
122#define FSTACK_IS_EMPTY JOIN(FSTACK_NAME, is_empty)
123#define FSTACK_IS_FULL JOIN(FSTACK_NAME, is_full)
124#define FSTACK_INIT JOIN(FSTACK_NAME, init)
125#define FSTACK_CALC_SIZEOF JOIN(FSTACK_NAME, calc_sizeof)
127
128// }}}
129
130// type definitions: {{{
131
135struct FSTACK_NAME {
136 uint32_t count;
137 uint32_t capacity;
138 VALUE_TYPE values[];
139};
140
141// }}}
142
143// function definitions: {{{
144
151static inline FSTACK_TYPE *JOIN(FSTACK_NAME, init)(FSTACK_TYPE *self, const uint32_t capacity)
152{
153 assert(self);
154
155 self->count = 0;
156 self->capacity = capacity;
157
158 return self;
159}
160
171static inline FSTACK_TYPE *JOIN(FSTACK_NAME, create)(const uint32_t capacity)
172{
173 if (capacity == 0 || fstack_calc_sizeof_overflows(FSTACK_NAME, capacity)) {
174 return NULL;
175 }
176
177 const uint32_t size = fstack_calc_sizeof(FSTACK_NAME, capacity);
178
179 FSTACK_TYPE *self = (FSTACK_TYPE *)calloc(1, size);
180
181 if (!self) {
182 return NULL;
183 }
184
185 FSTACK_INIT(self, capacity);
186
187 return self;
188}
189
197static inline void JOIN(FSTACK_NAME, destroy)(FSTACK_TYPE *self)
198{
199 assert(self != NULL);
200
201 free(self);
202}
203
211static inline bool JOIN(FSTACK_NAME, is_empty)(const FSTACK_TYPE *self)
212{
213 assert(self != NULL);
214
215 return self->count == 0;
216}
217
225static inline bool JOIN(FSTACK_NAME, is_full)(const FSTACK_TYPE *self)
226{
227 assert(self != NULL);
228
229 return self->count == self->capacity;
230}
231
243static inline VALUE_TYPE JOIN(FSTACK_NAME, at)(const FSTACK_TYPE *self, const uint32_t index)
244{
245 assert(self != NULL);
246 assert(index < self->count);
247
248 return self->values[self->count - 1 - index];
249}
250
258static inline VALUE_TYPE JOIN(FSTACK_NAME, get_top)(const FSTACK_TYPE *self)
259{
260 assert(self != NULL);
261 assert(FSTACK_IS_EMPTY(self) == false);
262
263 return self->values[self->count - 1];
264}
265
273static inline VALUE_TYPE JOIN(FSTACK_NAME, get_bottom)(const FSTACK_TYPE *self)
274{
275 assert(self != NULL);
276 assert(FSTACK_IS_EMPTY(self) == false);
277
278 return self->values[0];
279}
280
288static inline VALUE_TYPE JOIN(FSTACK_NAME, peek)(const FSTACK_TYPE *self)
289{
290 return JOIN(FSTACK_NAME, get_top)(self);
291}
292
299static inline void JOIN(FSTACK_NAME, push)(FSTACK_TYPE *self, const VALUE_TYPE value)
300{
301 assert(self != NULL);
302 assert(FSTACK_IS_FULL(self) == false);
303
304 self->values[self->count++] = value;
305}
306
314static inline VALUE_TYPE JOIN(FSTACK_NAME, pop)(FSTACK_TYPE *self)
315{
316 assert(self != NULL);
317 assert(FSTACK_IS_EMPTY(self) == false);
318
319 return self->values[--self->count];
320}
321
327static inline void JOIN(FSTACK_NAME, clear)(FSTACK_TYPE *self)
328{
329 assert(self != NULL);
330 self->count = 0;
331}
332
339static inline void JOIN(FSTACK_NAME, copy)(FSTACK_TYPE *restrict dest_ptr, const FSTACK_TYPE *restrict src_ptr)
340{
341 assert(src_ptr != NULL);
342 assert(dest_ptr != NULL);
343 assert(src_ptr->count <= dest_ptr->capacity);
344 assert(FSTACK_IS_EMPTY(dest_ptr));
345
346 for (uint32_t i = 0; i < src_ptr->count; i++) {
347 dest_ptr->values[i] = src_ptr->values[i];
348 }
349 dest_ptr->count = src_ptr->count;
350}
351
352// }}}
353
354// macro undefs: {{{
355#undef NAME
356#undef VALUE_TYPE
357
358#undef FSTACK_NAME
359#undef FSTACK_TYPE
360#undef FSTACK_IS_EMPTY
361#undef FSTACK_IS_FULL
362#undef FSTACK_INIT
363#undef FSTACK_CALC_SIZEOF
364// }}}
365
366// vim: ft=c fdm=marker
#define VALUE_TYPE
The value type. This must be manually defined before including this header file.
Definition fhashtable.h:144
#define fstack_calc_sizeof(fstack_name, capacity)
Calculate the size of the stack struct. No overflow checks.
Definition fstack.h:76
#define VALUE_TYPE
Stack value type. This must be manually defined before including this header file.
Definition fstack.h:116
#define fstack_calc_sizeof_overflows(fstack_name, capacity)
Check for a given capacity, if the equivalent size of the stack struct overflows.
Definition fstack.h:89
C preprocessor macros for pasting tokens together.
#define JOIN(a, b)
First expand tokens, then paste them together with a _ in between.
Definition paste.h:35
uint32_t capacity
maximum number of values allocated for.
Definition fstack.h:137
uint32_t count
number of values.
Definition fstack.h:136