108 lines
2.5 KiB
C
108 lines
2.5 KiB
C
// retoor <retoor@molodetz.nl>
|
|||
|
|
|
||
|
|
#include "memory.h"
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
arena_t *arena_create(size_t chunk_size) {
|
||
|
|
if (chunk_size == 0) chunk_size = 4096;
|
||
|
|
|
||
|
|
arena_t *arena = calloc(1, sizeof(arena_t));
|
||
|
|
if (!arena) return NULL;
|
||
|
|
|
||
|
|
arena->block_size = chunk_size;
|
||
|
|
arena->current_block = malloc(chunk_size);
|
||
|
|
if (!arena->current_block) {
|
||
|
|
free(arena);
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
arena_block_t *block_info = calloc(1, sizeof(arena_block_t));
|
||
|
|
if (!block_info) {
|
||
|
|
free(arena->current_block);
|
||
|
|
free(arena);
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
block_info->data = arena->current_block;
|
||
|
|
block_info->size = chunk_size;
|
||
|
|
arena->blocks = block_info;
|
||
|
|
arena->block_count = 1;
|
||
|
|
|
||
|
|
return arena;
|
||
|
|
}
|
||
|
|
|
||
|
|
void *arena_alloc(arena_t *arena, size_t size) {
|
||
|
|
if (!arena || size == 0) return NULL;
|
||
|
|
|
||
|
|
size_t aligned_size = (size + 7) & ~7;
|
||
|
|
|
||
|
|
if (arena->block_used + aligned_size > arena->block_size) {
|
||
|
|
arena_block_t *new_block = calloc(1, sizeof(arena_block_t));
|
||
|
|
if (!new_block) return NULL;
|
||
|
|
|
||
|
|
char *new_data = malloc(arena->block_size);
|
||
|
|
if (!new_data) {
|
||
|
|
free(new_block);
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
new_block->data = new_data;
|
||
|
|
new_block->size = arena->block_size;
|
||
|
|
new_block->next = arena->blocks;
|
||
|
|
arena->blocks = new_block;
|
||
|
|
arena->current_block = new_data;
|
||
|
|
arena->block_used = 0;
|
||
|
|
arena->block_count++;
|
||
|
|
}
|
||
|
|
|
||
|
|
void *ptr = arena->current_block + arena->block_used;
|
||
|
|
arena->block_used += aligned_size;
|
||
|
|
|
||
|
|
return ptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
char *arena_strdup(arena_t *arena, const char *str) {
|
||
|
|
if (!arena || !str) return NULL;
|
||
|
|
|
||
|
|
size_t len = strlen(str);
|
||
|
|
char *copy = arena_alloc(arena, len + 1);
|
||
|
|
if (!copy) return NULL;
|
||
|
|
|
||
|
|
memcpy(copy, str, len + 1);
|
||
|
|
return copy;
|
||
|
|
}
|
||
|
|
|
||
|
|
void arena_reset(arena_t *arena) {
|
||
|
|
if (!arena) return;
|
||
|
|
arena->block_used = 0;
|
||
|
|
|
||
|
|
arena_block_t *block = arena->blocks;
|
||
|
|
while (block) {
|
||
|
|
arena_block_t *next = block->next;
|
||
|
|
if (block != arena->blocks) {
|
||
|
|
free(block->data);
|
||
|
|
free(block);
|
||
|
|
}
|
||
|
|
block = next;
|
||
|
|
}
|
||
|
|
|
||
|
|
arena->blocks->next = NULL;
|
||
|
|
arena->current_block = arena->blocks->data;
|
||
|
|
arena->block_count = 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
void arena_destroy(arena_t *arena) {
|
||
|
|
if (!arena) return;
|
||
|
|
|
||
|
|
arena_block_t *block = arena->blocks;
|
||
|
|
while (block) {
|
||
|
|
arena_block_t *next = block->next;
|
||
|
|
free(block->data);
|
||
|
|
free(block);
|
||
|
|
block = next;
|
||
|
|
}
|
||
|
|
|
||
|
|
free(arena);
|
||
|
|
}
|