aboutsummaryrefslogtreecommitdiff
path: root/memstack/src/memstack.c
blob: 10d1e30112c3ec89177b97cc3848abd7b5e88f02 (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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include "memstack.h"

#include <cassert.h>

#include <stdlib.h>
#include <string.h>

bool memstack_make(memstack* stack, size_t capacity, void* memory) {
  assert(stack);
  assert(capacity >= 1);

  // Allocate memory if not user-provided.
  uint8_t* stack_memory = memory;
  if (!stack_memory) {
    stack_memory = calloc(1, capacity);
    if (stack_memory == nullptr) {
      return false;
    }
  }
  assert(stack_memory);

  stack->capacity  = capacity;
  stack->base      = stack_memory;
  stack->watermark = stack_memory;
  stack->owned     = (stack_memory != memory);
  stack->trap      = true;

  return true;
}

void memstack_del(memstack* stack) {
  assert(stack);

  if (stack->owned && (stack->base != nullptr)) {
    free(stack->base);
    stack->base  = nullptr;
    stack->owned = false;
  }

  stack->capacity  = 0;
  stack->watermark = stack->base;
}

void memstack_clear(memstack* stack) {
  assert(stack);

  stack->watermark = stack->base;
  memset(stack->base, 0, stack->capacity);
}

void* memstack_alloc(memstack* stack, size_t bytes) {
  assert(stack);

  if ((memstack_size(stack) + bytes) > stack->capacity) {
    if (stack->trap) {
      FAIL("memstack allocation failed, increase the stack's capacity.");
    }
    return nullptr; // Block does not fit in remaining memory.
  }

  // Allocate the block.
  uint8_t* block = stack->watermark;
  stack->watermark += bytes;
  assert(memstack_size(stack) <= stack->capacity);

  return block;
}

size_t memstack_size(const memstack* stack) {
  assert(stack);
  return stack->watermark - stack->base;
}

size_t memstack_capacity(const memstack* stack) {
  assert(stack);
  return stack->capacity;
}

void memstack_enable_traps(memstack* stack, bool enable) {
  assert(stack);
  stack->trap = enable;
}