From acd5911cd41cad8d9c578edc977bde35220d40a5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Aug 2023 22:20:30 +0200 Subject: [PATCH] - StringPool class added This is a specialized stripped doen FMemArena. --- src/CMakeLists.txt | 1 + src/common/filesystem/fs_stringpool.cpp | 123 ++++++++++++++++++++++++ src/common/filesystem/fs_stringpool.h | 23 +++++ 3 files changed, 147 insertions(+) create mode 100644 src/common/filesystem/fs_stringpool.cpp create mode 100644 src/common/filesystem/fs_stringpool.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a35b048bf2..681a92016a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1222,6 +1222,7 @@ set( ZDOOM_SOURCES common/filesystem/files.cpp common/filesystem/files_decompress.cpp common/filesystem/fs_findfile.cpp + common/filesystem/fs_stringpool.cpp ) diff --git a/src/common/filesystem/fs_stringpool.cpp b/src/common/filesystem/fs_stringpool.cpp new file mode 100644 index 0000000000..4aa46a62f0 --- /dev/null +++ b/src/common/filesystem/fs_stringpool.cpp @@ -0,0 +1,123 @@ +/* +** stringpool.cpp +** allocate static strings from larger blocks +** +**--------------------------------------------------------------------------- +** Copyright 2010 Randy Heit +** Copyright 2023 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "stringpool.h" + +struct StringPool::Block +{ + Block *NextBlock; + void *Limit; // End of this block + void *Avail; // Start of free space in this block + void *alignme; // align to 16 bytes. + + void *Alloc(size_t size); +}; + +//========================================================================== +// +// StringPool Destructor +// +//========================================================================== + +StringPool::~StringPool() +{ + for (Block *next, *block = top; block != nullptr; block = next) + { + next = block->NextBlock; + free(block); + } + top = nullptr; +} + +//========================================================================== +// +// StringPool :: Alloc +// +//========================================================================== + +void *StringPool::Block::Alloc(size_t size) +{ + if ((char *)Avail + size > Limit) + { + return nullptr; + } + void *res = Avail; + Avail = RoundPointer((char *)Avail + size); + return res; +} + +StringPool::Block *StringPool::AddBlock(size_t size) +{ + size += sizeof(Block); // Account for header size + + // Allocate a new block + if (size < BlockSize) + { + size = BlockSize; + } + auto mem = (Block *)malloc(size); + if (mem == nullptr) + { + + } + mem->Limit = (uint8_t *)mem + size; + mem->Avail = &mem[1]; + mem->NextBlock = TopBlock; + TopBlock = mem; + return mem; +} + +void *StringPool::iAlloc(size_t size) +{ + Block *block; + + for (block = TopBlock; block != nullptr; block = block->NextBlock) + { + void *res = block->Alloc(size); + if (res != nullptr) + { + return res; + } + } + block = AddBlock(size); + return block->Alloc(size); +} + +const char* StringPool::Strdup(const char* str) +{ + char* p = (char*)iAlloc((strlen(str) + 15) & ~15 ); + strcpy(p, str); + return p; +} diff --git a/src/common/filesystem/fs_stringpool.h b/src/common/filesystem/fs_stringpool.h new file mode 100644 index 0000000000..ce1e7d83f6 --- /dev/null +++ b/src/common/filesystem/fs_stringpool.h @@ -0,0 +1,23 @@ +#pragma once + +// Storage for all the static strings the file system must hold. +class StringPool +{ +public: + StringPool(size_t blocksize = 10*1024) : TopBlock(nullptr), FreeBlocks(nullptr), BlockSize(blocksize) {} + ~StringPool(); + const char* Strdup(const char*); + +protected: + struct Block; + + Block *AddBlock(size_t size); + void *iAlloc(size_t size); + + Block *TopBlock; + Block *FreeBlocks; + size_t BlockSize; +public: + bool shared; +}; +