Add some container classes

This commit is contained in:
2021-10-13 00:57:43 +02:00
parent fe12fe649d
commit cccb674c3a
2 changed files with 299 additions and 0 deletions

View 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];
}
};
}

View 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(); }
};
}