summaryrefslogtreecommitdiff
path: root/examples/custom_alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/custom_alloc.c')
-rw-r--r--examples/custom_alloc.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/examples/custom_alloc.c b/examples/custom_alloc.c
new file mode 100644
index 0000000..42843ce
--- /dev/null
+++ b/examples/custom_alloc.c
@@ -0,0 +1,93 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdalign.h>
+#include <stddef.h>
+#include <string.h>
+
+#include <pom.h>
+
+// Custom memory allocation functions
+typedef struct {
+ uint64_t allocations, frees;
+ size_t memory_used;
+ alignas(max_align_t) char memory[100000];
+} Memory;
+static void *my_calloc(void *udata, size_t nmemb, size_t sz) {
+ Memory *my_memory = udata;
+ char *mem = (char *)my_memory->memory + my_memory->memory_used;
+ size_t new_memory_used = my_memory->memory_used;
+ while ((uintptr_t)mem & 7)
+ mem++, new_memory_used++;
+ new_memory_used += 8 + nmemb * sz;
+ if (new_memory_used > sizeof my_memory->memory) {
+ // out of memory: return NULL
+ return NULL;
+ }
+ my_memory->allocations++;
+ my_memory->memory_used = new_memory_used;
+ // store size of allocation
+ *(uint64_t *)mem = nmemb * sz;
+ return mem + sizeof (uint64_t);
+}
+static void my_free(void *udata, void *ptr) {
+ if (!ptr) {
+ // free must do nothing when null pointer is passed
+ return;
+ }
+ Memory *my_memory = udata;
+ my_memory->frees++;
+}
+
+static void *my_realloc(void *udata, void *ptr, size_t new_size) {
+ if (!ptr) {
+ // realloc(ptr = NULL) is equivalent to malloc
+ return my_calloc(udata, new_size, 1);
+ }
+ // inefficient but correct realloc implementation:
+ // just free the old memory and allocate brand new memory
+ size_t old_size = ((uint64_t *)ptr)[-1];
+ void *new_ptr = my_calloc(udata, new_size, 1);
+ if (!new_ptr) {
+ // out-of-memory: return NULL
+ return NULL;
+ }
+ memcpy(new_ptr, ptr, old_size);
+ my_free(udata, ptr);
+ return new_ptr;
+}
+
+int main(void) {
+ pom_error *error;
+ pom_settings settings = {0};
+ // set allocation functions
+ settings.calloc = my_calloc;
+ settings.realloc = my_realloc;
+ settings.free = my_free;
+ static Memory my_memory;
+ // set udata pointer which is passed to the functions
+ settings.allocator_udata = &my_memory;
+
+ pom_conf *conf = pom_load_string(&settings, "conf.pom",
+ "foo = bar\n"
+ "[core]\n"
+ "list = 1,6,78,9\n",
+ &error);
+ if (!conf) {
+ pom_error_print(error);
+ // error must be freed with custom allocation function
+ my_free(&my_memory, error);
+ return EXIT_FAILURE;
+ }
+ char **list = pom_conf_get_list(conf, "core.list");
+ for (size_t i = 0; list[i]; i++)
+ printf("- %s\n",list[i]);
+ // lists must be freed with custom allocation function
+ my_free(&my_memory, list);
+ pom_conf_free(conf);
+ if (my_memory.allocations != my_memory.frees) {
+ // if this ever happens, it's a bug in libpom
+ fprintf(stderr, "libpom is leaking memory!!!\n");
+ return EXIT_FAILURE;
+ }
+ return 0;
+}