diff options
Diffstat (limited to 'kernel/collection/include')
-rw-r--r-- | kernel/collection/include/collection/rbuffer.h | 83 |
1 files changed, 53 insertions, 30 deletions
diff --git a/kernel/collection/include/collection/rbuffer.h b/kernel/collection/include/collection/rbuffer.h index dbdd6ee..01d5418 100644 --- a/kernel/collection/include/collection/rbuffer.h +++ b/kernel/collection/include/collection/rbuffer.h @@ -3,45 +3,68 @@ #include <stddef.h> -#define EEMPTY -1 -#define EFULL -2 - -typedef char rbuffer_byte_t; - struct rbuffer_t { - rbuffer_byte_t* address; - size_t size; - size_t head; - size_t tail; + char* address_begin; + char* address_end; + char* volatile head; + char* volatile tail; }; -#define RBUFFER_INIT(array, length) \ +#define RBUFFER_ARRAY_INIT(array, length) \ { \ - .address = array, \ - .size = length, \ - .head=0, \ - .tail=0 \ + .address_begin = array, \ + .address_end = array + length, \ + .head=array, \ + .tail=array \ } -void rbuffer_init(struct rbuffer_t* rb, rbuffer_byte_t* address, size_t size); +static inline int rbuffer_empty(struct rbuffer_t* const rb) { + return rb->head == rb->tail; +} + +#define __rbuffer_overlap(rb, ptr) \ + if (ptr >= rb->address_end) ptr = rb->address_begin + +static inline int rbuffer_write_char(struct rbuffer_t* const rb, char data) { + char* next_head = rb->head + 1; + __rbuffer_overlap(rb, next_head); + if (rb->tail == next_head) return 0; + *rb->head = data; + rb->head = next_head; + return 1; +} -/** Read data from ringbuffer. */ -static inline int rbuffer_read(struct rbuffer_t* const rb, rbuffer_byte_t* const data_out) { - if (rb->head == rb->tail) return EEMPTY; - *data_out = rb->address[rb->head]; - rb->head = rb->head + 1; - if (rb->head >= rb->size) rb->head=0; - return 0; +static inline int rbuffer_read_char(struct rbuffer_t* const rb, char* const data) { + if (rbuffer_empty(rb)) return 0; + *data = *rb->tail; + rb->tail += 1; + __rbuffer_overlap(rb, rb->tail); + return 1; } -static inline int rbuffer_write(struct rbuffer_t* const rb, rbuffer_byte_t data_in) { - size_t next_tail = rb->tail + 1; - if (next_tail >= rb->size) next_tail = 0; - if (rb->head == next_tail) return EFULL; - - rb->address[rb->tail] = data_in; - rb->tail = next_tail; - return 0; +static inline size_t rbuffer_write(struct rbuffer_t* const rb, const char* const data, size_t size) { + size_t wrote = 0; + for (size_t i = 0; i < size; ++i) { + if (rbuffer_write_char(rb, data[i])) { + wrote += 1; + } else { + return wrote; + } + } + return wrote; } +static inline size_t rbuffer_read(struct rbuffer_t* const rb, char* const data, size_t size) { + size_t read = 0; + for (size_t i = 0; i < size; ++i) { + if (rbuffer_read_char(rb, &data[i])) { + read += 1; + } else { + return read; + } + } + return read; +} + + #endif |