Add ring implementation

This commit is contained in:
Nicholas Chambers 2020-05-30 01:49:07 -05:00
parent 26ff7b226d
commit d6f8c09e17
2 changed files with 213 additions and 0 deletions

54
include/ring.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef __HALO_INCLUDE_RING_
#define __HALO_INCLUDE_RING_
#include <stddef.h>
/*
* 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

159
src/ring.c Normal file
View File

@ -0,0 +1,159 @@
#include <ring.h>
#include <stdlib.h>
/*
* 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);
}