diff options
Diffstat (limited to 'src/liballoc/allocator.h')
-rw-r--r-- | src/liballoc/allocator.h | 141 |
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 */ |