summaryrefslogtreecommitdiffstats
path: root/src/basic/alloc-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic/alloc-util.c')
-rw-r--r--src/basic/alloc-util.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/basic/alloc-util.c b/src/basic/alloc-util.c
new file mode 100644
index 0000000..ab7a42c
--- /dev/null
+++ b/src/basic/alloc-util.c
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include "alloc-util.h"
+#include "macro.h"
+#include "util.h"
+
+void* memdup(const void *p, size_t l) {
+ void *ret;
+
+ assert(l == 0 || p);
+
+ ret = malloc(l ?: 1);
+ if (!ret)
+ return NULL;
+
+ memcpy(ret, p, l);
+ return ret;
+}
+
+void* memdup_suffix0(const void *p, size_t l) {
+ void *ret;
+
+ assert(l == 0 || p);
+
+ /* The same as memdup() but place a safety NUL byte after the allocated memory */
+
+ ret = malloc(l + 1);
+ if (!ret)
+ return NULL;
+
+ *((uint8_t*) mempcpy(ret, p, l)) = 0;
+ return ret;
+}
+
+void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
+ size_t a, newalloc;
+ void *q;
+
+ assert(p);
+ assert(allocated);
+
+ if (*allocated >= need)
+ return *p;
+
+ newalloc = MAX(need * 2, 64u / size);
+ a = newalloc * size;
+
+ /* check for overflows */
+ if (a < size * need)
+ return NULL;
+
+ q = realloc(*p, a);
+ if (!q)
+ return NULL;
+
+ *p = q;
+ *allocated = newalloc;
+ return q;
+}
+
+void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
+ size_t prev;
+ uint8_t *q;
+
+ assert(p);
+ assert(allocated);
+
+ prev = *allocated;
+
+ q = greedy_realloc(p, allocated, need, size);
+ if (!q)
+ return NULL;
+
+ if (*allocated > prev)
+ memzero(q + prev * size, (*allocated - prev) * size);
+
+ return q;
+}