|
@@ -100,6 +100,56 @@ void _buf_resize(struct buffer *buf, size_t size) {
|
|
|
buf->base_size = size;
|
|
|
}
|
|
|
|
|
|
+void _buf_unwrap(struct buffer *buf, size_t cont) {
|
|
|
+ ssize_t len, by = cont - (buf->wrap - buf->readp);
|
|
|
+ size_t size;
|
|
|
+ u8_t *scratch;
|
|
|
+
|
|
|
+ // do nothing if we have enough space
|
|
|
+ if (by <= 0 || cont >= buf->size) return;
|
|
|
+
|
|
|
+ // buffer already unwrapped, just move it up
|
|
|
+ if (buf->writep >= buf->readp) {
|
|
|
+ memmove(buf->readp - by, buf->readp, buf->writep - buf->readp);
|
|
|
+ buf->readp -= by;
|
|
|
+ buf->writep -= by;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // how much is overlapping
|
|
|
+ size = by - (buf->readp - buf->writep);
|
|
|
+ len = buf->writep - buf->buf;
|
|
|
+
|
|
|
+ // buffer is wrapped and enough free space to move data up directly
|
|
|
+ if (size <= 0) {
|
|
|
+ memmove(buf->readp - by, buf->readp, buf->wrap - buf->readp);
|
|
|
+ buf->readp -= by;
|
|
|
+ memcpy(buf->wrap - by, buf->buf, min(len, by));
|
|
|
+ if (len > by) {
|
|
|
+ memmove(buf->buf, buf->buf + by, len - by);
|
|
|
+ buf->writep -= by;
|
|
|
+ } else buf->writep += buf->size - by;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ scratch = malloc(size);
|
|
|
+
|
|
|
+ // buffer is wrapped but not enough free room => use scratch zone
|
|
|
+ if (scratch) {
|
|
|
+ memcpy(scratch, buf->writep - size, size);
|
|
|
+ memmove(buf->readp - by, buf->readp, buf->wrap - buf->readp);
|
|
|
+ buf->readp -= by;
|
|
|
+ memcpy(buf->wrap - by, buf->buf, by);
|
|
|
+ memmove(buf->buf, buf->buf + by, len - by - size);
|
|
|
+ buf->writep -= by;
|
|
|
+ memcpy(buf->writep - size, scratch, size);
|
|
|
+ free(scratch);
|
|
|
+ } else {
|
|
|
+ _buf_unwrap(buf, cont / 2);
|
|
|
+ _buf_unwrap(buf, cont - cont / 2);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void buf_init(struct buffer *buf, size_t size) {
|
|
|
buf->buf = malloc(size);
|
|
|
buf->readp = buf->buf;
|