2026-02-20 16:12:16 +01:00

121 lines
3.1 KiB
C

#ifndef QUEUE_H
#define QUEUE_H
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
//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