arena.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #ifndef ARENA_H
  2. #define ARENA_H
  3. #include <stdint.h>
  4. #include <stdlib.h>
  5. typedef uint8_t err_t;
  6. struct arena_chunk {
  7. uintptr_t start;
  8. size_t size;
  9. };
  10. struct arena {
  11. uint8_t *data;
  12. size_t cur;
  13. size_t cap;
  14. struct {
  15. struct arena_chunk *items;
  16. size_t size;
  17. size_t cap;
  18. } chunks;
  19. };
  20. struct arena_err_t {
  21. struct arena arena;
  22. err_t err;
  23. };
  24. struct arena_void_p_err_t {
  25. struct arena arena;
  26. err_t err;
  27. void *ptr;
  28. };
  29. enum arena_err {
  30. ARENA_ERR_OK = 0,
  31. ARENA_ERR_MALLOC_FAIL,
  32. ARENA_ERR_HIT_CAP,
  33. ARENA_ERR_INVALID_PTR
  34. };
  35. struct arena_err_t arena_create(size_t cap);
  36. err_t arena_destroy(struct arena arena);
  37. struct arena_void_p_err_t arena_alloc(struct arena arena, size_t size,
  38. _Bool zero_it);
  39. struct arena_err_t arena_free(struct arena arena, void *ptr);
  40. struct arena_err_t arena_forget(struct arena arena, _Bool zero_it);
  41. err_t arena_dump_chunks(struct arena arena);
  42. #if defined(ARENA_IMP) || defined(IMP)
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include "da.h"
  46. struct arena_err_t
  47. arena_create(size_t cap)
  48. {
  49. void *data = calloc(cap, sizeof(uint8_t));
  50. if ( data == NULL ) {
  51. return (struct arena_err_t) { .err = ARENA_ERR_MALLOC_FAIL };
  52. }
  53. struct arena arena = {
  54. .data = data,
  55. .cap = cap,
  56. .cur = 0
  57. };
  58. DA_CREATE(arena.chunks, sizeof(struct arena_chunk));
  59. return (struct arena_err_t) { .arena = arena, .err = ARENA_ERR_OK };
  60. }
  61. err_t
  62. arena_destroy(struct arena arena)
  63. {
  64. free(arena.data);
  65. DA_DESTROY(arena.chunks);
  66. return ARENA_ERR_OK;
  67. }
  68. struct arena_void_p_err_t
  69. arena_alloc(struct arena arena, size_t size, _Bool zero_it)
  70. {
  71. if ( arena.cur + size >= arena.cap ) {
  72. return (struct arena_void_p_err_t) {
  73. .arena = arena,
  74. .ptr = NULL,
  75. .err = ARENA_ERR_HIT_CAP
  76. };
  77. }
  78. void *ptr = (void *) (arena.data + arena.cur);
  79. arena.cur += size;
  80. struct arena_chunk chunk = {
  81. .start = (uintptr_t) ptr,
  82. .size = size
  83. };
  84. DA_APPEND(arena.chunks, chunk);
  85. if ( zero_it != 0 ) {
  86. memset(ptr, 0, size);
  87. }
  88. return (struct arena_void_p_err_t) {
  89. .arena = arena,
  90. .ptr = ptr,
  91. .err = ARENA_ERR_OK
  92. };
  93. }
  94. struct arena_err_t
  95. arena_free(struct arena arena, void *ptr)
  96. {
  97. uintptr_t p = (uintptr_t) ptr;
  98. struct arena_chunk ac = {0};
  99. _Bool found = 0;
  100. size_t chunk_index = 0;
  101. for ( ; chunk_index < arena.chunks.size; ++chunk_index ) {
  102. ac = arena.chunks.items[chunk_index];
  103. if ( ac.start == p ) {
  104. found = 1;
  105. break;
  106. }
  107. }
  108. if ( found == 0 ) {
  109. return (struct arena_err_t) {
  110. .arena = arena,
  111. .err = ARENA_ERR_INVALID_PTR
  112. };
  113. }
  114. DA_DELETE(arena.chunks, chunk_index);
  115. return (struct arena_err_t) {
  116. .arena = arena,
  117. .err = ARENA_ERR_OK
  118. };
  119. }
  120. struct arena_err_t
  121. arena_forget(struct arena arena, _Bool zero_it)
  122. {
  123. arena.cur = 0;
  124. if ( zero_it != 0 ) {
  125. memset(arena.data, 0, arena.cap);
  126. }
  127. DA_CLEAR(arena.chunks);
  128. return (struct arena_err_t) {
  129. .arena = arena,
  130. .err = ARENA_ERR_OK
  131. };
  132. }
  133. #include <stdio.h>
  134. err_t
  135. arena_dump_chunks(struct arena arena)
  136. {
  137. struct arena_chunk ac = {0};
  138. printf("Allocated Chunks (%li)\n", arena.chunks.size);
  139. for ( size_t i = 0; i < arena.chunks.size; ++i ) {
  140. ac = arena.chunks.items[i];
  141. printf("\tstart: %ld, size: %li\n", ac.start, ac.size);
  142. }
  143. return ARENA_ERR_OK;
  144. }
  145. #endif /* ARENA_IMP || IMPLEMENTATIONS */
  146. #endif /* ARENA_H */