Add ring implementation
This commit is contained in:
parent
26ff7b226d
commit
d6f8c09e17
2 changed files with 213 additions and 0 deletions
54
include/ring.h
Normal file
54
include/ring.h
Normal 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
159
src/ring.c
Normal 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);
|
||||||
|
}
|
Loading…
Reference in a new issue