#ifndef QUEUE_H #define QUEUE_H #include #include #include //This was vibecoded #FML typedef struct { void *data; size_t head; size_t tail; size_t count; size_t capacity; size_t stride; // Size of one element bool is_dynamic; } queue_t; // Public API void queue_init_static(queue_t *q, void *buffer, size_t capacity, size_t stride); bool queue_init_dynamic(queue_t *q, size_t initial_capacity, size_t stride); void queue_free(queue_t *q); bool queue_push(queue_t *q, const void *val); // The "try_push" version bool queue_pop(queue_t *q, void *out_val); bool queue_peek(queue_t *q, void *out_val); #define queue_is_empty(q) ((q)->count == 0) #define queue_is_full(q) ((q)->count == (q)->capacity) #ifdef QUEUE_IMPLEMENTATION void queue_init_static(queue_t *q, void *buffer, size_t capacity, size_t stride) { q->data = buffer; q->head = 0; q->tail = 0; q->count = 0; q->capacity = capacity; q->stride = stride; q->is_dynamic = false; } bool queue_init_dynamic(queue_t *q, size_t initial_capacity, size_t stride) { q->capacity = (initial_capacity > 0) ? initial_capacity : 8; q->stride = stride; q->data = malloc(q->capacity * q->stride); if (!q->data) return false; q->head = 0; q->tail = 0; q->count = 0; q->is_dynamic = true; return true; } void queue_free(queue_t *q) { if (q->is_dynamic && q->data) { free(q->data); } q->data = NULL; } static bool _queue_grow(queue_t *q) { size_t new_cap = q->capacity * 2; void *new_data = malloc(new_cap * q->stride); if (!new_data) return false; // Copy data in order: from head to end, then from beginning to tail for (size_t i = 0; i < q->count; ++i) { size_t old_idx = (q->head + i) % q->capacity; memcpy((char*)new_data + (i * q->stride), (char*)q->data + (old_idx * q->stride), q->stride); } if (q->is_dynamic) free(q->data); q->data = new_data; q->head = 0; q->tail = q->count; q->capacity = new_cap; q->is_dynamic = true; // Even if it was static, it's dynamic now return true; } bool queue_push(queue_t *q, const void *val) { if (queue_is_full(q)) { if (q->is_dynamic) { if (!_queue_grow(q)) return false; } else { return false; // Static queue full } } memcpy((char*)q->data + (q->tail * q->stride), val, q->stride); q->tail = (q->tail + 1) % q->capacity; q->count++; return true; } bool queue_pop(queue_t *q, void *out_val) { if (queue_is_empty(q)) return false; if (out_val) { memcpy(out_val, (char*)q->data + (q->head * q->stride), q->stride); } q->head = (q->head + 1) % q->capacity; q->count--; return true; } bool queue_peek(queue_t *q, void *out_val) { if (queue_is_empty(q)) return false; memcpy(out_val, (char*)q->data + (q->head * q->stride), q->stride); return true; } #endif // QUEUE_IMPLEMENTATION #endif // QUEUE_H