ish/util/buffer.c
Theodore Dubois f1e63c43e0 Rename sys directory to kernel
A number of the headers in it were conflicting with macOS system
headers.
2017-10-13 16:54:11 -07:00

85 lines
2.0 KiB
C

#include <string.h>
#include "util/buffer.h"
#include "kernel/errno.h"
int buf_init(struct buffer *buf, size_t capacity) {
buf->data = malloc(capacity);
if (buf->data == NULL)
return _ENOMEM;
buf->capacity = capacity;
buf->start = buf->unread = 0;
pthread_mutex_init(&buf->lock, NULL);
pthread_cond_init(&buf->changed, NULL);
return 0;
}
void buf_free(struct buffer *buf) {
free(buf->data);
}
size_t buf_unread(struct buffer *buf) {
lock(buf);
size_t unread = buf->unread;
unlock(buf);
return unread;
}
size_t buf_remaining(struct buffer *buf) {
lock(buf);
size_t remaining = buf->capacity - buf->unread;
unlock(buf);
return remaining;
}
size_t buf_read(struct buffer *buf, char *str, size_t len, int flags) {
lock(buf);
while (len > buf_unread(buf)) {
if (flags & BUF_BLOCK)
wait_for(buf, changed);
else
return 0;
}
// read up to the end of the buffer
size_t len1 = len;
if (buf->start + len > buf->capacity)
len1 = buf->capacity - buf->start;
memcpy(str, buf->data + buf->start, len1);
// wrap around if necessary
memcpy(str + len1, buf->data, len - len1);
buf->start += len;
if (buf->start >= buf->capacity)
buf->start -= buf->capacity;
buf->unread -= len;
notify(buf, changed);
unlock(buf);
return len;
}
size_t buf_write(struct buffer *buf, char *str, size_t len, int flags) {
lock(buf);
while (len > buf_remaining(buf)) {
if (flags & BUF_BLOCK)
wait_for(buf, changed);
else
return 0;
}
size_t end = buf->start + buf->unread;
// copy data up to the end of the buffer
size_t len1 = len;
if (end + len > buf->capacity)
len1 = buf->capacity - end;
memcpy(buf->data + end, str, len1);
// if we have to wrap around, do so
memcpy(buf->data, str + len1, len - len1);
buf->unread += len;
notify(buf, changed);
unlock(buf);
return len;
}