/** * Puts data into the ring buffer. If there isn't enough free space * then the ring buffer will drop the data in FIFO fashion. If you * attempt to put in more data than the ring buffer has capacity, it * will treat the data in FIFO fashion and will keep the latter portion * of the data given up to its capacity. * @param data The data to put into the buffer. * @param size The amount of data to put in from the buffer. */ size_t ring_buffer_put(struct ring_buff *rb, const void *data, size_t size) { /* If buffer size > capacity of ring buffer */ const size_t cap = ring_buffer_capacity(rb); if (size > cap) { data += size - cap; size = cap; } /* If data is getting overwritten, update tail. */ if (size > ring_buffer_bytes_free(rb)) rb->tail = get_new_ptr_val(rb, rb->tail, size + 1); const size_t dist = rb->buff - rb->head + rb->size; if (size < dist) { memcpy(rb->head, data, size); } else { void *offset = (char*) data + dist; memcpy(rb->head, data, dist); memcpy(rb->buff, offset, size - dist); } rb->head = get_new_ptr_val(rb, rb->head, size); return size; }
size_t ring_buffer_bytes_free(struct ring_buff *rb) { if (rb->tail <= rb->head) return ring_buffer_capacity(rb) - (rb->head - rb->tail); else return rb->tail - rb->head - 1; }
static void test_init_buffer_state() { RingBuffer rb; _ringbuffer_init(&rb); assert_false(ring_buffer_is_full(&rb), "buffer should not be full"); assert_true(ring_buffer_is_empty(&rb), "buffer should be empty"); assert_true(ring_buffer_count(&rb) == 0, "buffer should be empty"); assert_true(ring_buffer_capacity(&rb) == capacity, "invalid buffer capacity"); ring_buffer_free(&rb); }
size_t ring_buffer_bytes_used(struct ring_buff *rb) { return ring_buffer_capacity(rb) - ring_buffer_bytes_free(rb); }