Derive-C
Loading...
Searching...
No Matches
template.h File Reference
#include <stdint.h>
#include <string.h>
#include <derive-c/core/helpers.h>
#include <derive-c/core/panic.h>
#include <derive-c/core/self/def.h>
#include <derive-c/core/self/undef.h>
Include dependency graph for template.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  SELF
 An allocator that prints to stdout when it allocates or frees memory. More...

Macros

#define CAPACITY   1024
 A very simple bump allocator making use of a provided fixed size buffer (e.g. statically allocated).
#define USED   uint8_t

Functions

static SELF new ()
static void clear (SELF *self)
 Clear the allocator, note that all data should be freed before this occurs.
static USED get_used (SELF const *self)
static void * malloc (SELF *self, size_t size)
static void free (SELF *DEBUG_UNUSED(self), void *DEBUG_UNUSED(ptr))
static void * realloc (SELF *self, void *ptr, size_t new_size)
static void * calloc (SELF *self, size_t count, size_t size)

Variables

static size_t metadata_size = sizeof(USED)

Macro Definition Documentation

◆ CAPACITY

#define CAPACITY   1024

A very simple bump allocator making use of a provided fixed size buffer (e.g. statically allocated).

  • Useful when an upper bound for allocation size is known at compile time
  • Can be used when no global allocator is available (e.g. embedded systems, kernel dev)

Definition at line 17 of file template.h.

◆ USED

#define USED   uint8_t

Definition at line 25 of file template.h.

Function Documentation

◆ calloc()

void * calloc ( SELF * self,
size_t count,
size_t size )
static

Definition at line 138 of file template.h.

138 {
139 // JUSTIFY:
140 // - We already zeroed the buffer in `new()`
141 return NS(SELF, malloc)(self, count * size);
142}
static void * malloc(SELF *self, size_t size)
Definition template.h:23
#define NS(pre, post)
Definition helpers.h:6
#define SELF
Definition def.h:51
static INDEX_TYPE size(SELF const *self)
Definition template.h:220
Here is the call graph for this function:

◆ clear()

void clear ( SELF * self)
static

Clear the allocator, note that all data should be freed before this occurs.

Definition at line 52 of file template.h.

52 {
53 DEBUG_ASSERT(self);
54
55#if !defined NDEBUG
56 // JUSTIFY: Allocations & sizes zeroed on free in debug, we check all data has been freed.
57 for (size_t i = 0; i < self->used; i++) {
58 if (self->buffer[i] != 0) {
59 PANIC("Data not freed before clearing the static bump allocator");
60 }
61 }
62#endif
63 memset(self->buffer, 0, self->used);
64 self->used = 0;
65}
#define DEBUG_ASSERT(expr)
Definition panic.h:34
#define PANIC(...)
Definition panic.h:7
size_t used
Definition template.h:35
char buffer[CAPACITY]
Definition template.h:36
Here is the call graph for this function:
Here is the caller graph for this function:

◆ free()

void free ( SELF * DEBUG_UNUSEDself,
void * DEBUG_UNUSEDptr )
static

Definition at line 84 of file template.h.

84 {
85 DEBUG_ASSERT(self);
86 DEBUG_ASSERT(ptr);
87
88#if !defined NDEBUG
89 // JUSTIFY: Zero memory in debug.
90 // - Expensive for release, but helpful when debugging
91 // NOTE: This means that users should free, before they clear and reuse the buffer.
92 USED* used_ptr = (USED*)((char*)ptr - sizeof(USED));
93 memset(ptr, 0, *used_ptr);
94 *used_ptr = 0;
95#endif
96}
#define USED
Definition template.h:25
Here is the call graph for this function:

◆ get_used()

USED get_used ( SELF const * self)
static

Definition at line 67 of file template.h.

67 {
68 DEBUG_ASSERT(self);
69 return self->used;
70}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ malloc()

void * malloc ( SELF * self,
size_t size )
static

Definition at line 72 of file template.h.

72 {
73 DEBUG_ASSERT(self);
74 if (self->used + (size + sizeof(USED)) > CAPACITY) {
75 return NULL;
76 }
77 char* ptr = &self->buffer[self->used];
78 USED* used_ptr = (USED*)ptr;
79 *used_ptr = size;
80 self->used += size + sizeof(USED);
81 return ptr + sizeof(USED);
82}
#define CAPACITY
A very simple bump allocator making use of a provided fixed size buffer (e.g. statically allocated).
Definition template.h:17
Here is the call graph for this function:

◆ new()

SELF new ( )
static

Definition at line 42 of file template.h.

42 {
43 SELF self = {.used = 0, .derive_c_staticbumpalloc = {}};
44 // JUSTIFY: Zeroed buffer
45 // - For easier debugging & view in gdb.
46 // - Additionally allows for calloc to be malloc.
47 memset(self.buffer, 0, CAPACITY);
48 return self;
49}

◆ realloc()

void * realloc ( SELF * self,
void * ptr,
size_t new_size )
static

Definition at line 98 of file template.h.

98 {
99 DEBUG_ASSERT(self);
100
101 if (!ptr) {
102 return NS(SELF, malloc)(self, new_size);
103 }
104
105 char* byte_ptr = (char*)ptr;
106 USED* old_size = (USED*)(byte_ptr - sizeof(USED));
107 const bool was_last_alloc = (byte_ptr + *old_size == self->buffer + self->used);
108
109 if (was_last_alloc) {
110 if (self->used + (new_size - *old_size) > CAPACITY) {
111 return NULL;
112 }
113
114 self->used += (new_size - *old_size);
115 *old_size = new_size;
116 return ptr;
117 }
118
119 if (new_size < *old_size) {
120 // JUSTIFY: Shrinking an allocation
121 // - Can become a noop - as we cannot re-extend the allocation
122 // afterwards - no metadata for unused capacity not at end of buffer.
123 *old_size = new_size;
124 return ptr;
125 }
126
127 void* new_buff = NS(SELF, malloc)(self, new_size);
128 if (!new_buff) {
129 return NULL;
130 }
131
132 memcpy(new_buff, ptr, *old_size);
133
134 NS(SELF, free)(self, ptr);
135 return new_buff;
136}
static void free(SELF *self, void *ptr)
Definition template.h:56
Here is the call graph for this function:

Variable Documentation

◆ metadata_size

size_t metadata_size = sizeof(USED)
static

Definition at line 40 of file template.h.