// Author: Ershov V. // Modified: Sychov. A / 12/2020 #include "ringbuffer/ring_buffer.h" #include #include #include "my_assert.h" STATIC_ASSERT(sizeof(RING_BUFFER_RC_TYPE) >= sizeof(RING_BUFFER_RC_TYPE), error); //see ringbuf_pop STATIC_ASSERT(sizeof(RING_BUFFER_RC_TYPE) > RING_BUFFER_ELEMENT_SIZE, error); //ToDo ring buffer with power of 2 buffer size RING_BUFFER_RC_TYPE ringbuf_write_s(ringbuf_t * self, const RING_BUFFER_ELEMENT_TYPE * buffer, RING_BUFFER_SIZE_TYPE size); static inline RING_BUFFER_SIZE_TYPE ringbuf_wr_index_to_tail_s(const ringbuf_t * self); static inline RING_BUFFER_SIZE_TYPE ringbuf_rd_index_to_tail_s(const ringbuf_t * self); static inline void ringbuf_add_index_s(RING_BUFFER_SIZE_TYPE * index, RING_BUFFER_SIZE_TYPE capacity, RING_BUFFER_SIZE_TYPE add); static inline void ringbuf_add_write_index_s(ringbuf_t * self, RING_BUFFER_SIZE_TYPE add); static inline void ringbuf_add_read_index_s(ringbuf_t * self, RING_BUFFER_SIZE_TYPE add); static inline void ringbuf_reset_s(ringbuf_t * self); RING_BUFFER_RC_TYPE ringbuf_init(ringbuf_t * self, void * buffer, RING_BUFFER_SIZE_TYPE capacity) { RINGBUF_ASSERT(self); if(NULL == buffer || 0 >= capacity) { return RINGBUF_RC_BAD_PARAM; } memset(self, 0x00, sizeof(*self)); self->buffer = buffer; self->capacity = capacity; return RINGBUF_RC_NO_ERROR; } RING_BUFFER_RC_TYPE ringbuf_peek_offset(const ringbuf_t * self, void * buffer, RING_BUFFER_SIZE_TYPE size, RING_BUFFER_SIZE_TYPE offset ) { RINGBUF_ASSERT(self && buffer); if(NULL == buffer || 0 >= size) { return RINGBUF_RC_BAD_PARAM; } char * buf = buffer; RING_BUFFER_RC_TYPE rc = self->size; if( offset >= rc ) { return RINGBUF_RC_NO_DATA; } if(rc > size + offset) { rc = size; } else { size = rc - offset; rc -= offset; } RING_BUFFER_SIZE_TYPE readIndex = self->readIndex; ringbuf_add_index_s(&readIndex, self->capacity, offset); while(size) { RING_BUFFER_SIZE_TYPE bytes = self->capacity - readIndex; if(bytes > size) { bytes = size; } memcpy(buf, &self->buffer[readIndex], bytes); buf += bytes; size -= bytes; ringbuf_add_index_s(&readIndex, self->capacity, bytes); } return rc; } RING_BUFFER_RC_TYPE ringbuf_read(ringbuf_t * self, void * buffer, RING_BUFFER_SIZE_TYPE size) { RINGBUF_ASSERT(self); if(NULL == buffer || 0 >= size) { return RINGBUF_RC_BAD_PARAM; } char * buf = buffer; RING_BUFFER_RC_TYPE rc = self->size; if(rc > size) { rc = size; } else { size = rc; } while(size) { RING_BUFFER_SIZE_TYPE bytes = ringbuf_rd_index_to_tail_s(self); if(bytes > size) { bytes = size; } memcpy(buf, &self->buffer[self->readIndex], bytes); buf += bytes; size -= bytes; ringbuf_add_read_index_s(self, bytes); } self->size -= rc; #if 0 // refactoring RING_BUFFER_SIZE_TYPE tail = ringbuf_bytes_to_tail_s(self); if(tail < size) { memcpy(buffer, &self->buffer[self->readIndex], tail); buffer += tail; size -= tail; self->readIndex = 0; } if(size) { memcpy(buffer, &self->buffer[self->readIndex], size); } ringbuf_add_read_index_s(self, size); self->size -= rc; #endif return rc; } RING_BUFFER_RC_TYPE ringbuf_write(ringbuf_t * self, const void * buffer, RING_BUFFER_SIZE_TYPE size) { RINGBUF_ASSERT(self); if(NULL == buffer || 0 >= size) { return RINGBUF_RC_BAD_PARAM; } RING_BUFFER_RC_TYPE rc = ringbuf_free_space(self); #if 0 // refactoring if(rc > size) { rc = size; } else { size = rc; } #endif if(size > rc) { size = rc; } return ringbuf_write_s(self, buffer, size); #if 0 // refactoring while(size) { RING_BUFFER_SIZE_TYPE bytes = ringbuf_wr_index_to_tail_s(self); if(bytes > size) { bytes = size; } memcpy(&self->buffer[self->writeIndex], buffer, bytes); buffer += bytes; size -= bytes; ringbuf_add_write_index_s(self, bytes); } self->size += rc; #endif #if 0 // refactoring RING_BUFFER_SIZE_TYPE tail = ringbuf_space_to_tail_s(self); if(tail < size) { memcpy(&self->buffer[self->writeIndex], buffer, tail); buffer += tail; size -= tail; self->writeIndex = 0; } if(size) { memcpy(&self->buffer[self->writeIndex], buffer, size); } ringbuf_add_write_index_s(self, size); self->size += rc; #endif //return rc; } RING_BUFFER_RC_TYPE ringbuf_write_front(ringbuf_t * self, const void * buffer, RING_BUFFER_SIZE_TYPE size) { RINGBUF_ASSERT(self); if(NULL == buffer || 0 >= size) { return RINGBUF_RC_BAD_PARAM; } const char * buf = buffer; RING_BUFFER_RC_TYPE rc = ringbuf_free_space(self); if(size > rc) { size = rc; } // Caching return value. rc = size; // Using read index instead of write index because it is a front writing. // Shifting read index into initial position. self->readIndex -= size; if(self->readIndex < 0) { self->readIndex += self->capacity; } RING_BUFFER_SIZE_TYPE readIndex = self->readIndex; while(size) { RING_BUFFER_SIZE_TYPE bytes = ringbuf_rd_index_to_tail_s(self); if(bytes > size) { bytes = size; } memcpy(&self->buffer[readIndex], buf, size); buf += bytes; size -= bytes; ringbuf_add_index_s(&readIndex, self->capacity, bytes); } self->size += rc; return rc; } RING_BUFFER_RC_TYPE ringbuf_front(const ringbuf_t * self) { RINGBUF_ASSERT(self); if(!self->size) { return RINGBUF_RC_NO_DATA; } return self->buffer[self->readIndex]; } RING_BUFFER_RC_TYPE ringbuf_back(const ringbuf_t * self) { RINGBUF_ASSERT(self); if(!self->size) { return RINGBUF_RC_NO_DATA; } RING_BUFFER_SIZE_TYPE readIndex = self->readIndex; ringbuf_add_index_s(&readIndex, self->capacity, self->size); return self->buffer[readIndex]; } RING_BUFFER_RC_TYPE ringbuf_push(ringbuf_t * self, RING_BUFFER_ELEMENT_TYPE element) { RINGBUF_ASSERT(self); if(!ringbuf_free_space(self)) { return RINGBUF_RC_OVERFLOW; } self->buffer[self->writeIndex] = element; ringbuf_add_write_index_s(self, 1); ++self->size; return 1; } RING_BUFFER_RC_TYPE ringbuf_pop(ringbuf_t * self) { RINGBUF_ASSERT(self); if(!self->size) { return RINGBUF_RC_NO_DATA; } RING_BUFFER_RC_TYPE rc = self->buffer[self->readIndex]; ringbuf_add_read_index_s(self, 1); --self->size; return rc; } //RING_BUFFER_RC_TYPE ringbuf_push_front(ringbuf_t * self, // RING_BUFFER_ELEMENT_TYPE element); //RING_BUFFER_RC_TYPE ringbuf_pop_front(ringbuf_t * self); //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); RING_BUFFER_RC_TYPE ringbuf_at(const ringbuf_t * self, RING_BUFFER_SIZE_TYPE index) { RINGBUF_ASSERT(self); if(index >= self->size) { return RINGBUF_RC_BAD_PARAM; } RING_BUFFER_SIZE_TYPE readIndex = self->readIndex; ringbuf_add_index_s(&readIndex, self->capacity, index); return self->buffer[readIndex]; } void ringbuf_clear(ringbuf_t * self) { RINGBUF_ASSERT(self); self->size = 0; self->writeIndex = 0; self->readIndex = 0; } RING_BUFFER_RC_TYPE ringbuf_erase(ringbuf_t * self, RING_BUFFER_SIZE_TYPE count) { RINGBUF_ASSERT(self); RING_BUFFER_RC_TYPE rc = self->size; if(rc > count) { rc = count; } else { count = rc; } ringbuf_add_read_index_s(self, rc); self->size -= rc; return rc; } RING_BUFFER_RC_TYPE ringbuf_copy(ringbuf_t * lhs, ringbuf_t * rhs) { if(NULL == lhs || NULL == rhs) { return RINGBUF_RC_BAD_PARAM; } if(ringbuf_free_space(lhs) < rhs->size) { return RINGBUF_RC_OVERFLOW; } RING_BUFFER_SIZE_TYPE size = rhs->size; RING_BUFFER_SIZE_TYPE readIndex = rhs->readIndex; while(size) { RING_BUFFER_SIZE_TYPE bytes = rhs->capacity - readIndex; if(bytes > size) { bytes = size; } size -= ringbuf_write_s(lhs, &rhs->buffer[readIndex], bytes); ringbuf_add_index_s(&readIndex, rhs->capacity, bytes); } return rhs->size; } RING_BUFFER_RC_TYPE ringbuf_move(ringbuf_t * lhs, ringbuf_t * rhs) { if(NULL == lhs || NULL == rhs) { return RINGBUF_RC_BAD_PARAM; } memcpy(lhs, rhs, sizeof(*lhs)); ringbuf_reset_s(rhs); return RINGBUF_RC_NO_ERROR; } RING_BUFFER_RC_TYPE ringbuf_find(ringbuf_t * self, void * context, pfRingbuf_predicate_t predicate) { RINGBUF_ASSERT(self); if(NULL == predicate) { return RINGBUF_RC_BAD_PARAM; } RING_BUFFER_SIZE_TYPE index = 0; RING_BUFFER_SIZE_TYPE size = self->size; RING_BUFFER_SIZE_TYPE readIndex = self->readIndex; while(size--) { if(predicate(context, self->buffer[readIndex])) { goto FEND; } ringbuf_add_index_s(&readIndex, self->capacity, 1); ++index; } index = RINGBUF_RC_NO_DATA; FEND: return index; } RING_BUFFER_RC_TYPE ringbuf_visit(ringbuf_t * self, void * context, pfRingbuf_visitor_t visitor) { RINGBUF_ASSERT(self); if(NULL == visitor) { return RINGBUF_RC_BAD_PARAM; } RING_BUFFER_SIZE_TYPE size = self->size; RING_BUFFER_SIZE_TYPE readIndex = self->readIndex; while(size--) { visitor(context, self->buffer[readIndex]); ringbuf_add_index_s(&readIndex, self->capacity, 1); } return self->size; } RING_BUFFER_RC_TYPE ringbuf_write_s(ringbuf_t * self, const RING_BUFFER_ELEMENT_TYPE * buffer, RING_BUFFER_SIZE_TYPE size) { RINGBUF_ASSERT(self && buffer && size >= 0); RING_BUFFER_RC_TYPE rc = size; while(size) { RING_BUFFER_SIZE_TYPE bytes = ringbuf_wr_index_to_tail_s(self); if(bytes > size) { bytes = size; } memcpy(&self->buffer[self->writeIndex], buffer, bytes); buffer += bytes; size -= bytes; ringbuf_add_write_index_s(self, bytes); } self->size += rc; return rc; } static inline RING_BUFFER_SIZE_TYPE ringbuf_wr_index_to_tail_s(const ringbuf_t * self) { RINGBUF_ASSERT(self); return self->capacity - self->writeIndex; } static inline RING_BUFFER_SIZE_TYPE ringbuf_rd_index_to_tail_s(const ringbuf_t * self) { RINGBUF_ASSERT(self); return self->capacity - self->readIndex; } static inline void ringbuf_add_index_s(RING_BUFFER_SIZE_TYPE * index, RING_BUFFER_SIZE_TYPE capacity, RING_BUFFER_SIZE_TYPE add) { RINGBUF_ASSERT(index && capacity > 0 && add >= 0); *index += add; if(*index >= capacity) { *index -= capacity; } } static inline void ringbuf_add_write_index_s(ringbuf_t * self, RING_BUFFER_SIZE_TYPE add) { RINGBUF_ASSERT(self); ringbuf_add_index_s(&self->writeIndex, self->capacity, add); } static inline void ringbuf_add_read_index_s(ringbuf_t * self, RING_BUFFER_SIZE_TYPE add) { RINGBUF_ASSERT(self); ringbuf_add_index_s(&self->readIndex, self->capacity, add); } static inline void ringbuf_reset_s(ringbuf_t * self) { RINGBUF_ASSERT(self); memset(self, 0x00, sizeof(*self)); }