/// __ ___ __ ___ _ __ __ _ /// \ \/ / '__/ _ \ '_ \ / _` | /// > <| | | __/ | | | (_| | /// /_/\_\_| \___|_| |_|\__,_| /// /// 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 { ulong block_count; ulong block_limit; struct { ulong count; ulong capacity; char * buffer; } * * block_array; } * arena = null; static void arena_initialize (void) { ulong 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 void arena_deinitialize (void) { for (ulong 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 void * arena_add (ulong size) { ulong 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 ((void*) & arena->block_array [current]->buffer [arena->block_array [current]->count - size]); } static char * arena_add_data (void * data, ulong size) { void * pointer = arena_add (size); memory_copy (pointer, data, size); return (pointer); } static char * arena_add_file (char * path, uint flag, bool null_terminate) { int file = -1; ulong size = 0; char * data = null; file = file_open (path, flag); size = file_size (path) + (ulong) null_terminate; data = arena_add (size); file_read (file, data, size - (ulong) null_terminate); file = file_close (file); return (data); } static ulong arena_usage (void) { ulong usage = 0; for (ulong block = 0; block < arena->block_count; ++block) { usage += arena->block_array [block]->count; } return (usage); }