aboutsummaryrefslogtreecommitdiff
path: root/src/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem.c')
-rw-r--r--src/mem.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/src/mem.c b/src/mem.c
new file mode 100644
index 0000000..3d35299
--- /dev/null
+++ b/src/mem.c
@@ -0,0 +1,49 @@
+#include <u.h>
+
+// -------------------------------------------------------------------------
+// Dynamic buffer.
+
+/* 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
+_bufpop(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--;
+}
+