impl pair_by_index
[lbutingtaon.git] / lbutingtaon.h
blob64a1d04d1833ec6df4020215f84e88adcac6e3ab
2 /**
3 @section <a href="https://github.com/tsoding/arena">Arena
4 Allocator</a> library from Mr. Zozin.
6 I split up the code to have the header declarations come first and
7 the implementation after that of this library's.
8 */
10 #ifndef ARENA_H_
11 #define ARENA_H_
13 #include <stddef.h>
14 #include <stdint.h>
15 #include <bits/stdint-intn.h>
16 #include <string.h>
18 #ifndef ARENA_NOSTDIO
19 #include <stdarg.h>
20 #include <stdio.h>
21 #endif // ARENA_NOSTDIO
23 #ifndef ARENA_ASSERT
24 #include <assert.h>
25 #define ARENA_ASSERT assert
26 #endif
28 #define ARENA_BACKEND_LIBC_MALLOC 0
29 #define ARENA_BACKEND_LINUX_MMAP 1
30 #define ARENA_BACKEND_WIN32_VIRTUALALLOC 2
31 #define ARENA_BACKEND_WASM_HEAPBASE 3
33 #ifndef ARENA_BACKEND
34 #define ARENA_BACKEND ARENA_BACKEND_LIBC_MALLOC
35 #endif // ARENA_BACKEND
37 typedef struct Region Region;
39 struct Region {
40 Region *next;
41 size_t count;
42 size_t capacity;
43 uintptr_t data[];
46 typedef struct {
47 Region *begin, *end;
48 } Arena;
50 typedef struct {
51 Region *region;
52 size_t count;
53 } Arena_Mark;
55 #define REGION_DEFAULT_CAPACITY (8*1024)
57 Region *new_region(size_t capacity);
58 void free_region(Region *r);
60 void *arena_alloc(Arena *a, size_t size_bytes);
61 void *arena_realloc(Arena *a, void *oldptr, size_t oldsz, size_t newsz);
62 char *arena_strdup(Arena *a, const char *cstr);
63 void *arena_memdup(Arena *a, void *data, size_t size);
64 #ifndef ARENA_NOSTDIO
65 char *arena_sprintf(Arena *a, const char *format, ...);
66 #endif // ARENA_NOSTDIO
68 Arena_Mark arena_snapshot(Arena *a);
69 void arena_reset(Arena *a);
70 void arena_rewind(Arena *a, Arena_Mark m);
71 void arena_free(Arena *a);
72 void arena_trim(Arena *a);
74 #define ARENA_DA_INIT_CAP 256
76 #ifdef __cplusplus
77 #define cast_ptr(ptr) (decltype(ptr))
78 #else
79 #define cast_ptr(...)
80 #endif
82 #define arena_da_append(a, da, item) \
83 do { \
84 if ((da)->count >= (da)->capacity) { \
85 size_t new_capacity = (da)->capacity == 0 ? ARENA_DA_INIT_CAP : (da)->capacity*2; \
86 (da)->items = cast_ptr((da)->items)arena_realloc( \
87 (a), (da)->items, \
88 (da)->capacity*sizeof(*(da)->items), \
89 new_capacity*sizeof(*(da)->items)); \
90 (da)->capacity = new_capacity; \
91 } \
93 (da)->items[(da)->count++] = (item); \
94 } while (0)
96 #endif // ARENA_H_
99 #ifndef LIBBUTINGTAON_H
100 #define LIBBUTINGTAON_H 1
102 #include <stddef.h>
103 #include <assert.h>
104 #include <stdint.h>
106 extern int LBTTN_ERRNO;
108 char* lbttn_decode_errno(int errno);
110 typedef struct lbttn_cell lbttn_cell;
112 typedef lbttn_cell *(*transform_fn)(Arena *context, lbttn_cell *cell, void *param);
113 typedef void (*callback_fn)(lbttn_cell *cell, void *param);
114 typedef int (*compare_fn)(lbttn_cell*, lbttn_cell*);
115 typedef int (*pred_fn)(lbttn_cell*);
116 typedef lbttn_cell *(*reducer_fn)(Arena *context, lbttn_cell *prev, lbttn_cell *next);
118 typedef lbttn_cell *(*from_int_fn)(Arena *context, int64_t integer);
119 typedef lbttn_cell *(*from_uint_fn)(Arena *context, uint64_t uint);
120 typedef lbttn_cell *(*from_dec_fn)(Arena *context, double dec);
121 typedef lbttn_cell *(*from_byte_fn)(Arena *context, char byte);
122 typedef lbttn_cell *(*from_cstring_fn)(Arena *context, char *cstring);
123 typedef int64_t (*cell_get_int_fn)(lbttn_cell *cell);
124 typedef uint64_t (*cell_get_uint_fn)(lbttn_cell *cell);
125 typedef double (*cell_get_decimal_fn)(lbttn_cell *cell);
126 typedef char (*cell_get_byte_fn)(lbttn_cell *cell);
127 typedef char *(*cell_get_cstr_fn)(lbttn_cell *cell);
128 typedef int64_t (*cell_get_cstrlen_fn)(lbttn_cell *cell);
129 typedef int (*cell_set_int_fn)(lbttn_cell *cell, int64_t integer);
130 typedef int (*cell_set_uint_fn)(lbttn_cell *cell, uint64_t uint);
131 typedef int (*cell_set_decimal_fn)(lbttn_cell *cell, double decimal);
132 typedef int (*cell_set_byte_fn)(lbttn_cell *cell, char byte);
133 typedef int (*cell_set_cstr_fn)(lbttn_cell *cell, char* cstr);
136 typedef struct lbttn_cell_vt lbttn_cell_vt;
138 struct lbttn_cell_vt
140 from_int_fn from_int;
141 from_uint_fn from_uint;
142 from_dec_fn from_decimal;
143 from_byte_fn from_byte;
144 from_cstring_fn from_cstr;
145 cell_get_int_fn get_int;
146 cell_get_uint_fn get_uint;
147 cell_get_decimal_fn get_decimal;
148 cell_get_byte_fn get_byte;
149 cell_get_cstr_fn get_cstr;
150 cell_get_cstrlen_fn get_cstrlen;
151 cell_set_int_fn set_int;
152 cell_set_uint_fn set_uint;
153 cell_set_decimal_fn set_decimal;
154 cell_set_byte_fn set_byte;
155 cell_set_cstr_fn set_cstr;
158 extern lbttn_cell_vt Cell_Vt;
160 typedef lbttn_cell *(*pair_head_fn)(lbttn_cell *pair);
161 typedef lbttn_cell *(*pair_rest_fn)(lbttn_cell *pair);
162 typedef lbttn_cell *(*pair_cons_fn)(Arena *context, lbttn_cell *value, lbttn_cell *pair);
163 typedef unsigned int *(*pair_count_fn)(lbttn_cell *pair);
164 typedef lbttn_cell *(*pair_by_index_fn)(lbttn_cell *pair, unsigned int skip);
165 typedef lbttn_cell *(*pair_reverse_fn)(Arena *context, lbttn_cell *pair);
166 typedef lbttn_cell *(*pair_append_fn)(Arena *context, lbttn_cell *pair1, lbttn_cell *pair2);
167 typedef lbttn_cell *(*pair_min_fn)(lbttn_cell *pair, compare_fn compare);
168 typedef lbttn_cell *(*pair_sort_fn)(Arena *context, lbttn_cell *pair, compare_fn compare);
169 typedef lbttn_cell *(*pair_filter_fn)(Arena *context, lbttn_cell *pair, pred_fn predicate);
170 typedef lbttn_cell *(*pair_nil_fn)();
171 typedef lbttn_cell *(*pair_map_fn)(Arena *context, lbttn_cell *pair, transform_fn transform, void *param);
172 typedef void (*pair_foreach_fn)(lbttn_cell *pair, callback_fn callback, void *param);
173 typedef lbttn_cell *(*pair_reduce_fn)(Arena *context, lbttn_cell *pair, reducer_fn reducer);
175 typedef struct lbttn_list_vt lbttn_list_vt;
177 struct lbttn_list_vt
179 pair_head_fn head;
180 pair_rest_fn rest;
181 pair_cons_fn cons;
182 pair_count_fn count;
183 pair_by_index_fn by_index;
184 pair_reverse_fn reverse;
185 pair_append_fn append;
186 pair_min_fn min;
187 pair_sort_fn sort;
188 pair_filter_fn filter;
189 pair_nil_fn nil;
190 pair_map_fn map;
191 pair_foreach_fn foreach;
192 pair_reduce_fn reduce;
195 extern lbttn_list_vt List_Vt;
197 #endif
199 #define LIBBUTINGTAON_IMPL 1
200 #ifdef LIBBUTINGTAON_IMPL
201 #define ARENA_IMPLEMENTATION
203 enum lbttn_type
205 LBTTN_BYTE,
206 LBTTN_INT,
207 LBTTN_UINT,
208 LBTTN_DECIMAL,
209 LBTTN_STRING,
210 LBTTN_ARRAY,
211 LBTTN_PAIR,
212 LBTTN_HASHMAP,
213 LBTTN_CUSTOM
217 @brief The "header" type.
219 This is the entrypoint for the data structures in this library. It
220 uses the header+data approach to type generics in C.
222 struct lbttn_cell
224 enum lbttn_type type;
225 size_t size;
226 void *data;
229 lbttn_cell *cell_from_int(Arena *context, int64_t integer);
230 lbttn_cell *cell_from_uint(Arena *context, uint64_t uint);
231 lbttn_cell *cell_from_decimal(Arena *context, double decimal);
232 lbttn_cell *cell_from_byte(Arena *context, char byte);
233 lbttn_cell *cell_from_cstring(Arena *context, char *cstring);
234 int64_t cell_get_int(lbttn_cell *cell);
235 uint64_t cell_get_uint(lbttn_cell *cell);
236 double cell_get_decimal(lbttn_cell *cell);
237 char cell_get_byte(lbttn_cell *cell);
238 char *cell_get_cstr(lbttn_cell *cell);
239 int64_t cell_get_cstrlen(lbttn_cell *cell);
240 int cell_set_int(lbttn_cell *cell, int64_t integer);
241 int cell_set_uint(lbttn_cell *cell, uint64_t uint);
242 int cell_set_decimal(lbttn_cell *cell, double decimal);
243 int cell_set_byte(lbttn_cell *cell, char byte);
244 int cell_set_cstr(lbttn_cell *cell, char* cstr);
246 lbttn_cell_vt Cell_Vt = (lbttn_cell_vt)
248 .from_int = cell_from_int,
249 .from_uint = cell_from_uint,
250 .from_decimal = cell_from_decimal,
251 .from_byte = cell_from_byte,
252 .from_cstr = cell_from_cstring,
253 .get_int = cell_get_int,
254 .get_uint = cell_get_uint,
255 .get_decimal = cell_get_decimal,
256 .get_byte = cell_get_byte,
257 .get_cstr = cell_get_cstr,
258 .get_cstrlen = cell_get_cstrlen,
259 .set_int = cell_set_int,
260 .set_uint = cell_set_uint,
261 .set_decimal = cell_set_decimal,
262 .set_byte = cell_set_byte,
263 .set_cstr = cell_set_cstr,
266 lbttn_cell *cell_from_int(Arena *context, int64_t integer)
268 lbttn_cell *result = (lbttn_cell *) arena_alloc(context, sizeof(lbttn_cell));
269 result->type = LBTTN_INT;
270 result->size = sizeof(int64_t);
271 result->data = arena_alloc(context, result->size);
272 *((int64_t *) result->data) = integer;
274 return result;
277 lbttn_cell *cell_from_uint(Arena *context, uint64_t uint)
279 lbttn_cell *result = (lbttn_cell *) arena_alloc(context, sizeof(lbttn_cell));
280 result->type = LBTTN_UINT;
281 result->size = sizeof(uint64_t);
282 result->data = arena_alloc(context, result->size);
283 *((uint64_t *) result->data) = uint;
285 return result;
288 lbttn_cell *cell_from_decimal(Arena *context, double decimal)
290 lbttn_cell *result = (lbttn_cell *) arena_alloc(context, sizeof(lbttn_cell));
291 result->type = LBTTN_DECIMAL;
292 result->size = sizeof(double);
293 result->data = arena_alloc(context, result->size);
294 *((double *) result->data) = decimal;
296 return result;
299 lbttn_cell *cell_from_byte(Arena *context, char byte)
301 lbttn_cell *result = (lbttn_cell *) arena_alloc(context, sizeof(lbttn_cell));
302 result->type = LBTTN_BYTE;
303 result->size = sizeof(char);
304 result->data = arena_alloc(context, result->size);
305 *((char *) result->data) = byte;
307 return result;
310 lbttn_cell *cell_from_cstring(Arena *context, char *cstring)
312 lbttn_cell *result = (lbttn_cell *) arena_alloc(context, sizeof(lbttn_cell));
313 int64_t length = 0;
314 char *buffer;
316 result->type = LBTTN_STRING;
319 for ( int64_t index = 0; cstring[index]; index++ ) length++;
322 buffer = (char *) arena_alloc(context, length + 1);
323 result->size = (size_t) length;
326 for ( int64_t index = 0; index < length + 1; index++ ) buffer[index] = 0;
330 for ( int64_t index = 0; index < length; index++ )
331 buffer[index] = cstring[index];
334 result->data = buffer;
336 return result;
339 int64_t cell_get_int(lbttn_cell *cell) { return *((int64_t *) cell->data); }
340 uint64_t cell_get_uint(lbttn_cell *cell) { return *((uint64_t *) cell->data); }
341 double cell_get_decimal(lbttn_cell *cell) { return *((double *) cell->data); }
342 char cell_get_byte(lbttn_cell *cell) { return *((char *) cell->data); }
343 char *cell_get_cstr(lbttn_cell *cell) { return (char *) cell->data; }
344 int64_t cell_get_cstrlen(lbttn_cell *cell) { return (int64_t) cell->size; }
346 int cell_set_int(lbttn_cell *cell, int64_t integer)
348 if ( cell->type != LBTTN_INT )
350 LBTTN_ERRNO = 1;
351 return 1;
354 *((int64_t *) cell->data) = integer;
355 return 0;
359 int cell_set_uint(lbttn_cell *cell, uint64_t uint)
361 if ( cell->type != LBTTN_UINT )
363 LBTTN_ERRNO = 1;
364 return 1;
367 *((uint64_t *) cell->data) = uint;
368 return 0;
371 int cell_set_decimal(lbttn_cell *cell, double decimal)
373 if ( cell->type != LBTTN_DECIMAL )
375 LBTTN_ERRNO = 1;
376 return 1;
379 *((double *) cell->data) = decimal;
380 return 0;
383 int cell_set_byte(lbttn_cell *cell, char byte)
385 if ( cell->type != LBTTN_BYTE )
387 LBTTN_ERRNO = 1;
388 return 1;
391 *((char *) cell->data) = byte;
392 return 0;
395 int cell_set_cstr(lbttn_cell *cell, char* cstr)
397 if ( cell->type != LBTTN_STRING )
399 LBTTN_ERRNO = 1;
400 return 1;
403 cell->data = cstr;
404 return 0;
407 lbttn_cell *pair_head(lbttn_cell *pair);
408 lbttn_cell *pair_rest(lbttn_cell *pair);
409 lbttn_cell *pair_cons(Arena *context, lbttn_cell *value, lbttn_cell *pair);
410 unsigned int *pair_count(lbttn_cell *pair);
411 lbttn_cell *pair_by_index(lbttn_cell *pair, unsigned int skip);
412 lbttn_cell *pair_reverse(Arena *context, lbttn_cell *pair);
413 lbttn_cell *pair_append(Arena *context, lbttn_cell *pair1, lbttn_cell *pair2);
414 lbttn_cell *pair_nil();
416 lbttn_list_vt List_Vt = (lbttn_list_vt)
418 .head = pair_head,
419 .rest = pair_rest,
420 .cons = pair_cons,
421 .by_index = pair_by_index,
422 .reverse = pair_reverse,
423 .nil = pair_nil,
426 struct lbttn_pair
428 lbttn_cell *head;
429 lbttn_cell *rest;
432 static lbttn_cell PAIR_NIL = (lbttn_cell)
434 .type = LBTTN_PAIR,
435 .size = 0,
436 .data = 0
439 lbttn_cell *pair_head(lbttn_cell *pair)
441 if ( pair && pair->data )
443 struct lbttn_pair *as_pair = (struct lbttn_pair *) pair->data;
444 return as_pair->head;
447 else return 0;
450 lbttn_cell *pair_rest(lbttn_cell *pair)
452 struct lbttn_pair *as_pair = (struct lbttn_pair *) pair->data;
453 return as_pair->rest;
456 lbttn_cell *pair_cons(Arena *context, lbttn_cell *value, lbttn_cell *pair)
458 lbttn_cell *result = (lbttn_cell *) arena_alloc(context, sizeof(lbttn_cell));
459 struct lbttn_pair *new_pair = (struct lbttn_pair *) arena_alloc(context, sizeof(struct lbttn_pair));
461 result->type = LBTTN_PAIR;
462 new_pair->head = value;
463 new_pair->rest = pair;
464 result->data = new_pair;
465 result->size = sizeof(struct lbttn_cell);
467 return result;
470 lbttn_cell *pair_reverse(Arena *context, lbttn_cell *pair)
472 lbttn_cell *result = pair_nil();
474 for ( lbttn_cell *tracker = pair;
475 pair_head(tracker);
476 tracker = pair_rest(tracker) )
478 result = pair_cons(context, pair_head(tracker), result);
481 return result;
484 lbttn_cell *pair_nil() { return &PAIR_NIL; }
486 lbttn_cell *pair_by_index(lbttn_cell *pair, unsigned int skip)
488 lbttn_cell *result = pair;
490 for ( unsigned int index = skip; index > 0; index-- )
492 result = pair_rest(result);
495 return result;
498 char* lbttn_decode_errno(int errno) { return ""; };
500 #endif // LIBBUTINGTAON_IMPL
502 #ifdef ARENA_IMPLEMENTATION
504 #if ARENA_BACKEND == ARENA_BACKEND_LIBC_MALLOC
505 #include <stdlib.h>
507 // TODO: instead of accepting specific capacity new_region() should accept the size of the object we want to fit into the region
508 // It should be up to new_region() to decide the actual capacity to allocate
509 Region *new_region(size_t capacity)
511 size_t size_bytes = sizeof(Region) + sizeof(uintptr_t)*capacity;
512 // TODO: it would be nice if we could guarantee that the regions are allocated by ARENA_BACKEND_LIBC_MALLOC are page aligned
513 Region *r = (Region*)malloc(size_bytes);
514 ARENA_ASSERT(r);
515 r->next = NULL;
516 r->count = 0;
517 r->capacity = capacity;
518 return r;
521 void free_region(Region *r)
523 free(r);
525 #elif ARENA_BACKEND == ARENA_BACKEND_LINUX_MMAP
526 #include <unistd.h>
527 #include <sys/mman.h>
529 Region *new_region(size_t capacity)
531 size_t size_bytes = sizeof(Region) + sizeof(uintptr_t) * capacity;
532 Region *r = mmap(NULL, size_bytes, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
533 ARENA_ASSERT(r != MAP_FAILED);
534 r->next = NULL;
535 r->count = 0;
536 r->capacity = capacity;
537 return r;
540 void free_region(Region *r)
542 size_t size_bytes = sizeof(Region) + sizeof(uintptr_t) * r->capacity;
543 int ret = munmap(r, size_bytes);
544 ARENA_ASSERT(ret == 0);
547 #elif ARENA_BACKEND == ARENA_BACKEND_WIN32_VIRTUALALLOC
549 #if !defined(_WIN32)
550 # error "Current platform is not Windows"
551 #endif
553 #define WIN32_LEAN_AND_MEAN
554 #include <windows.h>
556 #define INV_HANDLE(x) (((x) == NULL) || ((x) == INVALID_HANDLE_VALUE))
558 Region *new_region(size_t capacity)
560 SIZE_T size_bytes = sizeof(Region) + sizeof(uintptr_t) * capacity;
561 Region *r = VirtualAllocEx(
562 GetCurrentProcess(), /* Allocate in current process address space */
563 NULL, /* Unknown position */
564 size_bytes, /* Bytes to allocate */
565 MEM_COMMIT | MEM_RESERVE, /* Reserve and commit allocated page */
566 PAGE_READWRITE /* Permissions ( Read/Write )*/
568 if (INV_HANDLE(r))
569 ARENA_ASSERT(0 && "VirtualAllocEx() failed.");
571 r->next = NULL;
572 r->count = 0;
573 r->capacity = capacity;
574 return r;
577 void free_region(Region *r)
579 if (INV_HANDLE(r))
580 return;
582 BOOL free_result = VirtualFreeEx(
583 GetCurrentProcess(), /* Deallocate from current process address space */
584 (LPVOID)r, /* Address to deallocate */
585 0, /* Bytes to deallocate ( Unknown, deallocate entire page ) */
586 MEM_RELEASE /* Release the page ( And implicitly decommit it ) */
589 if (FALSE == free_result)
590 ARENA_ASSERT(0 && "VirtualFreeEx() failed.");
593 #elif ARENA_BACKEND == ARENA_BACKEND_WASM_HEAPBASE
594 # error "TODO: WASM __heap_base backend is not implemented yet"
595 #else
596 # error "Unknown Arena backend"
597 #endif
599 // TODO: add debug statistic collection mode for arena
600 // Should collect things like:
601 // - How many times new_region was called
602 // - How many times existing region was skipped
603 // - How many times allocation exceeded REGION_DEFAULT_CAPACITY
605 void *arena_alloc(Arena *a, size_t size_bytes)
607 size_t size = (size_bytes + sizeof(uintptr_t) - 1)/sizeof(uintptr_t);
609 if (a->end == NULL) {
610 ARENA_ASSERT(a->begin == NULL);
611 size_t capacity = REGION_DEFAULT_CAPACITY;
612 if (capacity < size) capacity = size;
613 a->end = new_region(capacity);
614 a->begin = a->end;
617 while (a->end->count + size > a->end->capacity && a->end->next != NULL) {
618 a->end = a->end->next;
621 if (a->end->count + size > a->end->capacity) {
622 ARENA_ASSERT(a->end->next == NULL);
623 size_t capacity = REGION_DEFAULT_CAPACITY;
624 if (capacity < size) capacity = size;
625 a->end->next = new_region(capacity);
626 a->end = a->end->next;
629 void *result = &a->end->data[a->end->count];
630 a->end->count += size;
631 return result;
634 void *arena_realloc(Arena *a, void *oldptr, size_t oldsz, size_t newsz)
636 if (newsz <= oldsz) return oldptr;
637 void *newptr = arena_alloc(a, newsz);
638 char *newptr_char = (char*)newptr;
639 char *oldptr_char = (char*)oldptr;
640 for (size_t i = 0; i < oldsz; ++i) {
641 newptr_char[i] = oldptr_char[i];
643 return newptr;
646 char *arena_strdup(Arena *a, const char *cstr)
648 size_t n = strlen(cstr);
649 char *dup = (char*)arena_alloc(a, n + 1);
650 memcpy(dup, cstr, n);
651 dup[n] = '\0';
652 return dup;
655 void *arena_memdup(Arena *a, void *data, size_t size)
657 return memcpy(arena_alloc(a, size), data, size);
660 #ifndef ARENA_NOSTDIO
661 char *arena_sprintf(Arena *a, const char *format, ...)
663 va_list args;
664 va_start(args, format);
665 int n = vsnprintf(NULL, 0, format, args);
666 va_end(args);
668 ARENA_ASSERT(n >= 0);
669 char *result = (char*)arena_alloc(a, n + 1);
670 va_start(args, format);
671 vsnprintf(result, n + 1, format, args);
672 va_end(args);
674 return result;
676 #endif // ARENA_NOSTDIO
678 Arena_Mark arena_snapshot(Arena *a)
680 Arena_Mark m;
681 if(a->end == NULL){ //snapshot of uninitialized arena
682 ARENA_ASSERT(a->begin == NULL);
683 m.region = a->end;
684 m.count = 0;
685 }else{
686 m.region = a->end;
687 m.count = a->end->count;
690 return m;
693 void arena_reset(Arena *a)
695 for (Region *r = a->begin; r != NULL; r = r->next) {
696 r->count = 0;
699 a->end = a->begin;
702 void arena_rewind(Arena *a, Arena_Mark m)
704 if(m.region == NULL){ //snapshot of uninitialized arena
705 arena_reset(a); //leave allocation
706 return;
709 m.region->count = m.count;
710 for (Region *r = m.region->next; r != NULL; r = r->next) {
711 r->count = 0;
714 a->end = m.region;
717 void arena_free(Arena *a)
719 Region *r = a->begin;
720 while (r) {
721 Region *r0 = r;
722 r = r->next;
723 free_region(r0);
725 a->begin = NULL;
726 a->end = NULL;
729 void arena_trim(Arena *a){
730 Region *r = a->end->next;
731 while (r) {
732 Region *r0 = r;
733 r = r->next;
734 free_region(r0);
736 a->end->next = NULL;
739 #endif // ARENA_IMPLEMENTATION