diff --git a/include/ring.h b/include/ring.h new file mode 100644 index 0000000..1a9f4f7 --- /dev/null +++ b/include/ring.h @@ -0,0 +1,54 @@ +#ifndef __HALO_INCLUDE_RING_ +#define __HALO_INCLUDE_RING_ + +#include + +/* + * circular ring buffer for continous reading and writing + */ + +struct ring_t { + /* + * the current length of the unread data in the buffer + */ + + size_t buflen; + + /* + * the full buffer + */ + + char *buffer; + + /* + * the beginning of the full buffer + */ + + char *begin; + + /* + * the ending of the full buffer + */ + + char *end; + + /* + * the beginning of the unread data in the buffer + */ + + char *reader; + + /* + * the end of the unread data in the buffer + */ + + char *writer; +}; + +struct ring_t *ring_new(struct ring_t *buf, size_t len); +size_t ring_write(struct ring_t *buf, char *str, size_t orig_len); +char *ring_read(struct ring_t *buf, size_t *len); +char *ring_readln(struct ring_t *buf, size_t *len); +void ring_del(struct ring_t *buf); + +#endif diff --git a/src/ring.c b/src/ring.c new file mode 100644 index 0000000..8c7e92a --- /dev/null +++ b/src/ring.c @@ -0,0 +1,159 @@ +#include +#include + +/* + * ring_new + * build a new ring buffer object + * + * parameters: + * struct ring_t *buf - ring object (provided by user) + * size_t len - length to build the buffer + * + * returns the ring object (buf) or NULL if there is an error + */ + +struct ring_t *ring_new(struct ring_t *buf, size_t len) { + if(len < 3) { + return NULL; + } + + buf->buflen = len + 1; + buf->buffer = malloc(buf->buflen); + + if(buf->buffer == NULL) { + return NULL; + } + + buf->begin = buf->buffer; + buf->end = buf->buffer + len; + buf->writer = buf->buffer; + buf->reader = buf->buffer; + return buf; +} + +/* + * ring_write + * write data into the buffer + * + * parameters: + * struct ring_t *buf - ring object (provided by user) + * char *str - string to write to the buffer + * size_t orig_len - length of the string to write + * + * returns the number of characters left to write + */ + +size_t ring_write(struct ring_t *buf, char *str, size_t orig_len) { + size_t len = orig_len; + + while(len > 0) { + if(buf->writer == buf->end && buf->reader == buf->begin) { + break; + } else if(buf->writer == buf->end + 1) { + buf->writer = buf->begin; + } + + if(buf->writer == buf->reader - 1) { + break; + } + + *buf->writer = *str; + --len, ++str, ++buf->writer; + } + + return len; +} + +/* + * ring_read + * read data from the buffer + * + * parameters: + * struct ring_t *buf - ring object (provided by user) + * size_t *len - length of the string to read (modified to the number of characters read) + * + * returns the number of characters left to read + */ + +char *ring_read(struct ring_t *buf, size_t *len) { + char *str = malloc(*len); + size_t index = 0; + + if(str == NULL) { + return NULL; + } + + while(index < *len && buf->reader != buf->writer) { + str[index] = *buf->reader; + ++index, ++buf->reader; + + if(buf->reader == buf->end + 1) { + buf->reader = buf->begin; + } + } + + if(index == 0) { + *len = 0; + return NULL; + } else { + *len -= index; + return str; + } +} + +/* + * ring_readln + * read a line of data from the buffer + * + * parameters: + * struct ring_t *buf - ring object (provided by user) + * size_t *len - length of the line read + * + * returns the retreived line + */ + +char *ring_readln(struct ring_t *buf, size_t *len) { + *len = 0; + char *index = buf->reader; + + while(*index != '\n' && index != buf->writer) { + ++index, ++(*len); + + if(index == buf->end + 1) { + index = buf->begin; + } + } + + if(*index != '\n') { + *len = 0; + return NULL; + } else { + size_t length = *len + 1; + char *str = ring_read(buf, &length); + + if(str != NULL) { + str[*len] = '\0'; + } + + return str; + } +} + +/* + * ring_del + * delete a ring buffer object + * + * parameters: + * struct ring_t *buf - ring object (provided by user) + * + * returns nothing + */ + +void ring_del(struct ring_t *buf) { + buf->buflen = 0; + buf->begin = NULL; + buf->end = NULL; + buf->writer = NULL; + buf->reader = NULL; + free(buf->buffer); +}