diff --git a/core/include/blue/core/ringbuffer.h b/core/include/blue/core/ringbuffer.h index ff78840..ff6687b 100644 --- a/core/include/blue/core/ringbuffer.h +++ b/core/include/blue/core/ringbuffer.h @@ -1,32 +1,25 @@ -#ifndef BLUELIB_CORE_RINGBUFFER_H_ -#define BLUELIB_CORE_RINGBUFFER_H_ +#ifndef BLUE_CORE_RINGBUFFER_H_ +#define BLUE_CORE_RINGBUFFER_H_ +#include #include #include -typedef enum b_ringbuffer_flags { - B_RINGBUFFER_SELF_MALLOC = 0x01u, - B_RINGBUFFER_BUFFER_MALLOC = 0x02u, - B_RINGBUFFER_READ_LOCKED = 0x04u, - B_RINGBUFFER_WRITE_LOCKED = 0x08u, -} b_ringbuffer_flags; +B_DECLS_BEGIN; -typedef struct b_ringbuffer { - b_ringbuffer_flags r_flags; - void *r_buf, *r_opened_buf; - unsigned long r_capacity, r_opened_capacity; - unsigned long r_write_ptr, r_read_ptr; -} b_ringbuffer; +#define B_TYPE_RINGBUFFER (b_ringbuffer_get_type()) + +B_DECLARE_TYPE(b_ringbuffer); + +B_TYPE_CLASS_DECLARATION_BEGIN(b_ringbuffer) +B_TYPE_CLASS_DECLARATION_END(b_ringbuffer) + +BLUE_API b_type b_ringbuffer_get_type(void); BLUE_API b_ringbuffer *b_ringbuffer_create(size_t capacity); BLUE_API b_ringbuffer *b_ringbuffer_create_with_buffer(void *ptr, size_t capacity); -BLUE_API b_status b_ringbuffer_init(b_ringbuffer *buf, size_t capacity); -BLUE_API b_status b_ringbuffer_init_with_buffer( - b_ringbuffer *buf, void *ptr, size_t capacity); - -BLUE_API b_status b_ringbuffer_reset(b_ringbuffer *buf); -BLUE_API b_status b_ringbuffer_destroy(b_ringbuffer *buf); +BLUE_API b_status b_ringbuffer_clear(b_ringbuffer *buf); BLUE_API b_status b_ringbuffer_read( b_ringbuffer *buf, void *p, size_t count, size_t *nr_read); @@ -49,4 +42,6 @@ BLUE_API b_status b_ringbuffer_open_write_buffer( BLUE_API b_status b_ringbuffer_close_write_buffer( b_ringbuffer *buf, void **ptr, size_t nr_written); +B_DECLS_END; + #endif diff --git a/core/ringbuffer.c b/core/ringbuffer.c index d488fc2..efb4565 100644 --- a/core/ringbuffer.c +++ b/core/ringbuffer.c @@ -2,78 +2,28 @@ #include #include -#define BUF_LOCKED(buf) \ - (((buf)->r_flags & (B_RINGBUFFER_READ_LOCKED | B_RINGBUFFER_WRITE_LOCKED)) \ +#define BUF_LOCKED(buf) \ + (((buf)->r_flags & (RINGBUFFER_READ_LOCKED | RINGBUFFER_WRITE_LOCKED)) \ != 0) -struct b_ringbuffer *b_ringbuffer_create(size_t capacity) -{ - struct b_ringbuffer *buf = malloc(sizeof *buf); - if (!buf) { - return NULL; - } +/*** PRIVATE DATA *************************************************************/ - void *p = malloc(capacity); - if (!p) { - free(buf); - return NULL; - } +enum ringbuffer_flags { + RINGBUFFER_BUFFER_MALLOC = 0x02u, + RINGBUFFER_READ_LOCKED = 0x04u, + RINGBUFFER_WRITE_LOCKED = 0x08u, +}; - memset(buf, 0x0, sizeof *buf); +struct b_ringbuffer_p { + enum ringbuffer_flags r_flags; + void *r_buf, *r_opened_buf; + unsigned long r_capacity, r_opened_capacity; + unsigned long r_write_ptr, r_read_ptr; +}; - buf->r_flags = B_RINGBUFFER_SELF_MALLOC | B_RINGBUFFER_BUFFER_MALLOC; - buf->r_buf = p; - buf->r_capacity = capacity; +/*** PRIVATE FUNCTIONS ********************************************************/ - return buf; -} - -struct b_ringbuffer *b_ringbuffer_create_with_buffer(void *ptr, size_t capacity) -{ - struct b_ringbuffer *buf = malloc(sizeof *buf); - if (!buf) { - return NULL; - } - - memset(buf, 0x0, sizeof *buf); - - buf->r_flags = B_RINGBUFFER_SELF_MALLOC; - buf->r_buf = ptr; - buf->r_capacity = capacity; - - return buf; -} - -enum b_status b_ringbuffer_init(struct b_ringbuffer *buf, size_t capacity) -{ - void *p = malloc(capacity); - if (!p) { - free(buf); - return B_ERR_NO_MEMORY; - } - - memset(buf, 0x0, sizeof *buf); - - buf->r_flags = B_RINGBUFFER_BUFFER_MALLOC; - buf->r_buf = p; - buf->r_capacity = capacity; - - return B_SUCCESS; -} - -enum b_status b_ringbuffer_init_with_buffer( - struct b_ringbuffer *buf, void *ptr, size_t capacity) -{ - memset(buf, 0x0, sizeof *buf); - - buf->r_flags = 0; - buf->r_buf = ptr; - buf->r_capacity = capacity; - - return B_SUCCESS; -} - -enum b_status b_ringbuffer_reset(struct b_ringbuffer *buf) +static enum b_status ringbuffer_clear(struct b_ringbuffer_p *buf) { if (BUF_LOCKED(buf)) { return B_ERR_BUSY; @@ -84,144 +34,7 @@ enum b_status b_ringbuffer_reset(struct b_ringbuffer *buf) return B_SUCCESS; } -enum b_status b_ringbuffer_destroy(struct b_ringbuffer *buf) -{ - if (BUF_LOCKED(buf)) { - return B_ERR_BUSY; - } - - if (buf->r_flags & B_RINGBUFFER_BUFFER_MALLOC) { - free(buf->r_buf); - } - - if (buf->r_flags & B_RINGBUFFER_SELF_MALLOC) { - free(buf); - } - - return B_SUCCESS; -} - -enum b_status b_ringbuffer_read( - struct b_ringbuffer *buf, void *p, size_t count, size_t *nr_read) -{ - if (BUF_LOCKED(buf)) { - return B_ERR_BUSY; - } - - size_t r = 0; - unsigned char *dest = p; - size_t remaining = count; - - while (remaining > 0) { - const void *src; - size_t available; - enum b_status status - = b_ringbuffer_open_read_buffer(buf, &src, &available); - - if (status == B_ERR_NO_DATA) { - break; - } - - if (!B_OK(status)) { - return status; - } - - size_t to_copy = remaining; - if (to_copy > available) { - to_copy = available; - } - - memcpy(dest, src, to_copy); - - remaining -= to_copy; - dest += to_copy; - r += to_copy; - - b_ringbuffer_close_read_buffer(buf, &src, to_copy); - } - - *nr_read = r; - return B_SUCCESS; -} - -enum b_status b_ringbuffer_write( - struct b_ringbuffer *buf, const void *p, size_t count, size_t *nr_written) -{ - if (BUF_LOCKED(buf)) { - return B_ERR_BUSY; - } - - size_t w = 0; - const unsigned char *src = p; - size_t remaining = count; - - while (remaining > 0) { - void *dest; - size_t available; - enum b_status status - = b_ringbuffer_open_write_buffer(buf, &dest, &available); - - if (status == B_ERR_NO_SPACE) { - break; - } - - if (!B_OK(status)) { - return status; - } - - size_t to_copy = remaining; - if (to_copy > available) { - to_copy = available; - } - - memcpy(dest, src, to_copy); - - remaining -= to_copy; - src += to_copy; - w += to_copy; - - b_ringbuffer_close_write_buffer(buf, &dest, to_copy); - } - - *nr_written = w; - return B_SUCCESS; -} - -int b_ringbuffer_getc(struct b_ringbuffer *buf) -{ - size_t available = b_ringbuffer_available_data_remaining(buf); - if (available == 0) { - return -1; - } - - char *p = buf->r_buf; - char c = p[buf->r_read_ptr++]; - - if (buf->r_read_ptr >= buf->r_capacity) { - buf->r_read_ptr = 0; - } - - return c; -} - -enum b_status b_ringbuffer_putc(struct b_ringbuffer *buf, int c) -{ - size_t available = b_ringbuffer_write_capacity_remaining(buf); - if (available == 0) { - return B_ERR_NO_SPACE; - } - - char *p = buf->r_buf; - p[buf->r_write_ptr++] = c; - - if (buf->r_write_ptr >= buf->r_capacity) { - buf->r_write_ptr = 0; - } - - return c; -} - -size_t b_ringbuffer_write_capacity_remaining(const struct b_ringbuffer *buf) +static size_t ringbuffer_write_capacity_remaining(const struct b_ringbuffer_p *buf) { if (buf->r_read_ptr > buf->r_write_ptr) { return buf->r_read_ptr - buf->r_write_ptr - 1; @@ -230,7 +43,7 @@ size_t b_ringbuffer_write_capacity_remaining(const struct b_ringbuffer *buf) } } -size_t b_ringbuffer_available_data_remaining(const struct b_ringbuffer *buf) +static size_t ringbuffer_available_data_remaining(const struct b_ringbuffer_p *buf) { if (buf->r_read_ptr < buf->r_write_ptr) { return buf->r_write_ptr - buf->r_read_ptr; @@ -241,8 +54,8 @@ size_t b_ringbuffer_available_data_remaining(const struct b_ringbuffer *buf) } } -enum b_status b_ringbuffer_open_read_buffer( - struct b_ringbuffer *buf, const void **ptr, size_t *length) +static enum b_status ringbuffer_open_read_buffer( + struct b_ringbuffer_p *buf, const void **ptr, size_t *length) { if (BUF_LOCKED(buf)) { return B_ERR_BUSY; @@ -262,17 +75,17 @@ enum b_status b_ringbuffer_open_read_buffer( buf->r_opened_buf = (char *)buf->r_buf + buf->r_read_ptr; buf->r_opened_capacity = contiguous_capacity; - buf->r_flags |= B_RINGBUFFER_READ_LOCKED; + buf->r_flags |= RINGBUFFER_READ_LOCKED; *ptr = buf->r_opened_buf; *length = contiguous_capacity; return B_SUCCESS; } -enum b_status b_ringbuffer_close_read_buffer( - struct b_ringbuffer *buf, const void **ptr, size_t nr_read) +static enum b_status ringbuffer_close_read_buffer( + struct b_ringbuffer_p *buf, const void **ptr, size_t nr_read) { - if (!(buf->r_flags & B_RINGBUFFER_READ_LOCKED)) { + if (!(buf->r_flags & RINGBUFFER_READ_LOCKED)) { return B_ERR_BAD_STATE; } @@ -299,13 +112,13 @@ enum b_status b_ringbuffer_close_read_buffer( buf->r_opened_buf = NULL; buf->r_opened_capacity = 0; - buf->r_flags &= ~B_RINGBUFFER_READ_LOCKED; + buf->r_flags &= ~RINGBUFFER_READ_LOCKED; return B_SUCCESS; } -enum b_status b_ringbuffer_open_write_buffer( - struct b_ringbuffer *buf, void **ptr, size_t *capacity) +static enum b_status ringbuffer_open_write_buffer( + struct b_ringbuffer_p *buf, void **ptr, size_t *capacity) { if (BUF_LOCKED(buf)) { return B_ERR_BUSY; @@ -329,17 +142,17 @@ enum b_status b_ringbuffer_open_write_buffer( buf->r_opened_buf = (char *)buf->r_buf + buf->r_write_ptr; buf->r_opened_capacity = contiguous_capacity; - buf->r_flags |= B_RINGBUFFER_WRITE_LOCKED; + buf->r_flags |= RINGBUFFER_WRITE_LOCKED; *ptr = buf->r_opened_buf; *capacity = contiguous_capacity; return B_SUCCESS; } -enum b_status b_ringbuffer_close_write_buffer( - struct b_ringbuffer *buf, void **ptr, size_t nr_written) +static enum b_status ringbuffer_close_write_buffer( + struct b_ringbuffer_p *buf, void **ptr, size_t nr_written) { - if (!(buf->r_flags & B_RINGBUFFER_WRITE_LOCKED)) { + if (!(buf->r_flags & RINGBUFFER_WRITE_LOCKED)) { return B_ERR_BAD_STATE; } @@ -358,7 +171,272 @@ enum b_status b_ringbuffer_close_write_buffer( buf->r_opened_buf = NULL; buf->r_opened_capacity = 0; - buf->r_flags &= ~B_RINGBUFFER_WRITE_LOCKED; + buf->r_flags &= ~RINGBUFFER_WRITE_LOCKED; return B_SUCCESS; } + +static enum b_status ringbuffer_read( + struct b_ringbuffer_p *buf, void *p, size_t count, size_t *nr_read) +{ + if (BUF_LOCKED(buf)) { + return B_ERR_BUSY; + } + + size_t r = 0; + unsigned char *dest = p; + size_t remaining = count; + + while (remaining > 0) { + const void *src; + size_t available; + enum b_status status + = ringbuffer_open_read_buffer(buf, &src, &available); + + if (status == B_ERR_NO_DATA) { + break; + } + + if (!B_OK(status)) { + return status; + } + + size_t to_copy = remaining; + if (to_copy > available) { + to_copy = available; + } + + memcpy(dest, src, to_copy); + + remaining -= to_copy; + dest += to_copy; + r += to_copy; + + ringbuffer_close_read_buffer(buf, &src, to_copy); + } + + *nr_read = r; + return B_SUCCESS; +} + +static enum b_status ringbuffer_write( + struct b_ringbuffer_p *buf, const void *p, size_t count, size_t *nr_written) +{ + if (BUF_LOCKED(buf)) { + return B_ERR_BUSY; + } + + size_t w = 0; + const unsigned char *src = p; + size_t remaining = count; + + while (remaining > 0) { + void *dest; + size_t available; + enum b_status status + = ringbuffer_open_write_buffer(buf, &dest, &available); + + if (status == B_ERR_NO_SPACE) { + break; + } + + if (!B_OK(status)) { + return status; + } + + size_t to_copy = remaining; + if (to_copy > available) { + to_copy = available; + } + + memcpy(dest, src, to_copy); + + remaining -= to_copy; + src += to_copy; + w += to_copy; + + ringbuffer_close_write_buffer(buf, &dest, to_copy); + } + + *nr_written = w; + return B_SUCCESS; +} + +static int ringbuffer_getc(struct b_ringbuffer_p *buf) +{ + size_t available = ringbuffer_available_data_remaining(buf); + if (available == 0) { + return -1; + } + + char *p = buf->r_buf; + char c = p[buf->r_read_ptr++]; + + if (buf->r_read_ptr >= buf->r_capacity) { + buf->r_read_ptr = 0; + } + + return c; +} + +static enum b_status ringbuffer_putc(struct b_ringbuffer_p *buf, int c) +{ + size_t available = ringbuffer_write_capacity_remaining(buf); + if (available == 0) { + return B_ERR_NO_SPACE; + } + + char *p = buf->r_buf; + p[buf->r_write_ptr++] = c; + + if (buf->r_write_ptr >= buf->r_capacity) { + buf->r_write_ptr = 0; + } + + return c; +} + +/*** PUBLIC FUNCTIONS *********************************************************/ + +b_ringbuffer *b_ringbuffer_create(size_t capacity) +{ + b_ringbuffer *ringbuf = b_object_create(B_TYPE_RINGBUFFER); + if (!ringbuf) { + return NULL; + } + + struct b_ringbuffer_p *p + = b_object_get_private(ringbuf, B_TYPE_RINGBUFFER); + + void *buffer = malloc(capacity); + if (!buffer) { + b_ringbuffer_unref(ringbuf); + return NULL; + } + + p->r_flags = RINGBUFFER_BUFFER_MALLOC; + p->r_buf = buffer; + p->r_capacity = capacity; + + return ringbuf; +} + +b_ringbuffer *b_ringbuffer_create_with_buffer(void *ptr, size_t capacity) +{ + b_ringbuffer *ringbuf = b_object_create(B_TYPE_RINGBUFFER); + if (!ringbuf) { + return NULL; + } + + struct b_ringbuffer_p *p + = b_object_get_private(ringbuf, B_TYPE_RINGBUFFER); + + p->r_flags = 0; + p->r_buf = ptr; + p->r_capacity = capacity; + + return ringbuf; +} + +enum b_status b_ringbuffer_clear(b_ringbuffer *buf) +{ + B_CLASS_DISPATCH_STATIC_0(B_TYPE_RINGBUFFER, ringbuffer_clear, buf); +} + +enum b_status b_ringbuffer_read( + b_ringbuffer *buf, void *p, size_t count, size_t *nr_read) +{ + B_CLASS_DISPATCH_STATIC( + B_TYPE_RINGBUFFER, ringbuffer_read, buf, p, count, nr_read); +} + +enum b_status b_ringbuffer_write( + b_ringbuffer *buf, const void *p, size_t count, size_t *nr_written) +{ + B_CLASS_DISPATCH_STATIC( + B_TYPE_RINGBUFFER, ringbuffer_write, buf, p, count, nr_written); +} + +int b_ringbuffer_getc(b_ringbuffer *buf) +{ + B_CLASS_DISPATCH_STATIC_0(B_TYPE_RINGBUFFER, ringbuffer_getc, buf); +} + +enum b_status b_ringbuffer_putc(b_ringbuffer *buf, int c) +{ + B_CLASS_DISPATCH_STATIC(B_TYPE_RINGBUFFER, ringbuffer_putc, buf, c); +} + +size_t b_ringbuffer_write_capacity_remaining(const b_ringbuffer *buf) +{ + B_CLASS_DISPATCH_STATIC_0( + B_TYPE_RINGBUFFER, ringbuffer_write_capacity_remaining, buf); +} + +size_t b_ringbuffer_available_data_remaining(const b_ringbuffer *buf) +{ + B_CLASS_DISPATCH_STATIC_0( + B_TYPE_RINGBUFFER, ringbuffer_available_data_remaining, buf); +} + +enum b_status b_ringbuffer_open_read_buffer( + b_ringbuffer *buf, const void **ptr, size_t *length) +{ + B_CLASS_DISPATCH_STATIC( + B_TYPE_RINGBUFFER, ringbuffer_open_read_buffer, buf, ptr, length); +} + +enum b_status b_ringbuffer_close_read_buffer( + b_ringbuffer *buf, const void **ptr, size_t nr_read) +{ + B_CLASS_DISPATCH_STATIC( + B_TYPE_RINGBUFFER, ringbuffer_close_read_buffer, buf, ptr, nr_read); +} + +enum b_status b_ringbuffer_open_write_buffer( + b_ringbuffer *buf, void **ptr, size_t *capacity) +{ + B_CLASS_DISPATCH_STATIC( + B_TYPE_RINGBUFFER, ringbuffer_open_write_buffer, buf, ptr, + capacity); +} + +enum b_status b_ringbuffer_close_write_buffer( + b_ringbuffer *buf, void **ptr, size_t nr_written) +{ + B_CLASS_DISPATCH_STATIC( + B_TYPE_RINGBUFFER, ringbuffer_close_write_buffer, buf, ptr, + nr_written); +} + +/*** VIRTUAL FUNCTIONS ********************************************************/ + +static void ringbuffer_init(b_object *obj, void *priv) +{ + struct b_ringbuffer_p *buf = priv; +} + +static void ringbuffer_fini(b_object *obj, void *priv) +{ + struct b_ringbuffer_p *buf = priv; + + if (buf->r_flags & RINGBUFFER_BUFFER_MALLOC) { + free(buf->r_buf); + } +} + +/*** CLASS DEFINITION *********************************************************/ + +B_TYPE_CLASS_DEFINITION_BEGIN(b_ringbuffer) + B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT) + B_INTERFACE_ENTRY(to_string) = NULL; + B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT) +B_TYPE_CLASS_DEFINITION_END(b_ringbuffer) + +B_TYPE_DEFINITION_BEGIN(b_ringbuffer) + B_TYPE_ID(0xb0493774, 0xef13, 0x4905, 0xa865, 0x1595607ccad9); + B_TYPE_CLASS(b_ringbuffer_class); + B_TYPE_INSTANCE_PRIVATE(struct b_ringbuffer_p); + B_TYPE_INSTANCE_INIT(ringbuffer_init); + B_TYPE_INSTANCE_FINI(ringbuffer_fini); +B_TYPE_DEFINITION_END(b_ringbuffer)