/* ring_buffer.c */ #include "ring_buffer.h" #include #include bool rb_init(RingBuffer *rb, size_t capacity, size_t elem_size) { rb->buffer = malloc(capacity * elem_size); if (!rb->buffer) return false; rb->max = capacity; rb->sz = elem_size; rb->head = 0; rb->tail = 0; rb->full = false; return true; } void rb_free(RingBuffer *rb) { free(rb->buffer); rb->buffer = NULL; } void rb_reset(RingBuffer *rb) { rb->head = rb->tail = 0; rb->full = false; } bool rb_empty(const RingBuffer *rb) { return (!rb->full && (rb->head == rb->tail)); } bool rb_full(const RingBuffer *rb) { return rb->full; } bool rb_put(RingBuffer *rb, const void *data) { if (rb->full) return false; memcpy((char*)rb->buffer + (rb->head * rb->sz), data, rb->sz); rb->head = (rb->head + 1) % rb->max; rb->full = (rb->head == rb->tail); return true; } bool rb_get(RingBuffer *rb, void *data) { if (rb_empty(rb)) return false; memcpy(data, (char*)rb->buffer + (rb->tail * rb->sz), rb->sz); rb->full = false; rb->tail = (rb->tail + 1) % rb->max; return true; } size_t rb_size(const RingBuffer *rb) { size_t size = rb->max; if (!rb->full) { if (rb->head >= rb->tail) { size = rb->head - rb->tail; } else { size = rb->max + rb->head - rb->tail; } } return size; } size_t rb_get_bulk(RingBuffer *rb, void *data, size_t len) { if (rb_empty(rb)) { return 0; } size_t curr_size = rb_size(rb); size_t to_read = len < curr_size ? len : curr_size; // 第一次拷贝:从 tail 到缓冲区末尾 size_t cnt1 = rb->max - rb->tail; if (cnt1 > to_read) cnt1 = to_read; memcpy(data, (char*)rb->buffer + rb->tail * rb->sz, cnt1 * rb->sz); // 第二次拷贝:如果需要,从缓冲区开头继续读取 size_t cnt2 = to_read - cnt1; if (cnt2 > 0) { memcpy((char*)data + cnt1 * rb->sz, rb->buffer, cnt2 * rb->sz); } rb->tail = (rb->tail + to_read) % rb->max; rb->full = false; return to_read; } size_t rb_put_bulk(RingBuffer *rb, const void *data, size_t len) { // 如果缓冲区已满,直接返回 0 if (rb->full) { return 0; } // 计算当前可用空间(元素数) size_t curr_size = rb_size(rb); size_t avail = rb->max - curr_size; // 实际要写入的元素数 size_t to_write = len < avail ? len : avail; if (to_write == 0) { return 0; } // 第一次拷贝:从 head 开始直到缓冲区末尾 size_t cnt1 = rb->max - rb->head; if (cnt1 > to_write) { cnt1 = to_write; } memcpy((char*)rb->buffer + rb->head * rb->sz, data, cnt1 * rb->sz); // 第二次拷贝:如果还要写入,则回绕到缓冲区开头 size_t cnt2 = to_write - cnt1; if (cnt2 > 0) { memcpy(rb->buffer, (const char*)data + cnt1 * rb->sz, cnt2 * rb->sz); } // 更新 head 索引 rb->head = (rb->head + to_write) % rb->max; // 如果写满,则置 full if (to_write == avail) { rb->full = true; } return to_write; }