81 lines
1.5 KiB
C
81 lines
1.5 KiB
C
#ifndef ARENA_
|
|
#define ARENA_
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define ARENA_BLOCK_SIZE 256
|
|
|
|
#include "byte_slice.c"
|
|
|
|
struct arena {
|
|
uint8_t *ptr;
|
|
size_t len;
|
|
size_t capacity;
|
|
};
|
|
|
|
int arena_init(struct arena *arena) {
|
|
arena->ptr = malloc(ARENA_BLOCK_SIZE);
|
|
if (!arena->ptr) {
|
|
return -1;
|
|
}
|
|
|
|
arena->len = 0;
|
|
arena->capacity = ARENA_BLOCK_SIZE;
|
|
return 0;
|
|
}
|
|
|
|
void arena_deinit(struct arena *arena) {
|
|
free(arena->ptr);
|
|
arena->ptr = NULL;
|
|
}
|
|
|
|
static uint64_t div_round_up(uint64_t a, uint64_t b) {
|
|
return a % b == 0 ? a / b * b : (a / b + 1) * b;
|
|
}
|
|
|
|
void *arena_alloc(struct arena *arena, size_t size) {
|
|
if (arena->ptr == NULL && arena_init(arena)) {
|
|
return NULL;
|
|
}
|
|
|
|
if (arena->len + size > arena->capacity) {
|
|
size_t new_capacity = div_round_up(arena->len + size, ARENA_BLOCK_SIZE);
|
|
void *new_ptr = realloc(arena->ptr, new_capacity);
|
|
if (!new_ptr) {
|
|
return NULL;
|
|
}
|
|
arena->ptr = new_ptr;
|
|
arena->capacity = new_capacity;
|
|
}
|
|
|
|
void *result = (void*)&arena->ptr[arena->len];
|
|
arena->len += size;
|
|
return result;
|
|
}
|
|
|
|
void *arena_dupe(struct arena *arena, void *ptr, size_t len) {
|
|
void *new_ptr = arena_alloc(arena, len);
|
|
if (!new_ptr) {
|
|
return NULL;
|
|
}
|
|
|
|
if (ptr) {
|
|
memcpy(new_ptr, ptr, len);
|
|
}
|
|
|
|
return new_ptr;
|
|
}
|
|
|
|
struct byte_slice arena_dupe_slice(struct arena *arena, struct byte_slice slice) {
|
|
void *new_ptr = arena_dupe(arena, slice.ptr, slice.len);
|
|
if (!new_ptr) {
|
|
return byte_slice_init_zero();
|
|
}
|
|
|
|
return byte_slice_init(new_ptr, slice.len);
|
|
}
|
|
|
|
#endif //ARENA_
|