#include "ringbuf.h" #include #include #include struct crt_ringbuf { uint8_t* buffer; size_t capacity; size_t head; size_t tail; atomic_size_t count; }; crt_ringbuf_t* crt_ringbuf_create(size_t capacity) { crt_ringbuf_t* rb = calloc(1, sizeof(crt_ringbuf_t)); if (!rb) return NULL; rb->buffer = malloc(capacity); if (!rb->buffer) { free(rb); return NULL; } rb->capacity = capacity; rb->head = 0; rb->tail = 0; atomic_init(&rb->count, 0); return rb; } void crt_ringbuf_destroy(crt_ringbuf_t* rb) { if (!rb) return; free(rb->buffer); free(rb); } bool crt_ringbuf_push(crt_ringbuf_t* rb, const void* data, size_t len) { if (!rb || !data || len == 0) return false; if (len + sizeof(size_t) > rb->capacity) return false; size_t current = atomic_load(&rb->count); if (current >= rb->capacity - len - sizeof(size_t)) return false; size_t head = rb->head; size_t needed = len + sizeof(size_t); if (head + needed <= rb->capacity) { memcpy(rb->buffer + head, &len, sizeof(size_t)); memcpy(rb->buffer + head + sizeof(size_t), data, len); rb->head = (head + needed) % rb->capacity; } else { size_t first_part = rb->capacity - head; if (first_part >= sizeof(size_t)) { memcpy(rb->buffer + head, &len, sizeof(size_t)); memcpy(rb->buffer + head + sizeof(size_t), data, first_part - sizeof(size_t)); memcpy(rb->buffer, (uint8_t*)data + first_part - sizeof(size_t), len - (first_part - sizeof(size_t))); } else { memcpy(rb->buffer + head, &len, first_part); memcpy(rb->buffer, (uint8_t*)&len + first_part, sizeof(size_t) - first_part); memcpy(rb->buffer + sizeof(size_t) - first_part, data, len); } rb->head = needed - first_part; } atomic_fetch_add(&rb->count, needed); return true; } bool crt_ringbuf_pop(crt_ringbuf_t* rb, void* out, size_t* len) { if (!rb || !out || !len) return false; if (atomic_load(&rb->count) == 0) return false; size_t tail = rb->tail; size_t stored_len; if (tail + sizeof(size_t) <= rb->capacity) { memcpy(&stored_len, rb->buffer + tail, sizeof(size_t)); } else { size_t first_part = rb->capacity - tail; memcpy(&stored_len, rb->buffer + tail, first_part); memcpy((uint8_t*)&stored_len + first_part, rb->buffer, sizeof(size_t) - first_part); } size_t total_size = stored_len + sizeof(size_t); if (tail + total_size <= rb->capacity) { memcpy(out, rb->buffer + tail + sizeof(size_t), stored_len); } else { size_t first_part = rb->capacity - tail - sizeof(size_t); memcpy(out, rb->buffer + tail + sizeof(size_t), first_part); memcpy((uint8_t*)out + first_part, rb->buffer, stored_len - first_part); } rb->tail = (tail + total_size) % rb->capacity; atomic_fetch_sub(&rb->count, total_size); *len = stored_len; return true; } bool crt_ringbuf_peek(crt_ringbuf_t* rb, void* out, size_t* len) { if (!rb || !out || !len) return false; if (atomic_load(&rb->count) == 0) return false; size_t tail = rb->tail; size_t stored_len; if (tail + sizeof(size_t) <= rb->capacity) { memcpy(&stored_len, rb->buffer + tail, sizeof(size_t)); } else { size_t first_part = rb->capacity - tail; memcpy(&stored_len, rb->buffer + tail, first_part); memcpy((uint8_t*)&stored_len + first_part, rb->buffer, sizeof(size_t) - first_part); } size_t total_size = stored_len + sizeof(size_t); if (tail + total_size <= rb->capacity) { memcpy(out, rb->buffer + tail + sizeof(size_t), stored_len); } else { size_t first_part = rb->capacity - tail - sizeof(size_t); memcpy(out, rb->buffer + tail + sizeof(size_t), first_part); memcpy((uint8_t*)out + first_part, rb->buffer, stored_len - first_part); } *len = stored_len; return true; } size_t crt_ringbuf_count(crt_ringbuf_t* rb) { return rb ? atomic_load(&rb->count) : 0; } size_t crt_ringbuf_capacity(crt_ringbuf_t* rb) { return rb ? rb->capacity : 0; } bool crt_ringbuf_empty(crt_ringbuf_t* rb) { return rb ? atomic_load(&rb->count) == 0 : true; } bool crt_ringbuf_full(crt_ringbuf_t* rb) { return rb ? atomic_load(&rb->count) >= rb->capacity : true; } void crt_ringbuf_clear(crt_ringbuf_t* rb) { if (!rb) return; rb->head = 0; rb->tail = 0; atomic_store(&rb->count, 0); }