summaryrefslogtreecommitdiff
path: root/src/liballoc/allocator.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/liballoc/allocator.h')
-rw-r--r--src/liballoc/allocator.h141
1 files changed, 141 insertions, 0 deletions
diff --git a/src/liballoc/allocator.h b/src/liballoc/allocator.h
new file mode 100644
index 0000000..48be179
--- /dev/null
+++ b/src/liballoc/allocator.h
@@ -0,0 +1,141 @@
+#ifndef NEOAS_ALLOCATOR_H_INCLUDED
+# define NEOAS_ALLOCATOR_H_INCLUDED
+
+struct memory_allocator
+{
+ void *(*allocate) (void *, size_t, size_t);
+ void *(*reallocate) (void *, void *, size_t, size_t);
+ void (*deallocate) (void *, void *);
+ void *context;
+};
+
+static inline const struct memory_allocator *default_memory_allocator (void);
+
+static inline int safe_allocate (const struct memory_allocator *allocator,
+ size_t n, size_t size, void **allocated);
+
+static inline int safe_reallocate (const struct memory_allocator *allocator,
+ void **memory, size_t n, size_t size);
+
+static inline void safe_deallocate (const struct memory_allocator *allocator,
+ void **allocated);
+
+static inline void copy_allocator (struct memory_allocator *dest,
+ const struct memory_allocator *src);
+
+# include <stdlib.h>
+
+# define ALLOCATE(ptr, n) \
+ (safe_allocate (allocator, n, sizeof (*ptr), (void **) (&ptr)))
+
+# define REALLOCATE(ptr, n) \
+ (safe_reallocate (allocator, (void **) (&ptr), n, sizeof (*ptr)))
+
+# define DEALLOCATE(ptr) \
+ (safe_deallocate (allocator, (void **) (&ptr)))
+
+static void *
+default_allocate (void *unused, size_t n, size_t type)
+{
+ (void) unused;
+ return calloc (n, type);
+}
+
+static void *
+default_reallocate (void *unused, void *mem, size_t n, size_t type)
+{
+ (void) unused;
+ return realloc (mem, n * type);
+}
+
+static void
+default_deallocate (void *unused, void *mem)
+{
+ (void) unused;
+ free (mem);
+}
+
+static inline const struct memory_allocator *
+default_memory_allocator (void)
+{
+ static const struct memory_allocator alloc = {
+ .allocate = default_allocate,
+ .reallocate = default_reallocate,
+ .deallocate = default_deallocate,
+ .context = NULL
+ };
+ return &alloc;
+}
+
+static inline int
+safe_allocate (const struct memory_allocator *allocator,
+ size_t n, size_t size, void **allocated)
+{
+ if (allocator == NULL)
+ {
+ allocator = default_memory_allocator ();
+ }
+ *allocated = allocator->allocate ((void *) allocator->context, n, size);
+ if (*allocated == NULL)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+static inline int
+safe_reallocate (const struct memory_allocator *allocator,
+ void **memory, size_t n, size_t size)
+{
+ if (allocator == NULL)
+ {
+ allocator = default_memory_allocator ();
+ }
+ if (n == 0)
+ {
+ n = 1;
+ }
+ if (size == 0)
+ {
+ size = 1;
+ }
+ void *reallocated =
+ allocator->reallocate (allocator->context, *memory, n, size);
+ if (reallocated == NULL)
+ {
+ return -1;
+ }
+ *memory = reallocated;
+ return 0;
+}
+
+static inline void
+safe_deallocate (const struct memory_allocator *allocator, void **allocated)
+{
+ if (allocator == NULL)
+ {
+ allocator = default_memory_allocator ();
+ }
+ void *ptr = *allocated;
+ if (ptr)
+ {
+ allocator->deallocate (allocator->context, ptr);
+ }
+ *allocated = NULL;
+}
+
+static inline void
+copy_allocator (struct memory_allocator *dest,
+ const struct memory_allocator *src)
+{
+ if (src == NULL)
+ {
+ src = default_memory_allocator ();
+ }
+ dest->allocate = src->allocate;
+ dest->reallocate = src->reallocate;
+ dest->deallocate = src->deallocate;
+ dest->context = src->context;
+}
+
+#endif /* not NEOAS_ALLOCATOR_H_INCLUDED */