http.c/src/arena.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_