generic circular buffer implementation in C
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
circbuf/circbuf_deque/circbuf.h

151 lines
3.5 KiB

/**
* @file circbuf.h
* @author Ondřej Hruška, 2016,2023
*
* Circular buffer / queue / stack.
* Slots are pre-allocated, values are copied into the buffer.
*
* The buffer may be used as a stack, event queue or a simple buffer.
*
* MIT license
*/
#ifndef CIRCBUF_H
#define CIRCBUF_H
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
// Enable to zero a freed slots after pop, useful for debugging
#define CIRCBUF_ZERO_FREE_SLOTS
// size_t can be replaced by a more suitable type for circbuf, e.g. uint8_t for tiny buffers
typedef uint32_t circbuf_size_t;
/** Instance structure - public to allow static allocation, but consider the structure internal matter */
struct circbuf_struct {
void *buf;
circbuf_size_t num_used;
circbuf_size_t elem_size;
circbuf_size_t cap;
circbuf_size_t back;
// circbuf_size_t front;
};
typedef struct circbuf_struct CircBuf;
/**
* @brief Initialize a circular buffer
*
* @param[in,out] cb - pointer to the buffer to init, can be statically or dynamically allocated
* @param buf : backing buffer, can be statically or dynamically allocated
* @param capacity : buffer capacity
* @param elem_size : size of one element
*/
void cbuf_init(CircBuf *cb, void *buf, circbuf_size_t capacity, circbuf_size_t elem_size);
/** Test for full buffer */
bool cbuf_full(const CircBuf *cb);
/** Test for empty buffer */
bool cbuf_empty(const CircBuf *cb);
/** Get the max capacity of the buffer */
circbuf_size_t cbuf_capacity(const CircBuf *cb);
/** Get the current number of items in the buffer */
circbuf_size_t cbuf_count(const CircBuf *cb);
/** Peek at the nth element (counted from back) */
bool cbuf_nth(const CircBuf *cb, circbuf_size_t num, void *dest);
/** Get a mutable reference to nth element (counted from back) */
void *cbuf_ptr_nth(const CircBuf *cb, circbuf_size_t num);
/** @brief Remove all data from buffer */
void cbuf_clear(CircBuf *cb);
/**
* @brief Append a value to the buffer (FIFO)
* @param cb : buffer
* @param source : pointer to a value (will be copied)
* @return success
*/
bool cbuf_push(CircBuf *cb, const void *source);
/**
* @brief Read a value from the buffer, return susccess.
*
* @param cb : buffer
* @param dest : read destination. If NULL, value is discarded.
* @return success
*/
bool cbuf_pop(CircBuf *cb, void *dest);
/**
* @brief Copy the frontmost element without changing the buffer
* @param cb : buffer
* @param dest : read destination
* @return success
*/
bool cbuf_peek(const CircBuf *cb, void *dest);
/**
* @brief Get a mutable reference to the front element
* @param cb : buffer
* @param dest : read destination
* @return reference or NULL
*/
void * cbuf_ptr(const CircBuf *cb);
/**
* @brief Push a value into the circbuf (LIFO).
*
* @param cb : buffer
* @param source : pointer to a value (will be copied)
* @return success
*/
bool cbuf_push_back(CircBuf *cb, const void *source);
/**
* @brief Read a value from the buffer, return susccess.
*
* @param cb : buffer
* @param dest : read destination. If NULL, value is discarded.
* @return success
*/
bool cbuf_pop_back(CircBuf *cb, void *dest);
/**
* @brief Copy the backmost element without changing the buffer
* @param cb : buffer
* @param dest : read destination
* @return success
*/
bool cbuf_peek_back(const CircBuf *cb, void *dest);
/**
* @brief Get a mutable reference to the backmost element
* @param cb : buffer
* @param dest : read destination
* @return reference or NULL
*/
void* cbuf_ptr_back(const CircBuf *cb);
#endif // CIRCBUF_H