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>
12#include <derive-c/core.h>
13#include <derive-c/panic.h>
14#include <derive-c/self.h>
15
16#ifndef ALLOC
17#ifndef __clang_analyzer__
18#error "The allocator being wrapped must be defined"
19#endif
20#include <derive-c/allocs/null.h> // NOLINT(misc-include-cleaner)
21#define ALLOC nullalloc
22#endif
23
24#ifndef ENTRIES
25#ifndef __clang_analyzer__
26#error "The name of the type to generate for storing entries must be defined"
27#endif
28#define ENTRIES derive_c_entries_placeholder_name
29#endif
30
31#ifdef NDEBUG
32
33typedef struct {
34 ALLOC* alloc;
35} SELF;
36
37static SELF NAME(SELF, new)(ALLOC* alloc) { return (SELF){.alloc = alloc}; }
38
39static void* NAME(SELF, malloc)(SELF* self, size_t size) {
40 return NAME(ALLOC, malloc)(self->alloc, size);
41}
42
43static void* NAME(SELF, calloc)(SELF* self, size_t count, size_t size) {
44 return NAME(ALLOC, calloc)(self->alloc, count, size);
45}
46
47static void* NAME(SELF, realloc)(SELF* self, void* ptr, size_t size) {
48 return NAME(ALLOC, realloc)(self->alloc, ptr, size);
49}
50
51static void NAME(SELF, free)(SELF* self, void* ptr) { return NAME(ALLOC, free)(self->alloc, ptr); }
52
53#else
54
55#define TRACKED_ENTRY NAME(ENTRIES, entry)
56
57typedef struct {
58 void* ptr;
59 bool freed;
61
62#pragma push_macro("SELF")
63#undef SELF
64
65// JUSTIFY: Using a vector rather than a faster lookup map.
66// - Give this will be used for test & debug, performance matters less
67// - Much easier to explore a vector, than a hashmap in gdb.
68#define T TRACKED_ENTRY
69#define ALLOC stdalloc
70#define SELF ENTRIES
72
73#pragma pop_macro("SELF")
74
75typedef struct {
78} SELF;
79
80static SELF NAME(SELF, new)(ALLOC* alloc) {
81 return (SELF){.alloc = alloc, .entries = NAME(ENTRIES, new)(stdalloc_get())};
82}
83
84static ENTRIES const* NAME(SELF, get_entries)(SELF const* self) {
85 DEBUG_ASSERT(self);
86 return &self->entries;
87}
88
89static void NAME(SELF, unleak_and_delete)(SELF* self) {
90 NAME(ENTRIES, iter) iter = NAME(ENTRIES, get_iter)(&self->entries);
91 TRACKED_ENTRY* entry;
92
93 while ((entry = NAME(ENTRIES, iter_next)(&iter))) {
94 if (!entry->freed) {
95 NAME(ALLOC, free)(self->alloc, entry->ptr);
96 }
97 }
98
99 NAME(ENTRIES, delete)(&self->entries);
100}
101
102static void* NAME(SELF, calloc)(SELF* self, size_t count, size_t size) {
103 DEBUG_ASSERT(self);
104 void* ptr = NAME(ALLOC, calloc)(self->alloc, count, size);
105 if (ptr) {
106 NAME(ENTRIES, push)(&self->entries, (TRACKED_ENTRY){
107 .ptr = ptr,
108 .freed = false,
109 });
110 }
111 return ptr;
112}
113
114static void* NAME(SELF, malloc)(SELF* self, size_t size) {
115 DEBUG_ASSERT(self);
116 void* ptr = NAME(ALLOC, malloc)(self->alloc, size);
117 if (ptr) {
118 NAME(ENTRIES, push)(&self->entries, (TRACKED_ENTRY){
119 .ptr = ptr,
120 .freed = false,
121 });
122 }
123 return ptr;
124}
125
126static void* NAME(SELF, realloc)(SELF* self, void* ptr, size_t size) {
127 DEBUG_ASSERT(self);
128 DEBUG_ASSERT(ptr);
129 return NAME(ALLOC, realloc)(self->alloc, ptr, size);
130}
131
132static void NAME(SELF, free)(SELF* self, void* ptr) {
133 DEBUG_ASSERT(ptr);
134 DEBUG_ASSERT(self);
135
136 NAME(ENTRIES, iter) iter = NAME(ENTRIES, get_iter)(&self->entries);
137 TRACKED_ENTRY* entry;
138
139 while ((entry = NAME(ENTRIES, iter_next)(&iter))) {
140 if (entry->ptr == ptr) {
141 DEBUG_ASSERT(!entry->freed);
142 entry->freed = true;
143 break;
144 }
145 }
146
147 NAME(ALLOC, free)(self->alloc, ptr);
148}
149
150#undef ENTRIES
151#undef TRACKED_ENTRY
152
153#endif
154
155#undef SELF
#define ALLOC
An allocator that prints to stdout when it allocates or frees memory.
Definition template.h:17
static void free(SELF *self, void *ptr)
Definition template.h:62
static void * realloc(SELF *self, void *ptr, size_t size)
Definition template.h:51
static void * malloc(SELF *self, size_t size)
Definition template.h:29
static void * calloc(SELF *self, size_t count, size_t size)
Definition template.h:40
#define TRACKED_ENTRY
Definition template.h:55
#define ENTRIES
Definition template.h:28
#define SELF
Definition template.h:70
static void unleak_and_delete(SELF *self)
Definition template.h:89
static ENTRIES const * get_entries(SELF const *self)
Definition template.h:84
#define NAME(pre, post)
Definition core.h:5
#define DEBUG_ASSERT(expr)
Definition panic.h:23
ENTRIES entries
Definition template.h:77
ALLOC * alloc
Definition template.h:76
bool freed
Definition template.h:59
void * ptr
Definition template.h:58
static ITER get_iter(SELF *self)
Definition template.h:312
static INDEX_TYPE size(SELF const *self)
Definition template.h:207
static T * push(SELF *self, T value)
Definition template.h:102
#define ALLOC
A simple vector.
Definition template.h:15