/* SPDX-License-Identifier: MIT */ #pragma once #ifndef rb_size_t #define rb_size_t int #endif /** Signatures of allocators */ typedef void *(*ALLOC_T)(rb_size_t); /** Signature of memcpy */ typedef void *(*MEMCPY_T)(void *, const void *, rb_size_t); /** * @brief Ring buffer, also known as circular buffer. */ struct RingBuf { rb_size_t struct_size; /** Size of the struct */ rb_size_t capacity; /** The physical capacity of the entire ringbuf */ rb_size_t count; /** The number of elements in the buffer */ void *write_head; /** Address of the write head */ void *read_head; /** Address of the read head */ void *buffer; /** The actual data */ void *buffer_end; /** The end of the buffer */ } __attribute__((packed)); enum WriteResult { Full, WriteOk }; /** Result of a write */ enum ReadResult { Empty, ReadOk }; /** Result of a read */ /** * @brief Initialize the ring buffer * @param rb The ring buffer to initialize * @param capacity The capacity of the ring buffer * @param alloc The allocator function * @param struct_size The size of the struct * @return void */ void rb_init(struct RingBuf *rb, rb_size_t capacity, ALLOC_T alloc, rb_size_t struct_size); /** * @brief Insert data to the ring buffer * @param rb The ring buffer * @param item The item to insert * @param memcpy_fn The memcpy function * @return WriteResult */ enum WriteResult rb_push_back(struct RingBuf *rb, const void *item, MEMCPY_T memcpy_fn); /** * @brief Insert multiple data to the ring buffer * * @details This function is more efficient than calling rb_push_back multiple * times. It only advances the write head once, and attempts to write all the * memory in one go. * * If n is greater than the capacity, it will return Full. * If the full write will overflow, it will wrap around. * * If the buffer is full, it will return Full and not write * anything. * * @param rb The ring buffer * @param items The items to insert * @param memcpy_fn The memcpy function * @param n The number of items to insert * @return WriteResult */ enum WriteResult rb_push_many(struct RingBuf *rb, const void *items, MEMCPY_T memcpy_fn, rb_size_t n); /** * @brief Read data from the ring buffer * @param rb The ring buffer * @param item The item to read into * @return ReadResult */ enum ReadResult rb_pop_front(struct RingBuf *rb, void *item, MEMCPY_T memcpy_fn); /** * @brief Free the ring buffer * @param rb The ring buffer * @param free The free function */ void rb_destroy(struct RingBuf *rb, void(free)());