aboutsummaryrefslogtreecommitdiff
path: root/kernel/collection/include/collection/rbuffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/collection/include/collection/rbuffer.h')
-rw-r--r--kernel/collection/include/collection/rbuffer.h83
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