From 6f36e38651b99a77c3b2ca13b57843de2b668815 Mon Sep 17 00:00:00 2001 From: Matthew Fioravante Date: Wed, 19 Aug 2020 03:20:05 -0400 Subject: [PATCH] DBArrayBase -> DBArrayAlloc static class Break header dependencies on dbarray.h --- CMakeLists.txt | 1 + Makefile.am | 1 + src/dbarray.cpp | 9 ++++---- src/lcf/dbarray.h | 49 ++++++++++-------------------------------- src/lcf/dbarrayalloc.h | 46 +++++++++++++++++++++++++++++++++++++++ src/lcf/dbbitarray.h | 18 ++++++++-------- src/lcf/dbstring.h | 16 +++++++------- 7 files changed, 81 insertions(+), 59 deletions(-) create mode 100644 src/lcf/dbarrayalloc.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2edd3a3a4..80edffe20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -196,6 +196,7 @@ set(LCF_SOURCES set(LCF_HEADERS src/lcf/data.h src/lcf/dbarray.h + src/lcf/dbarrayalloc.h src/lcf/dbbitarray.h src/lcf/dbstring.h src/lcf/encoder.h diff --git a/Makefile.am b/Makefile.am index 64c138320..f06e7b2ee 100644 --- a/Makefile.am +++ b/Makefile.am @@ -203,6 +203,7 @@ liblcf_la_SOURCES = \ lcfinclude_HEADERS = \ src/lcf/data.h \ src/lcf/dbarray.h \ + src/lcf/dbarrayalloc.h \ src/lcf/dbbitarray.h \ src/lcf/dbstring.h \ src/lcf/encoder.h \ diff --git a/src/dbarray.cpp b/src/dbarray.cpp index 8e216838b..0f0debe3f 100644 --- a/src/dbarray.cpp +++ b/src/dbarray.cpp @@ -1,3 +1,4 @@ +#include "lcf/dbarrayalloc.h" #include "lcf/dbarray.h" #include "lcf/dbstring.h" #include @@ -11,11 +12,11 @@ namespace lcf { -constexpr DBArrayBase::size_type DBArrayBase::_empty_buf; +constexpr DBArrayAlloc::size_type DBArrayAlloc::_empty_buf; constexpr DBString::size_type DBString::npos; static ptrdiff_t HeaderSize(size_t align) { - return std::max(sizeof(DBArrayBase::size_type), align); + return std::max(sizeof(DBArrayAlloc::size_type), align); } static size_t AllocSize(size_t size, size_t align) { @@ -26,7 +27,7 @@ static void* Adjust(void* p, ptrdiff_t off) { return reinterpret_cast(reinterpret_cast(p) + off); } -void* DBArrayBase::alloc(size_type size, size_type field_size, size_type align) { +void* DBArrayAlloc::alloc(size_type size, size_type field_size, size_type align) { if (size == 0) { return empty_buf(); } @@ -46,7 +47,7 @@ void* DBArrayBase::alloc(size_type size, size_type field_size, size_type align) return p; } -void DBArrayBase::free(void* p, size_type align) noexcept { +void DBArrayAlloc::free(void* p, size_type align) noexcept { assert(p != nullptr); if (p != empty_buf()) { auto* raw = Adjust(p, -HeaderSize(align)); diff --git a/src/lcf/dbarray.h b/src/lcf/dbarray.h index 038ad94a2..6415c510f 100644 --- a/src/lcf/dbarray.h +++ b/src/lcf/dbarray.h @@ -17,43 +17,18 @@ #include #include +#include "lcf/dbarrayalloc.h" #include "lcf/scope_guard.h" namespace lcf { -class DBArrayBase { - public: - using size_type = uint32_t; - - protected: - constexpr DBArrayBase() = default; - - static void* alloc(size_type size, size_type field_size, size_type align); - static void free(void* p, size_type align) noexcept; - - static constexpr void* empty_buf() { - return const_cast(&_empty_buf + 1); - } - - static size_type* get_size_ptr(void* p) { - return reinterpret_cast(p) - 1; - } - - static const size_type* get_size_ptr(const void* p) { - return reinterpret_cast(p) - 1; - } - - private: - static constexpr const size_type _empty_buf = 0; -}; - // An array data structure optimized for database storage. // Low memory footprint and not dynamically resizable. template -class DBArray : private DBArrayBase { +class DBArray { public: using value_type = T; - using DBArrayBase::size_type; + using size_type = DBArrayAlloc::size_type; using iterator = T*; using const_iterator = const T*; @@ -123,15 +98,15 @@ class DBArray : private DBArrayBase { const_reverse_iterator crend() const { return rend(); } bool empty() const { return size() == 0; } - size_type size() const { return *get_size_ptr(_storage); } + size_type size() const { return *DBArrayAlloc::get_size_ptr(_storage); } private: T* alloc(size_t count) { - return reinterpret_cast(DBArrayBase::alloc(count * sizeof(T), count, alignof(T))); + return reinterpret_cast(DBArrayAlloc::alloc(count * sizeof(T), count, alignof(T))); } void free(void* p) { - DBArrayBase::free(p, alignof(T)); + DBArrayAlloc::free(p, alignof(T)); } template @@ -140,7 +115,7 @@ class DBArray : private DBArrayBase { void destroy() noexcept; void destroy_impl(size_type n) noexcept; private: - void* _storage = DBArrayBase::empty_buf(); + void* _storage = DBArrayAlloc::empty_buf(); }; template @@ -197,18 +172,16 @@ void DBArray::construct(size_type count, const F& make) { template void DBArray::destroy() noexcept { - if (empty()) { - return; + if (_storage != DBArrayAlloc::empty_buf()) { + destroy_impl(size()); + _storage = DBArrayAlloc::empty_buf(); } - destroy_impl(size()); - _storage = DBArrayBase::empty_buf(); } template void DBArray::destroy_impl(size_type n) noexcept { while (n > 0) { - --n; - data()[n].~T(); + data()[--n].~T(); } free(_storage); } diff --git a/src/lcf/dbarrayalloc.h b/src/lcf/dbarrayalloc.h new file mode 100644 index 000000000..6cb6e8709 --- /dev/null +++ b/src/lcf/dbarrayalloc.h @@ -0,0 +1,46 @@ +/* + * This file is part of liblcf. Copyright (c) 2020 liblcf authors. + * https://github.com/EasyRPG/liblcf - https://easyrpg.org + * + * liblcf is Free/Libre Open Source Software, released under the MIT License. + * For the full copyright and license information, please view the COPYING + * file that was distributed with this source code. + */ + +#ifndef LCF_DBARRAYALLOC_H +#define LCF_DBARRAYALLOC_H +#include +#include +#include +#include +#include +#include +#include + +namespace lcf { + +struct DBArrayAlloc { + using size_type = uint32_t; + + static void* alloc(size_type size, size_type field_size, size_type align); + static void free(void* p, size_type align) noexcept; + + static constexpr void* empty_buf() { + return const_cast(&_empty_buf + 1); + } + + static constexpr size_type* get_size_ptr(void* p) { + return static_cast(p) - 1; + } + + static constexpr const size_type* get_size_ptr(const void* p) { + return static_cast(p) - 1; + } + + private: + static constexpr const size_type _empty_buf = 0; +}; + +} // namespace lcf + +#endif diff --git a/src/lcf/dbbitarray.h b/src/lcf/dbbitarray.h index 71f3e3c05..bfedb0297 100644 --- a/src/lcf/dbbitarray.h +++ b/src/lcf/dbbitarray.h @@ -24,7 +24,7 @@ namespace lcf { class DBBitProxy { public: - using size_type = DBArrayBase::size_type; + using size_type = DBArrayAlloc::size_type; constexpr DBBitProxy() = default; @@ -109,10 +109,10 @@ class DBBitProxyIterator { // An array data structure optimized for database storage. // Low memory footprint and not dynamically resizable. -class DBBitArray : private DBArrayBase { +class DBBitArray { public: using value_type = bool; - using DBArrayBase::size_type; + using size_type = DBArrayAlloc::size_type; using iterator = DBBitProxyIterator; using const_iterator = DBBitProxyIterator; @@ -177,7 +177,7 @@ class DBBitArray : private DBArrayBase { const_reverse_iterator crend() const { return rend(); } bool empty() const { return size() == 0; } - size_type size() const { return *get_size_ptr(_storage); } + size_type size() const { return *DBArrayAlloc::get_size_ptr(_storage); } void set_all() { std::memset(_storage, 0xff, bytes_up_from_bits(size())); } void reset_all() { std::memset(_storage, 0, bytes_up_from_bits(size())); } @@ -199,16 +199,16 @@ class DBBitArray : private DBArrayBase { void* alloc(size_type bits) { auto bytes = bytes_up_from_bits(bits); - return DBArrayBase::alloc(bytes, bits, alignof(size_type)); + return DBArrayAlloc::alloc(bytes, bits, alignof(size_type)); } void free(void* p) { - DBArrayBase::free(p, alignof(size_type)); + DBArrayAlloc::free(p, alignof(size_type)); } void destroy() noexcept; private: - void* _storage = DBArrayBase::empty_buf(); + void* _storage = DBArrayAlloc::empty_buf(); }; inline bool operator==(const DBBitArray& l, const DBBitArray& r) { return std::equal(l.begin(), l.end(), r.begin(), r.end()); } @@ -236,9 +236,9 @@ inline DBBitArray& DBBitArray::operator=(DBBitArray&& o) noexcept { } void DBBitArray::destroy() noexcept { - if (_storage != this->empty_buf()) { + if (_storage != DBArrayAlloc::empty_buf()) { free(_storage); - _storage = this->empty_buf(); + _storage = DBArrayAlloc::empty_buf(); } } diff --git a/src/lcf/dbstring.h b/src/lcf/dbstring.h index 95f4a8a1b..686aeb3cd 100644 --- a/src/lcf/dbstring.h +++ b/src/lcf/dbstring.h @@ -19,14 +19,14 @@ #include #include "lcf/string_view.h" -#include "lcf/dbarray.h" +#include "lcf/dbarrayalloc.h" namespace lcf { // A custom string class optimized for database storage. // This string type is good for storing and retrieving values. // It is not good for string manipulation like insertion or concatenation. -class DBString : public DBArrayBase { +class DBString { public: using value_type = char; using size_type = uint32_t; @@ -100,20 +100,20 @@ class DBString : public DBArrayBase { const_reverse_iterator crend() const { return rend(); } bool empty() const { return size() == 0; } - size_type size() const { return *this->get_size_ptr(_storage); } + size_type size() const { return *DBArrayAlloc::get_size_ptr(_storage); } private: char* alloc(size_t count) { - return reinterpret_cast(DBArrayBase::alloc(count + 1, count, 1)); + return reinterpret_cast(DBArrayAlloc::alloc(count + 1, count, 1)); } void free(void* p) { - DBArrayBase::free(p, 1); + DBArrayAlloc::free(p, 1); } void destroy() noexcept; char* construct_z(const char* s, size_t len); char* construct_sv(const char* s, size_t len); private: - void* _storage = this->empty_buf(); + void* _storage = DBArrayAlloc::empty_buf(); }; // This should be used over the conversion operator, so we can track all dbstr -> str instances @@ -163,9 +163,9 @@ inline DBString& DBString::operator=(DBString&& o) noexcept { } inline void DBString::destroy() noexcept { - if (_storage != this->empty_buf()) { + if (_storage != DBArrayAlloc::empty_buf()) { free(_storage); - _storage = this->empty_buf(); + _storage = DBArrayAlloc::empty_buf(); } }