/* * 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; }