aboutsummaryrefslogtreecommitdiff
path: root/src/base/mem/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/mem/buffer.c')
-rw-r--r--src/base/mem/buffer.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/base/mem/buffer.c b/src/base/mem/buffer.c
new file mode 100644
index 0000000..b684d35
--- /dev/null
+++ b/src/base/mem/buffer.c
@@ -0,0 +1,45 @@
+#include "internal.h"
+
+/* Grow to particular size */
+void*
+·bufgrow(void* buf, vlong newLen, vlong eltsize)
+{
+ assert(bufcap(buf) <= (SIZE_MAX - 1) / 2);
+
+ vlong newCap = MAX(16, MAX(1 + 2 * bufcap(buf), newLen));
+
+ assert(newLen <= newCap);
+ assert(newCap <= (SIZE_MAX - offsetof(BufHdr, buf)) / eltsize);
+
+ vlong newSize = offsetof(BufHdr, buf) + newCap * eltsize;
+
+ BufHdr* newHdr;
+ if (buf) {
+ newHdr = bufhdr(buf);
+ newHdr = (BufHdr*)realloc((void*)newHdr, newSize);
+ } else {
+ newHdr = (BufHdr*)malloc(newSize);
+ newHdr->len = 0;
+ }
+
+ newHdr->cap = newCap;
+ return (void*)newHdr->buf;
+}
+
+/* Pop out a value */
+void
+·bufdel(void *buf, int i, vlong eltsize)
+{
+ int n;
+ byte *b;
+ byte stk[1024];
+ assert(eltsize < sizeof(stk));
+
+ b = (byte*)buf;
+ if(n = buflen(buf), i < n) {
+ memcpy(stk, b+eltsize*i, eltsize);
+ memcpy(b+eltsize*i, b+eltsize*(i+1), eltsize*(n-i-1));
+ memcpy(b+eltsize*(n-1), stk, eltsize);
+ }
+ bufhdr(buf)->len--;
+}