aboutsummaryrefslogtreecommitdiff
path: root/MemoryManager.c
diff options
context:
space:
mode:
Diffstat (limited to 'MemoryManager.c')
-rw-r--r--MemoryManager.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/MemoryManager.c b/MemoryManager.c
index 53f906e..dd3a7fc 100644
--- a/MemoryManager.c
+++ b/MemoryManager.c
@@ -3,6 +3,8 @@
#include <stdlib.h>
#include <string.h>
+/** M_std **/
+
Result
std_alloc(MemoryManager mm, void **ptr, usize size) {
if (NULL == ptr)
@@ -46,6 +48,154 @@ M_std() {
};
}
+/** M_std_tracked **/
+
+struct MemoryTracking {
+ usize alloc;
+ void **ptrs;
+};
+
+static inline Result
+MemoryTracking_store(struct MemoryTracking *mt, void *ptr) {
+ if (NULL == mt || NULL == ptr)
+ return R_NullArgument;
+
+ if (NULL == mt->ptrs || 0 == mt->alloc)
+ return R_Uninitialized;
+
+ usize index = 0;
+ while (index < mt->alloc && NULL != mt->ptrs[index]) {
+ ++index;
+ }
+
+ if (index == mt->alloc) {
+ mt->ptrs = realloc(mt->ptrs, sizeof(void*) * (mt->alloc << 1));
+ memset(mt->ptrs + (sizeof(void*) * mt->alloc), 0, sizeof(void*) * mt->alloc);
+
+ if (NULL == mt->ptrs) {
+ mt->alloc = 0;
+ return R_OutOfMemory;
+ }
+
+ mt->alloc <<= 1;
+ }
+
+ mt->ptrs[index] = ptr;
+ return R_Ok;
+}
+
+static inline Result
+MemoryTracking_remove(struct MemoryTracking *mt, void *ptr) {
+ if (NULL == mt || NULL == ptr)
+ return R_NullArgument;
+
+ if (NULL == mt->ptrs || 0 == mt->alloc)
+ return R_Uninitialized;
+
+ usize index = 0;
+ while (index < mt->alloc && ptr != mt->ptrs[index]) {
+ ++index;
+ }
+
+ if (index == mt->alloc)
+ return R_NotFound;
+
+ mt->ptrs[index] = NULL;
+ return R_Ok;
+}
+
+Result
+stdt_alloc(MemoryManager mm, void **ptr, usize size) {
+ if (NULL == ptr)
+ return R_NullArgument;
+
+ if (NULL == mm.priv)
+ return R_Uninitialized;
+
+ *ptr = malloc(size);
+ if (NULL == *ptr)
+ return R_Err;
+
+ return MemoryTracking_store(mm.priv, *ptr);
+}
+
+Result
+stdt_realloc(MemoryManager mm, void **ptr, usize new_size) {
+ if (NULL == ptr)
+ return R_NullArgument;
+
+ if (NULL == mm.priv)
+ return R_Uninitialized;
+
+ void *ptr_orig = *ptr;
+ *ptr = realloc(*ptr, new_size);
+
+ if (NULL == *ptr)
+ return R_Err;
+
+ if (ptr_orig != *ptr) {
+ RETURN_NOTOK(MemoryTracking_remove(mm.priv, ptr_orig));
+ RETURN_NOTOK(MemoryTracking_store(mm.priv, *ptr));
+ }
+ return R_Ok;
+}
+
+Result
+stdt_free(MemoryManager mm, void **ptr) {
+ if (NULL == ptr)
+ return R_NullArgument;
+
+ if (NULL == mm.priv)
+ return R_Uninitialized;
+
+ RETURN_NOTOK(MemoryTracking_remove(mm.priv, *ptr));
+
+ free(*ptr);
+ *ptr = NULL;
+
+ return R_Ok;
+}
+
+Result
+stdt_destroy(MemoryManager *mm) {
+ if (NULL == mm)
+ return R_NullArgument;
+
+ if (NULL == mm->priv)
+ return R_Uninitialized;
+
+ struct MemoryTracking *mt = mm->priv;
+
+ for (usize i = 0; i < mt->alloc; ++i) {
+ if (NULL != mt->ptrs[i])
+ free(mt->ptrs[i]);
+ }
+
+ free(mt->ptrs);
+ free(mt);
+ mm->priv = NULL;
+
+ return R_Ok;
+}
+
+MemoryManager
+M_std_tracked() {
+ struct MemoryTracking *mt = malloc(sizeof(struct MemoryTracking));
+ mt->alloc = 8;
+ mt->ptrs = malloc(sizeof(void*) * mt->alloc);
+ memset(mt->ptrs, 0, sizeof(void*) * mt->alloc);
+
+ return (MemoryManager) {
+ .alloc = &stdt_alloc,
+ .realloc = &stdt_realloc,
+ .free = &stdt_free,
+ .destroy = &stdt_destroy,
+ .priv = mt,
+ };
+}
+
+/* Helper functions */
+
char*
M_strdup(MemoryManager mm, const char* str) {
if (NULL == str)