137 lines
3.2 KiB
C
137 lines
3.2 KiB
C
global const SizeU default_reserve_size = gib(4);
|
|
global const SizeU default_alignment = 8;
|
|
global const SizeU additional_commit_size = mib(1);
|
|
function SizeU align_up(SizeU size, SizeU align);
|
|
|
|
function void
|
|
memory_copy(void *dst, void *src, SizeU size){
|
|
U8 *d = (U8*)dst;
|
|
U8 *s = (U8*)src;
|
|
for(SizeU i = 0; i < size; i++){
|
|
d[i] = s[i];
|
|
}
|
|
}
|
|
|
|
function void
|
|
memory_zero(void *p, SizeU size){
|
|
U8 *pp = (U8 *)p;
|
|
for(SizeU i = 0; i < size; i++)
|
|
pp[i] = 0;
|
|
}
|
|
|
|
function int
|
|
max_int(int a, int b){
|
|
if(a>b) return a;
|
|
return b;
|
|
}
|
|
|
|
function void
|
|
arena_init(Arena *a){
|
|
a->memory = os_reserve(default_reserve_size);
|
|
a->alignment = default_alignment;
|
|
}
|
|
|
|
function void *
|
|
arena_push_size(Arena *a, SizeU size){
|
|
SizeU generous_size = size;
|
|
if(a->memory.commit+generous_size>a->memory.commit){
|
|
if(a->memory.reserve == 0){
|
|
arena_init(a);
|
|
}
|
|
os_commit(&a->memory, generous_size+additional_commit_size);
|
|
}
|
|
|
|
a->len = align_up(a->len, a->alignment);
|
|
void *result = (U8*)a->memory.data + a->len;
|
|
a->len += size;
|
|
|
|
memory_zero(result, size);
|
|
return result;
|
|
}
|
|
|
|
function void *
|
|
arena_push_copy(Arena *a, void *pointer, SizeU size){
|
|
void *result = arena_push_size(a, size);
|
|
memory_copy(result, pointer, size);
|
|
return result;
|
|
}
|
|
|
|
function SizeU
|
|
clamp_top_sizeu(SizeU val, SizeU max){
|
|
if(val>max)return max;
|
|
return val;
|
|
}
|
|
|
|
function void
|
|
arena_pop_pos(Arena *arena, SizeU pos){
|
|
pos = clamp_top_sizeu(pos, arena->len);
|
|
arena->len = pos;
|
|
}
|
|
|
|
function Arena_Checkpoint
|
|
arena_checkpoint(Arena *arena){
|
|
Arena_Checkpoint result = {arena, arena->len};
|
|
return result;
|
|
}
|
|
|
|
function void
|
|
arena_restore(Arena_Checkpoint checkpoint){
|
|
arena_pop_pos(checkpoint.arena, checkpoint.pos);
|
|
}
|
|
|
|
function String
|
|
arena_push_string_copy(Arena *arena, String string){
|
|
U8 *copy = arena_push_array(arena, U8, string.len+1);
|
|
memory_copy(copy, string.str, string.len);
|
|
copy[string.len] = 0;
|
|
return (String){copy, string.len};
|
|
}
|
|
|
|
function String
|
|
string_fmtv(Arena *arena, const char *str, va_list args1) {
|
|
va_list args2;
|
|
va_copy(args2, args1);
|
|
S64 len = vsnprintf(0, 0, str, args2);
|
|
va_end(args2);
|
|
|
|
char *result = (char *)arena_push_size(arena, len + 1);
|
|
vsnprintf(result, len + 1, str, args1);
|
|
if (arena->len > 0)
|
|
arena->len -= 1;
|
|
|
|
String res = {(U8 *)result, len};
|
|
return res;
|
|
}
|
|
|
|
#define STRING_FMT(arena, str, result) \
|
|
va_list args1; \
|
|
va_start(args1, str); \
|
|
String result = string_fmtv(arena, str, args1); \
|
|
va_end(args1)
|
|
|
|
function String
|
|
string_fmt(Arena *arena, const char *str, ...) {
|
|
STRING_FMT(arena, str, result);
|
|
return result;
|
|
}
|
|
|
|
function void
|
|
string_listf(Arena *arena, String_List *list, const char *str, ...){
|
|
STRING_FMT(arena, str, string);
|
|
String_Node *node = arena_push_struct(arena, String_Node);
|
|
node->string = string;
|
|
SLLQueuePush(list->first, list->last, node);
|
|
list->char_count += node->string.len;
|
|
list->node_count += 1;
|
|
}
|
|
|
|
function String
|
|
string_list_flatten(Arena *arena, String_List *list){
|
|
String result = {(U8 *)arena_push_size(arena, list->char_count + 1)};
|
|
for(String_Node *node = list->first; node; node=node->next){
|
|
memory_copy(result.str+result.len, node->str, node->len);
|
|
result.len += node->len;
|
|
}
|
|
return result;
|
|
}
|