80 lines
1.6 KiB
C++
80 lines
1.6 KiB
C++
struct bytebuffer {
|
|
char *buf;
|
|
int len;
|
|
int cap;
|
|
};
|
|
|
|
static void bytebuffer_reserve(struct bytebuffer *b, int cap) {
|
|
if (b->cap >= cap) {
|
|
return;
|
|
}
|
|
|
|
// prefer doubling capacity
|
|
if (b->cap * 2 >= cap) {
|
|
cap = b->cap * 2;
|
|
}
|
|
|
|
char *newbuf = malloc(cap);
|
|
if (b->len > 0) {
|
|
// copy what was there, b->len > 0 assumes b->buf != null
|
|
memcpy(newbuf, b->buf, b->len);
|
|
}
|
|
if (b->buf) {
|
|
// in case there was an allocated buffer, free it
|
|
free(b->buf);
|
|
}
|
|
b->buf = newbuf;
|
|
b->cap = cap;
|
|
}
|
|
|
|
static void bytebuffer_init(struct bytebuffer *b, int cap) {
|
|
b->cap = 0;
|
|
b->len = 0;
|
|
b->buf = 0;
|
|
|
|
if (cap > 0) {
|
|
b->cap = cap;
|
|
b->buf = malloc(cap); // just assume malloc works always
|
|
}
|
|
}
|
|
|
|
static void bytebuffer_free(struct bytebuffer *b) {
|
|
if (b->buf)
|
|
free(b->buf);
|
|
}
|
|
|
|
static void bytebuffer_clear(struct bytebuffer *b) {
|
|
b->len = 0;
|
|
}
|
|
|
|
static void bytebuffer_append(struct bytebuffer *b, const char *data, int len) {
|
|
bytebuffer_reserve(b, b->len + len);
|
|
memcpy(b->buf + b->len, data, len);
|
|
b->len += len;
|
|
}
|
|
|
|
static void bytebuffer_puts(struct bytebuffer *b, const char *str) {
|
|
bytebuffer_append(b, str, strlen(str));
|
|
}
|
|
|
|
static void bytebuffer_resize(struct bytebuffer *b, int len) {
|
|
bytebuffer_reserve(b, len);
|
|
b->len = len;
|
|
}
|
|
|
|
static void bytebuffer_flush(struct bytebuffer *b, int fd) {
|
|
int yyy = write(fd, b->buf, b->len);
|
|
(void) yyy;
|
|
bytebuffer_clear(b);
|
|
}
|
|
|
|
static void bytebuffer_truncate(struct bytebuffer *b, int n) {
|
|
if (n <= 0)
|
|
return;
|
|
if (n > b->len)
|
|
n = b->len;
|
|
const int nmove = b->len - n;
|
|
memmove(b->buf, b->buf+n, nmove);
|
|
b->len -= n;
|
|
}
|