From cccb674c3a153ab97e343196f6b6a72b4f4d47ca Mon Sep 17 00:00:00 2001 From: GeorgH93 Date: Wed, 13 Oct 2021 00:57:43 +0200 Subject: [PATCH] Add some container classes --- .../Data/Containers/ChunkedArrayList.hpp | 72 ++++++ .../Data/Containers/SharedDualTypeBuffer.hpp | 227 ++++++++++++++++++ 2 files changed, 299 insertions(+) create mode 100644 openVulkanoCpp/Data/Containers/ChunkedArrayList.hpp create mode 100644 openVulkanoCpp/Data/Containers/SharedDualTypeBuffer.hpp diff --git a/openVulkanoCpp/Data/Containers/ChunkedArrayList.hpp b/openVulkanoCpp/Data/Containers/ChunkedArrayList.hpp new file mode 100644 index 0000000..ab166b8 --- /dev/null +++ b/openVulkanoCpp/Data/Containers/ChunkedArrayList.hpp @@ -0,0 +1,72 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +namespace openVulkanoCpp +{ + template + class ChunkedArrayList + { + size_t m_chunkSize, m_size; + std::vector> m_chunks; //TODO optimize + + void EnsureBuffer() + { + if (m_chunks.empty() || m_chunks.back().capacity() - m_chunks.back().size() == 0) + { + m_chunks.emplace_back().reserve(m_chunkSize); + } + } + + public: + ChunkedArrayList() : m_chunkSize(8192), m_size(0) + {} + + explicit ChunkedArrayList(ChunkedArrayList&& old) noexcept + : m_chunkSize(old.m_chunkSize), m_size(old.m_size), m_chunks(std::move(old.m_chunks)) + { + old.m_size = 0; + } + + template + T& EmplaceBack(ARGS&&... args) + { + EnsureBuffer(); + m_size++; + return m_chunks.back().emplace_back(std::forward(args)...); + } + + T& InsertBack(const T& value) + { + EnsureBuffer(); + m_size++; + return m_chunks.back().insert(value); + } + + T& back() + { + return m_chunks.back().back(); + } + + [[nodiscard]] size_t size() const noexcept + { + return m_size; + } + + T& operator[](size_t n) + { + return m_chunks[n / m_chunkSize][n % m_chunkSize]; + } + + const T& operator[](size_t n) const + { + return m_chunks[n / m_chunkSize][n % m_chunkSize]; + } + }; +} diff --git a/openVulkanoCpp/Data/Containers/SharedDualTypeBuffer.hpp b/openVulkanoCpp/Data/Containers/SharedDualTypeBuffer.hpp new file mode 100644 index 0000000..e3d2ec6 --- /dev/null +++ b/openVulkanoCpp/Data/Containers/SharedDualTypeBuffer.hpp @@ -0,0 +1,227 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include + +namespace openVulkanoCpp +{ + template>> + class SharedDualTypeBuffer + { + uint64_t m_size; + uint32_t m_countFront; + uint32_t m_countBack; + void* m_buffer; + BACK_TYPE* m_end; + bool m_ownsMemory; + + static constexpr BACK_TYPE* CalculateEnd(void* buffer, size_t size) + { + return reinterpret_cast(static_cast(buffer) + size); + } + + public: + SharedDualTypeBuffer(std::istream& stream, void* buffer = nullptr) + : m_ownsMemory(!buffer) + { + stream.read(reinterpret_cast(&m_size), sizeof(uint64_t) + 2 * sizeof(uint32_t)); + m_buffer = buffer ? buffer : ::operator new(m_size); + m_end = CalculateEnd(m_buffer, m_size); + stream.read(static_cast(m_buffer), m_countFront * sizeof(FRONT_TYPE)); + stream.read(reinterpret_cast(GetBackBuffer()), m_countBack * sizeof(BACK_TYPE)); + } + + SharedDualTypeBuffer(size_t size, void* buffer = nullptr) : m_size(size), m_countFront(0), m_countBack(0) + , m_buffer(buffer ? buffer : ::operator new(size)), m_end(CalculateEnd(m_buffer, size)), m_ownsMemory(!buffer) + {} + + SharedDualTypeBuffer(SharedDualTypeBuffer&& buffer) noexcept + : m_size(buffer.m_size), m_countFront(buffer.m_countFront) + , m_countBack(buffer.m_countBack), m_buffer(buffer.m_buffer) + , m_end(buffer.m_end), m_ownsMemory(buffer.m_ownsMemory) + { + buffer.m_size = 0; + buffer.m_countFront = 0; + buffer.m_countBack = 0; + buffer.m_buffer = nullptr; + buffer.m_end = nullptr; + buffer.m_ownsMemory = false; + } + + SharedDualTypeBuffer(const SharedDualTypeBuffer& buffer) + : SharedDualTypeBuffer(buffer.m_size) + { + memcpy(m_buffer, buffer.m_buffer, buffer.m_size); + } + + virtual ~SharedDualTypeBuffer() + { + Clear(); + if (m_ownsMemory) ::operator delete(m_buffer); + } + + void Clear() + { + for(uint32_t i = 0; i < GetFrontCount(); i++) + { + GetFrontBuffer()[i].~FRONT_TYPE(); + } + for (uint32_t i = 0; i < GetBackCount(); i++) + { + GetBackBuffer()[i].~BACK_TYPE(); + } + m_countFront = 0; + m_countBack = 0; + } + + void ToStream(std::ostream& stream) const + { + stream.write(reinterpret_cast(&m_size), sizeof(uint64_t) + 2 * sizeof(uint32_t)); + stream.write(static_cast(m_buffer), m_countFront * sizeof(FRONT_TYPE)); + stream.write(reinterpret_cast(GetBackBuffer()), m_countBack * sizeof(BACK_TYPE)); + } + + SharedDualTypeBuffer& operator =(SharedDualTypeBuffer&& buffer) noexcept + { + if (m_ownsMemory) ::operator delete(m_buffer); + + m_size = buffer.m_size; + m_countFront = buffer.m_countFront; + m_countBack = buffer.m_countBack; + m_buffer = buffer.m_buffer; + m_ownsMemory = buffer.m_ownsMemory; + + buffer.m_size = 0; + buffer.m_countFront = 0; + buffer.m_countBack = 0; + buffer.m_buffer = nullptr; + buffer.m_ownsMemory = false; + } + + [[nodiscard]] size_t GetSizeFree() const + { + return m_size - (sizeof(BACK_TYPE) * m_countBack + sizeof(FRONT_TYPE) * m_countFront); + } + + [[nodiscard]] size_t GetSize() const + { + return m_size; + } + + [[nodiscard]] FRONT_TYPE* GetFrontBuffer() + { + return static_cast(m_buffer); + } + + [[nodiscard]] const FRONT_TYPE* GetFrontBuffer() const + { + return static_cast(m_buffer); + } + + [[nodiscard]] BACK_TYPE* GetBackBuffer() + { + return m_end - GetBackCount(); + } + + [[nodiscard]] const BACK_TYPE* GetBackBuffer() const + { + return const_cast(this)->GetBackBuffer(); + } + + [[nodiscard]] uint32_t GetFrontCount() const + { + return m_countFront; + } + + [[nodiscard]] uint32_t GetBackCount() const + { + return m_countBack; + } + + FRONT_TYPE* InsertFront(const FRONT_TYPE& value) + { + if (GetSizeFree() < sizeof(FRONT_TYPE)) return nullptr; + GetFrontBuffer()[m_countFront] = value; + m_countFront++; + return GetFrontBuffer()[m_countFront - 1]; + } + + FRONT_TYPE* InsertFront(FRONT_TYPE&& value) + { + if (GetSizeFree() < sizeof(FRONT_TYPE)) return nullptr; + GetFrontBuffer()[m_countFront] = std::move(value); + m_countFront++; + return GetFrontBuffer()[m_countFront - 1]; + } + + template + FRONT_TYPE* EmplaceFront(ARGS&&... args) + { + if (GetSizeFree() < sizeof(FRONT_TYPE)) return nullptr; + FRONT_TYPE* result = new (&GetFrontBuffer()[m_countFront]) FRONT_TYPE(std::forward(args)...); + m_countFront++; + return result; + } + + BACK_TYPE* InsertBack(const BACK_TYPE& value) + { + if (GetSizeFree() < sizeof(BACK_TYPE)) return nullptr; + m_countBack++; + GetBackBuffer()[0] = value; + return GetBackBuffer(); + } + + BACK_TYPE* InsertBack(BACK_TYPE&& value) + { + if (GetSizeFree() < sizeof(BACK_TYPE)) return nullptr; + m_countBack++; + GetBackBuffer()[0] = std::move(value); + return GetBackBuffer(); + } + + template + BACK_TYPE* EmplaceBack(ARGS&&... args) + { + if (GetSizeFree() < sizeof(BACK_TYPE)) return nullptr; + m_countBack++; + return new (&GetBackBuffer()[0]) BACK_TYPE(std::forward(args)...); + } + + FRONT_TYPE* Insert(const FRONT_TYPE& value) { return InsertFront(value); } + FRONT_TYPE* Insert(FRONT_TYPE&& value) { return InsertFront(value); } + + BACK_TYPE* Insert(const BACK_TYPE& value) { return InsertBack(value); } + BACK_TYPE* Insert(BACK_TYPE&& value) { return InsertBack(value); } + + FRONT_TYPE& GetFront(size_t index) + { + return GetFrontBuffer()[index]; + } + + const FRONT_TYPE& GetFront(size_t index) const + { + return GetFrontBuffer()[index]; + } + + BACK_TYPE& GetBack(size_t index) + { + return m_end[-index - 1]; + } + + const BACK_TYPE& GetBack(size_t index) const + { + return const_cast(this)->GetBack(index); + } + + // Iterators + FRONT_TYPE* BeginFront() { return GetFrontBuffer(); } + FRONT_TYPE* EndFront() { return GetFrontBuffer() + GetSize(); } + }; +}