// Author: Ershov V. // Modified: Sychov. A / 12/2020 #ifndef RING_BUFFER_H #define RING_BUFFER_H #ifdef __cplusplus extern "C" { #endif #define RING_BUFFER_HC #include "my_assert.h" #include #include #ifndef RINGBUF_ASSERT #define RINGBUF_ASSERT(CONDITION) my_assert(CONDITION) #endif #ifndef RING_BUFFER_RC_TYPE #define RING_BUFFER_RC_TYPE int16_t #endif #ifndef RING_BUFFER_SIZE_TYPE #define RING_BUFFER_SIZE_TYPE int16_t #endif #ifndef RING_BUFFER_ELEMENT_TYPE #define RING_BUFFER_ELEMENT_TYPE unsigned char #endif #ifndef RING_BUFFER_ELEMENT_SIZE #define RING_BUFFER_ELEMENT_SIZE sizeof(RING_BUFFER_ELEMENT_TYPE) #endif typedef RING_BUFFER_RC_TYPE (*pfRingbuf_predicate_t)( void * context, RING_BUFFER_ELEMENT_TYPE element); typedef void (*pfRingbuf_visitor_t)(void * context, RING_BUFFER_ELEMENT_TYPE element); typedef enum ringbuf_rc_t { RINGBUF_RC_NO_ERROR = 0, RINGBUF_RC_BAD_PARAM = -1, RINGBUF_RC_NO_DATA = -2, RINGBUF_RC_OVERFLOW = -3 }ringbuf_rc_t; typedef struct ringbuf_t { RING_BUFFER_ELEMENT_TYPE * buffer; RING_BUFFER_SIZE_TYPE capacity; RING_BUFFER_SIZE_TYPE size; RING_BUFFER_SIZE_TYPE writeIndex; RING_BUFFER_SIZE_TYPE readIndex; }ringbuf_t; /// /// \brief Initializing ring buffer. /// \param self Pointer to the ring buffer. /// \param buffer Pointer to the memory block for the ring buffer. /// \param capacity Size of the memory block. /// \return RINGBUF_RC_NO_ERROR if success, error code otherwise. /// RING_BUFFER_RC_TYPE ringbuf_init(ringbuf_t * self, void * buffer, RING_BUFFER_SIZE_TYPE capacity); /// /// \brief Getting data with size \p from ring buffer to buffer \p buffer /// without extracting them. /// \param self Pointer to the ring buffer. /// \param buffer Pointer to the buffer for storing data. /// \param size Capacity of the buffer for storing data. /// \param offset Reading offset from the begining of the ringbuf (amount of bytes to skip). /// \return size of received data or error code. /// RING_BUFFER_RC_TYPE ringbuf_peek_offset(const ringbuf_t * self, void * buffer, RING_BUFFER_SIZE_TYPE size, RING_BUFFER_SIZE_TYPE offset); /// /// \brief Getting data with size \p from ring buffer to buffer \p buffer /// without extracting them. /// \param self Pointer to the ring buffer. /// \param buffer Pointer to the buffer for storing data. /// \param size Capacity of the buffer for storing data. /// \return size of received data or error code. /// static inline RING_BUFFER_RC_TYPE ringbuf_peek(const ringbuf_t * self, void * buffer, RING_BUFFER_SIZE_TYPE size) { return ringbuf_peek_offset( self, buffer, size, 0 ); } /// /// \brief Extracting data with size \p from ring buffer to buffer \p buffer. /// \param self Pointer to the ring buffer. /// \param buffer Pointer to the buffer for storing data. /// \param size Capacity of the buffer for storing data. /// \return size of received data or error code. /// RING_BUFFER_RC_TYPE ringbuf_read(ringbuf_t * self, void * buffer, RING_BUFFER_SIZE_TYPE size); /// /// \brief Writing data in \p buffer with size \p size into the end of a ring /// buffer. /// \param self Pointer to the ring buffer. /// \param buffer Pointer to the data for writing. /// \param size Size of data for writing. /// \return Size of written data or error code. /// RING_BUFFER_RC_TYPE ringbuf_write(ringbuf_t * self, const void * buffer, RING_BUFFER_SIZE_TYPE size); /// /// \brief Writing data in \p buffer with size \p size into the front of a ring /// buffer. /// \param self Pointer to the ring buffer. /// \param buffer Pointer to the data for writing. /// \param size Size of data for writing. /// \return Size of written data or error code. /// RING_BUFFER_RC_TYPE ringbuf_write_front(ringbuf_t * self, const void * buffer, RING_BUFFER_SIZE_TYPE size); /// /// \brief Getting the first element in ring buffer without extracting it. /// \param self Pointer to the ring buffer. /// \return The first element or error code. /// RING_BUFFER_RC_TYPE ringbuf_front(const ringbuf_t * self); /// /// \brief Getting the last element in ring buffer without extracting it. /// \param self Pointer to the ring buffer. /// \return The last element or error code. /// RING_BUFFER_RC_TYPE ringbuf_back(const ringbuf_t * self); /// /// \brief Adding element to the end of ring buffer. /// \param self Pointer to the ring buffer. /// \param element Element for adding. /// \return Size of element or error code. /// RING_BUFFER_RC_TYPE ringbuf_push(ringbuf_t * self, RING_BUFFER_ELEMENT_TYPE element); /// /// \brief Extracting the first element from a ring buffer. /// \param self Pointer to the ring buffer. /// \return Extracted element or error code. /// RING_BUFFER_RC_TYPE ringbuf_pop(ringbuf_t * self); //RING_BUFFER_RC_TYPE ringbuf_push_front(ringbuf_t * self, // RING_BUFFER_ELEMENT_TYPE element); //RING_BUFFER_RC_TYPE ringbuf_pop_front(rb_t * rb); //RING_BUFFER_RC_TYPE ringbuf_push_back(ringbuf_t * self, // RING_BUFFER_ELEMENT_TYPE element); //RING_BUFFER_RC_TYPE ringbuf_pop_back(ringbuf_t * self); /// /// \brief Direct access to the underlying array. /// \param self Pointer to the ring buffer. /// \return Pointer to the underlying array. /// static inline const void * ringbuf_buffer_const(const ringbuf_t * self) { RINGBUF_ASSERT(self); return self->buffer; } /// /// \brief Direct access to the underlying array. /// \param self Pointer to the ring buffer. /// \return Pointer to the underlying array. /// static inline void * ringbuf_buffer(ringbuf_t * self) { RINGBUF_ASSERT(self); return self->buffer; } /// /// \brief Getting the sprecified by \p index element from a ring buffer. /// \param self Pointer to the ring buffer. /// \param index Position of the element to return. /// \return Requested element or error code. /// RING_BUFFER_RC_TYPE ringbuf_at(const ringbuf_t * self, RING_BUFFER_SIZE_TYPE index); /// /// \brief Checking whether the container is full. /// \param self Pointer to the ring buffer. /// \return true if conrainer if full, false otherwise. /// static inline bool ringbuf_is_full(const ringbuf_t * self) { RINGBUF_ASSERT(self); return self->size >= self->capacity; } /// /// \brief Checking whether the container is empty. /// \param self Pointer to the ring buffer. /// \return true if conrainer if empty, false otherwise. /// static inline bool ringbuf_is_empty(const ringbuf_t * self) { RINGBUF_ASSERT(self); return !self->size; } /// /// \brief Returns the number of elements that can be held in an underlying /// storage. /// \param self Pointer to the ring buffer. /// \return number of elements. /// static inline RING_BUFFER_RC_TYPE ringbuf_capacity(const ringbuf_t * self) { RINGBUF_ASSERT(self); return self->capacity; } /// /// \brief Returns the number of elements in a ring buffer. /// \param self Pointer to the ring buffer. /// \return number of elements. /// static inline RING_BUFFER_RC_TYPE ringbuf_size(const ringbuf_t * self) { RINGBUF_ASSERT(self); return self->size; } /// /// \brief Returns free space in an underlying ring buffer storage. /// \param self Pointer to the ring buffer. /// \return number of elements. /// static inline RING_BUFFER_RC_TYPE ringbuf_free_space(const ringbuf_t * self) { RINGBUF_ASSERT(self); return self->capacity - self->size; } /// /// \brief Clears the contents of ring buffer. /// \param self Pointer to the ring buffer. /// void ringbuf_clear(ringbuf_t * self); /// /// \brief Erases the first \p count element from the begging (front) of a /// ring buffer. /// \param self Pointer to the ring buffer. /// \param count Number of elements to remove. /// \return Number of removed elements. /// RING_BUFFER_RC_TYPE ringbuf_erase(ringbuf_t * self, RING_BUFFER_SIZE_TYPE count); /// /// \brief Copyies elements from \p rhs ring buffer to the end of \p lhs ring /// buffer. /// \param lhs Pointer to the ring buffer. Destination. /// \param rhs Pointer to the ring buffer. Source. /// \return number of copied elements or error code. /// RING_BUFFER_RC_TYPE ringbuf_copy(ringbuf_t * lhs, ringbuf_t * rhs); /// /// \brief Moving elements from \p rhs ring buffer to the end of \p lhs ring /// buffer. /// \note After moving procedure rhs buffer is empty (== uninitialized). /// \param lhs Pointer to the ring buffer. Destination. /// \param rhs Pointer to the ring buffer. Source. /// \return number of moved elements or error code. /// RING_BUFFER_RC_TYPE ringbuf_move(ringbuf_t * lhs, ringbuf_t * rhs); /// /// \brief Realizes search algorithm for a ring buffer container. /// \param self Pointer to the ring buffer. /// \param context Pointer to the user context. /// \param predicate Pointer to the user search functor. /// \return index of found element or error code. /// RING_BUFFER_RC_TYPE ringbuf_find(ringbuf_t * self, void * context, pfRingbuf_predicate_t predicate); /// /// \brief Realized visitor algorithm for a ring buffer container. /// \param self Pointer to the ring buffer. /// \param context Pointer to the user context. /// \param visitor Pointer to the visitor function. It is called on each /// ring buffer element. /// \return number of iterated elements or error code. /// RING_BUFFER_RC_TYPE ringbuf_visit(ringbuf_t * self, void * context, pfRingbuf_visitor_t visitor); //RING_BUFFER_RC_TYPE ringbuf_linearize(ringbuf_t * self); //RING_BUFFER_RC_TYPE ringbuf_is_linearized(ringbuf_t * self); #ifdef __cplusplus } #endif #endif