Add some container classes
This commit is contained in:
72
openVulkanoCpp/Data/Containers/ChunkedArrayList.hpp
Normal file
72
openVulkanoCpp/Data/Containers/ChunkedArrayList.hpp
Normal file
@@ -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 <vector>
|
||||
|
||||
namespace openVulkanoCpp
|
||||
{
|
||||
template<typename T>
|
||||
class ChunkedArrayList
|
||||
{
|
||||
size_t m_chunkSize, m_size;
|
||||
std::vector<std::vector<T>> 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<T>&& old) noexcept
|
||||
: m_chunkSize(old.m_chunkSize), m_size(old.m_size), m_chunks(std::move(old.m_chunks))
|
||||
{
|
||||
old.m_size = 0;
|
||||
}
|
||||
|
||||
template<typename ...ARGS>
|
||||
T& EmplaceBack(ARGS&&... args)
|
||||
{
|
||||
EnsureBuffer();
|
||||
m_size++;
|
||||
return m_chunks.back().emplace_back(std::forward<ARGS>(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];
|
||||
}
|
||||
};
|
||||
}
|
||||
227
openVulkanoCpp/Data/Containers/SharedDualTypeBuffer.hpp
Normal file
227
openVulkanoCpp/Data/Containers/SharedDualTypeBuffer.hpp
Normal file
@@ -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 <memory>
|
||||
#include <ostream>
|
||||
#include <istream>
|
||||
|
||||
namespace openVulkanoCpp
|
||||
{
|
||||
template<typename FRONT_TYPE, typename BACK_TYPE, typename = std::enable_if<!std::is_same_v<FRONT_TYPE, BACK_TYPE>>>
|
||||
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<BACK_TYPE*>(static_cast<uint8_t*>(buffer) + size);
|
||||
}
|
||||
|
||||
public:
|
||||
SharedDualTypeBuffer(std::istream& stream, void* buffer = nullptr)
|
||||
: m_ownsMemory(!buffer)
|
||||
{
|
||||
stream.read(reinterpret_cast<char*>(&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<char*>(m_buffer), m_countFront * sizeof(FRONT_TYPE));
|
||||
stream.read(reinterpret_cast<char*>(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<const char*>(&m_size), sizeof(uint64_t) + 2 * sizeof(uint32_t));
|
||||
stream.write(static_cast<const char*>(m_buffer), m_countFront * sizeof(FRONT_TYPE));
|
||||
stream.write(reinterpret_cast<const char*>(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<FRONT_TYPE*>(m_buffer);
|
||||
}
|
||||
|
||||
[[nodiscard]] const FRONT_TYPE* GetFrontBuffer() const
|
||||
{
|
||||
return static_cast<const FRONT_TYPE*>(m_buffer);
|
||||
}
|
||||
|
||||
[[nodiscard]] BACK_TYPE* GetBackBuffer()
|
||||
{
|
||||
return m_end - GetBackCount();
|
||||
}
|
||||
|
||||
[[nodiscard]] const BACK_TYPE* GetBackBuffer() const
|
||||
{
|
||||
return const_cast<SharedDualTypeBuffer*>(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<typename ...ARGS>
|
||||
FRONT_TYPE* EmplaceFront(ARGS&&... args)
|
||||
{
|
||||
if (GetSizeFree() < sizeof(FRONT_TYPE)) return nullptr;
|
||||
FRONT_TYPE* result = new (&GetFrontBuffer()[m_countFront]) FRONT_TYPE(std::forward<ARGS>(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<typename ...ARGS>
|
||||
BACK_TYPE* EmplaceBack(ARGS&&... args)
|
||||
{
|
||||
if (GetSizeFree() < sizeof(BACK_TYPE)) return nullptr;
|
||||
m_countBack++;
|
||||
return new (&GetBackBuffer()[0]) BACK_TYPE(std::forward<ARGS>(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<SharedDualTypeBuffer*>(this)->GetBack(index);
|
||||
}
|
||||
|
||||
// Iterators
|
||||
FRONT_TYPE* BeginFront() { return GetFrontBuffer(); }
|
||||
FRONT_TYPE* EndFront() { return GetFrontBuffer() + GetSize(); }
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user