diff options
Diffstat (limited to 'plugins/alsa/ringbuf.h')
-rw-r--r-- | plugins/alsa/ringbuf.h | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/plugins/alsa/ringbuf.h b/plugins/alsa/ringbuf.h new file mode 100644 index 0000000..c72bfae --- /dev/null +++ b/plugins/alsa/ringbuf.h @@ -0,0 +1,243 @@ +#ifndef INCLUDED_RINGBUF_H +#define INCLUDED_RINGBUF_H + +/* + * ringbuf.h - C ring buffer (FIFO) interface. + * + * Written in 2011 by Drew Hess <dhess-src@bothan.net>. + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to + * the public domain worldwide. This software is distributed without + * any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +/* + * A byte-addressable ring buffer FIFO implementation. + * + * The ring buffer's head pointer points to the starting location + * where data should be written when copying data *into* the buffer + * (e.g., with ringbuf_read). The ring buffer's tail pointer points to + * the starting location where data should be read when copying data + * *from* the buffer (e.g., with ringbuf_write). + */ + +#include <stddef.h> +#include <sys/types.h> + +typedef struct ringbuf_t *ringbuf_t; + +/* + * Create a new ring buffer with the given capacity (usable + * bytes). Note that the actual internal buffer size may be one or + * more bytes larger than the usable capacity, for bookkeeping. + * + * Returns the new ring buffer object, or 0 if there's not enough + * memory to fulfill the request for the given capacity. + */ +ringbuf_t +ringbuf_new(size_t capacity); + +/* + * The size of the internal buffer, in bytes. One or more bytes may be + * unusable in order to distinguish the "buffer full" state from the + * "buffer empty" state. + * + * For the usable capacity of the ring buffer, use the + * ringbuf_capacity function. + */ +size_t +ringbuf_buffer_size(const struct ringbuf_t *rb); + +/* + * Deallocate a ring buffer, and, as a side effect, set the pointer to + * 0. + */ +void +ringbuf_free(ringbuf_t *rb); + +/* + * Reset a ring buffer to its initial state (empty). + */ +void +ringbuf_reset(ringbuf_t rb); + +/* + * The usable capacity of the ring buffer, in bytes. Note that this + * value may be less than the ring buffer's internal buffer size, as + * returned by ringbuf_buffer_size. + */ +size_t +ringbuf_capacity(const struct ringbuf_t *rb); + +/* + * The number of free/available bytes in the ring buffer. This value + * is never larger than the ring buffer's usable capacity. + */ +size_t +ringbuf_bytes_free(const struct ringbuf_t *rb); + +/* + * The number of bytes currently being used in the ring buffer. This + * value is never larger than the ring buffer's usable capacity. + */ +size_t +ringbuf_bytes_used(const struct ringbuf_t *rb); + +int +ringbuf_is_full(const struct ringbuf_t *rb); + +int +ringbuf_is_empty(const struct ringbuf_t *rb); + +/* + * Const access to the head and tail pointers of the ring buffer. + */ +const void * +ringbuf_tail(const struct ringbuf_t *rb); + +const void * +ringbuf_head(const struct ringbuf_t *rb); + +/* + * Locate the first occurrence of character c (converted to an + * unsigned char) in ring buffer rb, beginning the search at offset + * bytes from the ring buffer's tail pointer. The function returns the + * offset of the character from the ring buffer's tail pointer, if + * found. If c does not occur in the ring buffer, the function returns + * the number of bytes used in the ring buffer. + * + * Note that the offset parameter and the returned offset are logical + * offsets from the tail pointer, not necessarily linear offsets. + */ +size_t +ringbuf_findchr(const struct ringbuf_t *rb, int c, size_t offset); + +/* + * Beginning at ring buffer dst's head pointer, fill the ring buffer + * with a repeating sequence of len bytes, each of value c (converted + * to an unsigned char). len can be as large as you like, but the + * function will never write more than ringbuf_buffer_size(dst) bytes + * in a single invocation, since that size will cause all bytes in the + * ring buffer to be written exactly once each. + * + * Note that if len is greater than the number of free bytes in dst, + * the ring buffer will overflow. When an overflow occurs, the state + * of the ring buffer is guaranteed to be consistent, including the + * head and tail pointers; old data will simply be overwritten in FIFO + * fashion, as needed. However, note that, if calling the function + * results in an overflow, the value of the ring buffer's tail pointer + * may be different than it was before the function was called. + * + * Returns the actual number of bytes written to dst: len, if + * len < ringbuf_buffer_size(dst), else ringbuf_buffer_size(dst). + */ +size_t +ringbuf_memset(ringbuf_t dst, int c, size_t len); + +/* + * Copy n bytes from a contiguous memory area src into the ring buffer + * dst. Returns the ring buffer's new head pointer. + * + * It is possible to copy more data from src than is available in the + * buffer; i.e., it's possible to overflow the ring buffer using this + * function. When an overflow occurs, the state of the ring buffer is + * guaranteed to be consistent, including the head and tail pointers; + * old data will simply be overwritten in FIFO fashion, as + * needed. However, note that, if calling the function results in an + * overflow, the value of the ring buffer's tail pointer may be + * different than it was before the function was called. + */ +void * +ringbuf_memcpy_into(ringbuf_t dst, const void *src, size_t count); + +/* + * This convenience function calls read(2) on the file descriptor fd, + * using the ring buffer rb as the destination buffer for the read, + * and returns the value returned by read(2). It will only call + * read(2) once, and may return a short count. + * + * It is possible to read more data from the file descriptor than is + * available in the buffer; i.e., it's possible to overflow the ring + * buffer using this function. When an overflow occurs, the state of + * the ring buffer is guaranteed to be consistent, including the head + * and tail pointers: old data will simply be overwritten in FIFO + * fashion, as needed. However, note that, if calling the function + * results in an overflow, the value of the ring buffer's tail pointer + * may be different than it was before the function was called. + */ +ssize_t +ringbuf_read(int fd, ringbuf_t rb, size_t count); + +/* + * Copy n bytes from the ring buffer src, starting from its tail + * pointer, into a contiguous memory area dst. Returns the value of + * src's tail pointer after the copy is finished. + * + * Note that this copy is destructive with respect to the ring buffer: + * the n bytes copied from the ring buffer are no longer available in + * the ring buffer after the copy is complete, and the ring buffer + * will have n more free bytes than it did before the function was + * called. + * + * This function will *not* allow the ring buffer to underflow. If + * count is greater than the number of bytes used in the ring buffer, + * no bytes are copied, and the function will return 0. + */ +void * +ringbuf_memcpy_from(void *dst, ringbuf_t src, size_t count); + +/* + * This convenience function calls write(2) on the file descriptor fd, + * using the ring buffer rb as the source buffer for writing (starting + * at the ring buffer's tail pointer), and returns the value returned + * by write(2). It will only call write(2) once, and may return a + * short count. + * + * Note that this copy is destructive with respect to the ring buffer: + * any bytes written from the ring buffer to the file descriptor are + * no longer available in the ring buffer after the copy is complete, + * and the ring buffer will have N more free bytes than it did before + * the function was called, where N is the value returned by the + * function (unless N is < 0, in which case an error occurred and no + * bytes were written). + * + * This function will *not* allow the ring buffer to underflow. If + * count is greater than the number of bytes used in the ring buffer, + * no bytes are written to the file descriptor, and the function will + * return 0. + */ +ssize_t +ringbuf_write(int fd, ringbuf_t rb, size_t count); + +/* + * Copy count bytes from ring buffer src, starting from its tail + * pointer, into ring buffer dst. Returns dst's new head pointer after + * the copy is finished. + * + * Note that this copy is destructive with respect to the ring buffer + * src: any bytes copied from src into dst are no longer available in + * src after the copy is complete, and src will have 'count' more free + * bytes than it did before the function was called. + * + * It is possible to copy more data from src than is available in dst; + * i.e., it's possible to overflow dst using this function. When an + * overflow occurs, the state of dst is guaranteed to be consistent, + * including the head and tail pointers; old data will simply be + * overwritten in FIFO fashion, as needed. However, note that, if + * calling the function results in an overflow, the value dst's tail + * pointer may be different than it was before the function was + * called. + * + * It is *not* possible to underflow src; if count is greater than the + * number of bytes used in src, no bytes are copied, and the function + * returns 0. + */ +void * +ringbuf_copy(ringbuf_t dst, ringbuf_t src, size_t count); + +#endif /* INCLUDED_RINGBUF_H */ |