/* ringbuffer.h ring buffer Copyright (C) 2020 Bill Currie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to: Free Software Foundation, Inc. 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA */ #ifndef __QF_ringbuffer_h #define __QF_ringbuffer_h #define RING_BUFFER(type, size) \ struct { \ type buffer[size]; \ unsigned head; \ unsigned tail; \ } #define RB_buffer_size(ring_buffer) \ ({ __auto_type rb = (ring_buffer); \ sizeof (rb->buffer) / sizeof (rb->buffer[0]); \ }) #define RB_SPACE_AVAILABLE(ring_buffer) \ ({ __auto_type rb = &(ring_buffer); \ (rb->tail + RB_buffer_size(rb) - rb->head - 1) % RB_buffer_size(rb);\ }) #define RB_DATA_AVAILABLE(ring_buffer) \ ({ __auto_type rb = &(ring_buffer); \ (rb->head + RB_buffer_size (rb) - rb->tail) % RB_buffer_size (rb); \ }) #define RB_WRITE_DATA(ring_buffer, data, count) \ ({ __auto_type rb = &(ring_buffer); \ const typeof (rb->buffer[0]) *d = (data); \ unsigned c = (count); \ unsigned h = rb->head; \ rb->head = (h + c) % RB_buffer_size (rb); \ if (c > RB_buffer_size (rb) - h) { \ memcpy (rb->buffer + h, d, \ (RB_buffer_size (rb) - h) * sizeof (rb->buffer[0])); \ c -= RB_buffer_size (rb) - h; \ d += RB_buffer_size (rb) - h; \ h = 0; \ } \ memcpy (rb->buffer + h, d, c * sizeof (rb->buffer[0])); \ }) #define RB_READ_DATA(ring_buffer, data, count) \ ({ __auto_type rb = &(ring_buffer); \ typeof (&rb->buffer[0]) d = (data); \ unsigned c = (count); \ unsigned oc = c; \ unsigned t = rb->tail; \ if (c > RB_buffer_size (rb) - t) { \ memcpy (d, rb->buffer + t, \ (RB_buffer_size (rb) - t) * sizeof (rb->buffer[0])); \ c -= RB_buffer_size (rb) - t; \ d += RB_buffer_size (rb) - t; \ t = 0; \ } \ memcpy (d, rb->buffer + t, c * sizeof (rb->buffer[0])); \ rb->tail = (t + oc) % RB_buffer_size (rb); \ }) #define RB_DROP_DATA(ring_buffer, count) \ ({ __auto_type rb = &(ring_buffer); \ unsigned c = (count); \ unsigned t = rb->tail; \ rb->tail = (t + c) % RB_buffer_size (rb); \ }) #define RB_PEEK_DATA(ring_buffer, ahead) \ ({ __auto_type rb = &(ring_buffer); \ rb->buffer[(rb->tail + ahead) % RB_buffer_size (rb)]; \ }) #define RB_POKE_DATA(ring_buffer, ahead, data) \ ({ __auto_type rb = &(ring_buffer); \ rb->buffer[(rb->tail + ahead) % RB_buffer_size (rb)] = (data); \ }) #endif//__QF_ringbuffer_h