/** * @file circbuf.h * @author Ondřej Hruška, 2016,2023 * * Circular buffer / queue / stack. * * The buffer may be used as a stack, event queue or a simple buffer. * * ------------------------------------- * * NW LR * append -> [][][][] -> pop * <- push * * NW - next write pointer (stack base) * LR - last read position (stack top) * * ------------------------------------- * * 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 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 elem_size; circbuf_size_t cap; circbuf_size_t lr; // last read pos circbuf_size_t nw; // next write pos }; 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); /** * @brief Push to front * @param cb : buffer * @param source : pointer to a value (will be copied) * @return success */ bool cbuf_push(CircBuf *cb, const void *source); /** * @brief Pop from front * @param cb : buffer * @param dest : read destination. If NULL, value is discarded. * @return success */ bool cbuf_pop(CircBuf *cb, void *dest); /** * @brief Push to end * @param cb : buffer * @param source : pointer to a value (will be copied) * @return success */ bool cbuf_push_back(CircBuf *cb, const void *source); /** * @brief Pop from end * @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 frontmost element without changing the buffer * @param cb : buffer * @param dest : read destination * @return success */ bool cbuf_peek(const 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 Remove all data from buffer */ void cbuf_clear(CircBuf *cb); #endif // CIRCBUF_H