144 lines
2.9 KiB
C
144 lines
2.9 KiB
C
#include "arena.h"
|
|
#include <string.h>
|
|
|
|
|
|
char* arena_strdup(Arena* ref_arena, const char* s){
|
|
char* str = (char*) arena_alloc(ref_arena, strlen(s) + 1);
|
|
if(str == NULL){
|
|
return NULL;
|
|
}
|
|
strcpy(str, s);
|
|
return str;
|
|
}
|
|
|
|
void* arena_chunk_alloc(Arena* ref_arena, Chunk* chunk, size_t s){
|
|
size_t aligned = (chunk->offset + (ARENA_MEMORY_ALIGN - 1)) & ~(ARENA_MEMORY_ALIGN -1);
|
|
if ((aligned + s <= chunk->size)){
|
|
chunk->offset = aligned;
|
|
void* start = (void *)(chunk->buffer + chunk->offset);
|
|
chunk->offset = aligned + s;
|
|
return start;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
Chunk* arena_chunk_create(size_t s){
|
|
printf("Creating a new chunk of %zu bytes\n", s);
|
|
Chunk* chunk1 = (Chunk*)malloc(sizeof(Chunk));
|
|
|
|
if(chunk1 == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
chunk1->size = s;
|
|
chunk1->offset = 0;
|
|
chunk1->next = NULL;
|
|
|
|
chunk1->buffer = (unsigned char *)malloc(s);
|
|
|
|
if(chunk1->buffer == NULL){
|
|
perror("Error creando chunk...\n");
|
|
free(chunk1);
|
|
chunk1 = NULL;
|
|
return NULL;
|
|
}
|
|
|
|
printf("Chunk creado correctamente\n");
|
|
|
|
return chunk1;
|
|
|
|
}
|
|
|
|
void arena_chunk_free(Chunk* chunk){
|
|
printf("Liberando %zu bytes de memoria\n", chunk->size);
|
|
if(chunk->buffer != NULL){
|
|
free(chunk->buffer);
|
|
chunk->buffer = NULL;
|
|
}
|
|
free(chunk);
|
|
}
|
|
|
|
void* arena_alloc(Arena* ref_arena, size_t s){
|
|
if(ref_arena == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
if(ref_arena->current == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
Chunk* current_chunk = ref_arena->current;
|
|
|
|
void* ptr = arena_chunk_alloc(ref_arena, current_chunk, s);
|
|
|
|
if(ptr == NULL){
|
|
|
|
size_t new_size = current_chunk->size * 2;
|
|
|
|
if(new_size < s){
|
|
new_size = s;
|
|
}
|
|
|
|
Chunk *new_chunk = arena_chunk_create(new_size);
|
|
if(new_chunk == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
current_chunk->next = new_chunk;
|
|
new_chunk->next = NULL;
|
|
ref_arena->current = new_chunk;
|
|
|
|
return arena_alloc(ref_arena, s);
|
|
}
|
|
|
|
return ptr;
|
|
|
|
|
|
}
|
|
|
|
Arena arena_create(size_t s){
|
|
Arena new_arena = {
|
|
.current = NULL,
|
|
.first = NULL
|
|
};
|
|
|
|
Chunk* chunk1 = arena_chunk_create(s);
|
|
|
|
if(chunk1 == NULL){
|
|
perror("Error creando arena\n");
|
|
exit(1);
|
|
}
|
|
|
|
new_arena.current = chunk1;
|
|
new_arena.first = chunk1;
|
|
|
|
printf("Arena creada correctamente\n");
|
|
|
|
return new_arena;
|
|
|
|
}
|
|
|
|
void arena_free(Arena* ref_arena){
|
|
Chunk* item = ref_arena->first;
|
|
while (item != NULL) {
|
|
Chunk *next = item->next;
|
|
arena_chunk_free(item);
|
|
item = next;
|
|
}
|
|
|
|
ref_arena->first = NULL;
|
|
ref_arena->current = NULL;
|
|
|
|
printf("Arena liberada\n");
|
|
}
|
|
|
|
void arena_print(Arena* ref_arena){
|
|
printf("ARENA INFO\n");
|
|
printf("==========\n");
|
|
|
|
printf("first: %p\n", ref_arena->first);
|
|
printf("next: %p\n", ref_arena->current);
|
|
|
|
printf("==========\n");
|
|
}
|