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