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