From b2220d981ff96770428d71734df6418f568cd7a7 Mon Sep 17 00:00:00 2001 From: Romain BOULLARD Date: Fri, 31 Jul 2026 18:27:05 +0200 Subject: [PATCH] References. Removed testing, will rewrite the tests tomorrow --- .../Benchmarks/Utils/Container/SlotMap.cpp | 16 +- Bigfoot/Sources/Engine/Asset/Reference.cpp | 34 + .../Engine/Include/Engine/Asset/Asset.hpp | 87 +- .../Include/Engine/Asset/AssetContainer.hpp | 163 +++- .../Include/Engine/Asset/AssetHelper.hpp | 8 +- .../Include/Engine/Asset/AssetLibrary.hpp | 59 +- .../Engine/Asset/AssetTypeID_generated.hpp | 7 + .../Include/Engine/Asset/Asset_generated.hpp | 7 + .../Engine/Include/Engine/Asset/Reference.fbs | 14 +- .../Engine/Include/Engine/Asset/Reference.hpp | 282 +++++- .../Engine/Asset/Reference_generated.hpp | 99 ++ .../Include/System/Time/Time_generated.hpp | 7 + .../Include/System/UUID/UUID_generated.hpp | 7 + .../Include/Utils/Containers/SlotMap.hpp | 852 +++++++++++++++--- .../Utils/Include/Utils/Log/Log_generated.hpp | 7 + Bigfoot/Tests/Engine/Asset/Asset.cpp | 205 ----- Bigfoot/Tests/Engine/Asset/AssetContainer.cpp | 72 -- Bigfoot/Tests/Engine/Asset/AssetLibrary.cpp | 74 -- Bigfoot/Tests/Engine/BigFile/BigFile.cpp | 147 --- .../Misc/AssetsForTesting/Asset/AssetA.cpp | 2 +- .../Misc/AssetsForTesting/Asset/AssetB.cpp | 2 +- .../Misc/AssetsForTesting/Asset/AssetC.cpp | 2 +- .../Include/AssetsForTesting/Asset/AssetA.fbs | 2 +- .../Include/AssetsForTesting/Asset/AssetA.hpp | 2 +- .../Asset/AssetA_generated.hpp | 30 + .../Include/AssetsForTesting/Asset/AssetB.fbs | 4 +- .../Include/AssetsForTesting/Asset/AssetB.hpp | 2 +- .../Asset/AssetB_generated.hpp | 37 + .../Include/AssetsForTesting/Asset/AssetC.fbs | 11 +- .../Include/AssetsForTesting/Asset/AssetC.hpp | 2 +- .../Asset/AssetC_generated.hpp | 93 +- Bigfoot/Tests/Utils/Containers/SlotMap.cpp | 539 ----------- 32 files changed, 1525 insertions(+), 1350 deletions(-) create mode 100644 Bigfoot/Sources/Engine/Asset/Reference.cpp delete mode 100644 Bigfoot/Tests/Engine/Asset/Asset.cpp delete mode 100644 Bigfoot/Tests/Engine/Asset/AssetContainer.cpp delete mode 100644 Bigfoot/Tests/Engine/Asset/AssetLibrary.cpp delete mode 100644 Bigfoot/Tests/Engine/BigFile/BigFile.cpp delete mode 100644 Bigfoot/Tests/Utils/Containers/SlotMap.cpp diff --git a/Bigfoot/Benchmarks/Utils/Container/SlotMap.cpp b/Bigfoot/Benchmarks/Utils/Container/SlotMap.cpp index ae8bc14..6b11307 100644 --- a/Bigfoot/Benchmarks/Utils/Container/SlotMap.cpp +++ b/Bigfoot/Benchmarks/Utils/Container/SlotMap.cpp @@ -37,22 +37,23 @@ static_assert(sizeof(MyComplexStruct) == 64, "Payload should be exactly one cach static_assert(std::is_trivially_copyable_v, "Container moves should be a plain memcpy, not a heap-touching move."); +template class SlotMapAdaptor { public: - using Key = SlotMap::InternalSlotKey; + using Key = SlotMapKey; - Key Add(MyComplexStruct&& p_value) + SlotMapKey Add(MyComplexStruct&& p_value) { return m_container.Insert(std::move(p_value)); } - const MyComplexStruct* Find(const Key p_key) const + const MyComplexStruct* Find(const SlotMapKey p_key) const { return m_container.Get(p_key); } - void Remove(const Key p_key) + void Remove(const SlotMapKey p_key) { m_container.Remove(p_key); } @@ -72,7 +73,7 @@ class SlotMapAdaptor } private: - SlotMap m_container; + SLOTMAP m_container; }; template @@ -233,13 +234,16 @@ void Iterate(benchmark::State& state) BENCHMARK_TEMPLATE(Get, ADAPTOR)->Name(NAME "/Get")->Arg(512)->Arg(8192)->Arg(262'144)->Arg(4'194'304); \ BENCHMARK_TEMPLATE(Iterate, ADAPTOR)->Name(NAME "/Iterate")->Arg(512)->Arg(8192)->Arg(262'144)->Arg(4'194'304); +using DenseSlotMapHarness = SlotMapAdaptor>; +using StableSlotMapHarness = SlotMapAdaptor>; using UnorderedDenseMapHarness = HashMapHarnessAdaptor>; using UnorderedDenseSegementedMapHarness = HashMapHarnessAdaptor>; using UnorderedMapHarness = HashMapHarnessAdaptor>; using MapHarness = HashMapHarnessAdaptor>; -BIGFOOT_REGISTER_BENCHMARKS(SlotMapAdaptor, "Bigfoot::SlotMap"); +BIGFOOT_REGISTER_BENCHMARKS(DenseSlotMapHarness, "Bigfoot::DenseSlotMap"); +BIGFOOT_REGISTER_BENCHMARKS(StableSlotMapHarness, "Bigfoot::StableSlotMap"); BIGFOOT_REGISTER_BENCHMARKS(UnorderedDenseMapHarness, "ankerl::unordered_dense::map"); BIGFOOT_REGISTER_BENCHMARKS(UnorderedDenseSegementedMapHarness, "ankerl::unordered_dense::segmented_map"); BIGFOOT_REGISTER_BENCHMARKS(UnorderedMapHarness, "std::unordered_map"); diff --git a/Bigfoot/Sources/Engine/Asset/Reference.cpp b/Bigfoot/Sources/Engine/Asset/Reference.cpp new file mode 100644 index 0000000..a9f9ce6 --- /dev/null +++ b/Bigfoot/Sources/Engine/Asset/Reference.cpp @@ -0,0 +1,34 @@ +/********************************************************************* + * \file Reference.cpp + * + * \author Romain BOULLARD + * \date July 2026 + *********************************************************************/ +#include + +#include + +namespace flatbuffers +{ +Flat::Bigfoot::AnyHardReference Pack(const ::Bigfoot::AnyHardReference& p_ref) +{ + return {Pack(p_ref.GetUUID())}; +} + +::Bigfoot::AnyHardReference UnPack(const Flat::Bigfoot::AnyHardReference& p_ref) +{ + return {UnPack(p_ref.uuid())}; +} + +/****************************************************************************************/ + +Flat::Bigfoot::AnySoftReference Pack(const ::Bigfoot::AnySoftReference& p_ref) +{ + return {Pack(p_ref.GetUUID())}; +} + +::Bigfoot::AnySoftReference UnPack(const Flat::Bigfoot::AnySoftReference& p_ref) +{ + return {UnPack(p_ref.uuid())}; +} +} // namespace flatbuffers diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp index 31eff7e..264ba6b 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp @@ -17,21 +17,31 @@ namespace Bigfoot { +class AssetBase +{ + public: + virtual ~AssetBase() = default; + + protected: + AssetBase() = default; + + AssetBase(const AssetBase& p_asset) = default; + AssetBase(AssetBase&& p_asset) = default; + + AssetBase& operator=(const AssetBase& p_asset) = default; + AssetBase& operator=(AssetBase&& p_asset) = default; +}; + template -class Asset +class Asset: public AssetBase { public: using FLAT_ASSET = typename ASSET::FLAT; - Asset(): - m_hardRefCount(0), - m_softRefCount(0), - m_header(::Flat::Bigfoot::AssetHeaderT {.uuid = UUID {}, - .name = eastl::string {}, - .type_id = GetTypeID(), - .type_name = eastl::string {GetTypeName()}, - .version = 0}) + Asset() { + m_header.type_id = GetTypeID(); + m_header.type_name = eastl::string {GetTypeName()}; } explicit Asset(const eastl::span p_flatbuffer): @@ -58,39 +68,7 @@ class Asset Asset(const Asset& p_asset) = delete; Asset(Asset&& p_asset) = default; - virtual ~Asset() = default; - - void IncrementHardRefCount() - { - m_hardRefCount++; - } - - void DecrementHardRefCount() - { - m_hardRefCount--; - } - - [[nodiscard]] - std::uint32_t GetHardRefCount() const - { - return m_hardRefCount; - } - - void IncrementSoftRefCount() - { - m_softRefCount++; - } - - void DecrementSoftRefCount() - { - m_hardRefCount--; - } - - [[nodiscard]] - std::uint32_t GetSoftRefCount() const - { - return m_softRefCount; - } + ~Asset() = default; [[nodiscard]] const ::Flat::Bigfoot::AssetHeaderT& GetHeader() const @@ -98,6 +76,16 @@ class Asset return m_header; } + void SetName(const eastl::string_view p_name) + { + m_header.name = p_name; + } + + void SetVersion(const std::uint32_t p_version) + { + m_header.version = p_version; + } + [[nodiscard]] const typename FLAT_ASSET::NativeTableType& GetAsset() const { @@ -128,16 +116,6 @@ class Asset std::bit_cast(assetFbb.GetBufferPointer() + assetFbb.GetSize())}; } - void SetName(const eastl::string_view p_name) - { - m_header.name = p_name; - } - - void SetVersion(const std::uint32_t p_version) - { - m_header.version = p_version; - } - [[nodiscard]] static std::uint64_t GetTypeID() { @@ -156,11 +134,8 @@ class Asset Asset& operator=(Asset&& p_asset) = default; private: - std::uint32_t m_hardRefCount; - std::uint32_t m_softRefCount; - - ::Flat::Bigfoot::AssetHeaderT m_header; typename FLAT_ASSET::NativeTableType m_asset; + ::Flat::Bigfoot::AssetHeaderT m_header; }; } // namespace Bigfoot diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetContainer.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetContainer.hpp index 82d728c..3ae2212 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetContainer.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetContainer.hpp @@ -17,86 +17,159 @@ namespace Bigfoot { +class ContainerHandle +{ + public: + ContainerHandle() = default; + + ContainerHandle(const ContainerHandle& p_handle) = default; + ContainerHandle(ContainerHandle&& p_handle) = default; + + ~ContainerHandle() = default; + + void IncrementHardRefCount() + { + ++m_hardRefCount; + } + + void DecrementHardRefCount() + { + --m_hardRefCount; + } + + void IncrementSoftRefCount() + { + ++m_softRefCount; + } + + void DecrementSoftRefCount() + { + --m_softRefCount; + } + + [[nodiscard]] + AssetBase* GetAsset() const + { + return m_asset; + } + + void SetAsset(AssetBase* p_asset) + { + m_asset = p_asset; + } + + ContainerHandle& operator=(const ContainerHandle& p_handle) = default; + ContainerHandle& operator=(ContainerHandle&& p_handle) = default; + + private: + std::uint32_t m_hardRefCount = 0; + std::uint32_t m_softRefCount = 0; + AssetBase* m_asset = nullptr; +}; + +class AssetContainerBase +{ + public: + virtual ~AssetContainerBase() = default; + + [[nodiscard]] + SlotMapKey GetAssetSlotKey(const UUID& p_uuid) const + { + if (const auto it = m_uuidToAssetSlotKey.find(p_uuid); it != m_uuidToAssetSlotKey.end()) + { + return it->second; + } + + return SlotMapKey {}; + } + + [[nodiscard]] + bool Has(const UUID& p_uuid) const + { + return m_uuidToAssetSlotKey.contains(p_uuid); + } + + [[nodiscard]] + ContainerHandle& AcquireHandle(const UUID& p_uuid) + { + if (const auto it = m_uuidToContainerHandleSlotKey.find(p_uuid); it != m_uuidToContainerHandleSlotKey.end()) + { + return *m_handles.Get(it->second); + } + + const SlotMapKey key = m_handles.Insert(); + m_uuidToContainerHandleSlotKey.insert({p_uuid, key}); + + return *m_handles.Get(key); + } + + AssetContainerBase& operator=(const AssetContainerBase& p_container) = delete; + AssetContainerBase& operator=(AssetContainerBase&& p_container) = default; + + protected: + AssetContainerBase() = default; + + AssetContainerBase(const AssetContainerBase& p_container) = delete; + AssetContainerBase(AssetContainerBase&& p_container) = default; + + ankerl::unordered_dense::segmented_map m_uuidToAssetSlotKey; + ankerl::unordered_dense::segmented_map m_uuidToContainerHandleSlotKey; + + private: + StableSlotMap m_handles; +}; + template -class AssetContainer +class AssetContainer: public AssetContainerBase { public: AssetContainer() = default; - AssetContainer(const AssetContainer& p_container) = default; + AssetContainer(const AssetContainer& p_container) = delete; AssetContainer(AssetContainer&& p_container) = default; ~AssetContainer() = default; template [[nodiscard]] - typename SlotMap::SlotKey Insert(ARGS&&... p_args) + SlotMapKey Insert(ARGS&&... p_args) { - const typename SlotMap::SlotKey slotKey = m_assets.Insert(std::forward(p_args)...); - m_uuidToSlotKey.insert({m_assets.Get(slotKey)->GetHeader().uuid, slotKey}); + const SlotMapKey slotKey = m_assets.Insert(std::forward(p_args)...); + ASSET* asset = m_assets.Get(slotKey); + m_uuidToAssetSlotKey.insert({asset->GetHeader().uuid, slotKey}); + + AcquireHandle(asset->GetHeader().uuid).SetAsset(asset); return slotKey; } [[nodiscard]] - ASSET* Get(const typename SlotMap::SlotKey p_key) + ASSET* Get(const SlotMapKey p_key) { return m_assets.Get(p_key); } [[nodiscard]] - const ASSET* Get(const typename SlotMap::SlotKey p_key) const + const ASSET* Get(const SlotMapKey p_key) const { return m_assets.Get(p_key); } - [[nodiscard]] - typename SlotMap::SlotKey GetSlotKey(const UUID& p_uuid) const - { - if (const auto it = m_uuidToSlotKey.find(p_uuid); it != m_uuidToSlotKey.end()) - { - return it->second; - } - return typename SlotMap::SlotKey {}; - } - - [[nodiscard]] - bool Has(const typename SlotMap::SlotKey p_key) const - { - return m_assets.Has(p_key); - } - - [[nodiscard]] - bool Has(const UUID& p_uuid) const - { - return m_uuidToSlotKey.contains(p_uuid); - } - - void Remove(const typename SlotMap::SlotKey p_key) - { - if (const ASSET* asset = Get(p_key)) - { - const UUID uuid = asset->GetHeader().uuid; - m_assets.Remove(p_key); - m_uuidToSlotKey.erase(uuid); - } - } - void Remove(const UUID& p_uuid) { - if (const auto it = m_uuidToSlotKey.find(p_uuid); it != m_uuidToSlotKey.end()) + if (const auto it = m_uuidToAssetSlotKey.find(p_uuid); it != m_uuidToAssetSlotKey.end()) { - Remove(it->second); + AcquireHandle(p_uuid).SetAsset(nullptr); + m_assets.Remove(it->second); + m_uuidToAssetSlotKey.erase(it->first); } } - AssetContainer& operator=(const AssetContainer& p_container) = default; + AssetContainer& operator=(const AssetContainer& p_container) = delete; AssetContainer& operator=(AssetContainer&& p_container) = default; private: - ankerl::unordered_dense::segmented_map::SlotKey> m_uuidToSlotKey; - - SlotMap m_assets; + StableSlotMap m_assets; }; } // namespace Bigfoot diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetHelper.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetHelper.hpp index c4aa601..db18acd 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetHelper.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetHelper.hpp @@ -8,10 +8,16 @@ #define BIGFOOT_ENGINE_ASSET_ASSETHELPER_HPP #include #include +#include -#define ASSET_CONTAINER(AssetName, AssetType) \ +#define BIGFOOT_ASSET(AssetName, AssetType) \ namespace Bigfoot \ { \ + template<> \ + AssetTypeID GetAssetTypeID() \ + { \ + return AssetType::GetTypeID(); \ + } \ AssetContainer g_containerFor##AssetName; \ const bool g_insertedContainerFor##AssetName = g_assetLibrary.Insert(&g_containerFor##AssetName); \ } diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetLibrary.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetLibrary.hpp index c99f61f..11d2410 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetLibrary.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetLibrary.hpp @@ -9,7 +9,6 @@ #include #include -#include #include namespace Bigfoot @@ -44,12 +43,7 @@ class AssetLibrary AssetContainer* Get() { static const AssetTypeID typeID = ASSET::GetTypeID(); - if (const auto container = m_assetContainers.find(typeID); container != m_assetContainers.end()) - { - return eastl::any_cast*>(container->second); - } - - return nullptr; + return static_cast*>(GetBase(typeID)); } template @@ -57,9 +51,54 @@ class AssetLibrary const AssetContainer* Get() const { static const AssetTypeID typeID = ASSET::GetTypeID(); - if (const auto container = m_assetContainers.find(typeID); container != m_assetContainers.end()) + return static_cast*>(GetBase(typeID)); + } + + [[nodiscard]] + AssetContainerBase* GetBase(const AssetTypeID p_typeID) + { + if (const auto container = m_assetContainers.find(p_typeID); container != m_assetContainers.end()) { - return eastl::any_cast*>(container->second); + return container->second; + } + + return nullptr; + } + + [[nodiscard]] + const AssetContainerBase* GetBase(const AssetTypeID p_typeID) const + { + if (const auto container = m_assetContainers.find(p_typeID); container != m_assetContainers.end()) + { + return container->second; + } + + return nullptr; + } + + [[nodiscard]] + AssetContainerBase* FindContainer(const UUID& p_uuid) + { + for (const auto& [typeID, container]: m_assetContainers) + { + if (container->GetAssetSlotKey(p_uuid).Valid()) + { + return container; + } + } + + return nullptr; + } + + [[nodiscard]] + const AssetContainerBase* FindContainer(const UUID& p_uuid) const + { + for (const auto& [typeID, container]: m_assetContainers) + { + if (container->GetAssetSlotKey(p_uuid).Valid()) + { + return container; + } } return nullptr; @@ -69,7 +108,7 @@ class AssetLibrary AssetLibrary& operator=(AssetLibrary&& p_library) = default; private: - ankerl::unordered_dense::segmented_map m_assetContainers; + ankerl::unordered_dense::segmented_map m_assetContainers; }; inline AssetLibrary g_assetLibrary; diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetTypeID_generated.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetTypeID_generated.hpp index 152b30a..d7b9b51 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetTypeID_generated.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetTypeID_generated.hpp @@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && FLATBUFFERS_VERSION_MINOR == 12 && FLATBUFFERS_VERSION_REVISION == 19, "Non-compatible flatbuffers version included"); +// Ensure the included flatbuffers.h is Bigfoot's fork - stock +// flatbuffers (or a differently versioned Bigfoot fork) is not compatible. +#ifndef FLATBUFFERS_BIGFOOT_VERSION +#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible" +#endif +static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1, + "Non-compatible Bigfoot flatbuffers fork version included"); #include "Engine/Asset/AssetTypeID.hpp" diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset_generated.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset_generated.hpp index fdfe9d3..a3269dc 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset_generated.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset_generated.hpp @@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && FLATBUFFERS_VERSION_MINOR == 12 && FLATBUFFERS_VERSION_REVISION == 19, "Non-compatible flatbuffers version included"); +// Ensure the included flatbuffers.h is Bigfoot's fork - stock +// flatbuffers (or a differently versioned Bigfoot fork) is not compatible. +#ifndef FLATBUFFERS_BIGFOOT_VERSION +#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible" +#endif +static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1, + "Non-compatible Bigfoot flatbuffers fork version included"); #include "Engine/Asset/AssetTypeID.hpp" #include "System/UUID/UUID.hpp" diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/Reference.fbs b/Bigfoot/Sources/Engine/Include/Engine/Asset/Reference.fbs index 2b69919..24e160a 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/Reference.fbs +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/Reference.fbs @@ -4,12 +4,22 @@ native_include "Engine/Asset/Reference.hpp"; namespace Flat.Bigfoot; -struct HardReference (native_type_template: "::Bigfoot::HardReference") +struct HardReference (bigfoot_ref_wrapper: "::Bigfoot::HardReference") { uuid: UUID; } -struct SoftReference (native_type_template: "::Bigfoot::SoftReference") +struct SoftReference (bigfoot_ref_wrapper: "::Bigfoot::SoftReference") +{ + uuid: UUID; +} + +struct AnyHardReference (native_type: "::Bigfoot::AnyHardReference") +{ + uuid: UUID; +} + +struct AnySoftReference (native_type: "::Bigfoot::AnySoftReference") { uuid: UUID; } \ No newline at end of file diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/Reference.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/Reference.hpp index 31b66ab..77cb77d 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/Reference.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/Reference.hpp @@ -14,6 +14,9 @@ namespace Bigfoot { +template +AssetTypeID GetAssetTypeID(); + template class HardReference { @@ -28,14 +31,14 @@ class HardReference HardReference(const HardReference& p_ref): m_uuid(p_ref.m_uuid), - m_slotKey(p_ref.m_slotKey) + m_handle(p_ref.m_handle) { Acquire(); } HardReference(HardReference&& p_ref) noexcept: m_uuid(std::exchange(p_ref.m_uuid, UUID::NULL_UUID)), - m_slotKey(std::exchange(p_ref.m_slotKey, typename SlotMap::SlotKey {})) + m_handle(std::exchange(p_ref.m_handle, nullptr)) { } @@ -45,6 +48,12 @@ class HardReference return m_uuid; } + [[nodiscard]] + ASSET* Get() const + { + return m_handle ? static_cast(m_handle->GetAsset()) : nullptr; + } + ~HardReference() { Release(); @@ -56,7 +65,7 @@ class HardReference { Release(); m_uuid = p_ref.m_uuid; - m_slotKey = p_ref.m_slotKey; + m_handle = p_ref.m_handle; Acquire(); } return *this; @@ -68,7 +77,7 @@ class HardReference { Release(); m_uuid = std::exchange(p_ref.m_uuid, UUID::NULL_UUID); - std::exchange(p_ref.m_slotKey, typename SlotMap::SlotKey {}); + m_handle = std::exchange(p_ref.m_handle, nullptr); } return *this; } @@ -82,34 +91,28 @@ class HardReference private: void Acquire() { - if (AssetContainer* assetContainer = g_assetLibrary.Get(); assetContainer && m_uuid) + if (AssetContainerBase* assetContainer = g_assetLibrary.GetBase(GetAssetTypeID()); + assetContainer && m_uuid) { - if (!m_slotKey.Valid()) + if (!m_handle) { - m_slotKey = assetContainer->GetSlotKey(m_uuid); - } - - if (ASSET* asset = assetContainer->Get(m_slotKey)) - { - asset->IncrementHardRefCount(); + m_handle = &assetContainer->AcquireHandle(m_uuid); } + m_handle->IncrementHardRefCount(); } } void Release() { - if (AssetContainer* assetContainer = g_assetLibrary.Get(); assetContainer && m_uuid) + if (m_handle) { - // Acquire always happens before Release, so slot key should be valid - if (ASSET* asset = assetContainer->Get(m_slotKey)) - { - asset->DecrementHardRefCount(); - } + m_handle->DecrementHardRefCount(); + m_handle = nullptr; } } UUID m_uuid = UUID::NULL_UUID; - typename SlotMap::SlotKey m_slotKey; + ContainerHandle* m_handle = nullptr; }; template @@ -126,14 +129,14 @@ class SoftReference SoftReference(const SoftReference& p_ref): m_uuid(p_ref.m_uuid), - m_slotKey(p_ref.m_slotKey) + m_handle(p_ref.m_handle) { Acquire(); } SoftReference(SoftReference&& p_ref) noexcept: m_uuid(std::exchange(p_ref.m_uuid, UUID::NULL_UUID)), - m_slotKey(std::exchange(p_ref.m_slotKey, typename SlotMap::SlotKey {})) + m_handle(std::exchange(p_ref.m_handle, nullptr)) { } @@ -143,6 +146,12 @@ class SoftReference return m_uuid; } + [[nodiscard]] + ASSET* Get() const + { + return m_handle ? static_cast(m_handle->GetAsset()) : nullptr; + } + ~SoftReference() { Release(); @@ -154,7 +163,7 @@ class SoftReference { Release(); m_uuid = p_ref.m_uuid; - m_slotKey = p_ref.m_slotKey; + m_handle = p_ref.m_handle; Acquire(); } return *this; @@ -166,7 +175,7 @@ class SoftReference { Release(); m_uuid = std::exchange(p_ref.m_uuid, UUID::NULL_UUID); - m_slotKey = std::exchange(p_ref.m_slotKey, typename SlotMap::SlotKey {}); + m_handle = std::exchange(p_ref.m_handle, nullptr); } return *this; } @@ -180,34 +189,231 @@ class SoftReference private: void Acquire() { - if (AssetContainer* assetContainer = g_assetLibrary.Get(); assetContainer && m_uuid) + if (AssetContainerBase* assetContainer = g_assetLibrary.GetBase(GetAssetTypeID()); + assetContainer && m_uuid) { - if (!m_slotKey.Valid()) + if (!m_handle) { - m_slotKey = assetContainer->GetSlotKey(m_uuid); - } - - if (ASSET* asset = assetContainer->Get(m_slotKey)) - { - asset->IncrementSoftRefCount(); + m_handle = &assetContainer->AcquireHandle(m_uuid); } + m_handle->IncrementSoftRefCount(); } } void Release() { - if (AssetContainer* assetContainer = g_assetLibrary.Get(); assetContainer && m_uuid) + if (m_handle) { - // Acquire always happens before Release, so slot key should be valid - if (ASSET* asset = assetContainer->Get(m_slotKey)) - { - asset->DecrementSoftRefCount(); - } + m_handle->DecrementSoftRefCount(); + m_handle = nullptr; } } UUID m_uuid = UUID::NULL_UUID; - typename SlotMap::SlotKey m_slotKey; + ContainerHandle* m_handle = nullptr; +}; + +class AnyHardReference +{ + public: + AnyHardReference() = default; + + AnyHardReference(const UUID& p_uuid): + m_uuid(p_uuid) + { + Acquire(); + } + + AnyHardReference(const AnyHardReference& p_ref): + m_uuid(p_ref.m_uuid), + m_handle(p_ref.m_handle) + { + Acquire(); + } + + AnyHardReference(AnyHardReference&& p_ref) noexcept: + m_uuid(std::exchange(p_ref.m_uuid, UUID::NULL_UUID)), + m_handle(std::exchange(p_ref.m_handle, nullptr)) + { + } + + [[nodiscard]] + const UUID& GetUUID() const + { + return m_uuid; + } + + ~AnyHardReference() + { + Release(); + } + + AnyHardReference& operator=(const AnyHardReference& p_ref) + { + if (this != &p_ref) + { + Release(); + m_uuid = p_ref.m_uuid; + m_handle = p_ref.m_handle; + Acquire(); + } + return *this; + } + + AnyHardReference& operator=(AnyHardReference&& p_ref) noexcept + { + if (this != &p_ref) + { + Release(); + m_uuid = std::exchange(p_ref.m_uuid, UUID::NULL_UUID); + m_handle = std::exchange(p_ref.m_handle, nullptr); + } + return *this; + } + + [[nodiscard]] + bool operator==(const AnyHardReference& p_ref) const + { + return m_uuid == p_ref.m_uuid; + } + + private: + void Acquire() + { + if (AssetContainerBase* assetContainer = g_assetLibrary.FindContainer(m_uuid); assetContainer && m_uuid) + { + if (!m_handle) + { + m_handle = &assetContainer->AcquireHandle(m_uuid); + } + m_handle->IncrementHardRefCount(); + } + } + + void Release() + { + if (m_handle) + { + m_handle->DecrementHardRefCount(); + m_handle = nullptr; + } + } + + UUID m_uuid = UUID::NULL_UUID; + ContainerHandle* m_handle = nullptr; +}; + +class AnySoftReference +{ + public: + AnySoftReference() = default; + + AnySoftReference(const UUID& p_uuid): + m_uuid(p_uuid) + { + Acquire(); + } + + AnySoftReference(const AnySoftReference& p_ref): + m_uuid(p_ref.m_uuid), + m_handle(p_ref.m_handle) + { + Acquire(); + } + + AnySoftReference(AnySoftReference&& p_ref) noexcept: + m_uuid(std::exchange(p_ref.m_uuid, UUID::NULL_UUID)), + m_handle(std::exchange(p_ref.m_handle, nullptr)) + { + } + + [[nodiscard]] + const UUID& GetUUID() const + { + return m_uuid; + } + + ~AnySoftReference() + { + Release(); + } + + AnySoftReference& operator=(const AnySoftReference& p_ref) + { + if (this != &p_ref) + { + Release(); + m_uuid = p_ref.m_uuid; + m_handle = p_ref.m_handle; + Acquire(); + } + return *this; + } + + AnySoftReference& operator=(AnySoftReference&& p_ref) noexcept + { + if (this != &p_ref) + { + Release(); + m_uuid = std::exchange(p_ref.m_uuid, UUID::NULL_UUID); + m_handle = std::exchange(p_ref.m_handle, nullptr); + } + return *this; + } + + [[nodiscard]] + bool operator==(const AnySoftReference& p_ref) const + { + return m_uuid == p_ref.m_uuid; + } + + private: + void Acquire() + { + if (AssetContainerBase* assetContainer = g_assetLibrary.FindContainer(m_uuid); assetContainer && m_uuid) + { + if (!m_handle) + { + m_handle = &assetContainer->AcquireHandle(m_uuid); + } + m_handle->IncrementSoftRefCount(); + } + } + + void Release() + { + if (m_handle) + { + m_handle->DecrementSoftRefCount(); + m_handle = nullptr; + } + } + + UUID m_uuid = UUID::NULL_UUID; + ContainerHandle* m_handle = nullptr; }; } // namespace Bigfoot + +/****************************************************************************************/ + +namespace Flat +{ +namespace Bigfoot +{ +struct AnyHardReference; +struct AnySoftReference; +} // namespace Bigfoot +} // namespace Flat + +/****************************************************************************************/ + +namespace flatbuffers +{ +Flat::Bigfoot::AnyHardReference Pack(const ::Bigfoot::AnyHardReference& p_ref); +::Bigfoot::AnyHardReference UnPack(const Flat::Bigfoot::AnyHardReference& p_ref); + +Flat::Bigfoot::AnySoftReference Pack(const ::Bigfoot::AnySoftReference& p_ref); +::Bigfoot::AnySoftReference UnPack(const Flat::Bigfoot::AnySoftReference& p_ref); +} // namespace flatbuffers + #endif diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/Reference_generated.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/Reference_generated.hpp index 1d28c7e..f7ef4e1 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/Reference_generated.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/Reference_generated.hpp @@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && FLATBUFFERS_VERSION_MINOR == 12 && FLATBUFFERS_VERSION_REVISION == 19, "Non-compatible flatbuffers version included"); +// Ensure the included flatbuffers.h is Bigfoot's fork - stock +// flatbuffers (or a differently versioned Bigfoot fork) is not compatible. +#ifndef FLATBUFFERS_BIGFOOT_VERSION +#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible" +#endif +static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1, + "Non-compatible Bigfoot flatbuffers fork version included"); #include "System/UUID/UUID.hpp" #include "Engine/Asset/Reference.hpp" @@ -28,10 +35,18 @@ struct HardReference; struct SoftReference; +struct AnyHardReference; + +struct AnySoftReference; + inline const ::flatbuffers::TypeTable *HardReferenceTypeTable(); inline const ::flatbuffers::TypeTable *SoftReferenceTypeTable(); +inline const ::flatbuffers::TypeTable *AnyHardReferenceTypeTable(); + +inline const ::flatbuffers::TypeTable *AnySoftReferenceTypeTable(); + FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(1) HardReference FLATBUFFERS_FINAL_CLASS { private: Flat::Bigfoot::UUID uuid_; @@ -88,6 +103,62 @@ struct SoftReference::Traits { using type = SoftReference; }; +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(1) AnyHardReference FLATBUFFERS_FINAL_CLASS { + private: + Flat::Bigfoot::UUID uuid_; + + public: + struct Traits; + static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { + return AnyHardReferenceTypeTable(); + } + static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() { + return "Flat.Bigfoot.AnyHardReference"; + } + AnyHardReference() + : uuid_() { + } + AnyHardReference(const Flat::Bigfoot::UUID &_uuid) + : uuid_(_uuid) { + } + const Flat::Bigfoot::UUID &uuid() const { + return uuid_; + } +}; +FLATBUFFERS_STRUCT_END(AnyHardReference, 16); + +struct AnyHardReference::Traits { + using type = AnyHardReference; +}; + +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(1) AnySoftReference FLATBUFFERS_FINAL_CLASS { + private: + Flat::Bigfoot::UUID uuid_; + + public: + struct Traits; + static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { + return AnySoftReferenceTypeTable(); + } + static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() { + return "Flat.Bigfoot.AnySoftReference"; + } + AnySoftReference() + : uuid_() { + } + AnySoftReference(const Flat::Bigfoot::UUID &_uuid) + : uuid_(_uuid) { + } + const Flat::Bigfoot::UUID &uuid() const { + return uuid_; + } +}; +FLATBUFFERS_STRUCT_END(AnySoftReference, 16); + +struct AnySoftReference::Traits { + using type = AnySoftReference; +}; + inline const ::flatbuffers::TypeTable *HardReferenceTypeTable() { static const ::flatbuffers::TypeCode type_codes[] = { { ::flatbuffers::ET_SEQUENCE, 0, 0 } @@ -116,6 +187,34 @@ inline const ::flatbuffers::TypeTable *SoftReferenceTypeTable() { return &tt; } +inline const ::flatbuffers::TypeTable *AnyHardReferenceTypeTable() { + static const ::flatbuffers::TypeCode type_codes[] = { + { ::flatbuffers::ET_SEQUENCE, 0, 0 } + }; + static const ::flatbuffers::TypeFunction type_refs[] = { + Flat::Bigfoot::UUIDTypeTable + }; + static const int64_t values[] = { 0, 16 }; + static const ::flatbuffers::TypeTable tt = { + ::flatbuffers::ST_STRUCT, 1, type_codes, type_refs, nullptr, values, nullptr + }; + return &tt; +} + +inline const ::flatbuffers::TypeTable *AnySoftReferenceTypeTable() { + static const ::flatbuffers::TypeCode type_codes[] = { + { ::flatbuffers::ET_SEQUENCE, 0, 0 } + }; + static const ::flatbuffers::TypeFunction type_refs[] = { + Flat::Bigfoot::UUIDTypeTable + }; + static const int64_t values[] = { 0, 16 }; + static const ::flatbuffers::TypeTable tt = { + ::flatbuffers::ST_STRUCT, 1, type_codes, type_refs, nullptr, values, nullptr + }; + return &tt; +} + } // namespace Bigfoot } // namespace Flat diff --git a/Bigfoot/Sources/System/Include/System/Time/Time_generated.hpp b/Bigfoot/Sources/System/Include/System/Time/Time_generated.hpp index b764ac1..b71046f 100644 --- a/Bigfoot/Sources/System/Include/System/Time/Time_generated.hpp +++ b/Bigfoot/Sources/System/Include/System/Time/Time_generated.hpp @@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && FLATBUFFERS_VERSION_MINOR == 12 && FLATBUFFERS_VERSION_REVISION == 19, "Non-compatible flatbuffers version included"); +// Ensure the included flatbuffers.h is Bigfoot's fork - stock +// flatbuffers (or a differently versioned Bigfoot fork) is not compatible. +#ifndef FLATBUFFERS_BIGFOOT_VERSION +#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible" +#endif +static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1, + "Non-compatible Bigfoot flatbuffers fork version included"); #include "System/Time/Time.hpp" diff --git a/Bigfoot/Sources/System/Include/System/UUID/UUID_generated.hpp b/Bigfoot/Sources/System/Include/System/UUID/UUID_generated.hpp index 6faf6fa..f6b35a0 100644 --- a/Bigfoot/Sources/System/Include/System/UUID/UUID_generated.hpp +++ b/Bigfoot/Sources/System/Include/System/UUID/UUID_generated.hpp @@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && FLATBUFFERS_VERSION_MINOR == 12 && FLATBUFFERS_VERSION_REVISION == 19, "Non-compatible flatbuffers version included"); +// Ensure the included flatbuffers.h is Bigfoot's fork - stock +// flatbuffers (or a differently versioned Bigfoot fork) is not compatible. +#ifndef FLATBUFFERS_BIGFOOT_VERSION +#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible" +#endif +static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1, + "Non-compatible Bigfoot flatbuffers fork version included"); #include "System/UUID/UUID.hpp" diff --git a/Bigfoot/Sources/Utils/Include/Utils/Containers/SlotMap.hpp b/Bigfoot/Sources/Utils/Include/Utils/Containers/SlotMap.hpp index ff9d60e..3f182f0 100644 --- a/Bigfoot/Sources/Utils/Include/Utils/Containers/SlotMap.hpp +++ b/Bigfoot/Sources/Utils/Include/Utils/Containers/SlotMap.hpp @@ -8,21 +8,24 @@ #define BIGFOOT_UTILS_CONTAINERS_SLOTMAP_HPP #include +#include +#include +#include +#include +#include #include +#include #include #include namespace Bigfoot { -template && std::is_unsigned_v, bool> = true> class SlotMapKey { public: - using IndexType = INDEX_TYPE; - using VersionType = VERSION_TYPE; + using IndexType = std::uint32_t; + using VersionType = std::uint32_t; private: static constexpr std::uint32_t VERSION_BIT_COUNT = sizeof(VersionType) * std::numeric_limits::digits; @@ -78,234 +81,811 @@ class SlotMapKey std::uint64_t m_key; }; -template -class SlotMap +class SlotMapBase { public: - using InternalSlotKey = SlotMapKey; - - SlotMap(): - m_freeSlotHead(std::numeric_limits::max()) - { - } - - SlotMap(const SlotMap& p_map) = default; - SlotMap(SlotMap&& p_map) = default; - - ~SlotMap() = default; - - template - [[nodiscard]] - InternalSlotKey Insert(ARGS&&... p_args) - { - ASSERT(UtilsAssertHandler, m_slots.size() < InternalSlotKey::MAX_INDEX, "All slots have been exhausted!"); - - const typename InternalSlotKey::IndexType dataIndex = static_cast(m_data.size()); - m_data.emplace_back(std::forward(p_args)...); - - if (HasFreeSlots()) - { - const typename InternalSlotKey::IndexType slotIndex = m_freeSlotHead; - - m_freeSlotHead = m_slots[slotIndex].GetIndex(); - - m_slots[slotIndex] = InternalSlotKey {m_slots[slotIndex].GetVersion(), dataIndex}; - m_dataToSlots.push_back(slotIndex); - - return InternalSlotKey {m_slots[slotIndex].GetVersion(), slotIndex}; - } - - const typename InternalSlotKey::IndexType slotIndex = static_cast(m_slots.size()); - m_slots.emplace_back(1, dataIndex); - m_dataToSlots.push_back(slotIndex); - - return InternalSlotKey {1, slotIndex}; - } - - void Remove(const InternalSlotKey p_slotKey) - { - if (!Has(p_slotKey)) - { - return; - } - - const typename InternalSlotKey::IndexType dataIndex = m_slots[p_slotKey.GetIndex()].GetIndex(); - - m_data.erase_unsorted(m_data.begin() + dataIndex); - m_dataToSlots.erase_unsorted(m_dataToSlots.begin() + dataIndex); - - if (dataIndex < m_data.size()) - { - m_slots[m_dataToSlots[dataIndex]] = InternalSlotKey {m_slots[m_dataToSlots[dataIndex]].GetVersion(), - dataIndex}; - } - - RecycleSlot(p_slotKey.GetVersion() + 1, p_slotKey.GetIndex()); - } + ~SlotMapBase() = default; [[nodiscard]] - bool Has(const InternalSlotKey p_slotKey) const + bool Has(const SlotMapKey p_slotKey) const { return p_slotKey.Valid() && (p_slotKey.GetIndex() < m_slots.size() && p_slotKey.GetVersion() == m_slots[p_slotKey.GetIndex()].GetVersion()); } [[nodiscard]] - TYPE* Get(const InternalSlotKey p_slotKey) + std::size_t GetSize() const { - return Has(p_slotKey) ? &m_data[m_slots[p_slotKey.GetIndex()].GetIndex()] : nullptr; - } - - [[nodiscard]] - const TYPE* Get(const InternalSlotKey p_slotKey) const - { - return Has(p_slotKey) ? &m_data[m_slots[p_slotKey.GetIndex()].GetIndex()] : nullptr; - } - - void Reset() - { - m_data.clear(); - m_slots.clear(); - m_dataToSlots.clear(); - m_freeSlotHead = std::numeric_limits::max(); - } - - void Clear() - { - for (const typename eastl::vector::size_type slotIndex: m_dataToSlots) - { - RecycleSlot(m_slots[slotIndex].GetVersion() + 1, static_cast(slotIndex)); - } - - m_data.clear(); - m_dataToSlots.clear(); - } - - [[nodiscard]] - eastl::vector::size_type GetSize() const - { - return m_data.size(); - } - - [[nodiscard]] - eastl::vector::size_type GetCapacity() const - { - return m_data.capacity(); + return m_size; } [[nodiscard]] bool Empty() const { - return m_data.empty(); + return m_size == 0; } - void Reserve(const eastl::vector::size_type p_size) + SlotMapBase& operator=(const SlotMapBase& p_base) = default; + SlotMapBase& operator=(SlotMapBase&& p_base) = default; + + protected: + SlotMapBase() = default; + + SlotMapBase(const SlotMapBase& p_base) = default; + SlotMapBase(SlotMapBase&& p_base) = default; + + [[nodiscard]] + bool HasFreeSlots() const + { + return m_freeSlotHead != std::numeric_limits::max(); + } + + void RecycleSlot(const SlotMapKey::VersionType p_version, const SlotMapKey::IndexType p_slotIndex) + { + if (p_version == SlotMapKey::INVALID_VERSION) + { + m_slots[p_slotIndex] = SlotMapKey {SlotMapKey::INVALID_VERSION, 0}; + return; + } + + m_slots[p_slotIndex] = SlotMapKey {p_version, m_freeSlotHead}; + m_freeSlotHead = p_slotIndex; + } + + void ResetSlots() + { + m_size = 0; + m_slots.clear(); + m_freeSlotHead = std::numeric_limits::max(); + } + + void ReserveSlots(const std::size_t p_size) { - m_data.reserve(p_size); - m_dataToSlots.reserve(p_size); m_slots.reserve(p_size); } + std::size_t m_size = 0; + eastl::vector m_slots; + SlotMapKey::IndexType m_freeSlotHead = std::numeric_limits::max(); +}; + +template +class DenseSlotMap: public SlotMapBase +{ + public: + using iterator = typename eastl::vector::iterator; + using const_iterator = typename eastl::vector::const_iterator; + using reverse_iterator = typename eastl::vector::reverse_iterator; + using const_reverse_iterator = typename eastl::vector::const_reverse_iterator; + + DenseSlotMap() = default; + + DenseSlotMap(const DenseSlotMap& p_map) = default; + DenseSlotMap(DenseSlotMap&& p_map) = default; + + ~DenseSlotMap() = default; + + template [[nodiscard]] - eastl::vector::iterator begin() + SlotMapKey Insert(ARGS&&... p_args) + { + const SlotMapKey::IndexType dataIndex = static_cast(m_size); + m_data.emplace_back(std::forward(p_args)...); + ++m_size; + + return AcquireSlot(dataIndex); + } + + void Remove(const SlotMapKey p_slotKey) + { + if (!Has(p_slotKey)) + { + return; + } + + const SlotMapKey::IndexType dataIndex = GetDataIndex(p_slotKey); + + if (dataIndex != m_size - 1) + { + m_data[dataIndex] = eastl::move(m_data.back()); + } + m_data.pop_back(); + --m_size; + + ReleaseSlot(p_slotKey, dataIndex); + } + + [[nodiscard]] + TYPE* Get(const SlotMapKey p_slotKey) + { + return Has(p_slotKey) ? &m_data[GetDataIndex(p_slotKey)] : nullptr; + } + + [[nodiscard]] + const TYPE* Get(const SlotMapKey p_slotKey) const + { + return Has(p_slotKey) ? &m_data[GetDataIndex(p_slotKey)] : nullptr; + } + + void Reset() + { + m_data.clear(); + m_dataToSlots.clear(); + ResetSlots(); + } + + void Clear() + { + for (const std::size_t slotIndex: m_dataToSlots) + { + RecycleSlot(m_slots[slotIndex].GetVersion() + 1, static_cast(slotIndex)); + } + + m_size = 0; + m_data.clear(); + m_dataToSlots.clear(); + } + + [[nodiscard]] + std::size_t GetCapacity() const + { + return m_data.capacity(); + } + + void Reserve(const std::size_t p_size) + { + m_data.reserve(p_size); + m_dataToSlots.reserve(p_size); + ReserveSlots(p_size); + } + + [[nodiscard]] + iterator begin() { return m_data.begin(); } [[nodiscard]] - eastl::vector::iterator end() + iterator end() { return m_data.end(); } [[nodiscard]] - eastl::vector::const_iterator begin() const + const_iterator begin() const { return m_data.begin(); } [[nodiscard]] - eastl::vector::const_iterator end() const + const_iterator end() const { return m_data.end(); } [[nodiscard]] - eastl::vector::reverse_iterator rbegin() + reverse_iterator rbegin() { return m_data.rbegin(); } [[nodiscard]] - eastl::vector::reverse_iterator rend() + reverse_iterator rend() { return m_data.rend(); } [[nodiscard]] - eastl::vector::const_reverse_iterator rbegin() const + const_reverse_iterator rbegin() const { return m_data.rbegin(); } [[nodiscard]] - eastl::vector::const_reverse_iterator rend() const + const_reverse_iterator rend() const { return m_data.rend(); } [[nodiscard]] - eastl::vector::const_iterator cbegin() const + const_iterator cbegin() const { return m_data.cbegin(); } [[nodiscard]] - eastl::vector::const_iterator cend() const + const_iterator cend() const { return m_data.cend(); } [[nodiscard]] - eastl::vector::const_reverse_iterator crbegin() const + const_reverse_iterator crbegin() const { return m_data.crbegin(); } [[nodiscard]] - eastl::vector::const_reverse_iterator crend() const + const_reverse_iterator crend() const { return m_data.crend(); } - SlotMap& operator=(const SlotMap& p_slotMap) = default; - SlotMap& operator=(SlotMap&& p_slotMap) = default; + DenseSlotMap& operator=(const DenseSlotMap& p_map) = default; + DenseSlotMap& operator=(DenseSlotMap&& p_map) = default; private: [[nodiscard]] - bool HasFreeSlots() const + SlotMapKey::IndexType GetDataIndex(const SlotMapKey p_slotKey) const { - return m_freeSlotHead != std::numeric_limits::max(); + return m_slots[p_slotKey.GetIndex()].GetIndex(); } - void RecycleSlot(const InternalSlotKey::VersionType p_version, const InternalSlotKey::IndexType p_slotIndex) + [[nodiscard]] + SlotMapKey AcquireSlot(const SlotMapKey::IndexType p_dataIndex) { - if (p_version == InternalSlotKey::INVALID_VERSION) + ASSERT(UtilsAssertHandler, m_slots.size() < SlotMapKey::MAX_INDEX, "All slots have been exhausted!"); + + if (HasFreeSlots()) { - m_slots[p_slotIndex] = InternalSlotKey {InternalSlotKey::INVALID_VERSION, 0}; - return; + const SlotMapKey::IndexType slotIndex = m_freeSlotHead; + + m_freeSlotHead = m_slots[slotIndex].GetIndex(); + + m_slots[slotIndex] = SlotMapKey {m_slots[slotIndex].GetVersion(), p_dataIndex}; + m_dataToSlots.push_back(slotIndex); + + return SlotMapKey {m_slots[slotIndex].GetVersion(), slotIndex}; } - m_slots[p_slotIndex] = InternalSlotKey {p_version, m_freeSlotHead}; - m_freeSlotHead = p_slotIndex; + const SlotMapKey::IndexType slotIndex = static_cast(m_slots.size()); + m_slots.emplace_back(1, p_dataIndex); + m_dataToSlots.push_back(slotIndex); + + return SlotMapKey {1, slotIndex}; + } + + void ReleaseSlot(const SlotMapKey p_slotKey, const SlotMapKey::IndexType p_dataIndex) + { + m_dataToSlots.erase_unsorted(m_dataToSlots.begin() + p_dataIndex); + + if (p_dataIndex < m_size) + { + m_slots[m_dataToSlots[p_dataIndex]] = SlotMapKey {m_slots[m_dataToSlots[p_dataIndex]].GetVersion(), + p_dataIndex}; + } + + RecycleSlot(p_slotKey.GetVersion() + 1, p_slotKey.GetIndex()); } eastl::vector m_data; - eastl::vector m_slots; + eastl::vector m_dataToSlots; +}; - eastl::vector::size_type> m_dataToSlots; +template +class StableSlotMap: public SlotMapBase +{ + private: + static constexpr std::size_t PAGE_SIZE = 64; - InternalSlotKey::IndexType m_freeSlotHead; + struct Page + { + eastl::array, PAGE_SIZE> m_slots; + eastl::bitset m_occupied; + }; + + public: + class iterator + { + public: + using iterator_category = eastl::bidirectional_iterator_tag; + using value_type = TYPE; + using difference_type = std::ptrdiff_t; + using pointer = TYPE*; + using reference = TYPE&; + + iterator() = default; + + [[nodiscard]] + reference operator*() const + { + return *m_current; + } + + [[nodiscard]] + pointer operator->() const + { + return m_current; + } + + iterator& operator++() + { + Advance(); + return *this; + } + + iterator operator++(int) + { + const iterator temp = *this; + ++(*this); + return temp; + } + + iterator& operator--() + { + Retreat(); + return *this; + } + + iterator operator--(int) + { + const iterator temp = *this; + --(*this); + return temp; + } + + [[nodiscard]] + bool operator==(const iterator& p_other) const + { + return m_map == p_other.m_map && m_current == p_other.m_current; + } + + private: + friend class StableSlotMap; + + explicit iterator(StableSlotMap* p_map): + m_map(p_map) + { + } + + void SeekFirstFrom(std::size_t p_pageIndex) + { + for (; p_pageIndex < m_map->m_pages.size(); ++p_pageIndex) + { + const std::size_t offset = m_map->m_pages[p_pageIndex]->m_occupied.find_first(); + if (offset != PAGE_SIZE) + { + m_pageIndex = p_pageIndex; + m_offset = offset; + m_current = &(*m_map->m_pages[p_pageIndex]).m_slots[offset].value(); + return; + } + } + + m_pageIndex = m_map->m_pages.size(); + m_offset = 0; + m_current = nullptr; + } + + void SeekLastFrom(std::size_t p_pageIndex) + { + for (;;) + { + const std::size_t offset = m_map->m_pages[p_pageIndex]->m_occupied.find_last(); + if (offset != PAGE_SIZE) + { + m_pageIndex = p_pageIndex; + m_offset = offset; + m_current = &(*m_map->m_pages[p_pageIndex]).m_slots[offset].value(); + return; + } + + if (p_pageIndex == 0) + { + return; + } + --p_pageIndex; + } + } + + void Advance() + { + const std::size_t offset = m_map->m_pages[m_pageIndex]->m_occupied.find_next(m_offset); + if (offset != PAGE_SIZE) + { + m_offset = offset; + m_current = &(*m_map->m_pages[m_pageIndex]).m_slots[offset].value(); + return; + } + + SeekFirstFrom(m_pageIndex + 1); + } + + void Retreat() + { + if (m_current == nullptr) + { + SeekLastFrom(m_map->m_pages.size() - 1); + return; + } + + const std::size_t offset = m_map->m_pages[m_pageIndex]->m_occupied.find_prev(m_offset); + if (offset != PAGE_SIZE) + { + m_offset = offset; + m_current = &(*m_map->m_pages[m_pageIndex]).m_slots[offset].value(); + return; + } + + if (m_pageIndex == 0) + { + return; + } + SeekLastFrom(m_pageIndex - 1); + } + + StableSlotMap* m_map = nullptr; + std::size_t m_pageIndex = 0; + std::size_t m_offset = 0; + TYPE* m_current = nullptr; + }; + + class const_iterator + { + public: + using iterator_category = eastl::bidirectional_iterator_tag; + using value_type = TYPE; + using difference_type = std::ptrdiff_t; + using pointer = const TYPE*; + using reference = const TYPE&; + + const_iterator() = default; + + [[nodiscard]] + reference operator*() const + { + return *m_current; + } + + [[nodiscard]] + pointer operator->() const + { + return m_current; + } + + const_iterator& operator++() + { + Advance(); + return *this; + } + + const_iterator operator++(int) + { + const const_iterator temp = *this; + ++(*this); + return temp; + } + + const_iterator& operator--() + { + Retreat(); + return *this; + } + + const_iterator operator--(int) + { + const const_iterator temp = *this; + --(*this); + return temp; + } + + [[nodiscard]] + bool operator==(const const_iterator& p_other) const + { + return m_map == p_other.m_map && m_current == p_other.m_current; + } + + private: + friend class StableSlotMap; + + explicit const_iterator(const StableSlotMap* p_map): + m_map(p_map) + { + } + + void SeekFirstFrom(std::size_t p_pageIndex) + { + for (; p_pageIndex < m_map->m_pages.size(); ++p_pageIndex) + { + const std::size_t offset = m_map->m_pages[p_pageIndex]->m_occupied.find_first(); + if (offset != PAGE_SIZE) + { + m_pageIndex = p_pageIndex; + m_offset = offset; + m_current = &(*m_map->m_pages[p_pageIndex]).m_slots[offset].value(); + return; + } + } + + m_pageIndex = m_map->m_pages.size(); + m_offset = 0; + m_current = nullptr; + } + + void SeekLastFrom(std::size_t p_pageIndex) + { + for (;;) + { + const std::size_t offset = m_map->m_pages[p_pageIndex]->m_occupied.find_last(); + if (offset != PAGE_SIZE) + { + m_pageIndex = p_pageIndex; + m_offset = offset; + m_current = &(*m_map->m_pages[p_pageIndex]).m_slots[offset].value(); + return; + } + + if (p_pageIndex == 0) + { + return; + } + --p_pageIndex; + } + } + + void Advance() + { + const std::size_t offset = m_map->m_pages[m_pageIndex]->m_occupied.find_next(m_offset); + if (offset != PAGE_SIZE) + { + m_offset = offset; + m_current = &(*m_map->m_pages[m_pageIndex]).m_slots[offset].value(); + return; + } + + SeekFirstFrom(m_pageIndex + 1); + } + + void Retreat() + { + if (m_current == nullptr) + { + SeekLastFrom(m_map->m_pages.size() - 1); + return; + } + + const std::size_t offset = m_map->m_pages[m_pageIndex]->m_occupied.find_prev(m_offset); + if (offset != PAGE_SIZE) + { + m_offset = offset; + m_current = &(*m_map->m_pages[m_pageIndex]).m_slots[offset].value(); + return; + } + + if (m_pageIndex == 0) + { + return; + } + SeekLastFrom(m_pageIndex - 1); + } + + const StableSlotMap* m_map = nullptr; + std::size_t m_pageIndex = 0; + std::size_t m_offset = 0; + const TYPE* m_current = nullptr; + }; + + using reverse_iterator = eastl::reverse_iterator; + using const_reverse_iterator = eastl::reverse_iterator; + + StableSlotMap() = default; + + StableSlotMap(const StableSlotMap& p_map) = delete; + StableSlotMap(StableSlotMap&& p_map) = default; + + ~StableSlotMap() = default; + + template + [[nodiscard]] + SlotMapKey Insert(ARGS&&... p_args) + { + const SlotMapKey key = AcquireFreeSlot(); + const SlotMapKey::IndexType index = key.GetIndex(); + const std::size_t pageIndex = index / PAGE_SIZE; + if (pageIndex >= m_pages.size()) + { + m_pages.push_back(eastl::make_unique()); + } + + Page& page = *m_pages[pageIndex]; + const std::size_t offset = index % PAGE_SIZE; + page.m_slots[offset].emplace(std::forward(p_args)...); + page.m_occupied.set(offset); + ++m_size; + + return key; + } + + void Remove(const SlotMapKey p_slotKey) + { + if (!Has(p_slotKey)) + { + return; + } + + const SlotMapKey::IndexType index = p_slotKey.GetIndex(); + Page& page = *m_pages[index / PAGE_SIZE]; + const std::size_t offset = index % PAGE_SIZE; + page.m_slots[offset].reset(); + page.m_occupied.reset(offset); + --m_size; + + ReleaseSlotVersion(index); + } + + [[nodiscard]] + TYPE* Get(const SlotMapKey p_slotKey) + { + return Has(p_slotKey) ? &DataAt(p_slotKey.GetIndex()) : nullptr; + } + + [[nodiscard]] + const TYPE* Get(const SlotMapKey p_slotKey) const + { + return Has(p_slotKey) ? &DataAt(p_slotKey.GetIndex()) : nullptr; + } + + void Reset() + { + for (const eastl::unique_ptr& page: m_pages) + { + *page = Page {}; + } + + ResetSlots(); + } + + void Clear() + { + for (std::size_t pageIndex = 0; pageIndex < m_pages.size(); ++pageIndex) + { + Page& page = *m_pages[pageIndex]; + for (std::size_t offset = page.m_occupied.find_first(); offset != PAGE_SIZE; + offset = page.m_occupied.find_next(offset)) + { + page.m_slots[offset].reset(); + ReleaseSlotVersion(static_cast(pageIndex * PAGE_SIZE + offset)); + } + page.m_occupied.reset(); + } + + m_size = 0; + } + + [[nodiscard]] + std::size_t GetCapacity() const + { + return m_pages.size() * PAGE_SIZE; + } + + void Reserve(const std::size_t p_size) + { + const std::size_t pagesNeeded = (p_size + PAGE_SIZE - 1) / PAGE_SIZE; + m_pages.reserve(pagesNeeded); + for (std::size_t pageIndex = m_pages.size(); pageIndex < pagesNeeded; ++pageIndex) + { + m_pages.push_back(eastl::make_unique()); + } + + ReserveSlots(p_size); + } + + [[nodiscard]] + iterator begin() + { + iterator it {this}; + it.SeekFirstFrom(0); + return it; + } + + [[nodiscard]] + iterator end() + { + return iterator {this}; + } + + [[nodiscard]] + const_iterator begin() const + { + const_iterator it {this}; + it.SeekFirstFrom(0); + return it; + } + + [[nodiscard]] + const_iterator end() const + { + return const_iterator {this}; + } + + [[nodiscard]] + reverse_iterator rbegin() + { + return reverse_iterator {end()}; + } + + [[nodiscard]] + reverse_iterator rend() + { + return reverse_iterator {begin()}; + } + + [[nodiscard]] + const_reverse_iterator rbegin() const + { + return const_reverse_iterator {end()}; + } + + [[nodiscard]] + const_reverse_iterator rend() const + { + return const_reverse_iterator {begin()}; + } + + [[nodiscard]] + const_iterator cbegin() const + { + return begin(); + } + + [[nodiscard]] + const_iterator cend() const + { + return end(); + } + + [[nodiscard]] + const_reverse_iterator crbegin() const + { + return rbegin(); + } + + [[nodiscard]] + const_reverse_iterator crend() const + { + return rend(); + } + + StableSlotMap& operator=(const StableSlotMap& p_map) = delete; + StableSlotMap& operator=(StableSlotMap&& p_map) = default; + + private: + [[nodiscard]] + TYPE& DataAt(const std::size_t p_index) + { + return (*m_pages[p_index / PAGE_SIZE]).m_slots[p_index % PAGE_SIZE].value(); + } + + [[nodiscard]] + const TYPE& DataAt(const std::size_t p_index) const + { + return (*m_pages[p_index / PAGE_SIZE]).m_slots[p_index % PAGE_SIZE].value(); + } + + [[nodiscard]] + SlotMapKey AcquireFreeSlot() + { + ASSERT(UtilsAssertHandler, m_slots.size() < SlotMapKey::MAX_INDEX, "All slots have been exhausted!"); + + if (HasFreeSlots()) + { + const SlotMapKey::IndexType slotIndex = m_freeSlotHead; + m_freeSlotHead = m_slots[slotIndex].GetIndex(); + m_slots[slotIndex] = SlotMapKey {m_slots[slotIndex].GetVersion(), slotIndex}; + return m_slots[slotIndex]; + } + + const SlotMapKey::IndexType slotIndex = static_cast(m_slots.size()); + m_slots.emplace_back(1, slotIndex); + return m_slots[slotIndex]; + } + + void ReleaseSlotVersion(const SlotMapKey::IndexType p_index) + { + RecycleSlot(m_slots[p_index].GetVersion() + 1, p_index); + } + + eastl::vector> m_pages; }; } // namespace Bigfoot diff --git a/Bigfoot/Sources/Utils/Include/Utils/Log/Log_generated.hpp b/Bigfoot/Sources/Utils/Include/Utils/Log/Log_generated.hpp index 6606903..887afbe 100644 --- a/Bigfoot/Sources/Utils/Include/Utils/Log/Log_generated.hpp +++ b/Bigfoot/Sources/Utils/Include/Utils/Log/Log_generated.hpp @@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && FLATBUFFERS_VERSION_MINOR == 12 && FLATBUFFERS_VERSION_REVISION == 19, "Non-compatible flatbuffers version included"); +// Ensure the included flatbuffers.h is Bigfoot's fork - stock +// flatbuffers (or a differently versioned Bigfoot fork) is not compatible. +#ifndef FLATBUFFERS_BIGFOOT_VERSION +#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible" +#endif +static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1, + "Non-compatible Bigfoot flatbuffers fork version included"); #include "EASTL/unique_ptr.h" #include "EASTL/string.h" diff --git a/Bigfoot/Tests/Engine/Asset/Asset.cpp b/Bigfoot/Tests/Engine/Asset/Asset.cpp deleted file mode 100644 index 53976d7..0000000 --- a/Bigfoot/Tests/Engine/Asset/Asset.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/********************************************************************* - * \file BigFile.cpp - * - * \author Romain BOULLARD - * \date December 2025 - *********************************************************************/ -#include - -#include -#include -#include -#include - -namespace Bigfoot -{ -class AssetFixture: public ::testing::Test -{ - protected: -}; - -/****************************************************************************************/ - -TEST_F(AssetFixture, AssetATests) -{ - constexpr eastl::string_view name = "Hello"; - constexpr std::uint32_t version = 42; - constexpr std::uint32_t health = 100; - constexpr std::uint32_t mana = 50; - - AssetA assetA; - assetA.SetName(name); - assetA.SetVersion(version); - assetA.GetAsset().health = health; - assetA.GetAsset().mana = mana; - - const eastl::vector test = assetA.Save(); - - AssetA assetA_dup {test}; - - EXPECT_EQ(assetA.GetHeader().uuid, assetA_dup.GetHeader().uuid); - - EXPECT_EQ(assetA.GetHeader().type_id, AssetA::GetTypeID()); - EXPECT_EQ(assetA.GetHeader().type_id, assetA_dup.GetHeader().type_id); - - EXPECT_EQ(assetA.GetHeader().type_name, AssetA::GetTypeName()); - EXPECT_EQ(assetA.GetHeader().type_name, assetA_dup.GetHeader().type_name); - - EXPECT_EQ(assetA.GetHeader().name, name); - EXPECT_EQ(assetA.GetHeader().name, assetA_dup.GetHeader().name); - - EXPECT_EQ(assetA.GetHeader().version, version); - EXPECT_EQ(assetA.GetHeader().version, assetA_dup.GetHeader().version); - - EXPECT_EQ(assetA.GetAsset().health, health); - EXPECT_EQ(assetA.GetAsset().health, assetA_dup.GetAsset().health); - - EXPECT_EQ(assetA.GetAsset().mana, mana); - EXPECT_EQ(assetA.GetAsset().mana, assetA_dup.GetAsset().mana); -} - -/****************************************************************************************/ - -TEST_F(AssetFixture, AssetBTests) -{ - constexpr eastl::string_view nameA = "Hello"; - constexpr std::uint32_t versionA = 42; - constexpr std::uint32_t healthA = 100; - constexpr std::uint32_t manaA = 50; - - AssetA assetA; - assetA.SetName(nameA); - assetA.SetVersion(versionA); - assetA.GetAsset().health = healthA; - assetA.GetAsset().mana = manaA; - - constexpr eastl::string_view nameAA = "There"; - constexpr std::uint32_t versionAA = 42; - constexpr std::uint32_t healthAA = 100; - constexpr std::uint32_t manaAA = 50; - - AssetA assetAA; - assetAA.SetName(nameAA); - assetAA.SetVersion(versionAA); - assetAA.GetAsset().health = healthAA; - assetAA.GetAsset().mana = manaAA; - - constexpr eastl::string_view nameB = "Kenobi"; - constexpr std::uint32_t versionB = 1; - - AssetB assetB; - assetB.SetName(nameB); - assetB.SetVersion(versionB); - // assetB.GetAsset().asset_a_ref = HardReference {assetA.GetHeader().uuid}; - // assetB.GetAsset().asset_a_refs = {SoftReference {assetA.GetHeader().uuid}, - // SoftReference {assetAA.GetHeader().uuid}}; - - const eastl::vector test = assetB.Save(); - - AssetB assetB_dup {test}; - - EXPECT_EQ(assetB.GetHeader().uuid, assetB_dup.GetHeader().uuid); - - EXPECT_EQ(assetB.GetHeader().type_id, AssetB::GetTypeID()); - EXPECT_EQ(assetB.GetHeader().type_id, assetB_dup.GetHeader().type_id); - - EXPECT_EQ(assetB.GetHeader().type_name, AssetB::GetTypeName()); - EXPECT_EQ(assetB.GetHeader().type_name, assetB_dup.GetHeader().type_name); - - EXPECT_EQ(assetB.GetHeader().name, nameB); - EXPECT_EQ(assetB.GetHeader().name, assetB_dup.GetHeader().name); - - EXPECT_EQ(assetB.GetHeader().version, versionB); - EXPECT_EQ(assetB.GetHeader().version, assetB_dup.GetHeader().version); - - // EXPECT_EQ(assetB.GetAsset().asset_a_ref, HardReference {assetA.GetHeader().uuid}); - // EXPECT_EQ(assetB.GetAsset().asset_a_ref, assetB_dup.GetAsset().asset_a_ref); - - // EXPECT_EQ(assetB.GetAsset().asset_a_refs, - // (eastl::vector> {SoftReference {assetA.GetHeader().uuid}, - // SoftReference {assetAA.GetHeader().uuid}})); - // EXPECT_EQ(assetB.GetAsset().asset_a_refs, assetB_dup.GetAsset().asset_a_refs); -} - -/****************************************************************************************/ - -TEST_F(AssetFixture, AssetCTests) -{ - constexpr eastl::string_view nameA = "Hello"; - constexpr std::uint32_t versionA = 42; - constexpr std::uint32_t healthA = 100; - constexpr std::uint32_t manaA = 50; - - AssetA assetA; - assetA.SetName(nameA); - assetA.SetVersion(versionA); - assetA.GetAsset().health = healthA; - assetA.GetAsset().mana = manaA; - - constexpr eastl::string_view nameAA = "There"; - constexpr std::uint32_t versionAA = 42; - constexpr std::uint32_t healthAA = 100; - constexpr std::uint32_t manaAA = 50; - - AssetA assetAA; - assetAA.SetName(nameAA); - assetAA.SetVersion(versionAA); - assetAA.GetAsset().health = healthAA; - assetAA.GetAsset().mana = manaAA; - - constexpr eastl::string_view nameB = "Kenobi"; - constexpr std::uint32_t versionB = 1; - - AssetB assetB; - assetB.SetName(nameB); - assetB.SetVersion(versionB); - // assetB.GetAsset().asset_a_ref = HardReference {assetA.GetHeader().uuid}; - // assetB.GetAsset().asset_a_refs = {SoftReference {assetA.GetHeader().uuid}, - // SoftReference {assetAA.GetHeader().uuid}}; - - constexpr eastl::string_view nameC = "General"; - constexpr std::uint32_t versionC = 1; - - AssetC assetC; - assetC.SetName(nameC); - assetC.SetVersion(versionC); - // assetC.GetAsset().inner_table->asset_a_ref = HardReference {assetA.GetHeader().uuid}; - // assetC.GetAsset().inner_table->asset_a_refs = {HardReference {assetA.GetHeader().uuid}, - // HardReference {assetAA.GetHeader().uuid}}; - // assetC.GetAsset().asset_b_ref = HardReference {assetB.GetHeader().uuid}; - // assetC.GetAsset().asset_b_refs = {SoftReference {assetB.GetHeader().uuid}}; - - const eastl::vector test = assetC.Save(); - - AssetC assetC_dup {test}; - - EXPECT_EQ(assetC.GetHeader().uuid, assetC_dup.GetHeader().uuid); - - EXPECT_EQ(assetC.GetHeader().type_id, AssetC::GetTypeID()); - EXPECT_EQ(assetC.GetHeader().type_id, assetC_dup.GetHeader().type_id); - - EXPECT_EQ(assetC.GetHeader().type_name, AssetC::GetTypeName()); - EXPECT_EQ(assetC.GetHeader().type_name, assetC_dup.GetHeader().type_name); - - EXPECT_EQ(assetC.GetHeader().name, nameC); - EXPECT_EQ(assetC.GetHeader().name, assetC_dup.GetHeader().name); - - EXPECT_EQ(assetC.GetHeader().version, versionC); - EXPECT_EQ(assetC.GetHeader().version, assetC_dup.GetHeader().version); - - // EXPECT_EQ(assetC.GetAsset().asset_b_ref, HardReference {assetB.GetHeader().uuid}); - // EXPECT_EQ(assetC.GetAsset().asset_b_ref, assetC_dup.GetAsset().asset_b_ref); - - // EXPECT_EQ(assetC.GetAsset().asset_b_refs, - // (eastl::vector> {SoftReference {assetB.GetHeader().uuid}})); - // EXPECT_EQ(assetC.GetAsset().asset_b_refs, assetC_dup.GetAsset().asset_b_refs); - - // EXPECT_EQ(assetC.GetAsset().inner_table->asset_a_ref, HardReference {assetA.GetHeader().uuid}); - // EXPECT_EQ(assetC.GetAsset().inner_table->asset_a_ref, assetC_dup.GetAsset().inner_table->asset_a_ref); - - // EXPECT_EQ(assetC.GetAsset().inner_table->asset_a_refs, - // (eastl::vector> {HardReference {assetA.GetHeader().uuid}, - // HardReference {assetAA.GetHeader().uuid}})); - // EXPECT_EQ(assetC.GetAsset().inner_table->asset_a_refs, assetC_dup.GetAsset().inner_table->asset_a_refs); -} -} // namespace Bigfoot diff --git a/Bigfoot/Tests/Engine/Asset/AssetContainer.cpp b/Bigfoot/Tests/Engine/Asset/AssetContainer.cpp deleted file mode 100644 index a694905..0000000 --- a/Bigfoot/Tests/Engine/Asset/AssetContainer.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/********************************************************************* - * \file AssetContainer.cpp - * - * \author Romain BOULLARD - * \date December 2025 - *********************************************************************/ -#include - -#include -#include - -namespace Bigfoot -{ -class AssetContainerFixture: public ::testing::Test -{ - protected: - AssetContainer m_container; -}; - -/****************************************************************************************/ - -TEST_F(AssetContainerFixture, Insert) -{ - std::ignore = m_container.Insert(); -} - -/****************************************************************************************/ - -TEST_F(AssetContainerFixture, Get) -{ - const auto key = m_container.Insert(); - - const auto& constContainer = m_container; - - const auto validateKey = [&](auto& p_assetContainer) - { - const auto asset = p_assetContainer.Get(key); - EXPECT_NE(asset, nullptr); - }; - validateKey(m_container); - validateKey(constContainer); -} - -/****************************************************************************************/ - -TEST_F(AssetContainerFixture, GetSlotKey) -{ - const auto key = m_container.Insert(); - const auto asset = m_container.Get(key); - EXPECT_EQ(m_container.GetSlotKey(asset->GetHeader().uuid), key); -} - -/****************************************************************************************/ - -TEST_F(AssetContainerFixture, Has) -{ - const auto key = m_container.Insert(); - EXPECT_TRUE(m_container.Has(key)); - EXPECT_TRUE(m_container.Has(m_container.Get(key)->GetHeader().uuid)); -} - -/****************************************************************************************/ - -TEST_F(AssetContainerFixture, Remove) -{ - const auto key1 = m_container.Insert(); - m_container.Remove(key1); - - const auto key2 = m_container.Insert(); - m_container.Remove(m_container.Get(key2)->GetHeader().uuid); -} -} // namespace Bigfoot diff --git a/Bigfoot/Tests/Engine/Asset/AssetLibrary.cpp b/Bigfoot/Tests/Engine/Asset/AssetLibrary.cpp deleted file mode 100644 index ad96349..0000000 --- a/Bigfoot/Tests/Engine/Asset/AssetLibrary.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/********************************************************************* - * \file AssetLibrary.cpp - * - * \author Romain BOULLARD - * \date July 2026 - *********************************************************************/ -#include - -#include -#include -#include -#include - -namespace Bigfoot -{ -class AssetLibraryFixture: public ::testing::Test -{ - protected: - void SetUp() override - { - std::ignore = m_library.Insert(&m_containerA); - std::ignore = m_library.Insert(&m_containerB); - } - - AssetContainer m_containerA; - AssetContainer m_containerB; - - AssetLibrary m_library; -}; - -/****************************************************************************************/ - -TEST_F(AssetLibraryFixture, Insert_ShouldReturnTrueIfTheContainerHasBeenInserted) -{ - AssetContainer containerC; - EXPECT_TRUE(m_library.Insert(&containerC)); -} - -/****************************************************************************************/ - -TEST_F(AssetLibraryFixture, Insert_ShouldReturnFalseIfTheContainerHasNotBeenInserted) -{ - EXPECT_FALSE(m_library.Insert(&m_containerA)); // Duplicate -} - -/****************************************************************************************/ - -TEST_F(AssetLibraryFixture, Get_ShouldReturnTheContainersIfTheyAreInTheLibrary) -{ - const AssetContainer* containerA = m_library.Get(); - const AssetContainer* containerB = m_library.Get(); - - EXPECT_EQ(&m_containerA, containerA); - EXPECT_EQ(&m_containerB, containerB); -} - -/****************************************************************************************/ - -TEST_F(AssetLibraryFixture, Get_ShouldReturnNullptrIfTheContainersAreNotInTheLibrary) -{ - const AssetContainer* containerC = m_library.Get(); - - EXPECT_EQ(nullptr, containerC); -} - -/****************************************************************************************/ - -TEST_F(AssetLibraryFixture, GlobalAssetLibraryShouldHaveAssetsRegistered) -{ - EXPECT_NE(g_assetLibrary.Get(), nullptr); - EXPECT_NE(g_assetLibrary.Get(), nullptr); - EXPECT_NE(g_assetLibrary.Get(), nullptr); -} -} // namespace Bigfoot diff --git a/Bigfoot/Tests/Engine/BigFile/BigFile.cpp b/Bigfoot/Tests/Engine/BigFile/BigFile.cpp deleted file mode 100644 index 19f2c31..0000000 --- a/Bigfoot/Tests/Engine/BigFile/BigFile.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/********************************************************************* - * \file BigFile.cpp - * - * \author Romain BOULLARD - * \date December 2025 - *********************************************************************/ -#include - -#include -#include - -#include - -#include -#include -#include - -namespace Bigfoot -{ -class BigFileFixture: public ::testing::Test -{ - protected: - void SetUp() override - { - BigFile::Request deleteHeader {m_bigFile, "DELETE FROM AssetHeader"}; - BigFile::Request deleteAsset {m_bigFile, "DELETE FROM Asset"}; - - m_bigFile.BeginTransaction(); - deleteHeader.Execute(); - deleteAsset.Execute(); - m_bigFile.CommitTransaction(); - } - - BigFile m_bigFile {File {BIGFILE_ENGINETESTS_LOCATION}}; -}; - -/****************************************************************************************/ - -TEST_F(BigFileFixture, BigFileManipulation) -{ - UUID uuid; - UUID uuid2; - UUID uuid3; - - constexpr eastl::array blob {std::byte {1}, std::byte {2}, std::byte {3}, std::byte {4}}; - constexpr eastl::array blob2 {std::byte {1}, std::byte {2}, std::byte {3}, std::byte {5}}; - constexpr eastl::array blob3 {std::byte {1}, std::byte {2}, std::byte {3}, std::byte {6}}; - constexpr eastl::array blob4 {std::byte {10}, std::byte {11}, std::byte {12}, std::byte {13}}; - - constexpr std::uint64_t typeIDRef = std::numeric_limits::max() - 1; - - { - BigFile::Request assetHeaderRequest { - m_bigFile, - "INSERT INTO AssetHeader (UUID, Name, TypeID, TypeName) VALUES(?, ?, ?, ?)"}; - assetHeaderRequest.Bind(1, uuid.ToBytes()); - assetHeaderRequest.Bind(2, "Test"); - assetHeaderRequest.Bind(3, typeIDRef); - assetHeaderRequest.Bind(4, "TypeTest"); - - BigFile::Request assetRequest {m_bigFile, "INSERT INTO Asset (UUID, Asset) VALUES(?, ?)"}; - assetRequest.Bind(1, uuid.ToBytes()); - assetRequest.Bind(2, blob); - - BigFile::Request assetHeaderRequest2 { - m_bigFile, - "INSERT INTO AssetHeader (UUID, Name, TypeID, TypeName) VALUES(?, ?, ?, ?)"}; - assetHeaderRequest2.Bind(1, uuid2.ToBytes()); - assetHeaderRequest2.Bind(2, "Test2"); - assetHeaderRequest2.Bind(3, typeIDRef); - assetHeaderRequest2.Bind(4, "TypeTest"); - - BigFile::Request assetRequest2 {m_bigFile, "INSERT INTO Asset (UUID, Asset) VALUES(?, ?)"}; - assetRequest2.Bind(1, uuid2.ToBytes()); - assetRequest2.Bind(2, blob3); - - BigFile::Request assetHeaderRequest3 { - m_bigFile, - "INSERT INTO AssetHeader (UUID, Name, TypeID, TypeName) VALUES(?, ?, ?, ?)"}; - assetHeaderRequest3.Bind(1, uuid3.ToBytes()); - assetHeaderRequest3.Bind(2, "Test3"); - assetHeaderRequest3.Bind(3, typeIDRef); - assetHeaderRequest3.Bind(4, "TypeTest"); - - BigFile::Request assetRequest3 {m_bigFile, "INSERT INTO Asset (UUID, Asset) VALUES(?, ?)"}; - assetRequest3.Bind(1, uuid3.ToBytes()); - assetRequest3.Bind(2, blob4); - - m_bigFile.BeginTransaction(); - std::uint32_t assetHeaderChangedCount = assetHeaderRequest.Execute(); - EXPECT_EQ(assetHeaderChangedCount, 1); - std::uint32_t assetChangedCount = assetRequest.Execute(); - EXPECT_EQ(assetChangedCount, 1); - - std::uint32_t assetHeaderChangedCount2 = assetHeaderRequest2.Execute(); - EXPECT_EQ(assetHeaderChangedCount2, 1); - std::uint32_t assetChangedCount2 = assetRequest2.Execute(); - EXPECT_EQ(assetChangedCount2, 1); - - std::uint32_t assetHeaderChangedCount3 = assetHeaderRequest3.Execute(); - EXPECT_EQ(assetHeaderChangedCount3, 1); - std::uint32_t assetChangedCount3 = assetRequest3.Execute(); - EXPECT_EQ(assetChangedCount3, 1); - - m_bigFile.CommitTransaction(); - } - - { - BigFile::Request updateAsset {m_bigFile, "UPDATE Asset SET Asset = ? WHERE UUID = ?"}; - updateAsset.Bind(1, blob2); - updateAsset.Bind(2, uuid.ToBytes()); - - m_bigFile.BeginTransaction(); - std::uint32_t updateAssetChangedCount = updateAsset.Execute(); - EXPECT_EQ(updateAssetChangedCount, 1); - m_bigFile.CommitTransaction(); - } - - { - BigFile::Request request { - m_bigFile, - "SELECT Name, TypeID, TypeName, CreateTime, ModificationTime FROM AssetHeader WHERE UUID = ?"}; - request.Bind(1, uuid.ToBytes()); - - const bool get = request.Step(); - EXPECT_TRUE(get); - - const eastl::string name {static_cast(request.Get(0))}; - EXPECT_STREQ(name.c_str(), "Test"); - const std::uint64_t typeID = static_cast(request.Get(1)); - EXPECT_EQ(typeID, typeIDRef); - const eastl::string typeName {static_cast(request.Get(2))}; - EXPECT_STREQ(typeName.c_str(), "TypeTest"); - - const Time createTime = static_cast(request.Get(3)); - const Time modificationTime = static_cast(request.Get(4)); - - EXPECT_GT(createTime.GetEpoch(), 0); - EXPECT_GT(modificationTime.GetEpoch(), 0); - - EXPECT_GE(createTime, modificationTime); - - EXPECT_GT(createTime.GetYear(), 2025); - EXPECT_GT(modificationTime.GetYear(), 2025); - } -} -} // namespace Bigfoot diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Asset/AssetA.cpp b/Bigfoot/Tests/Misc/AssetsForTesting/Asset/AssetA.cpp index e989e54..6c2a0d1 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Asset/AssetA.cpp +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Asset/AssetA.cpp @@ -8,4 +8,4 @@ #include -ASSET_CONTAINER(AssetA, ::Bigfoot::AssetA) +BIGFOOT_ASSET(AssetA, ::Bigfoot::AssetA) diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Asset/AssetB.cpp b/Bigfoot/Tests/Misc/AssetsForTesting/Asset/AssetB.cpp index b614402..9d14fa7 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Asset/AssetB.cpp +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Asset/AssetB.cpp @@ -8,4 +8,4 @@ #include -ASSET_CONTAINER(AssetB, ::Bigfoot::AssetB) +BIGFOOT_ASSET(AssetB, ::Bigfoot::AssetB) diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Asset/AssetC.cpp b/Bigfoot/Tests/Misc/AssetsForTesting/Asset/AssetC.cpp index a4a4e01..bb2d42d 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Asset/AssetC.cpp +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Asset/AssetC.cpp @@ -8,4 +8,4 @@ #include -ASSET_CONTAINER(AssetC, ::Bigfoot::AssetC) +BIGFOOT_ASSET(AssetC, ::Bigfoot::AssetC) diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA.fbs b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA.fbs index 3f12528..b778ca5 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA.fbs +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA.fbs @@ -7,7 +7,7 @@ table AssetA health: uint = 0; mana: uint = 0; - ref_a: SoftReference (native_inline, native_type_template_arg: "::Bigfoot::AssetA"); + ref_a: SoftReference (native_inline, bigfoot_ref: "::Bigfoot::AssetA"); } root_type AssetA; \ No newline at end of file diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA.hpp b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA.hpp index 7d172f2..9bee1f1 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA.hpp +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA.hpp @@ -30,7 +30,7 @@ class AssetA: public Asset AssetA(const AssetA& p_asset) = delete; AssetA(AssetA&& p_asset) = default; - ~AssetA() override = default; + ~AssetA() = default; AssetA& operator=(const AssetA& p_asset) = delete; AssetA& operator=(AssetA&& p_asset) = default; diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA_generated.hpp b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA_generated.hpp index adff89d..b1004e0 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA_generated.hpp +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetA_generated.hpp @@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && FLATBUFFERS_VERSION_MINOR == 12 && FLATBUFFERS_VERSION_REVISION == 19, "Non-compatible flatbuffers version included"); +// Ensure the included flatbuffers.h is Bigfoot's fork - stock +// flatbuffers (or a differently versioned Bigfoot fork) is not compatible. +#ifndef FLATBUFFERS_BIGFOOT_VERSION +#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible" +#endif +static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1, + "Non-compatible Bigfoot flatbuffers fork version included"); #include "System/UUID/UUID.hpp" #include "Engine/Asset/Reference.hpp" @@ -28,6 +35,21 @@ struct AssetA; struct AssetABuilder; struct AssetAT; +} // namespace Bigfoot +} // namespace Flat + +namespace Bigfoot { +class AssetA; +} // namespace Bigfoot + +namespace flatbuffers { +Flat::Bigfoot::SoftReference PackSoftReferenceAssetA(const ::Bigfoot::SoftReference<::Bigfoot::AssetA>& p_asset); +::Bigfoot::SoftReference<::Bigfoot::AssetA> UnPackSoftReferenceAssetA(const Flat::Bigfoot::SoftReference& p_asset); +} // namespace flatbuffers + +namespace Flat { +namespace Bigfoot { + inline const ::flatbuffers::TypeTable *AssetATypeTable(); struct AssetAT : public ::flatbuffers::NativeTable { @@ -218,4 +240,12 @@ inline eastl::unique_ptr UnPackSizePrefixedAssetA( } // namespace Bigfoot } // namespace Flat +namespace flatbuffers { +#ifndef FLATBUFFERS_BIGFOOT_REF_SOFTREFERENCEASSETA +#define FLATBUFFERS_BIGFOOT_REF_SOFTREFERENCEASSETA +inline Flat::Bigfoot::SoftReference PackSoftReferenceAssetA(const ::Bigfoot::SoftReference<::Bigfoot::AssetA>& p_asset) { return {Pack(p_asset.GetUUID())}; } +inline ::Bigfoot::SoftReference<::Bigfoot::AssetA> UnPackSoftReferenceAssetA(const Flat::Bigfoot::SoftReference& p_asset) { return {UnPack(p_asset.uuid())}; } +#endif // FLATBUFFERS_BIGFOOT_REF_SOFTREFERENCEASSETA +} // namespace flatbuffers + #endif // FLATBUFFERS_GENERATED_ASSETA_FLAT_BIGFOOT_H_ diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.fbs b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.fbs index 5026764..3cc2362 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.fbs +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.fbs @@ -4,8 +4,8 @@ namespace Flat.Bigfoot; table AssetB { - ref_a: HardReference (native_inline, native_type_template_arg: "::Bigfoot::AssetA"); - refs_a: [SoftReference] (native_inline, native_type_template_arg: "::Bigfoot::AssetA"); + ref_a: HardReference (native_inline, bigfoot_ref: "::Bigfoot::AssetA"); + refs_a: [SoftReference] (native_inline, bigfoot_ref: "::Bigfoot::AssetA"); } root_type AssetB; \ No newline at end of file diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.hpp b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.hpp index 4df701d..cc87034 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.hpp +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.hpp @@ -30,7 +30,7 @@ class AssetB: public Asset AssetB(const AssetB& p_asset) = delete; AssetB(AssetB&& p_asset) = default; - ~AssetB() override = default; + ~AssetB() = default; AssetB& operator=(const AssetB& p_asset) = delete; AssetB& operator=(AssetB&& p_asset) = default; diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB_generated.hpp b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB_generated.hpp index 8c620f5..9a55a7f 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB_generated.hpp +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB_generated.hpp @@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && FLATBUFFERS_VERSION_MINOR == 12 && FLATBUFFERS_VERSION_REVISION == 19, "Non-compatible flatbuffers version included"); +// Ensure the included flatbuffers.h is Bigfoot's fork - stock +// flatbuffers (or a differently versioned Bigfoot fork) is not compatible. +#ifndef FLATBUFFERS_BIGFOOT_VERSION +#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible" +#endif +static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1, + "Non-compatible Bigfoot flatbuffers fork version included"); #include "System/UUID/UUID.hpp" #include "Engine/Asset/Reference.hpp" @@ -28,6 +35,23 @@ struct AssetB; struct AssetBBuilder; struct AssetBT; +} // namespace Bigfoot +} // namespace Flat + +namespace Bigfoot { +class AssetA; +} // namespace Bigfoot + +namespace flatbuffers { +Flat::Bigfoot::HardReference PackHardReferenceAssetA(const ::Bigfoot::HardReference<::Bigfoot::AssetA>& p_asset); +::Bigfoot::HardReference<::Bigfoot::AssetA> UnPackHardReferenceAssetA(const Flat::Bigfoot::HardReference& p_asset); +Flat::Bigfoot::SoftReference PackSoftReferenceAssetA(const ::Bigfoot::SoftReference<::Bigfoot::AssetA>& p_asset); +::Bigfoot::SoftReference<::Bigfoot::AssetA> UnPackSoftReferenceAssetA(const Flat::Bigfoot::SoftReference& p_asset); +} // namespace flatbuffers + +namespace Flat { +namespace Bigfoot { + inline const ::flatbuffers::TypeTable *AssetBTypeTable(); struct AssetBT : public ::flatbuffers::NativeTable { @@ -205,4 +229,17 @@ inline eastl::unique_ptr UnPackSizePrefixedAssetB( } // namespace Bigfoot } // namespace Flat +namespace flatbuffers { +#ifndef FLATBUFFERS_BIGFOOT_REF_HARDREFERENCEASSETA +#define FLATBUFFERS_BIGFOOT_REF_HARDREFERENCEASSETA +inline Flat::Bigfoot::HardReference PackHardReferenceAssetA(const ::Bigfoot::HardReference<::Bigfoot::AssetA>& p_asset) { return {Pack(p_asset.GetUUID())}; } +inline ::Bigfoot::HardReference<::Bigfoot::AssetA> UnPackHardReferenceAssetA(const Flat::Bigfoot::HardReference& p_asset) { return {UnPack(p_asset.uuid())}; } +#endif // FLATBUFFERS_BIGFOOT_REF_HARDREFERENCEASSETA +#ifndef FLATBUFFERS_BIGFOOT_REF_SOFTREFERENCEASSETA +#define FLATBUFFERS_BIGFOOT_REF_SOFTREFERENCEASSETA +inline Flat::Bigfoot::SoftReference PackSoftReferenceAssetA(const ::Bigfoot::SoftReference<::Bigfoot::AssetA>& p_asset) { return {Pack(p_asset.GetUUID())}; } +inline ::Bigfoot::SoftReference<::Bigfoot::AssetA> UnPackSoftReferenceAssetA(const Flat::Bigfoot::SoftReference& p_asset) { return {UnPack(p_asset.uuid())}; } +#endif // FLATBUFFERS_BIGFOOT_REF_SOFTREFERENCEASSETA +} // namespace flatbuffers + #endif // FLATBUFFERS_GENERATED_ASSETB_FLAT_BIGFOOT_H_ diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC.fbs b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC.fbs index cae5c61..e21178e 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC.fbs +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC.fbs @@ -4,16 +4,19 @@ namespace Flat.Bigfoot; table InnerTable { - asset_a_ref: HardReference (native_inline, native_type_template_arg: "::Bigfoot::AssetA"); - asset_a_refs: [HardReference] (native_inline, native_type_template_arg: "::Bigfoot::AssetA"); + asset_a_ref: HardReference (native_inline, bigfoot_ref: "::Bigfoot::AssetA"); + asset_a_refs: [HardReference] (native_inline, bigfoot_ref: "::Bigfoot::AssetA"); + + any_asset: AnyHardReference (native_inline); + any_assets: [AnySoftReference] (native_inline); } table AssetC { inner_table: InnerTable (required); - asset_b_ref: HardReference (native_inline, native_type_template_arg: "::Bigfoot::AssetB"); - asset_b_refs: [SoftReference] (native_inline, native_type_template_arg: "::Bigfoot::AssetB"); + asset_b_ref: HardReference (native_inline, bigfoot_ref: "::Bigfoot::AssetB"); + asset_b_refs: [SoftReference] (native_inline, bigfoot_ref: "::Bigfoot::AssetB"); } root_type AssetC; \ No newline at end of file diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC.hpp b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC.hpp index 5b8557c..ecf5fae 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC.hpp +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC.hpp @@ -33,7 +33,7 @@ class AssetC: public Asset AssetC(const AssetC& p_asset) = delete; AssetC(AssetC&& p_asset) = default; - ~AssetC() override = default; + ~AssetC() = default; AssetC& operator=(const AssetC& p_asset) = delete; AssetC& operator=(AssetC&& p_asset) = default; diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC_generated.hpp b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC_generated.hpp index e5a57cf..eaab7e8 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC_generated.hpp +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetC_generated.hpp @@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && FLATBUFFERS_VERSION_MINOR == 12 && FLATBUFFERS_VERSION_REVISION == 19, "Non-compatible flatbuffers version included"); +// Ensure the included flatbuffers.h is Bigfoot's fork - stock +// flatbuffers (or a differently versioned Bigfoot fork) is not compatible. +#ifndef FLATBUFFERS_BIGFOOT_VERSION +#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible" +#endif +static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1, + "Non-compatible Bigfoot flatbuffers fork version included"); #include "System/UUID/UUID.hpp" #include "Engine/Asset/Reference.hpp" @@ -32,6 +39,29 @@ struct AssetC; struct AssetCBuilder; struct AssetCT; +} // namespace Bigfoot +} // namespace Flat + +namespace Bigfoot { +class AssetA; +} // namespace Bigfoot + +namespace Bigfoot { +class AssetB; +} // namespace Bigfoot + +namespace flatbuffers { +Flat::Bigfoot::HardReference PackHardReferenceAssetA(const ::Bigfoot::HardReference<::Bigfoot::AssetA>& p_asset); +::Bigfoot::HardReference<::Bigfoot::AssetA> UnPackHardReferenceAssetA(const Flat::Bigfoot::HardReference& p_asset); +Flat::Bigfoot::HardReference PackHardReferenceAssetB(const ::Bigfoot::HardReference<::Bigfoot::AssetB>& p_asset); +::Bigfoot::HardReference<::Bigfoot::AssetB> UnPackHardReferenceAssetB(const Flat::Bigfoot::HardReference& p_asset); +Flat::Bigfoot::SoftReference PackSoftReferenceAssetB(const ::Bigfoot::SoftReference<::Bigfoot::AssetB>& p_asset); +::Bigfoot::SoftReference<::Bigfoot::AssetB> UnPackSoftReferenceAssetB(const Flat::Bigfoot::SoftReference& p_asset); +} // namespace flatbuffers + +namespace Flat { +namespace Bigfoot { + inline const ::flatbuffers::TypeTable *InnerTableTypeTable(); inline const ::flatbuffers::TypeTable *AssetCTypeTable(); @@ -43,6 +73,8 @@ struct InnerTableT : public ::flatbuffers::NativeTable { } ::Bigfoot::HardReference<::Bigfoot::AssetA> asset_a_ref{}; eastl::vector<::Bigfoot::HardReference<::Bigfoot::AssetA>> asset_a_refs{}; + ::Bigfoot::AnyHardReference any_asset{}; + eastl::vector<::Bigfoot::AnySoftReference> any_assets{}; }; struct InnerTable FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { @@ -57,7 +89,9 @@ struct InnerTable FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { } enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_ASSET_A_REF = 4, - VT_ASSET_A_REFS = 6 + VT_ASSET_A_REFS = 6, + VT_ANY_ASSET = 8, + VT_ANY_ASSETS = 10 }; const Flat::Bigfoot::HardReference *asset_a_ref() const { return GetStruct(VT_ASSET_A_REF); @@ -65,12 +99,21 @@ struct InnerTable FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { const ::flatbuffers::Vector *asset_a_refs() const { return GetPointer *>(VT_ASSET_A_REFS); } + const Flat::Bigfoot::AnyHardReference *any_asset() const { + return GetStruct(VT_ANY_ASSET); + } + const ::flatbuffers::Vector *any_assets() const { + return GetPointer *>(VT_ANY_ASSETS); + } template bool Verify(::flatbuffers::VerifierTemplate &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, VT_ASSET_A_REF, 1) && VerifyOffset(verifier, VT_ASSET_A_REFS) && verifier.VerifyVector(asset_a_refs()) && + VerifyField(verifier, VT_ANY_ASSET, 1) && + VerifyOffset(verifier, VT_ANY_ASSETS) && + verifier.VerifyVector(any_assets()) && verifier.EndTable(); } InnerTableT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; @@ -88,6 +131,12 @@ struct InnerTableBuilder { void add_asset_a_refs(::flatbuffers::Offset<::flatbuffers::Vector> asset_a_refs) { fbb_.AddOffset(InnerTable::VT_ASSET_A_REFS, asset_a_refs); } + void add_any_asset(const Flat::Bigfoot::AnyHardReference *any_asset) { + fbb_.AddStruct(InnerTable::VT_ANY_ASSET, any_asset); + } + void add_any_assets(::flatbuffers::Offset<::flatbuffers::Vector> any_assets) { + fbb_.AddOffset(InnerTable::VT_ANY_ASSETS, any_assets); + } explicit InnerTableBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); @@ -102,8 +151,12 @@ struct InnerTableBuilder { inline ::flatbuffers::Offset CreateInnerTable( ::flatbuffers::FlatBufferBuilder &_fbb, const Flat::Bigfoot::HardReference *asset_a_ref = nullptr, - ::flatbuffers::Offset<::flatbuffers::Vector> asset_a_refs = 0) { + ::flatbuffers::Offset<::flatbuffers::Vector> asset_a_refs = 0, + const Flat::Bigfoot::AnyHardReference *any_asset = nullptr, + ::flatbuffers::Offset<::flatbuffers::Vector> any_assets = 0) { InnerTableBuilder builder_(_fbb); + builder_.add_any_assets(any_assets); + builder_.add_any_asset(any_asset); builder_.add_asset_a_refs(asset_a_refs); builder_.add_asset_a_ref(asset_a_ref); return builder_.Finish(); @@ -224,6 +277,8 @@ inline void InnerTable::UnPackTo(InnerTableT *_o, const ::flatbuffers::resolver_ (void)_resolver; { auto _e = asset_a_ref(); if (_e) _o->asset_a_ref = ::flatbuffers::UnPackHardReferenceAssetA(*_e); } { auto _e = asset_a_refs(); if (_e) { _o->asset_a_refs.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->asset_a_refs[_i] = ::flatbuffers::UnPackHardReferenceAssetA(*_e->Get(_i)); } } else { _o->asset_a_refs.resize(0); } } + { auto _e = any_asset(); if (_e) _o->any_asset = ::flatbuffers::UnPack(*_e); } + { auto _e = any_assets(); if (_e) { _o->any_assets.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->any_assets[_i] = ::flatbuffers::UnPack(*_e->Get(_i)); } } else { _o->any_assets.resize(0); } } } inline ::flatbuffers::Offset CreateInnerTable(::flatbuffers::FlatBufferBuilder &_fbb, const InnerTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { @@ -236,10 +291,14 @@ inline ::flatbuffers::Offset InnerTable::Pack(::flatbuffers::FlatBuf struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const InnerTableT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; auto _asset_a_ref = ::flatbuffers::PackHardReferenceAssetA(_o->asset_a_ref); auto _asset_a_refs = _fbb.CreateVectorOfNativeStructs>(_o->asset_a_refs.data(), _o->asset_a_refs.size(), ::flatbuffers::PackHardReferenceAssetA); + auto _any_asset = ::flatbuffers::Pack(_o->any_asset); + auto _any_assets = _fbb.CreateVectorOfNativeStructs(_o->any_assets.data(), _o->any_assets.size()); return Flat::Bigfoot::CreateInnerTable( _fbb, &_asset_a_ref, - _asset_a_refs); + _asset_a_refs, + &_any_asset, + _any_assets); } inline AssetCT::AssetCT(const AssetCT &o) @@ -290,13 +349,17 @@ inline ::flatbuffers::Offset AssetC::Pack(::flatbuffers::FlatBufferBuild inline const ::flatbuffers::TypeTable *InnerTableTypeTable() { static const ::flatbuffers::TypeCode type_codes[] = { { ::flatbuffers::ET_SEQUENCE, 0, 0 }, - { ::flatbuffers::ET_SEQUENCE, 1, 0 } + { ::flatbuffers::ET_SEQUENCE, 1, 0 }, + { ::flatbuffers::ET_SEQUENCE, 0, 1 }, + { ::flatbuffers::ET_SEQUENCE, 1, 2 } }; static const ::flatbuffers::TypeFunction type_refs[] = { - Flat::Bigfoot::HardReferenceTypeTable + Flat::Bigfoot::HardReferenceTypeTable, + Flat::Bigfoot::AnyHardReferenceTypeTable, + Flat::Bigfoot::AnySoftReferenceTypeTable }; static const ::flatbuffers::TypeTable tt = { - ::flatbuffers::ST_TABLE, 2, type_codes, type_refs, nullptr, nullptr, nullptr + ::flatbuffers::ST_TABLE, 4, type_codes, type_refs, nullptr, nullptr, nullptr }; return &tt; } @@ -369,4 +432,22 @@ inline eastl::unique_ptr UnPackSizePrefixedAssetC( } // namespace Bigfoot } // namespace Flat +namespace flatbuffers { +#ifndef FLATBUFFERS_BIGFOOT_REF_HARDREFERENCEASSETA +#define FLATBUFFERS_BIGFOOT_REF_HARDREFERENCEASSETA +inline Flat::Bigfoot::HardReference PackHardReferenceAssetA(const ::Bigfoot::HardReference<::Bigfoot::AssetA>& p_asset) { return {Pack(p_asset.GetUUID())}; } +inline ::Bigfoot::HardReference<::Bigfoot::AssetA> UnPackHardReferenceAssetA(const Flat::Bigfoot::HardReference& p_asset) { return {UnPack(p_asset.uuid())}; } +#endif // FLATBUFFERS_BIGFOOT_REF_HARDREFERENCEASSETA +#ifndef FLATBUFFERS_BIGFOOT_REF_HARDREFERENCEASSETB +#define FLATBUFFERS_BIGFOOT_REF_HARDREFERENCEASSETB +inline Flat::Bigfoot::HardReference PackHardReferenceAssetB(const ::Bigfoot::HardReference<::Bigfoot::AssetB>& p_asset) { return {Pack(p_asset.GetUUID())}; } +inline ::Bigfoot::HardReference<::Bigfoot::AssetB> UnPackHardReferenceAssetB(const Flat::Bigfoot::HardReference& p_asset) { return {UnPack(p_asset.uuid())}; } +#endif // FLATBUFFERS_BIGFOOT_REF_HARDREFERENCEASSETB +#ifndef FLATBUFFERS_BIGFOOT_REF_SOFTREFERENCEASSETB +#define FLATBUFFERS_BIGFOOT_REF_SOFTREFERENCEASSETB +inline Flat::Bigfoot::SoftReference PackSoftReferenceAssetB(const ::Bigfoot::SoftReference<::Bigfoot::AssetB>& p_asset) { return {Pack(p_asset.GetUUID())}; } +inline ::Bigfoot::SoftReference<::Bigfoot::AssetB> UnPackSoftReferenceAssetB(const Flat::Bigfoot::SoftReference& p_asset) { return {UnPack(p_asset.uuid())}; } +#endif // FLATBUFFERS_BIGFOOT_REF_SOFTREFERENCEASSETB +} // namespace flatbuffers + #endif // FLATBUFFERS_GENERATED_ASSETC_FLAT_BIGFOOT_H_ diff --git a/Bigfoot/Tests/Utils/Containers/SlotMap.cpp b/Bigfoot/Tests/Utils/Containers/SlotMap.cpp deleted file mode 100644 index 2d4aa7e..0000000 --- a/Bigfoot/Tests/Utils/Containers/SlotMap.cpp +++ /dev/null @@ -1,539 +0,0 @@ -/********************************************************************* - * \file SlotMap.cpp - * - * \author Romain BOULLARD - * \date May 2026 - *********************************************************************/ -#include - -#include - -namespace Bigfoot -{ -template -struct SlotMapConfig -{ - using Version = VERSION_TYPE; - using Index = INDEX_TYPE; -}; - -using SlotMapConfigs = ::testing::Types, - SlotMapConfig, - SlotMapConfig, - SlotMapConfig, - SlotMapConfig, - SlotMapConfig, - SlotMapConfig, - SlotMapConfig, - SlotMapConfig>; - -struct SlotMapConfigNames -{ - template - static std::string GetName(int) - { - return "VERSION" + std::to_string(sizeof(typename T::Version) * 8) + "_INDEX" + - std::to_string(sizeof(typename T::Index) * 8); - } -}; - -/****************************************************************************************/ - -template -class SlotKeyFixture: public ::testing::Test -{ - protected: - using SlotMapVersionType = typename CONFIG::Version; - using SlotMapIndexType = typename CONFIG::Index; - - using SlotMapType = SlotMap; - using SlotKeyType = typename SlotMapType::InternalSlotKey; -}; - -TYPED_TEST_SUITE(SlotKeyFixture, SlotMapConfigs, SlotMapConfigNames); - -/****************************************************************************************/ - -TYPED_TEST(SlotKeyFixture, DefaultSlotKeyIsInvalid) -{ - constexpr typename TestFixture::SlotMapIndexType index = 0; - constexpr typename TestFixture::SlotMapVersionType version = 0; - - constexpr typename TestFixture::SlotKeyType slotKey {}; - EXPECT_FALSE(slotKey.Valid()); - EXPECT_EQ(slotKey.GetVersion(), version); - EXPECT_EQ(slotKey.GetIndex(), index); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotKeyFixture, Valid_ShouldReturnTrueIfTheSlotKeyIsValid) -{ - constexpr typename TestFixture::SlotMapIndexType index = 0; - constexpr typename TestFixture::SlotMapVersionType version = 1; - - constexpr typename TestFixture::SlotKeyType slotKey {version, index}; - EXPECT_TRUE(slotKey.Valid()); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotKeyFixture, Valid_ShouldReturnFalseIfTheSlotKeyIsValid) -{ - constexpr typename TestFixture::SlotMapIndexType index = 0; - constexpr typename TestFixture::SlotMapVersionType version = 0; - - constexpr typename TestFixture::SlotKeyType slotKey {version, index}; - EXPECT_FALSE(slotKey.Valid()); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotKeyFixture, GetVersion_ShouldReturnTheVersion) -{ - constexpr typename TestFixture::SlotMapIndexType index = 0; - constexpr typename TestFixture::SlotMapVersionType version = 42; - - constexpr typename TestFixture::SlotKeyType slotKey {version, index}; - EXPECT_EQ(slotKey.GetVersion(), version); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotKeyFixture, GetIndex_ShouldReturnTheIndex) -{ - constexpr typename TestFixture::SlotMapIndexType index = 42; - constexpr typename TestFixture::SlotMapVersionType version = 0; - - constexpr typename TestFixture::SlotKeyType slotKey {version, index}; - EXPECT_EQ(slotKey.GetIndex(), index); -} - -/****************************************************************************************/ - -template -class SlotMapFixture: public ::testing::Test -{ - protected: - using SlotMapVersionType = typename CONFIG::Version; - using SlotMapIndexType = typename CONFIG::Index; - - using SlotMapType = SlotMap; - using SlotKeyType = typename SlotMapType::InternalSlotKey; - - SlotMapType m_slotMap; -}; - -TYPED_TEST_SUITE(SlotMapFixture, SlotMapConfigs, SlotMapConfigNames); - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, Insert_ShouldReturnAValidSlotKey) -{ - const auto slotKey = this->m_slotMap.Insert(42); - EXPECT_TRUE(slotKey.Valid()); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, Insert_ShouldRecycleASlotKeyAfterARemove) -{ - const auto slotKey = this->m_slotMap.Insert(42); - this->m_slotMap.Remove(slotKey); - - const auto secondSlotKey = this->m_slotMap.Insert(69); - EXPECT_NE(secondSlotKey.GetVersion(), slotKey.GetVersion()); - EXPECT_EQ(secondSlotKey.GetIndex(), slotKey.GetIndex()); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, Has_ShouldReturnTrueIfTheSlotMapHasTheKey) -{ - const auto slotKey = this->m_slotMap.Insert(42); - EXPECT_TRUE(this->m_slotMap.Has(slotKey)); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, Has_ShouldReturnFalseIfTheSlotMapDoesNotHaveTheKey) -{ - const auto slotKey = this->m_slotMap.Insert(42); - this->m_slotMap.Remove(slotKey); - EXPECT_FALSE(this->m_slotMap.Has(slotKey)); - EXPECT_FALSE(this->m_slotMap.Has(typename TestFixture::SlotKeyType {1, 22})); - EXPECT_FALSE(this->m_slotMap.Has(typename TestFixture::SlotKeyType {})); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, Remove_ShouldRemoveTheSlotKey) -{ - const auto slotKey = this->m_slotMap.Insert(42); - this->m_slotMap.Remove(slotKey); - EXPECT_FALSE(this->m_slotMap.Has(slotKey)); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, Remove_ShouldNotRecycleASlotWhenVersionWasExhausted) -{ - if constexpr (std::is_same_v) - { - GTEST_SKIP() << "Skipped for 32-bit version: exhausting all versions is too slow."; - } - else - { - auto key = this->m_slotMap.Insert(1); - - for (typename TestFixture::SlotMapVersionType i = 1; - i < std::numeric_limits::max(); - ++i) - { - this->m_slotMap.Remove(key); - const auto newKey = this->m_slotMap.Insert(1); - EXPECT_EQ(newKey.GetIndex(), key.GetIndex()); - key = newKey; - } - - // Slot is at MAX_VERSION — one more remove should overflow and permanently deactivate it - EXPECT_EQ(key.GetVersion(), std::numeric_limits::max()); - this->m_slotMap.Remove(key); - - EXPECT_FALSE(this->m_slotMap.Has(key)); - - // Dead slot must not be recycled; a new insert must allocate a fresh slot index - const auto newKey = this->m_slotMap.Insert(2); - EXPECT_NE(newKey.GetIndex(), key.GetIndex()); - - // Ensure an invalid key does not return an exhausted slot - EXPECT_EQ(this->m_slotMap.Get(typename TestFixture::SlotKeyType {}), nullptr); - } -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, Remove_ShouldNotDoAnythingInCaseOfDoubleRemove) -{ - const auto slotKey1 = this->m_slotMap.Insert(42); - const auto slotKey2 = this->m_slotMap.Insert(69); - - this->m_slotMap.Remove(slotKey1); - this->m_slotMap.Remove(slotKey1); - - EXPECT_EQ(*this->m_slotMap.Get(slotKey2), 69); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, Remove_ShouldNotDoAnythingInCaseStaleKey) -{ - const auto slotKey1 = this->m_slotMap.Insert(42); - - this->m_slotMap.Remove(typename TestFixture::SlotKeyType {2, 0}); - - EXPECT_EQ(*this->m_slotMap.Get(slotKey1), 42); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, Get_ShouldReturnNullptrForInvalidSlotKeys) -{ - const auto slotKey = this->m_slotMap.Insert(42); - this->m_slotMap.Remove(slotKey); - - const auto validate = [&](auto& p_slotMap) - { - EXPECT_EQ(p_slotMap.Get(slotKey), nullptr); - EXPECT_EQ(p_slotMap.Get(typename TestFixture::SlotKeyType {1, 3}), nullptr); - EXPECT_EQ(p_slotMap.Get(typename TestFixture::SlotKeyType {}), nullptr); - }; - - validate(this->m_slotMap); - const auto& constSlotMap = this->m_slotMap; - validate(constSlotMap); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, Get_ShouldReturnTheValueForValidSlotKeys) -{ - const auto slotKey1 = this->m_slotMap.Insert(42); - const auto slotKey2 = this->m_slotMap.Insert(69); - const auto slotKey3 = this->m_slotMap.Insert(28); - const auto slotKey4 = this->m_slotMap.Insert(0); - - this->m_slotMap.Remove(slotKey2); - - const auto validate = [&](auto& p_slotMap) - { - EXPECT_EQ(*p_slotMap.Get(slotKey1), 42); - EXPECT_EQ(*p_slotMap.Get(slotKey3), 28); - EXPECT_EQ(*p_slotMap.Get(slotKey4), 0); - }; - - validate(this->m_slotMap); - const auto& constSlotMap = this->m_slotMap; - validate(constSlotMap); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, Reset_ResetsTheSlotMapAndMakesCollisionWithOldSlotKeys) -{ - const auto slotKey1 = this->m_slotMap.Insert(42); - std::ignore = this->m_slotMap.Insert(69); - std::ignore = this->m_slotMap.Insert(28); - std::ignore = this->m_slotMap.Insert(0); - - this->m_slotMap.Reset(); - - const auto slotKey5 = this->m_slotMap.Insert(128); - - EXPECT_EQ(slotKey1, slotKey5); - EXPECT_EQ(*this->m_slotMap.Get(slotKey5), 128); - EXPECT_EQ(*this->m_slotMap.Get(slotKey1), 128); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, Clear_ResetsTheSlotMapAndButGuaranteesNotCollisionWithOldSlotKeys) -{ - const auto slotKey1 = this->m_slotMap.Insert(42); - std::ignore = this->m_slotMap.Insert(69); - std::ignore = this->m_slotMap.Insert(28); - std::ignore = this->m_slotMap.Insert(0); - - this->m_slotMap.Clear(); - - const auto slotKey5 = this->m_slotMap.Insert(128); - - EXPECT_NE(slotKey1, slotKey5); - EXPECT_EQ(*this->m_slotMap.Get(slotKey5), 128); - EXPECT_EQ(this->m_slotMap.Get(slotKey1), nullptr); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, GetSize_ReturnTheSizeOfTheSlotMap) -{ - EXPECT_EQ(this->m_slotMap.GetSize(), 0); - - std::ignore = this->m_slotMap.Insert(42); - const auto slotKey2 = this->m_slotMap.Insert(69); - std::ignore = this->m_slotMap.Insert(28); - std::ignore = this->m_slotMap.Insert(0); - - EXPECT_EQ(this->m_slotMap.GetSize(), 4); - - this->m_slotMap.Remove(slotKey2); - - EXPECT_EQ(this->m_slotMap.GetSize(), 3); - - this->m_slotMap.Clear(); - - EXPECT_EQ(this->m_slotMap.GetSize(), 0); - - std::ignore = this->m_slotMap.Insert(42); - std::ignore = this->m_slotMap.Insert(69); - std::ignore = this->m_slotMap.Insert(28); - std::ignore = this->m_slotMap.Insert(0); - - EXPECT_EQ(this->m_slotMap.GetSize(), 4); - - this->m_slotMap.Reset(); - - EXPECT_EQ(this->m_slotMap.GetSize(), 0); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, Empty_ShouldReturnTrueIfTheSlotMapIsEmpty) -{ - EXPECT_TRUE(this->m_slotMap.Empty()); - - std::ignore = this->m_slotMap.Insert(42); - std::ignore = this->m_slotMap.Insert(69); - std::ignore = this->m_slotMap.Insert(28); - std::ignore = this->m_slotMap.Insert(0); - - this->m_slotMap.Clear(); - - EXPECT_TRUE(this->m_slotMap.Empty()); - - std::ignore = this->m_slotMap.Insert(42); - std::ignore = this->m_slotMap.Insert(69); - std::ignore = this->m_slotMap.Insert(28); - std::ignore = this->m_slotMap.Insert(0); - - this->m_slotMap.Reset(); - - EXPECT_TRUE(this->m_slotMap.Empty()); - - const auto slotKey9 = this->m_slotMap.Insert(42); - this->m_slotMap.Remove(slotKey9); - - EXPECT_TRUE(this->m_slotMap.Empty()); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, Empty_ShouldReturnFalseIfTheSlotMapIsNotEmpty) -{ - std::ignore = this->m_slotMap.Insert(42); - std::ignore = this->m_slotMap.Insert(69); - std::ignore = this->m_slotMap.Insert(28); - std::ignore = this->m_slotMap.Insert(0); - - EXPECT_FALSE(this->m_slotMap.Empty()); - - this->m_slotMap.Clear(); - - std::ignore = this->m_slotMap.Insert(42); - std::ignore = this->m_slotMap.Insert(69); - std::ignore = this->m_slotMap.Insert(28); - std::ignore = this->m_slotMap.Insert(0); - - EXPECT_FALSE(this->m_slotMap.Empty()); - - this->m_slotMap.Reset(); - - const auto slotKey9 = this->m_slotMap.Insert(42); - EXPECT_FALSE(this->m_slotMap.Empty()); - this->m_slotMap.Remove(slotKey9); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, Iterator) -{ - const auto slotKey1 = this->m_slotMap.Insert(42); - const auto slotKey2 = this->m_slotMap.Insert(69); - const auto slotKey3 = this->m_slotMap.Insert(28); - const auto slotKey4 = this->m_slotMap.Insert(0); - - this->m_slotMap.Remove(slotKey2); - - eastl::vector values; - for (auto it = this->m_slotMap.begin(); it != this->m_slotMap.end(); ++it) - { - values.push_back(*it); - } - - ASSERT_EQ(values.size(), 3); - EXPECT_EQ(values[0], 42); - EXPECT_EQ(values[1], 0); - EXPECT_EQ(values[2], 28); - - // The non-const iterator is mutable. - for (std::uint32_t& value: this->m_slotMap) - { - value += 100; - } - - EXPECT_EQ(*this->m_slotMap.Get(slotKey1), 142); - EXPECT_EQ(*this->m_slotMap.Get(slotKey3), 128); - EXPECT_EQ(*this->m_slotMap.Get(slotKey4), 100); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, ConstIterator) -{ - std::ignore = this->m_slotMap.Insert(42); - const auto slotKey2 = this->m_slotMap.Insert(69); - std::ignore = this->m_slotMap.Insert(28); - std::ignore = this->m_slotMap.Insert(0); - - this->m_slotMap.Remove(slotKey2); - - const auto& constSlotMap = this->m_slotMap; - - eastl::vector values; - for (auto it = constSlotMap.begin(); it != constSlotMap.end(); ++it) - { - values.push_back(*it); - } - - ASSERT_EQ(values.size(), 3); - EXPECT_EQ(values[0], 42); - EXPECT_EQ(values[1], 0); - EXPECT_EQ(values[2], 28); - - // cbegin/cend yield the same const traversal. - eastl::vector cValues; - for (auto it = this->m_slotMap.cbegin(); it != this->m_slotMap.cend(); ++it) - { - cValues.push_back(*it); - } - - EXPECT_EQ(values, cValues); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, ReverseIterator) -{ - const auto slotKey1 = this->m_slotMap.Insert(42); - const auto slotKey2 = this->m_slotMap.Insert(69); - const auto slotKey3 = this->m_slotMap.Insert(28); - const auto slotKey4 = this->m_slotMap.Insert(0); - - this->m_slotMap.Remove(slotKey2); - - eastl::vector values; - for (auto it = this->m_slotMap.rbegin(); it != this->m_slotMap.rend(); ++it) - { - values.push_back(*it); - } - - ASSERT_EQ(values.size(), 3); - EXPECT_EQ(values[0], 28); - EXPECT_EQ(values[1], 0); - EXPECT_EQ(values[2], 42); - - // The non-const reverse iterator is mutable. - for (auto it = this->m_slotMap.rbegin(); it != this->m_slotMap.rend(); ++it) - { - *it += 100; - } - - EXPECT_EQ(*this->m_slotMap.Get(slotKey1), 142); - EXPECT_EQ(*this->m_slotMap.Get(slotKey3), 128); - EXPECT_EQ(*this->m_slotMap.Get(slotKey4), 100); -} - -/****************************************************************************************/ - -TYPED_TEST(SlotMapFixture, ConstReverseIterator) -{ - std::ignore = this->m_slotMap.Insert(42); - const auto slotKey2 = this->m_slotMap.Insert(69); - std::ignore = this->m_slotMap.Insert(28); - std::ignore = this->m_slotMap.Insert(0); - - this->m_slotMap.Remove(slotKey2); - - const auto& constSlotMap = this->m_slotMap; - - eastl::vector values; - for (auto it = constSlotMap.rbegin(); it != constSlotMap.rend(); ++it) - { - values.push_back(*it); - } - - ASSERT_EQ(values.size(), 3); - EXPECT_EQ(values[0], 28); - EXPECT_EQ(values[1], 0); - EXPECT_EQ(values[2], 42); - - // crbegin/crend yield the same const reverse traversal. - eastl::vector crValues; - for (auto it = this->m_slotMap.crbegin(); it != this->m_slotMap.crend(); ++it) - { - crValues.push_back(*it); - } - - EXPECT_EQ(values, crValues); -} -} // namespace Bigfoot