aboutsummaryrefslogtreecommitdiff
path: root/memstack/include/memstack.h
blob: 9a8a7ee7f41f9317e7768265c53d8f3d69ff4539 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/*
 * Stack-based allocator.
 */
#pragma once

#include <stddef.h>
#include <stdint.h>

/// Stack-based allocator.
typedef struct memstack {
  size_t   capacity;  // Total size available.
  uint8_t* base;      // Base pointer to memory.
  uint8_t* watermark; // Pointer to next free area of memory.
  bool     owned;     // True if memory is owned by the memstack.
  bool     trap;      // Whether to trap when allocating beyond capacity.
} memstack;

/// Create a stack-based allocator.
///
/// `stack` may be user-provided or null.
/// - If null, the allocator malloc()s the memory for them.
/// - If given, `stack` must be at least `capacity` bytes.
///
/// The memory is zeroed out for convenience.
bool memstack_make(memstack*, size_t capacity, void* memory);

/// Destroy the stack.
///
/// If the allocator owns the memory, then this function frees it.
void memstack_del(memstack*);

/// Clear the stack.
void memstack_clear(memstack*);

/// Allocate a new block.
/// Return null if the block does not fit in the remaining memory.
/// When there is no space left in the stack, allocation can either trap
/// (default) or gracefully return null. Call mem_enable_traps() to toggle this
/// behaviour.
/// Newly allocated blocks are conveniently zeroed out.
void* memstack_alloc(memstack*, size_t bytes);

/// Return the stack's used size in bytes.
size_t memstack_size(const memstack*);

/// Return the stack's total capacity in bytes.
size_t memstack_capacity(const memstack*);

/// Set whether to trap when attempting to allocate beyond capacity.
void memstack_enable_traps(memstack*, bool);