13#define restrict __restrict__
34#define PASTE(a, b) a##b
42#define XPASTE(a, b) PASTE(a, b)
50#define JOIN(a, b) XPASTE(a, XPASTE(_, b))
61#define IS_POW2(X) ((X) != 0 && ((X) & ((X) - 1)) == 0)
74#ifndef FQUEUE_FOR_EACH
75#define FQUEUE_FOR_EACH(self, index, value) \
76 for ((index) = 0; (index) < (self)->count \
77 && ((value) = (self)->values[((self)->begin_index + (index)) & ((self)->capacity - 1)], true); \
91#ifndef FQUEUE_FOR_EACH_REVERSE
92#define FQUEUE_FOR_EACH_REVERSE(self, index, value) \
93 for ((index) = 0; (index) < (self)->count \
94 && ((value) = (self)->values[((self)->end_index - 1 - (index)) & ((self)->capacity - 1)], true); \
108#ifndef FQUEUE_CALC_SIZEOF
109#define FQUEUE_CALC_SIZEOF(fqueue_name, capacity) \
110 (uint32_t)(offsetof(struct fqueue_name, values) + capacity * sizeof(((struct fqueue_name *)0)->values[0]))
123#ifndef FQUEUE_CALC_SIZEOF_OVERFLOWS
124#define FQUEUE_CALC_SIZEOF_OVERFLOWS(fqueue_name, capacity) \
125 (capacity > (UINT32_MAX - offsetof(struct fqueue_name, values)) / sizeof(((struct fqueue_name *)0)->values[0]))
137#error "Must define NAME."
139#define FQUEUE_NAME NAME
150#define VALUE_TYPE int
151#define FUNCTION_DEFINITIONS
152#define TYPE_DEFINITIONS
153#error "Must define VALUE_TYPE."
160#ifndef FUNCTION_LINKAGE
161#define FUNCTION_LINKAGE
165#define FQUEUE_TYPE struct FQUEUE_NAME
166#define FQUEUE_INIT JOIN(FQUEUE_NAME, init)
167#define FQUEUE_IS_EMPTY JOIN(FQUEUE_NAME, is_empty)
168#define FQUEUE_IS_FULL JOIN(FQUEUE_NAME, is_full)
179#ifdef TYPE_DEFINITIONS
204FUNCTION_LINKAGE FQUEUE_TYPE *
JOIN(FQUEUE_NAME, init)(FQUEUE_TYPE *self,
const uint32_t pow2_capacity);
315FUNCTION_LINKAGE void JOIN(FQUEUE_NAME, copy)(FQUEUE_TYPE *restrict dest_ptr,
const FQUEUE_TYPE *restrict src_ptr);
325#ifdef FUNCTION_DEFINITIONS
327#include "round_up_pow2_32.h"
332 assert(
IS_POW2(pow2_capacity));
334 self->begin_index = self->end_index = 0;
336 self->capacity = pow2_capacity;
343 if (min_capacity == 0 || min_capacity > UINT32_MAX / 2 + 1) {
347 const uint32_t capacity = round_up_pow2_32(min_capacity);
355 FQUEUE_TYPE *self = (FQUEUE_TYPE *)calloc(1, size);
361 FQUEUE_INIT(self, capacity);
368 assert(self != NULL);
375 assert(self != NULL);
377 return self->count == 0;
382 assert(self != NULL);
384 return self->count == self->capacity;
389 assert(self != NULL);
390 assert(index < self->count);
392 const uint32_t index_mask = (self->capacity - 1);
394 return self->values[(self->begin_index + index) & index_mask];
399 assert(self != NULL);
400 assert(!FQUEUE_IS_EMPTY(self));
402 return self->values[self->begin_index];
407 assert(self != NULL);
408 assert(!FQUEUE_IS_EMPTY(self));
410 const uint32_t index_mask = (self->capacity - 1);
412 return self->values[(self->end_index - 1) & index_mask];
417 return JOIN(FQUEUE_NAME, get_front)(self);
422 assert(self != NULL);
423 assert(!FQUEUE_IS_FULL(self));
425 const uint32_t index_mask = (self->capacity - 1);
427 self->values[self->end_index] = value;
429 self->end_index &= index_mask;
437 assert(self != NULL);
438 assert(!FQUEUE_IS_EMPTY(self));
440 const uint32_t index_mask = (self->capacity - 1);
442 const VALUE_TYPE value = self->values[self->begin_index];
444 self->begin_index &= index_mask;
452 assert(self != NULL);
455 self->begin_index = self->end_index = 0;
458FUNCTION_LINKAGE void JOIN(FQUEUE_NAME, copy)(FQUEUE_TYPE *restrict dest_ptr,
const FQUEUE_TYPE *restrict src_ptr)
460 assert(src_ptr != NULL);
461 assert(dest_ptr != NULL);
462 assert(src_ptr->count <= dest_ptr->capacity);
463 assert(FQUEUE_IS_EMPTY(dest_ptr));
465 const uint32_t src_begin_index = src_ptr->begin_index;
466 const uint32_t src_index_mask = src_ptr->capacity - 1;
468 for (uint32_t i = 0; i < src_ptr->count; i++) {
469 dest_ptr->values[i] = src_ptr->values[(src_begin_index + i) & src_index_mask];
472 dest_ptr->count = src_ptr->count;
473 dest_ptr->begin_index = 0;
474 dest_ptr->end_index = src_ptr->count;
485#undef FUNCTION_LINKAGE
486#undef FUNCTION_DEFINITIONS
487#undef TYPE_DEFINITIONS
491#undef FQUEUE_CALC_SIZEOF
493#undef FQUEUE_IS_EMPTY
#define JOIN(a, b)
First expand tokens, then paste them together with a _ in between.
Definition fqueue_template.h:50
#define IS_POW2(X)
Macro to check if a number is a power of two.
Definition fqueue_template.h:61
#define FQUEUE_CALC_SIZEOF(fqueue_name, capacity)
Calculate the size of the queue struct. No overflow checks.
Definition fqueue_template.h:109
#define FQUEUE_CALC_SIZEOF_OVERFLOWS(fqueue_name, capacity)
Check for a given capacity, if the equivalent size of the queue struct overflows.
Definition fqueue_template.h:124
#define VALUE_TYPE
Queue value type. This must be manually defined before including this header file.
Definition fqueue_template.h:150
#define FUNCTION_LINKAGE
Specify function linkage e.g. static inline.
Definition fstack_template.h:146
#define VALUE_TYPE
Stack value type. This must be manually defined before including this header file.
Definition fstack_template.h:135
uint32_t count
Number of values.
Definition fqueue_template.h:187
uint32_t end_index
Index used to track the back of the queue.
Definition fqueue_template.h:186
VALUE_TYPE values[]
Array of values.
Definition fqueue_template.h:189
uint32_t begin_index
Index used to track the front of the queue.
Definition fqueue_template.h:185
uint32_t capacity
Maximum number of values allocated for.
Definition fqueue_template.h:188