Derive-C
Loading...
Searching...
No Matches
template.h
Go to the documentation of this file.
1
7// However, this is usable inside unit tests written in C.
8
9#include <stddef.h>
10
11#include <derive-c/allocs/std.h>
13#include <derive-c/core/panic.h>
14
17
18#ifdef NDEBUG
19typedef struct {
20 ALLOC* alloc;
21} SELF;
22
23static SELF NS(SELF, new)(ALLOC* alloc) { return (SELF){.alloc = alloc}; }
24
25static void* NS(SELF, malloc)(SELF* self, size_t size) {
26 return NS(ALLOC, malloc)(self->alloc, size);
27}
28
29static void* NS(SELF, calloc)(SELF* self, size_t count, size_t size) {
30 return NS(ALLOC, calloc)(self->alloc, count, size);
31}
32
33static void* NS(SELF, realloc)(SELF* self, void* ptr, size_t size) {
34 return NS(ALLOC, realloc)(self->alloc, ptr, size);
35}
36
37static void NS(SELF, free)(SELF* self, void* ptr) { return NS(ALLOC, free)(self->alloc, ptr); }
38
39#else
40 #define ENTRIES_VECTOR NS(NAME, entries)
41 #define TRACKED_ENTRY NS(EXPAND(ENTRIES), entry)
42
43typedef struct {
44 void* ptr;
45 bool freed;
47
48 #pragma push_macro("ALLOC")
49
50 // JUSTIFY: Using a vector rather than a faster lookup map.
51 // - Give this will be used for test & debug, performance matters less
52 // - Much easier to explore a vector, than a hashmap in gdb.
53 // JUSTIFY: Always use the std allocator for test book keeping
54 // - keeps the observed behaviour (e.g. allocator usage) the same as in release
55 #define ITEM TRACKED_ENTRY
56 #define ALLOC stdalloc
57 #define INTERNAL_NAME ENTRIES_VECTOR
59
60 #pragma pop_macro("ALLOC")
61
62typedef struct {
65} SELF;
66
67static SELF NS(SELF, new)(ALLOC* alloc) {
68 return (SELF){.alloc = alloc, .entries = NS(ENTRIES_VECTOR, new)(stdalloc_get())};
69}
70
71static ENTRIES_VECTOR const* NS(SELF, get_entries)(SELF const* self) {
72 DEBUG_ASSERT(self);
73 return &self->entries;
74}
75
76static void NS(SELF, unleak_and_delete)(SELF* self) {
77 NS(ENTRIES_VECTOR, iter) iter = NS(ENTRIES_VECTOR, get_iter)(&self->entries);
78 TRACKED_ENTRY* entry;
79
80 while ((entry = NS(ENTRIES_VECTOR, iter_next)(&iter))) {
81 if (!entry->freed) {
82 NS(ALLOC, free)(self->alloc, entry->ptr);
83 }
84 }
85
86 NS(ENTRIES_VECTOR, delete)(&self->entries);
87}
88
89static void* NS(SELF, calloc)(SELF* self, size_t count, size_t size) {
90 DEBUG_ASSERT(self);
91 void* ptr = NS(ALLOC, calloc)(self->alloc, count, size);
92 if (ptr) {
93 NS(ENTRIES_VECTOR, push)(&self->entries, (TRACKED_ENTRY){
94 .ptr = ptr,
95 .freed = false,
96 });
97 }
98 return ptr;
99}
100
101static void* NS(SELF, malloc)(SELF* self, size_t size) {
102 DEBUG_ASSERT(self);
103 void* ptr = NS(ALLOC, malloc)(self->alloc, size);
104 if (ptr) {
105 NS(ENTRIES_VECTOR, push)(&self->entries, (TRACKED_ENTRY){
106 .ptr = ptr,
107 .freed = false,
108 });
109 }
110 return ptr;
111}
112
113static void* NS(SELF, realloc)(SELF* self, void* ptr, size_t size) {
114 DEBUG_ASSERT(self);
115 DEBUG_ASSERT(ptr);
116 return NS(ALLOC, realloc)(self->alloc, ptr, size);
117}
118
119static void NS(SELF, free)(SELF* self, void* ptr) {
120 DEBUG_ASSERT(ptr);
121 DEBUG_ASSERT(self);
122
123 NS(ENTRIES_VECTOR, iter) iter = NS(ENTRIES_VECTOR, get_iter)(&self->entries);
124 TRACKED_ENTRY* entry;
125
126 while ((entry = NS(ENTRIES_VECTOR, iter_next)(&iter))) {
127 if (entry->ptr == ptr) {
128 DEBUG_ASSERT(!entry->freed);
129 entry->freed = true;
130 break;
131 }
132 }
133
134 NS(ALLOC, free)(self->alloc, ptr);
135}
136
137 #undef ENTRIES_VECTOR
138 #undef TRACKED_ENTRY
139#endif
140
static void free(SELF *self, void *ptr)
Definition template.h:56
static void * realloc(SELF *self, void *ptr, size_t size)
Definition template.h:45
static void * malloc(SELF *self, size_t size)
Definition template.h:23
static void * calloc(SELF *self, size_t count, size_t size)
Definition template.h:34
#define ALLOC
Definition template.h:56
#define TRACKED_ENTRY
Definition template.h:41
#define ENTRIES_VECTOR
For unit tests expected to throw, as C has no unwind, we cannot free allocated memory....
Definition template.h:40
static void unleak_and_delete(SELF *self)
Definition template.h:76
static ENTRIES_VECTOR const * get_entries(SELF const *self)
Definition template.h:71
#define NS(pre, post)
Definition helpers.h:6
#define DEBUG_ASSERT(expr)
Definition panic.h:34
#define SELF
Definition def.h:51
ENTRIES_VECTOR entries
Definition template.h:64
ALLOC * alloc
Definition template.h:63
bool freed
Definition template.h:45
void * ptr
Definition template.h:44
static ITER get_iter(SELF *self)
Definition template.h:318
static INDEX_TYPE size(SELF const *self)
Definition template.h:220
static ITEM * push(SELF *self, ITEM item)
Definition template.h:140