/** * @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 #include #include // 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