#ifndef UC_RINGBUG_H_ #define UC_RINGBUG_H_ #include #ifdef __cplusplus extern "C" { #endif typedef struct UCRingBuf UCRingBuf; struct UCRingBuf { char *base; uint32_t sz; uint32_t read_idx; uint32_t write_idx; }; /** * Creates a new ringbuffer of at least @sz length. * The length will be rounded up to the neares page size * * The ringbuffer is implementd by mapping the same physical memory * twice into virtual memory adjacent to eachother, avoiding * a splitting up read/writes when the ringbuffer wraps around. * * This means accessing rb.base[rb.len] up to rb.base[rb.len * 2 - 1] * is accessing the same memory as rb.base[0] up to rb.base[rb.len -1] * * @param rb UCRingBuf to initialize * @param sz minimum length of the ring buffer * @returns 0 on success */ int uc_ringbuf_init(UCRingBuf *rb, uint32_t sz); /** Free resources used by the ring buffer. * * @return 0 on success */ int uc_ringbuf_destroy(UCRingBuf *rb); /** * Write data to the ringbuffer. The number of bytes to write must fit * in the free space of the ringbuffer * * @param rb UCRingBuf to write to. * @param data data to write * @param sz number of bytes to write from data * @return 0 on success */ int uc_ringbuf_write(UCRingBuf *rb, const void *restrict data, uint32_t sz); /** Read data from the ringbuffer * * @param rb UCRingBuf to write to. * @param data buffer to copy data into * @param sz number of bytes to read, must not exceed available data * in the buffer * @return 0 on success */ int uc_ringbuf_read(UCRingBuf *rb, void *restrict data, uint32_t sz); /** Inspect how much free space is available for writing to the ring buffer * * @param rb UCRingBuf to inspect * @returns number of free bytes */ uint32_t uc_ringbuf_available(const UCRingBuf *rb); /** * Length of available data in the ringbuffer * * @param rb UCRingBuf get length of * * @return length of data available to read */ static inline uint32_t uc_ringbuf_len(const UCRingBuf *rb) { return rb->write_idx - rb->read_idx; } /** * Get a pointer to the first unread byte * Caller is responsible for reading no more than the available * data * * @param rb UCRingBuf to peek into * * @returns pointer to first unread byte */ static inline void *uc_ringbuf_peek(const UCRingBuf *rb) { return &rb->base[rb->read_idx]; } #ifdef __cplusplus } #endif #endif