diff options
Diffstat (limited to 'xrena.h')
| -rw-r--r-- | xrena.h | 110 |
1 files changed, 110 insertions, 0 deletions
@@ -0,0 +1,110 @@ +/// __ ___ __ ___ _ __ __ _ +/// \ \/ / '__/ _ \ '_ \ / _` | +/// > <| | | __/ | | | (_| | +/// /_/\_\_| \___|_| |_|\__,_| +/// +/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic +/// +/// xolatile@chud.cyou - xrena - Probably the most minimalistic arena allocator possible, and undoubtedly evil in implementation details. +/// +/// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU +/// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish... +/// +/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied +/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License +/// for more details, if you dare, it is a lot of text that nobody wants to read... + +#ifndef arena_block_limit +#define arena_block_limit (1024 * 1024) +#endif + +static struct { + natural_64 block_count; + natural_64 block_limit; + struct { + natural_64 count; + natural_64 capacity; + character * buffer; + } * * block_array; +} * arena = null; + +static procedure arena_initialize (none) { + natural_64 current = ++arena->block_count - 1; + + arena->block_limit = arena_block_limit; + + arena->block_array = reallocate (arena->block_array, arena->block_count * sizeof (* arena->block_array)); + + arena->block_array [current] = allocate (sizeof (* arena)); + + arena->block_array [current]->buffer = allocate (arena_block_limit); + arena->block_array [current]->count = 0; + arena->block_array [current]->capacity = arena_block_limit; +} + +static procedure arena_deinitialize (none) { + for (natural_64 index = 0; index < arena->block_count; ++index) { + arena->block_array [index]->buffer = deallocate (arena->block_array [index]->buffer); + arena->block_array [index] = deallocate (arena->block_array [index]); + } + + arena->block_array = deallocate (arena->block_array); + arena = deallocate (arena); +} + +static generic * arena_add (natural_64 size) { + natural_64 current = arena->block_count - 1; + + if (arena == null) { + clean_up (arena_deinitialize); + + arena = allocate (sizeof (* arena)); + + arena_initialize (); + } + + fatal_failure (size > arena->block_limit, "arena_add: Block limit reached."); + + if (arena->block_array [current]->count + size > arena->block_array [current]->capacity) { + arena_initialize (); + } + + arena->block_array [current]->count += size; + + return ((v0*) & arena->block_array [current]->buffer [arena->block_array [current]->count - size]); +} + +static character * arena_add_data (generic * data, natural_64 size) { + generic * pointer = arena_add (size); + + memory_copy (pointer, data, size); + + return (pointer); +} + +static character * arena_add_file (character * path, natural flag, boolean null_terminate) { + integer file = -1; + natural_64 size = 0; + character * data = null; + + file = file_open (path, flag); + size = file_size (path) + (natural_64) null_terminate; + data = arena_add (size); + + file_read (file, data, size - (natural_64) null_terminate); + + file = file_close (file); + + return (data); +} + +static natural_64 arena_usage (none) { + natural_64 usage = 0; + + for (natural_64 block = 0; block < arena->block_count; ++block) { + usage += arena->block_array [block]->count; + } + + return (usage); +} + |
