From 10bb8a05088f1d3bb24f7167f609b5f6fb0ba026 Mon Sep 17 00:00:00 2001 From: Johnny Richard Date: Wed, 30 Oct 2024 22:58:03 +0100 Subject: bootstrap project Signed-off-by: Johnny Richard --- src/arena.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 src/arena.c (limited to 'src/arena.c') diff --git a/src/arena.c b/src/arena.c new file mode 100644 index 0000000..8822fdd --- /dev/null +++ b/src/arena.c @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2025 Johnny Richard + * + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * This file is part of obe. + * + * obe is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * obe is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with obe. If not, see . + */ +#include +#include +#include +#include + +void* +obe_arena_alloc(obe_arena_t* arena, size_t size) +{ + if (arena->end == NULL) { + assert(arena->begin == NULL); + size_t capacity = OBE_ARENA_REGION_DEFAULT_CAPACITY; + if (capacity < OBE_ARENA_PADDING(size)) + capacity = size + OBE_ARENA_PADDING(size); + arena->end = obe_arena_region_new(capacity); + arena->begin = arena->end; + } + + while (arena->end->offset + size > arena->end->capacity && + arena->end->next != NULL) { + arena->end = arena->end->next; + } + + if (arena->end->offset + size > arena->end->capacity) { + assert(arena->end->next == NULL); + size_t capacity = OBE_ARENA_REGION_DEFAULT_CAPACITY; + if (capacity < size) + capacity = size + OBE_ARENA_PADDING(size); + arena->end->next = obe_arena_region_new(capacity); + arena->end = arena->end->next; + } + + void* ptr = arena->end->data + arena->end->offset; + arena->end->offset += size + OBE_ARENA_PADDING(size); + return ptr; +} + +void* +obe_arena_realloc(obe_arena_t* arena, + void* old_ptr, + size_t old_size, + size_t new_size) +{ + if (new_size <= old_size) + return old_ptr; + void* new_ptr = obe_arena_alloc(arena, new_size); + return memcpy(new_ptr, old_ptr, old_size); +} + +void +obe_arena_release(obe_arena_t* arena) +{ + for (obe_arena_region_t* r = arena->begin; r != NULL; r = r->next) { + r->offset = 0; + } + arena->end = arena->begin; +} + +void +obe_arena_free(obe_arena_t* arena) +{ + obe_arena_region_t* r = arena->begin; + while (r) { + obe_arena_region_t* r_tmp = r; + r = r->next; + obe_arena_region_free(r_tmp); + } + arena->begin = NULL; + arena->end = NULL; +} + +obe_arena_region_t* +obe_arena_region_new(size_t capacity) +{ + size_t size = sizeof(obe_arena_region_t) + sizeof(uint8_t) * capacity; + obe_arena_region_t* r = (obe_arena_region_t*)malloc(size); + assert(r); + r->next = NULL; + r->offset = 0; + r->capacity = capacity; + r->data = (uint8_t*)(r + 1); + return r; +} + +void +obe_arena_region_free(obe_arena_region_t* r) +{ + free(r); +} + +char* +obe_arena_strdup(obe_arena_t* arena, char* s) +{ + size_t slen = strlen(s); + char* d = obe_arena_alloc(arena, sizeof(char) * (slen + 1)); + assert(d); + + for (size_t i = 0; i <= slen; ++i) + d[i] = s[i]; + + return d; +} -- cgit v1.2.3