diff --git a/openVulkanoCpp/Data/Containers/BinSearchArrayMap.hpp b/openVulkanoCpp/Data/Containers/BinSearchArrayMap.hpp new file mode 100644 index 0000000..1439fc2 --- /dev/null +++ b/openVulkanoCpp/Data/Containers/BinSearchArrayMap.hpp @@ -0,0 +1,100 @@ +/* +* 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 +#include + +namespace OpenVulkano +{ + template class Pair = std::pair, + template class Vec = std::vector, typename = std::enable_if_t::value>> + class BinSearchArrayMap + { + public: + void Insert(K key, const V& value) + { + // Check if the key is bigger than the last element + if (m_data.empty() || key > m_data.back().first) + { + m_data.emplace_back(key, value); + return; + } + + throw std::runtime_error("Key cannot be lesser than the last used key."); + } + + template void Emplace(K key, Args&&... args) + { + // Check if the key is bigger than the last element + if (m_data.empty() || key > m_data.back().first) + { + m_data.emplace_back(key, std::forward(args)...); + return; + } + + throw std::runtime_error("Key cannot be lesser than the last used key."); + } + + void Remove(const K key) + { + std::streamsize index = FindIndexInVector(key); + m_data.erase(m_data.begin() + index); + } + + size_t Size() const { return m_data.size(); } + + V& operator[](const K key) noexcept { return Get(key); } + + V& Get(const K key) { return FindPair(key).second; } + + Pair& FindPair(const K key) + { + std::streamsize index = FindIndexInVector(key); + if (index < 0) + { + throw std::runtime_error("Key not found"); + } + return m_data[index]; + } + + std::streamsize FindIndexInVector(const K key) + { + size_t low = 0; + size_t high = m_data.size(); + + while (low <= high) + { + size_t mid = low + (high - low) / 2; + + if (m_data[mid].first == key) + { + return mid; + } + else if (m_data[mid].first < key) + { + low = mid + 1; + } + else + { + high = mid - 1; + } + } + + return -1; + } + + bool Contains(const K key) noexcept { return FindIndexInVector(key) >= 0; } + + void Clear() { m_data.clear(); } + + private: + Vec> m_data; + }; +} diff --git a/openVulkanoCpp/Data/Containers/StableVector.hpp b/openVulkanoCpp/Data/Containers/StableVector.hpp index ea57fa3..0685f32 100644 --- a/openVulkanoCpp/Data/Containers/StableVector.hpp +++ b/openVulkanoCpp/Data/Containers/StableVector.hpp @@ -1,3 +1,9 @@ +/* + * 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 "Base/Wrapper.hpp" @@ -9,6 +15,8 @@ #include #include +#include + #pragma warning(push) #pragma warning(disable : 4200) #pragma warning(disable : 6011) @@ -22,28 +30,31 @@ namespace OpenVulkano * * @throw Please know that this vector creates array gaps when you remove an element. */ - template class StableVector + template class StableVector { struct VectorChunk { - VectorChunk* m_prev = nullptr; - VectorChunk* m_next = nullptr; - size_t m_chunkSize; - int64_t m_lastUsedIndex; - bool* m_fill; - T m_data[0]; + VectorChunk* m_next = nullptr; // Next chunk + VectorChunk* m_prev = nullptr; // Previous chunk - VectorChunk(size_t size) : m_chunkSize(size), m_lastUsedIndex(-1) + size_t m_size; // Size of the chunk + size_t m_capacity; // Capacity of the chunk + size_t m_nextIndex; // Next index to insert + size_t m_gapCount; // Count of emptied gaps in the chunk + bool* m_occupiedIndices; // filled gaps array + T m_data[0]; // data array + + VectorChunk(size_t size) : m_size(0), m_capacity(size), m_nextIndex(0), m_gapCount(0) { - m_fill = reinterpret_cast(m_data + size); - memset(m_fill, 0, size * sizeof(bool)); + m_occupiedIndices = reinterpret_cast(m_data + size); + memset(m_occupiedIndices, 0, size * sizeof(bool)); } ~VectorChunk() { - for (size_t i = 0; i < m_chunkSize; i++) + for (size_t i = 0; i < m_capacity; i++) { - if (m_fill[i]) + if (m_occupiedIndices[i]) { m_data[i].~T(); } @@ -51,104 +62,181 @@ namespace OpenVulkano m_prev = nullptr; m_next = nullptr; } + + size_t GetRealIndex(size_t reqIndex) + { + if (m_gapCount == 0) + { + return reqIndex; + } + + size_t gapCount = 0; + for (size_t i = 0; i <= reqIndex; i++) + { + if (!m_occupiedIndices[i]) + { + gapCount++; + } + } + + for (size_t i = reqIndex + gapCount; i < m_capacity; i++) + { + if (m_occupiedIndices[i]) + { + return i; + } + } + + return reqIndex + gapCount; + } }; public: + template class Iterator { + friend class StableVector; + public: - Iterator(VectorChunk* ptr, size_t index = 0) : m_ptr(ptr), m_index(index) {} + Iterator(VectorChunk* chunk, size_t index) : m_chunk(chunk), m_index(index) {} - T& operator*() { return m_ptr->m_data[m_index]; } - T* operator->() { return &m_ptr->m_data[m_index]; } + U& operator*() + { + auto realIndex = m_chunk->GetRealIndex(m_index); + return m_chunk->m_data[realIndex]; + } - Iterator operator++() + U* operator->() { return &operator*(); } + + Iterator& operator++() { ++m_index; - MovetoNextValidChunk(); + MoveToNextChunk(); return *this; } Iterator operator++(int) { Iterator temp = *this; - ++(*this); + ++temp; return temp; } - bool operator==(const Iterator& other) const { return m_ptr == other.m_ptr && m_index == other.m_index; } + Iterator& operator--() + { + --m_index; + MoveToPrevChunk(); + return *this; + } + + Iterator operator--(int) + { + Iterator temp = *this; + --temp; + return temp; + } + + Iterator operator+(size_t n) + { + Iterator temp = *this; + temp.m_index += n; + temp.MoveToNextChunk(); + return temp; + } + + Iterator operator-(size_t n) + { + Iterator temp = *this; + temp.m_index -= n; + temp.MoveToPrevChunk(); + return temp; + } + + bool operator==(const Iterator& other) const + { + return m_chunk == other.m_chunk && m_index == other.m_index; + } + bool operator!=(const Iterator& other) const { return !(*this == other); } private: - void MovetoNextValidChunk() + void MoveToNextChunk() { - while (m_ptr && (m_index > m_ptr->m_chunkSize || !m_ptr->m_fill[m_index])) + while (m_chunk && m_index >= m_chunk->m_size) { - if (m_index >= m_ptr->m_chunkSize) - { - m_ptr = m_ptr->m_next; - m_index = 0; - } - else ++m_index; - } - - if (m_ptr && m_index >= m_ptr->m_chunkSize) - { - m_ptr = m_ptr->m_next; - m_index = 0; - MovetoNextValidChunk(); + m_index -= m_chunk->m_size; + m_chunk = m_chunk->m_next; } } + void MoveToPrevChunk() + { + while (m_chunk && m_index < 0) + { + m_index += m_chunk->m_size; + m_chunk = m_chunk->m_prev; + } + } + + std::streamsize GetIteratorIndex() const { return m_chunk->GetRealIndex(m_index); } + private: - VectorChunk* m_ptr; - size_t m_index; + VectorChunk* m_chunk; + std::streamsize m_index; }; public: - StableVector() : m_firstChunk(nullptr), m_lastChunk(nullptr) + using ConstIterator = Iterator; + using RegIterator = Iterator; + + StableVector(size_t size = DEFAULT_CHUNK_SIZE) + : m_firstChunk(nullptr), m_lastChunk(nullptr), m_size(0), m_capacity(0) { - VectorChunk* chunk = SpawnChunk(DEFAULT_CHUNK_SIZE); - m_firstChunk = chunk; - m_lastChunk = chunk; - m_currentSize = 0; - m_totalCap = DEFAULT_CHUNK_SIZE; + m_firstChunk = Grow(size); + m_lastChunk = m_firstChunk; + m_capacity = size; } - StableVector(const StableVector& copy) + StableVector(size_t size, const T& value) : StableVector(size) { - m_firstChunk = nullptr; - m_lastChunk = nullptr; - m_currentSize = 0; - m_totalCap = 0; - - VectorChunk* currentChunk = copy.m_firstChunk; - while (currentChunk) + for (size_t i = 0; i < size; i++) { - for (size_t i = 0; i < currentChunk->m_chunkSize; i++) - { - if (currentChunk->m_fill[i]) { PushBack(currentChunk->m_data[i]); } - } - - currentChunk = currentChunk->m_next; + PushBack(value); } } - StableVector(StableVector&& move) noexcept + StableVector(std::initializer_list list) : StableVector(list.size) + { + for (const T& value: list) + { + PushBack(value); + } + } + + StableVector(const StableVector& copy) : StableVector(copy.m_size) + { + for (size_t i = 0; i < copy.Size(); i++) + { + PushBack(copy.At(i)); + } + } + + StableVector(StableVector&& move) noexcept : m_firstChunk(nullptr) { m_firstChunk = move.m_firstChunk; m_lastChunk = move.m_lastChunk; - m_currentSize = move.m_currentSize; - m_totalCap = move.m_totalCap; + m_size = move.m_size; + m_capacity = move.m_capacity; move.m_firstChunk = nullptr; move.m_lastChunk = nullptr; - move.m_currentSize = 0; - move.m_totalCap = 0; + move.m_size = 0; + move.m_capacity = 0; } ~StableVector() { + // Destroy everything left VectorChunk* currentChunk = m_firstChunk; while (currentChunk) { @@ -159,112 +247,26 @@ namespace OpenVulkano } } - /** - * Adds the value to the first empty slot in the StableVector - * - * @param value - The value to be added - */ - void Add(const T& value) - { - VectorChunk* currentChunk = m_firstChunk; - while (currentChunk) - { - for (size_t i = 0; i < currentChunk->m_chunkSize; i++) - { - if (!currentChunk->m_fill[i]) - { - currentChunk->m_data[i] = value; - currentChunk->m_fill[i] = true; - m_currentSize++; - - if (i > currentChunk->m_lastUsedIndex) currentChunk->m_lastUsedIndex = i; - return; - } - } - - currentChunk = currentChunk->m_next; - } - - VectorChunk* chunk = SpawnChunk(size_t(m_lastChunk->m_chunkSize * GROWTH_FACTOR)); - - new (&m_lastChunk->m_data[++m_lastChunk->m_lastUsedIndex]) T(value); - m_lastChunk->m_fill[m_lastChunk->m_lastUsedIndex] = true; - m_currentSize++; - } - - void PushBack(const T& value) - { - if (m_lastChunk->m_lastUsedIndex + 1 == m_lastChunk->m_chunkSize) - { - VectorChunk* chunk = SpawnChunk(size_t(m_lastChunk->m_chunkSize * GROWTH_FACTOR)); - } - - new (&m_lastChunk->m_data[++m_lastChunk->m_lastUsedIndex]) T(value); - m_lastChunk->m_fill[m_lastChunk->m_lastUsedIndex] = true; - m_currentSize++; - } - - void PushBack(T&& value) noexcept - { - if (m_lastChunk->m_lastUsedIndex + 1 == m_lastChunk->m_chunkSize) - { - VectorChunk* chunk = SpawnChunk(size_t(m_lastChunk->m_chunkSize * GROWTH_FACTOR)); - } - - new (&m_lastChunk->m_data[++m_lastChunk->m_lastUsedIndex]) T(std::move(value)); - m_lastChunk->m_fill[m_lastChunk->m_lastUsedIndex] = true; - m_currentSize++; - } - - template void Emplace(Args&&... args) - { - VectorChunk* currentChunk = m_firstChunk; - - while (currentChunk) - { - for (size_t i = 0; i < currentChunk->m_chunkSize; i++) - { - if (!currentChunk->m_fill[i]) - { - currentChunk->m_data[i] = T(std::forward(args)...); - currentChunk->m_fill[i] = true; - m_currentSize++; - - if (i > currentChunk->m_lastUsedIndex) currentChunk->m_lastUsedIndex = i; - return; - } - } - - currentChunk = currentChunk->m_next; - } - - VectorChunk* chunk = SpawnChunk(size_t(m_lastChunk->m_chunkSize * GROWTH_FACTOR)); - - new (&m_lastChunk->m_data[++m_lastChunk->m_lastUsedIndex]) T(std::forward(args)...); - m_lastChunk->m_fill[m_lastChunk->m_lastUsedIndex] = true; - m_currentSize++; - } + void PushBack(const T& value) { new (InsertBack()) T(value); } + void PushBack(T&& value) noexcept { new (InsertBack()) T(std::move(value)); } template void EmplaceBack(Args&&... args) { - if (m_lastChunk->m_lastUsedIndex + 1 == m_lastChunk->m_chunkSize) - VectorChunk* chunk = SpawnChunk(size_t(m_lastChunk->m_chunkSize * GROWTH_FACTOR)); - - new (&m_lastChunk->m_data[++m_lastChunk->m_lastUsedIndex]) T(std::forward(args)...); - m_lastChunk->m_fill[m_lastChunk->m_lastUsedIndex] = true; - m_currentSize++; + new (InsertBack()) T(std::forward(args)...); } - /** - * Pops the last element of the StableVector - * - * @throw Please know that this pop function also reduces the chunk's lastUsedIndex - */ + void Push(const T& value) { new (Insert()) T(value); } + void Push(T&& value) noexcept { new (Insert()) T(std::move(value)); } + template void Emplace(Args&&... args) { new (Insert()) T(std::forward(args)...); } + void PopBack() { - if (m_currentSize == 0) return; + if (m_size == 0) + { + return; // return? or make + } - if (m_lastChunk->m_lastUsedIndex == -1) + if (m_lastChunk->m_nextIndex == -1) { VectorChunk* temp = m_lastChunk; m_lastChunk = m_lastChunk->m_prev; @@ -273,191 +275,219 @@ namespace OpenVulkano ::operator delete(temp); } - m_lastChunk->m_data[m_lastChunk->m_lastUsedIndex].~T(); - m_lastChunk->m_fill[m_lastChunk->m_lastUsedIndex] = false; - m_lastChunk->m_lastUsedIndex--; - m_currentSize--; + m_lastChunk->m_data[m_lastChunk->m_nextIndex - 1].~T(); + m_lastChunk->m_occupiedIndices[m_lastChunk->m_nextIndex - 1] = false; + m_lastChunk->m_size--; + m_lastChunk->m_gapCount++; + m_size--; + } + + constexpr T& Back() const + { + if (m_size == 0) + { + throw std::out_of_range("Index out of range"); + } + + return m_lastChunk->m_data[m_lastChunk->m_nextIndex - 1]; + } + + constexpr T& Front() const + { + if (m_size == 0) + { + throw std::out_of_range("Index out of range"); + } + + return m_firstChunk->m_data[0]; } void Remove(size_t index) { - size_t localIndex = index; - VectorChunk* chunk = GetChunk(localIndex); - - if (chunk) + auto handle = FindChunk(index); + if (!handle.first) { - chunk->m_data[localIndex].~T(); - chunk->m_fill[localIndex] = false; - m_currentSize--; - } - else throw std::out_of_range("Index out of range!"); - } - - void Remove(const T& value) - { - VectorChunk* currentChunk = m_firstChunk; - while (currentChunk) - { - for (size_t i = 0; i < currentChunk->m_chunkSize; i++) - { - if (currentChunk->m_fill[i] && currentChunk->m_data[i] == value) - { - currentChunk->m_data[i].~T(); - currentChunk->m_fill[i] = false; - m_currentSize--; - return; - } - } - - currentChunk = currentChunk->m_next; - } - } - - std::vector ToVector() const - { - std::vector vec; - VectorChunk* currentChunk = m_firstChunk; - while (currentChunk) - { - for (size_t i = 0; i < currentChunk->m_chunkSize; i++) - { - if (currentChunk->m_fill[i]) - { - vec.push_back(currentChunk->m_data[i]); - } - } - - currentChunk = currentChunk->m_next; + throw std::out_of_range("Index out of range"); } - return vec; - } - T& At(size_t index) const - { - if (index >= Size()) [[unlikely]] - throw std::out_of_range("Index out of range!"); - return (*this)[index]; - } - - T& operator[](size_t index) const - { - VectorChunk* chunk = m_firstChunk; - size_t localIndex = index; - while (chunk) + size_t realIndex = handle.first->GetRealIndex(handle.second); + if (realIndex >= handle.first->m_size) { - if (localIndex > chunk->m_chunkSize - 1) - { - localIndex -= (chunk->m_chunkSize); - chunk = chunk->m_next; - } - else break; + throw std::out_of_range("Index out of range"); } - return chunk->m_data[localIndex]; + Delete(realIndex, handle.first); } - size_t Size() const { return m_currentSize; } - size_t Capacity() const { return m_totalCap; } + void Remove(const RegIterator& it) + { + if (it.m_chunk == nullptr) + { + throw std::out_of_range("Index out of range"); + } + + Delete(it.GetIteratorIndex(), it.m_chunk); + } + + T& operator[](size_t index) noexcept + { + auto handle = FindChunk(index); + size_t realIndex = handle.first->GetRealIndex(handle.second); + return handle.first->m_data[realIndex]; + } + + T& At(size_t index) + { + if (index >= m_size) [[unlikely]] + { + throw std::out_of_range("Index out of range"); + } + + return operator[](index); + } void Clear() { - VectorChunk* currentChunk = m_firstChunk; + // Get the first chunk's cap + size_t cap = m_firstChunk->m_capacity; + + // Annihilate everything + VectorChunk* currentChunk = m_firstChunk->m_next; while (currentChunk) { VectorChunk* temp = currentChunk; currentChunk = currentChunk->m_next; - delete temp; + temp->~VectorChunk(); + ::operator delete(temp); } - m_firstChunk = nullptr; - m_lastChunk = nullptr; - m_currentSize = 0; - m_totalCap = DEFAULT_CHUNK_SIZE; - - m_firstChunk = SpawnChunk(DEFAULT_CHUNK_SIZE); + // Reset the first chunk + m_firstChunk->m_next = nullptr; m_lastChunk = m_firstChunk; + m_firstChunk->m_size = 0; + m_firstChunk->m_nextIndex = 0; + m_firstChunk->m_gapCount = 0; + m_firstChunk->~VectorChunk(); + new (m_firstChunk) VectorChunk(cap); + m_size = 0; + m_capacity = cap; } - StableVector& operator=(const StableVector& copy) - { - if (this == ©) return *this; + size_t Size() const noexcept { return m_size; } + size_t Capacity() const noexcept { return m_capacity; } + bool Empty() const noexcept { return m_size == 0; } - Clear(); + RegIterator begin() { return RegIterator(m_firstChunk, 0); } + RegIterator end() { return RegIterator(m_lastChunk, m_lastChunk->m_nextIndex - 1); } - m_firstChunk = nullptr; - m_lastChunk = nullptr; - m_currentSize = 0; - m_totalCap = 0; + ConstIterator cbegin() const { return ConstIterator(m_firstChunk, 0); } + ConstIterator cend() const { return ConstIterator(m_lastChunk, m_lastChunk->m_nextIndex - 1); } - VectorChunk* currentChunk = copy.m_firstChunk; - - for (auto it = copy.begin(); it != copy.end(); ++it) PushBack(*it); - } - - StableVector& operator=(StableVector&& move) noexcept - { - if (this == &move) return *this; - - Clear(); - - m_firstChunk = move.m_firstChunk; - m_lastChunk = move.m_lastChunk; - m_currentSize = move.m_currentSize; - m_totalCap = move.m_totalCap; - - move.m_firstChunk = nullptr; - move.m_lastChunk = nullptr; - move.m_currentSize = 0; - move.m_totalCap = 0; - - return *this; - } - - Iterator begin() { return Iterator(m_firstChunk, 0); } - Iterator end() { return Iterator(m_lastChunk, m_lastChunk->m_lastUsedIndex + 1); } - - const Iterator& cbegin() const { return Iterator(m_firstChunk, 0); } - const Iterator& cend() const { return Iterator(m_lastChunk, m_lastChunk->m_lastUsedIndex + 1); } + //region std aliases + void push_back(const T& value) { PushBack(value); } + void push_back(T&& value) { PushBack(std::move(value)); } + template void emplace_back(Args&&... args) { EmplaceBack(std::forward(args)...); } + void pop_back() { PopBack(); } + T& back() { return Back(); } + T& front() { return Front(); } + bool empty() const noexcept { return Empty(); } + void clear() { Clear(); } + void erase(const RegIterator& it) { Remove(it); } + size_t size() const noexcept { return Size(); } + size_t capacity() const noexcept { return Capacity(); } + //endregion private: - VectorChunk* SpawnChunk(size_t requestedSize) + VectorChunk* Grow(size_t requestSize) { - VectorChunk* chunk = static_cast( - ::operator new(sizeof(VectorChunk) + requestedSize * sizeof(T) + requestedSize * sizeof(bool))); - new (chunk) VectorChunk(requestedSize); + VectorChunk* newChunk = static_cast( + ::operator new(sizeof(VectorChunk) + requestSize * sizeof(T) + requestSize * sizeof(bool))); + new (newChunk) VectorChunk(requestSize); - if (m_lastChunk) - { - chunk->m_prev = m_lastChunk; - m_lastChunk->m_next = chunk; - m_lastChunk = chunk; - m_totalCap += m_lastChunk->m_chunkSize; - } - - return chunk; + return newChunk; } - VectorChunk* GetChunk(size_t& localIndex) + std::pair FindChunk(size_t index) { - VectorChunk* chunk = m_firstChunk; - while (chunk) + size_t leftIndex = index; + VectorChunk* currentChunk = m_firstChunk; + while (currentChunk) { - if (localIndex > chunk->m_chunkSize - 1) + if (leftIndex < currentChunk->m_size) { - localIndex -= (chunk->m_chunkSize); - chunk = chunk->m_next; + return { currentChunk, leftIndex }; } - else break; + + leftIndex -= currentChunk->m_size; + currentChunk = currentChunk->m_next; } - return chunk; + throw std::out_of_range("Index out of range"); + } + + T* InsertBack() + { + if (m_lastChunk->m_nextIndex == m_lastChunk->m_capacity) + { + VectorChunk* newChunk = Grow(m_lastChunk->m_capacity * GROW_FACTOR); + m_capacity += m_lastChunk->m_capacity * GROW_FACTOR; + m_lastChunk->m_next = newChunk; + newChunk->m_prev = m_lastChunk; + m_lastChunk = newChunk; + } + + m_lastChunk->m_occupiedIndices[m_lastChunk->m_nextIndex] = true; + m_lastChunk->m_size++; + m_lastChunk->m_gapCount++; + m_size++; + return &m_lastChunk->m_data[m_lastChunk->m_nextIndex++]; + } + + T* Insert() + { + T* target = nullptr; + VectorChunk* currentChunk = m_firstChunk; + while (currentChunk) + { + if (currentChunk->m_gapCount > 0) // If there is a gap check occupied indices to find the first gap + { + for (size_t i = 0; i < currentChunk->m_capacity; i++) + { + if (!currentChunk->m_occupiedIndices[i]) + { + target = ¤tChunk->m_data[i]; + currentChunk->m_occupiedIndices[i] = true; + currentChunk->m_size++; + currentChunk->m_gapCount--; + m_size++; + return target; + } + } + } + + currentChunk = currentChunk->m_next; + } + + return InsertBack(); + } + + void Delete(size_t index, VectorChunk* chunk) + { + chunk->m_data[index].~T(); + chunk->m_occupiedIndices[index] = false; + chunk->m_size--; + chunk->m_gapCount++; + m_size--; } private: VectorChunk* m_firstChunk; VectorChunk* m_lastChunk; - size_t m_currentSize; - size_t m_totalCap; + size_t m_size; + size_t m_capacity; + + static inline constexpr size_t DEFAULT_CHUNK_SIZE = 32; + static inline constexpr size_t GROW_FACTOR = 2; }; } diff --git a/tests/BinSearchArrayMapTest.cpp b/tests/BinSearchArrayMapTest.cpp new file mode 100644 index 0000000..65f628e --- /dev/null +++ b/tests/BinSearchArrayMapTest.cpp @@ -0,0 +1,141 @@ +/* +* 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/. +*/ + +#include + +#include +#include +#include +#include + +#include "Data/Containers/BinSearchArrayMap.hpp" +#include "Data/Containers/StableVector.hpp" + +using namespace OpenVulkano; + +TEST_CASE("BinSearchArrayMap With Default") +{ + SECTION("Insert") + { + BinSearchArrayMap map; + + for (int i = 0; i < 50; i++) + { + map.Insert(i, std::to_string(i)); + } + + REQUIRE(map.Size() == 50); + REQUIRE(map.Get(16) == "16"); + REQUIRE(map.Get(23) == "23"); + REQUIRE(map.Get(48) == "48"); + } + + SECTION("Remove") + { + BinSearchArrayMap map; + + for (int i = 0; i < 50; i++) + { + map.Insert(i, std::to_string(i)); + } + + map.Remove(16); + map.Remove(23); + map.Remove(48); + + REQUIRE(map.Size() == 47); + + for (int i = 0; i < 50; i++) + { + if (i == 16 || i == 23 || i == 48) + { + REQUIRE(!map.Contains(i)); + } + else + { + REQUIRE(map.Get(i) == std::to_string(i)); + } + } + } + + SECTION("Emplace") + { + BinSearchArrayMap map; + + for (int i = 0; i < 50; i++) + { + map.Emplace(i, std::to_string(i)); + } + + REQUIRE(map.Size() == 50); + REQUIRE(map.Get(16) == "16"); + REQUIRE(map.Get(23) == "23"); + REQUIRE(map.Get(48) == "48"); + } + + SECTION("FindPair") + { + BinSearchArrayMap map; + + for (int i = 0; i < 50; i++) + { + map.Insert(i, std::to_string(i)); + } + + auto pair = map.FindPair(16); + REQUIRE(pair.first == 16); + REQUIRE(pair.second == "16"); + } +} + +TEST_CASE("BinSearchArrayMap With StableVector") +{ + SECTION("Insert") + { + BinSearchArrayMap map; + + for (int i = 0; i < 50; i++) + { + map.Insert(i, std::to_string(i)); + } + + REQUIRE(map.Size() == 50); + REQUIRE(map.Get(16) == "16"); + REQUIRE(map.Get(23) == "23"); + REQUIRE(map.Get(48) == "48"); + + for (int i = 0; i < 50; i++) + { + REQUIRE(map.Get(i) == std::to_string(i)); + } + } + + SECTION("Remove") + { + BinSearchArrayMap map; + + for (int i = 0; i < 50; i++) + { + map.Insert(i, std::to_string(i)); + } + + map.Remove(16); + map.Remove(23); + map.Remove(48); + + for (int i = 0; i < 50; i++) + { + if (i == 16 || i == 23 || i == 48) + { + REQUIRE(!map.Contains(i)); + } + else + { + REQUIRE(map.Get(i) == std::to_string(i)); + } + } + } +} \ No newline at end of file diff --git a/tests/MemFileTests.cpp b/tests/MemFileTests.cpp index 117ffa5..3cb433e 100644 --- a/tests/MemFileTests.cpp +++ b/tests/MemFileTests.cpp @@ -95,7 +95,6 @@ TEST_CASE("MemMappedFileWrite") OpenVulkano::MemMappedFileWriteHelper::USE_CURRENT_FILE_SIZE); REQUIRE(helper.Data() != nullptr); std::string testData((char*) helper.Data()); - printf("size: %llu", helper.Size()); helper.Close(); std::ifstream file(path, std::ios::binary); @@ -112,8 +111,6 @@ TEST_CASE("MemMappedFileWrite") } REQUIRE(streamData.size() == testData.size()); - - printf("helper size: %llu\n", helper.Size()); } SECTION("Actual Size") diff --git a/tests/StableVectorTest.cpp b/tests/StableVectorTest.cpp index 51b15b3..d0efb35 100644 --- a/tests/StableVectorTest.cpp +++ b/tests/StableVectorTest.cpp @@ -136,7 +136,9 @@ TEST_CASE("ChunkVector") REQUIRE(vec.Size() == 100); vec.Remove(56); - vec.Add("z"); + REQUIRE(vec[56] == "a"); + + vec.Push("z"); REQUIRE(vec.Size() == 100); REQUIRE(vec[56] == "z");