References. Removed testing, will rewrite the tests tomorrow
Bigfoot / Build & Test Debug with ./ConanProfiles/clang (Unity Build: OFF) (push) Successful in 6m14s
Bigfoot / Build & Test Debug with ./ConanProfiles/clang (Unity Build: ON) (push) Successful in 5m44s
Bigfoot / Build & Test Debug with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Successful in 6m8s
Bigfoot / Build & Test Debug with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Successful in 6m4s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang (Unity Build: OFF) (push) Successful in 6m23s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang (Unity Build: ON) (push) Successful in 6m26s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Successful in 9m35s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Successful in 7m21s
Bigfoot / Build & Test Release with ./ConanProfiles/clang (Unity Build: OFF) (push) Successful in 6m14s
Bigfoot / Build & Test Release with ./ConanProfiles/clang (Unity Build: ON) (push) Successful in 6m12s
Bigfoot / Build & Test Release with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Successful in 7m11s
Bigfoot / Build & Test Release with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Successful in 6m59s
Bigfoot / Clang Format Checks (push) Successful in 1m42s
Bigfoot / Build & Test Debug with ./ConanProfiles/clang (Unity Build: OFF) (push) Successful in 6m14s
Bigfoot / Build & Test Debug with ./ConanProfiles/clang (Unity Build: ON) (push) Successful in 5m44s
Bigfoot / Build & Test Debug with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Successful in 6m8s
Bigfoot / Build & Test Debug with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Successful in 6m4s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang (Unity Build: OFF) (push) Successful in 6m23s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang (Unity Build: ON) (push) Successful in 6m26s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Successful in 9m35s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Successful in 7m21s
Bigfoot / Build & Test Release with ./ConanProfiles/clang (Unity Build: OFF) (push) Successful in 6m14s
Bigfoot / Build & Test Release with ./ConanProfiles/clang (Unity Build: ON) (push) Successful in 6m12s
Bigfoot / Build & Test Release with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Successful in 7m11s
Bigfoot / Build & Test Release with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Successful in 6m59s
Bigfoot / Clang Format Checks (push) Successful in 1m42s
This commit is contained in:
@@ -37,22 +37,23 @@ static_assert(sizeof(MyComplexStruct) == 64, "Payload should be exactly one cach
|
|||||||
static_assert(std::is_trivially_copyable_v<MyComplexStruct>,
|
static_assert(std::is_trivially_copyable_v<MyComplexStruct>,
|
||||||
"Container moves should be a plain memcpy, not a heap-touching move.");
|
"Container moves should be a plain memcpy, not a heap-touching move.");
|
||||||
|
|
||||||
|
template<class SLOTMAP>
|
||||||
class SlotMapAdaptor
|
class SlotMapAdaptor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using Key = SlotMap<MyComplexStruct>::InternalSlotKey;
|
using Key = SlotMapKey;
|
||||||
|
|
||||||
Key Add(MyComplexStruct&& p_value)
|
SlotMapKey Add(MyComplexStruct&& p_value)
|
||||||
{
|
{
|
||||||
return m_container.Insert(std::move(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);
|
return m_container.Get(p_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Remove(const Key p_key)
|
void Remove(const SlotMapKey p_key)
|
||||||
{
|
{
|
||||||
m_container.Remove(p_key);
|
m_container.Remove(p_key);
|
||||||
}
|
}
|
||||||
@@ -72,7 +73,7 @@ class SlotMapAdaptor
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SlotMap<MyComplexStruct> m_container;
|
SLOTMAP m_container;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class MAP>
|
template<class MAP>
|
||||||
@@ -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(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);
|
BENCHMARK_TEMPLATE(Iterate, ADAPTOR)->Name(NAME "/Iterate")->Arg(512)->Arg(8192)->Arg(262'144)->Arg(4'194'304);
|
||||||
|
|
||||||
|
using DenseSlotMapHarness = SlotMapAdaptor<DenseSlotMap<MyComplexStruct>>;
|
||||||
|
using StableSlotMapHarness = SlotMapAdaptor<StableSlotMap<MyComplexStruct>>;
|
||||||
using UnorderedDenseMapHarness = HashMapHarnessAdaptor<ankerl::unordered_dense::map<std::uint64_t, MyComplexStruct>>;
|
using UnorderedDenseMapHarness = HashMapHarnessAdaptor<ankerl::unordered_dense::map<std::uint64_t, MyComplexStruct>>;
|
||||||
using UnorderedDenseSegementedMapHarness =
|
using UnorderedDenseSegementedMapHarness =
|
||||||
HashMapHarnessAdaptor<ankerl::unordered_dense::segmented_map<std::uint64_t, MyComplexStruct>>;
|
HashMapHarnessAdaptor<ankerl::unordered_dense::segmented_map<std::uint64_t, MyComplexStruct>>;
|
||||||
using UnorderedMapHarness = HashMapHarnessAdaptor<std::unordered_map<std::uint64_t, MyComplexStruct>>;
|
using UnorderedMapHarness = HashMapHarnessAdaptor<std::unordered_map<std::uint64_t, MyComplexStruct>>;
|
||||||
using MapHarness = HashMapHarnessAdaptor<std::map<std::uint64_t, MyComplexStruct>>;
|
using MapHarness = HashMapHarnessAdaptor<std::map<std::uint64_t, MyComplexStruct>>;
|
||||||
|
|
||||||
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(UnorderedDenseMapHarness, "ankerl::unordered_dense::map");
|
||||||
BIGFOOT_REGISTER_BENCHMARKS(UnorderedDenseSegementedMapHarness, "ankerl::unordered_dense::segmented_map");
|
BIGFOOT_REGISTER_BENCHMARKS(UnorderedDenseSegementedMapHarness, "ankerl::unordered_dense::segmented_map");
|
||||||
BIGFOOT_REGISTER_BENCHMARKS(UnorderedMapHarness, "std::unordered_map");
|
BIGFOOT_REGISTER_BENCHMARKS(UnorderedMapHarness, "std::unordered_map");
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*********************************************************************
|
||||||
|
* \file Reference.cpp
|
||||||
|
*
|
||||||
|
* \author Romain BOULLARD
|
||||||
|
* \date July 2026
|
||||||
|
*********************************************************************/
|
||||||
|
#include <Engine/Asset/Reference.hpp>
|
||||||
|
|
||||||
|
#include <Engine/Asset/Reference_generated.hpp>
|
||||||
|
|
||||||
|
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
|
||||||
@@ -17,21 +17,31 @@
|
|||||||
|
|
||||||
namespace Bigfoot
|
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>
|
template<class ASSET>
|
||||||
class Asset
|
class Asset: public AssetBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using FLAT_ASSET = typename ASSET::FLAT;
|
using FLAT_ASSET = typename ASSET::FLAT;
|
||||||
|
|
||||||
Asset():
|
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})
|
|
||||||
{
|
{
|
||||||
|
m_header.type_id = GetTypeID();
|
||||||
|
m_header.type_name = eastl::string {GetTypeName()};
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit Asset(const eastl::span<const std::byte> p_flatbuffer):
|
explicit Asset(const eastl::span<const std::byte> p_flatbuffer):
|
||||||
@@ -58,39 +68,7 @@ class Asset
|
|||||||
Asset(const Asset& p_asset) = delete;
|
Asset(const Asset& p_asset) = delete;
|
||||||
Asset(Asset&& p_asset) = default;
|
Asset(Asset&& p_asset) = default;
|
||||||
|
|
||||||
virtual ~Asset() = default;
|
~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;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
const ::Flat::Bigfoot::AssetHeaderT& GetHeader() const
|
const ::Flat::Bigfoot::AssetHeaderT& GetHeader() const
|
||||||
@@ -98,6 +76,16 @@ class Asset
|
|||||||
return m_header;
|
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]]
|
[[nodiscard]]
|
||||||
const typename FLAT_ASSET::NativeTableType& GetAsset() const
|
const typename FLAT_ASSET::NativeTableType& GetAsset() const
|
||||||
{
|
{
|
||||||
@@ -128,16 +116,6 @@ class Asset
|
|||||||
std::bit_cast<std::byte*>(assetFbb.GetBufferPointer() + assetFbb.GetSize())};
|
std::bit_cast<std::byte*>(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]]
|
[[nodiscard]]
|
||||||
static std::uint64_t GetTypeID()
|
static std::uint64_t GetTypeID()
|
||||||
{
|
{
|
||||||
@@ -156,11 +134,8 @@ class Asset
|
|||||||
Asset& operator=(Asset&& p_asset) = default;
|
Asset& operator=(Asset&& p_asset) = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::uint32_t m_hardRefCount;
|
|
||||||
std::uint32_t m_softRefCount;
|
|
||||||
|
|
||||||
::Flat::Bigfoot::AssetHeaderT m_header;
|
|
||||||
typename FLAT_ASSET::NativeTableType m_asset;
|
typename FLAT_ASSET::NativeTableType m_asset;
|
||||||
|
::Flat::Bigfoot::AssetHeaderT m_header;
|
||||||
};
|
};
|
||||||
} // namespace Bigfoot
|
} // namespace Bigfoot
|
||||||
|
|
||||||
|
|||||||
@@ -17,86 +17,159 @@
|
|||||||
|
|
||||||
namespace Bigfoot
|
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<UUID, SlotMapKey> m_uuidToAssetSlotKey;
|
||||||
|
ankerl::unordered_dense::segmented_map<UUID, SlotMapKey> m_uuidToContainerHandleSlotKey;
|
||||||
|
|
||||||
|
private:
|
||||||
|
StableSlotMap<ContainerHandle> m_handles;
|
||||||
|
};
|
||||||
|
|
||||||
template<class ASSET>
|
template<class ASSET>
|
||||||
class AssetContainer
|
class AssetContainer: public AssetContainerBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AssetContainer() = default;
|
AssetContainer() = default;
|
||||||
|
|
||||||
AssetContainer(const AssetContainer& p_container) = default;
|
AssetContainer(const AssetContainer& p_container) = delete;
|
||||||
AssetContainer(AssetContainer&& p_container) = default;
|
AssetContainer(AssetContainer&& p_container) = default;
|
||||||
|
|
||||||
~AssetContainer() = default;
|
~AssetContainer() = default;
|
||||||
|
|
||||||
template<class... ARGS>
|
template<class... ARGS>
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
typename SlotMap<ASSET>::SlotKey Insert(ARGS&&... p_args)
|
SlotMapKey Insert(ARGS&&... p_args)
|
||||||
{
|
{
|
||||||
const typename SlotMap<ASSET>::SlotKey slotKey = m_assets.Insert(std::forward<ARGS>(p_args)...);
|
const SlotMapKey slotKey = m_assets.Insert(std::forward<ARGS>(p_args)...);
|
||||||
m_uuidToSlotKey.insert({m_assets.Get(slotKey)->GetHeader().uuid, slotKey});
|
ASSET* asset = m_assets.Get(slotKey);
|
||||||
|
m_uuidToAssetSlotKey.insert({asset->GetHeader().uuid, slotKey});
|
||||||
|
|
||||||
|
AcquireHandle(asset->GetHeader().uuid).SetAsset(asset);
|
||||||
|
|
||||||
return slotKey;
|
return slotKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
ASSET* Get(const typename SlotMap<ASSET>::SlotKey p_key)
|
ASSET* Get(const SlotMapKey p_key)
|
||||||
{
|
{
|
||||||
return m_assets.Get(p_key);
|
return m_assets.Get(p_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
const ASSET* Get(const typename SlotMap<ASSET>::SlotKey p_key) const
|
const ASSET* Get(const SlotMapKey p_key) const
|
||||||
{
|
{
|
||||||
return m_assets.Get(p_key);
|
return m_assets.Get(p_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
typename SlotMap<ASSET>::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<ASSET>::SlotKey {};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
bool Has(const typename SlotMap<ASSET>::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<ASSET>::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)
|
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;
|
AssetContainer& operator=(AssetContainer&& p_container) = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ankerl::unordered_dense::segmented_map<UUID, typename SlotMap<ASSET>::SlotKey> m_uuidToSlotKey;
|
StableSlotMap<ASSET> m_assets;
|
||||||
|
|
||||||
SlotMap<ASSET> m_assets;
|
|
||||||
};
|
};
|
||||||
} // namespace Bigfoot
|
} // namespace Bigfoot
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,16 @@
|
|||||||
#define BIGFOOT_ENGINE_ASSET_ASSETHELPER_HPP
|
#define BIGFOOT_ENGINE_ASSET_ASSETHELPER_HPP
|
||||||
#include <Engine/Asset/AssetContainer.hpp>
|
#include <Engine/Asset/AssetContainer.hpp>
|
||||||
#include <Engine/Asset/AssetLibrary.hpp>
|
#include <Engine/Asset/AssetLibrary.hpp>
|
||||||
|
#include <Engine/Asset/Reference.hpp>
|
||||||
|
|
||||||
#define ASSET_CONTAINER(AssetName, AssetType) \
|
#define BIGFOOT_ASSET(AssetName, AssetType) \
|
||||||
namespace Bigfoot \
|
namespace Bigfoot \
|
||||||
{ \
|
{ \
|
||||||
|
template<> \
|
||||||
|
AssetTypeID GetAssetTypeID<AssetType>() \
|
||||||
|
{ \
|
||||||
|
return AssetType::GetTypeID(); \
|
||||||
|
} \
|
||||||
AssetContainer<AssetType> g_containerFor##AssetName; \
|
AssetContainer<AssetType> g_containerFor##AssetName; \
|
||||||
const bool g_insertedContainerFor##AssetName = g_assetLibrary.Insert(&g_containerFor##AssetName); \
|
const bool g_insertedContainerFor##AssetName = g_assetLibrary.Insert(&g_containerFor##AssetName); \
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include <Engine/Asset/AssetContainer.hpp>
|
#include <Engine/Asset/AssetContainer.hpp>
|
||||||
#include <Engine/Asset/AssetTypeID.hpp>
|
#include <Engine/Asset/AssetTypeID.hpp>
|
||||||
|
|
||||||
#include <EASTL/any.h>
|
|
||||||
#include <ankerl/unordered_dense.h>
|
#include <ankerl/unordered_dense.h>
|
||||||
|
|
||||||
namespace Bigfoot
|
namespace Bigfoot
|
||||||
@@ -44,12 +43,7 @@ class AssetLibrary
|
|||||||
AssetContainer<ASSET>* Get()
|
AssetContainer<ASSET>* Get()
|
||||||
{
|
{
|
||||||
static const AssetTypeID typeID = ASSET::GetTypeID();
|
static const AssetTypeID typeID = ASSET::GetTypeID();
|
||||||
if (const auto container = m_assetContainers.find(typeID); container != m_assetContainers.end())
|
return static_cast<AssetContainer<ASSET>*>(GetBase(typeID));
|
||||||
{
|
|
||||||
return eastl::any_cast<AssetContainer<ASSET>*>(container->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class ASSET>
|
template<class ASSET>
|
||||||
@@ -57,9 +51,54 @@ class AssetLibrary
|
|||||||
const AssetContainer<ASSET>* Get() const
|
const AssetContainer<ASSET>* Get() const
|
||||||
{
|
{
|
||||||
static const AssetTypeID typeID = ASSET::GetTypeID();
|
static const AssetTypeID typeID = ASSET::GetTypeID();
|
||||||
if (const auto container = m_assetContainers.find(typeID); container != m_assetContainers.end())
|
return static_cast<const AssetContainer<ASSET>*>(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<const AssetContainer<ASSET>*>(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;
|
return nullptr;
|
||||||
@@ -69,7 +108,7 @@ class AssetLibrary
|
|||||||
AssetLibrary& operator=(AssetLibrary&& p_library) = default;
|
AssetLibrary& operator=(AssetLibrary&& p_library) = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ankerl::unordered_dense::segmented_map<AssetTypeID, eastl::any> m_assetContainers;
|
ankerl::unordered_dense::segmented_map<AssetTypeID, AssetContainerBase*> m_assetContainers;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline AssetLibrary g_assetLibrary;
|
inline AssetLibrary g_assetLibrary;
|
||||||
|
|||||||
@@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
|||||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||||
FLATBUFFERS_VERSION_REVISION == 19,
|
FLATBUFFERS_VERSION_REVISION == 19,
|
||||||
"Non-compatible flatbuffers version included");
|
"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 "Engine/Asset/AssetTypeID.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
|||||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||||
FLATBUFFERS_VERSION_REVISION == 19,
|
FLATBUFFERS_VERSION_REVISION == 19,
|
||||||
"Non-compatible flatbuffers version included");
|
"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 "Engine/Asset/AssetTypeID.hpp"
|
||||||
#include "System/UUID/UUID.hpp"
|
#include "System/UUID/UUID.hpp"
|
||||||
|
|||||||
@@ -4,12 +4,22 @@ native_include "Engine/Asset/Reference.hpp";
|
|||||||
|
|
||||||
namespace Flat.Bigfoot;
|
namespace Flat.Bigfoot;
|
||||||
|
|
||||||
struct HardReference (native_type_template: "::Bigfoot::HardReference")
|
struct HardReference (bigfoot_ref_wrapper: "::Bigfoot::HardReference")
|
||||||
{
|
{
|
||||||
uuid: UUID;
|
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;
|
uuid: UUID;
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,9 @@
|
|||||||
|
|
||||||
namespace Bigfoot
|
namespace Bigfoot
|
||||||
{
|
{
|
||||||
|
template<class ASSET>
|
||||||
|
AssetTypeID GetAssetTypeID();
|
||||||
|
|
||||||
template<class ASSET>
|
template<class ASSET>
|
||||||
class HardReference
|
class HardReference
|
||||||
{
|
{
|
||||||
@@ -28,14 +31,14 @@ class HardReference
|
|||||||
|
|
||||||
HardReference(const HardReference& p_ref):
|
HardReference(const HardReference& p_ref):
|
||||||
m_uuid(p_ref.m_uuid),
|
m_uuid(p_ref.m_uuid),
|
||||||
m_slotKey(p_ref.m_slotKey)
|
m_handle(p_ref.m_handle)
|
||||||
{
|
{
|
||||||
Acquire();
|
Acquire();
|
||||||
}
|
}
|
||||||
|
|
||||||
HardReference(HardReference&& p_ref) noexcept:
|
HardReference(HardReference&& p_ref) noexcept:
|
||||||
m_uuid(std::exchange(p_ref.m_uuid, UUID::NULL_UUID)),
|
m_uuid(std::exchange(p_ref.m_uuid, UUID::NULL_UUID)),
|
||||||
m_slotKey(std::exchange(p_ref.m_slotKey, typename SlotMap<ASSET>::SlotKey {}))
|
m_handle(std::exchange(p_ref.m_handle, nullptr))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +48,12 @@ class HardReference
|
|||||||
return m_uuid;
|
return m_uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
ASSET* Get() const
|
||||||
|
{
|
||||||
|
return m_handle ? static_cast<ASSET*>(m_handle->GetAsset()) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
~HardReference()
|
~HardReference()
|
||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
@@ -56,7 +65,7 @@ class HardReference
|
|||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
m_uuid = p_ref.m_uuid;
|
m_uuid = p_ref.m_uuid;
|
||||||
m_slotKey = p_ref.m_slotKey;
|
m_handle = p_ref.m_handle;
|
||||||
Acquire();
|
Acquire();
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@@ -68,7 +77,7 @@ class HardReference
|
|||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
m_uuid = std::exchange(p_ref.m_uuid, UUID::NULL_UUID);
|
m_uuid = std::exchange(p_ref.m_uuid, UUID::NULL_UUID);
|
||||||
std::exchange(p_ref.m_slotKey, typename SlotMap<ASSET>::SlotKey {});
|
m_handle = std::exchange(p_ref.m_handle, nullptr);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -82,34 +91,28 @@ class HardReference
|
|||||||
private:
|
private:
|
||||||
void Acquire()
|
void Acquire()
|
||||||
{
|
{
|
||||||
if (AssetContainer<ASSET>* assetContainer = g_assetLibrary.Get<ASSET>(); assetContainer && m_uuid)
|
if (AssetContainerBase* assetContainer = g_assetLibrary.GetBase(GetAssetTypeID<ASSET>());
|
||||||
|
assetContainer && m_uuid)
|
||||||
{
|
{
|
||||||
if (!m_slotKey.Valid())
|
if (!m_handle)
|
||||||
{
|
{
|
||||||
m_slotKey = assetContainer->GetSlotKey(m_uuid);
|
m_handle = &assetContainer->AcquireHandle(m_uuid);
|
||||||
}
|
|
||||||
|
|
||||||
if (ASSET* asset = assetContainer->Get(m_slotKey))
|
|
||||||
{
|
|
||||||
asset->IncrementHardRefCount();
|
|
||||||
}
|
}
|
||||||
|
m_handle->IncrementHardRefCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Release()
|
void Release()
|
||||||
{
|
{
|
||||||
if (AssetContainer<ASSET>* assetContainer = g_assetLibrary.Get<ASSET>(); assetContainer && m_uuid)
|
if (m_handle)
|
||||||
{
|
{
|
||||||
// Acquire always happens before Release, so slot key should be valid
|
m_handle->DecrementHardRefCount();
|
||||||
if (ASSET* asset = assetContainer->Get(m_slotKey))
|
m_handle = nullptr;
|
||||||
{
|
|
||||||
asset->DecrementHardRefCount();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID m_uuid = UUID::NULL_UUID;
|
UUID m_uuid = UUID::NULL_UUID;
|
||||||
typename SlotMap<ASSET>::SlotKey m_slotKey;
|
ContainerHandle* m_handle = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class ASSET>
|
template<class ASSET>
|
||||||
@@ -126,14 +129,14 @@ class SoftReference
|
|||||||
|
|
||||||
SoftReference(const SoftReference& p_ref):
|
SoftReference(const SoftReference& p_ref):
|
||||||
m_uuid(p_ref.m_uuid),
|
m_uuid(p_ref.m_uuid),
|
||||||
m_slotKey(p_ref.m_slotKey)
|
m_handle(p_ref.m_handle)
|
||||||
{
|
{
|
||||||
Acquire();
|
Acquire();
|
||||||
}
|
}
|
||||||
|
|
||||||
SoftReference(SoftReference&& p_ref) noexcept:
|
SoftReference(SoftReference&& p_ref) noexcept:
|
||||||
m_uuid(std::exchange(p_ref.m_uuid, UUID::NULL_UUID)),
|
m_uuid(std::exchange(p_ref.m_uuid, UUID::NULL_UUID)),
|
||||||
m_slotKey(std::exchange(p_ref.m_slotKey, typename SlotMap<ASSET>::SlotKey {}))
|
m_handle(std::exchange(p_ref.m_handle, nullptr))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +146,12 @@ class SoftReference
|
|||||||
return m_uuid;
|
return m_uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
ASSET* Get() const
|
||||||
|
{
|
||||||
|
return m_handle ? static_cast<ASSET*>(m_handle->GetAsset()) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
~SoftReference()
|
~SoftReference()
|
||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
@@ -154,7 +163,7 @@ class SoftReference
|
|||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
m_uuid = p_ref.m_uuid;
|
m_uuid = p_ref.m_uuid;
|
||||||
m_slotKey = p_ref.m_slotKey;
|
m_handle = p_ref.m_handle;
|
||||||
Acquire();
|
Acquire();
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@@ -166,7 +175,7 @@ class SoftReference
|
|||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
m_uuid = std::exchange(p_ref.m_uuid, UUID::NULL_UUID);
|
m_uuid = std::exchange(p_ref.m_uuid, UUID::NULL_UUID);
|
||||||
m_slotKey = std::exchange(p_ref.m_slotKey, typename SlotMap<ASSET>::SlotKey {});
|
m_handle = std::exchange(p_ref.m_handle, nullptr);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -180,34 +189,231 @@ class SoftReference
|
|||||||
private:
|
private:
|
||||||
void Acquire()
|
void Acquire()
|
||||||
{
|
{
|
||||||
if (AssetContainer<ASSET>* assetContainer = g_assetLibrary.Get<ASSET>(); assetContainer && m_uuid)
|
if (AssetContainerBase* assetContainer = g_assetLibrary.GetBase(GetAssetTypeID<ASSET>());
|
||||||
|
assetContainer && m_uuid)
|
||||||
{
|
{
|
||||||
if (!m_slotKey.Valid())
|
if (!m_handle)
|
||||||
{
|
{
|
||||||
m_slotKey = assetContainer->GetSlotKey(m_uuid);
|
m_handle = &assetContainer->AcquireHandle(m_uuid);
|
||||||
}
|
|
||||||
|
|
||||||
if (ASSET* asset = assetContainer->Get(m_slotKey))
|
|
||||||
{
|
|
||||||
asset->IncrementSoftRefCount();
|
|
||||||
}
|
}
|
||||||
|
m_handle->IncrementSoftRefCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Release()
|
void Release()
|
||||||
{
|
{
|
||||||
if (AssetContainer<ASSET>* assetContainer = g_assetLibrary.Get<ASSET>(); assetContainer && m_uuid)
|
if (m_handle)
|
||||||
{
|
{
|
||||||
// Acquire always happens before Release, so slot key should be valid
|
m_handle->DecrementSoftRefCount();
|
||||||
if (ASSET* asset = assetContainer->Get(m_slotKey))
|
m_handle = nullptr;
|
||||||
{
|
|
||||||
asset->DecrementSoftRefCount();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID m_uuid = UUID::NULL_UUID;
|
UUID m_uuid = UUID::NULL_UUID;
|
||||||
typename SlotMap<ASSET>::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 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
|
#endif
|
||||||
|
|||||||
@@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
|||||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||||
FLATBUFFERS_VERSION_REVISION == 19,
|
FLATBUFFERS_VERSION_REVISION == 19,
|
||||||
"Non-compatible flatbuffers version included");
|
"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 "System/UUID/UUID.hpp"
|
||||||
#include "Engine/Asset/Reference.hpp"
|
#include "Engine/Asset/Reference.hpp"
|
||||||
@@ -28,10 +35,18 @@ struct HardReference;
|
|||||||
|
|
||||||
struct SoftReference;
|
struct SoftReference;
|
||||||
|
|
||||||
|
struct AnyHardReference;
|
||||||
|
|
||||||
|
struct AnySoftReference;
|
||||||
|
|
||||||
inline const ::flatbuffers::TypeTable *HardReferenceTypeTable();
|
inline const ::flatbuffers::TypeTable *HardReferenceTypeTable();
|
||||||
|
|
||||||
inline const ::flatbuffers::TypeTable *SoftReferenceTypeTable();
|
inline const ::flatbuffers::TypeTable *SoftReferenceTypeTable();
|
||||||
|
|
||||||
|
inline const ::flatbuffers::TypeTable *AnyHardReferenceTypeTable();
|
||||||
|
|
||||||
|
inline const ::flatbuffers::TypeTable *AnySoftReferenceTypeTable();
|
||||||
|
|
||||||
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(1) HardReference FLATBUFFERS_FINAL_CLASS {
|
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(1) HardReference FLATBUFFERS_FINAL_CLASS {
|
||||||
private:
|
private:
|
||||||
Flat::Bigfoot::UUID uuid_;
|
Flat::Bigfoot::UUID uuid_;
|
||||||
@@ -88,6 +103,62 @@ struct SoftReference::Traits {
|
|||||||
using type = SoftReference;
|
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() {
|
inline const ::flatbuffers::TypeTable *HardReferenceTypeTable() {
|
||||||
static const ::flatbuffers::TypeCode type_codes[] = {
|
static const ::flatbuffers::TypeCode type_codes[] = {
|
||||||
{ ::flatbuffers::ET_SEQUENCE, 0, 0 }
|
{ ::flatbuffers::ET_SEQUENCE, 0, 0 }
|
||||||
@@ -116,6 +187,34 @@ inline const ::flatbuffers::TypeTable *SoftReferenceTypeTable() {
|
|||||||
return &tt;
|
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 Bigfoot
|
||||||
} // namespace Flat
|
} // namespace Flat
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
|||||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||||
FLATBUFFERS_VERSION_REVISION == 19,
|
FLATBUFFERS_VERSION_REVISION == 19,
|
||||||
"Non-compatible flatbuffers version included");
|
"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"
|
#include "System/Time/Time.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
|||||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||||
FLATBUFFERS_VERSION_REVISION == 19,
|
FLATBUFFERS_VERSION_REVISION == 19,
|
||||||
"Non-compatible flatbuffers version included");
|
"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 "System/UUID/UUID.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -8,21 +8,24 @@
|
|||||||
#define BIGFOOT_UTILS_CONTAINERS_SLOTMAP_HPP
|
#define BIGFOOT_UTILS_CONTAINERS_SLOTMAP_HPP
|
||||||
#include <Utils/UtilsAssertHandler.hpp>
|
#include <Utils/UtilsAssertHandler.hpp>
|
||||||
|
|
||||||
|
#include <EASTL/array.h>
|
||||||
|
#include <EASTL/bitset.h>
|
||||||
|
#include <EASTL/iterator.h>
|
||||||
|
#include <EASTL/optional.h>
|
||||||
|
#include <EASTL/unique_ptr.h>
|
||||||
#include <EASTL/vector.h>
|
#include <EASTL/vector.h>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
namespace Bigfoot
|
namespace Bigfoot
|
||||||
{
|
{
|
||||||
template<class VERSION_TYPE = std::uint32_t,
|
|
||||||
class INDEX_TYPE = std::uint32_t,
|
|
||||||
std::enable_if_t<std::is_unsigned_v<VERSION_TYPE> && std::is_unsigned_v<INDEX_TYPE>, bool> = true>
|
|
||||||
class SlotMapKey
|
class SlotMapKey
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using IndexType = INDEX_TYPE;
|
using IndexType = std::uint32_t;
|
||||||
using VersionType = VERSION_TYPE;
|
using VersionType = std::uint32_t;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr std::uint32_t VERSION_BIT_COUNT = sizeof(VersionType) * std::numeric_limits<unsigned char>::digits;
|
static constexpr std::uint32_t VERSION_BIT_COUNT = sizeof(VersionType) * std::numeric_limits<unsigned char>::digits;
|
||||||
@@ -78,234 +81,811 @@ class SlotMapKey
|
|||||||
std::uint64_t m_key;
|
std::uint64_t m_key;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class TYPE, class VERSION_TYPE = std::uint32_t, class INDEX_TYPE = std::uint32_t>
|
class SlotMapBase
|
||||||
class SlotMap
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using InternalSlotKey = SlotMapKey<VERSION_TYPE, INDEX_TYPE>;
|
~SlotMapBase() = default;
|
||||||
|
|
||||||
SlotMap():
|
|
||||||
m_freeSlotHead(std::numeric_limits<typename InternalSlotKey::IndexType>::max())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SlotMap(const SlotMap& p_map) = default;
|
|
||||||
SlotMap(SlotMap&& p_map) = default;
|
|
||||||
|
|
||||||
~SlotMap() = default;
|
|
||||||
|
|
||||||
template<class... ARGS>
|
|
||||||
[[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<InternalSlotKey::IndexType>(m_data.size());
|
|
||||||
m_data.emplace_back(std::forward<ARGS>(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<InternalSlotKey::IndexType>(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());
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
[[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() &&
|
return p_slotKey.Valid() && (p_slotKey.GetIndex() < m_slots.size() &&
|
||||||
p_slotKey.GetVersion() == m_slots[p_slotKey.GetIndex()].GetVersion());
|
p_slotKey.GetVersion() == m_slots[p_slotKey.GetIndex()].GetVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[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;
|
return m_size;
|
||||||
}
|
|
||||||
|
|
||||||
[[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<typename InternalSlotKey::IndexType>::max();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
for (const typename eastl::vector<TYPE>::size_type slotIndex: m_dataToSlots)
|
|
||||||
{
|
|
||||||
RecycleSlot(m_slots[slotIndex].GetVersion() + 1, static_cast<InternalSlotKey::IndexType>(slotIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_data.clear();
|
|
||||||
m_dataToSlots.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
eastl::vector<TYPE>::size_type GetSize() const
|
|
||||||
{
|
|
||||||
return m_data.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
eastl::vector<TYPE>::size_type GetCapacity() const
|
|
||||||
{
|
|
||||||
return m_data.capacity();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
bool Empty() const
|
bool Empty() const
|
||||||
{
|
{
|
||||||
return m_data.empty();
|
return m_size == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reserve(const eastl::vector<TYPE>::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<SlotMapKey::IndexType>::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<SlotMapKey::IndexType>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReserveSlots(const std::size_t p_size)
|
||||||
{
|
{
|
||||||
m_data.reserve(p_size);
|
|
||||||
m_dataToSlots.reserve(p_size);
|
|
||||||
m_slots.reserve(p_size);
|
m_slots.reserve(p_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t m_size = 0;
|
||||||
|
eastl::vector<SlotMapKey> m_slots;
|
||||||
|
SlotMapKey::IndexType m_freeSlotHead = std::numeric_limits<SlotMapKey::IndexType>::max();
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class TYPE>
|
||||||
|
class DenseSlotMap: public SlotMapBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using iterator = typename eastl::vector<TYPE>::iterator;
|
||||||
|
using const_iterator = typename eastl::vector<TYPE>::const_iterator;
|
||||||
|
using reverse_iterator = typename eastl::vector<TYPE>::reverse_iterator;
|
||||||
|
using const_reverse_iterator = typename eastl::vector<TYPE>::const_reverse_iterator;
|
||||||
|
|
||||||
|
DenseSlotMap() = default;
|
||||||
|
|
||||||
|
DenseSlotMap(const DenseSlotMap& p_map) = default;
|
||||||
|
DenseSlotMap(DenseSlotMap&& p_map) = default;
|
||||||
|
|
||||||
|
~DenseSlotMap() = default;
|
||||||
|
|
||||||
|
template<class... ARGS>
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
eastl::vector<TYPE>::iterator begin()
|
SlotMapKey Insert(ARGS&&... p_args)
|
||||||
|
{
|
||||||
|
const SlotMapKey::IndexType dataIndex = static_cast<SlotMapKey::IndexType>(m_size);
|
||||||
|
m_data.emplace_back(std::forward<ARGS>(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<SlotMapKey::IndexType>(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();
|
return m_data.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
eastl::vector<TYPE>::iterator end()
|
iterator end()
|
||||||
{
|
{
|
||||||
return m_data.end();
|
return m_data.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
eastl::vector<TYPE>::const_iterator begin() const
|
const_iterator begin() const
|
||||||
{
|
{
|
||||||
return m_data.begin();
|
return m_data.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
eastl::vector<TYPE>::const_iterator end() const
|
const_iterator end() const
|
||||||
{
|
{
|
||||||
return m_data.end();
|
return m_data.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
eastl::vector<TYPE>::reverse_iterator rbegin()
|
reverse_iterator rbegin()
|
||||||
{
|
{
|
||||||
return m_data.rbegin();
|
return m_data.rbegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
eastl::vector<TYPE>::reverse_iterator rend()
|
reverse_iterator rend()
|
||||||
{
|
{
|
||||||
return m_data.rend();
|
return m_data.rend();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
eastl::vector<TYPE>::const_reverse_iterator rbegin() const
|
const_reverse_iterator rbegin() const
|
||||||
{
|
{
|
||||||
return m_data.rbegin();
|
return m_data.rbegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
eastl::vector<TYPE>::const_reverse_iterator rend() const
|
const_reverse_iterator rend() const
|
||||||
{
|
{
|
||||||
return m_data.rend();
|
return m_data.rend();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
eastl::vector<TYPE>::const_iterator cbegin() const
|
const_iterator cbegin() const
|
||||||
{
|
{
|
||||||
return m_data.cbegin();
|
return m_data.cbegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
eastl::vector<TYPE>::const_iterator cend() const
|
const_iterator cend() const
|
||||||
{
|
{
|
||||||
return m_data.cend();
|
return m_data.cend();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
eastl::vector<TYPE>::const_reverse_iterator crbegin() const
|
const_reverse_iterator crbegin() const
|
||||||
{
|
{
|
||||||
return m_data.crbegin();
|
return m_data.crbegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
eastl::vector<TYPE>::const_reverse_iterator crend() const
|
const_reverse_iterator crend() const
|
||||||
{
|
{
|
||||||
return m_data.crend();
|
return m_data.crend();
|
||||||
}
|
}
|
||||||
|
|
||||||
SlotMap& operator=(const SlotMap& p_slotMap) = default;
|
DenseSlotMap& operator=(const DenseSlotMap& p_map) = default;
|
||||||
SlotMap& operator=(SlotMap&& p_slotMap) = default;
|
DenseSlotMap& operator=(DenseSlotMap&& p_map) = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
bool HasFreeSlots() const
|
SlotMapKey::IndexType GetDataIndex(const SlotMapKey p_slotKey) const
|
||||||
{
|
{
|
||||||
return m_freeSlotHead != std::numeric_limits<typename InternalSlotKey::IndexType>::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};
|
const SlotMapKey::IndexType slotIndex = m_freeSlotHead;
|
||||||
return;
|
|
||||||
|
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};
|
const SlotMapKey::IndexType slotIndex = static_cast<SlotMapKey::IndexType>(m_slots.size());
|
||||||
m_freeSlotHead = p_slotIndex;
|
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<TYPE> m_data;
|
eastl::vector<TYPE> m_data;
|
||||||
eastl::vector<InternalSlotKey> m_slots;
|
eastl::vector<std::size_t> m_dataToSlots;
|
||||||
|
};
|
||||||
|
|
||||||
eastl::vector<typename eastl::vector<TYPE>::size_type> m_dataToSlots;
|
template<class TYPE>
|
||||||
|
class StableSlotMap: public SlotMapBase
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static constexpr std::size_t PAGE_SIZE = 64;
|
||||||
|
|
||||||
InternalSlotKey::IndexType m_freeSlotHead;
|
struct Page
|
||||||
|
{
|
||||||
|
eastl::array<eastl::optional<TYPE>, PAGE_SIZE> m_slots;
|
||||||
|
eastl::bitset<PAGE_SIZE> 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<iterator>;
|
||||||
|
using const_reverse_iterator = eastl::reverse_iterator<const_iterator>;
|
||||||
|
|
||||||
|
StableSlotMap() = default;
|
||||||
|
|
||||||
|
StableSlotMap(const StableSlotMap& p_map) = delete;
|
||||||
|
StableSlotMap(StableSlotMap&& p_map) = default;
|
||||||
|
|
||||||
|
~StableSlotMap() = default;
|
||||||
|
|
||||||
|
template<class... ARGS>
|
||||||
|
[[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& page = *m_pages[pageIndex];
|
||||||
|
const std::size_t offset = index % PAGE_SIZE;
|
||||||
|
page.m_slots[offset].emplace(std::forward<ARGS>(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>& 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<SlotMapKey::IndexType>(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<Page>());
|
||||||
|
}
|
||||||
|
|
||||||
|
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<SlotMapKey::IndexType>(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<eastl::unique_ptr<Page>> m_pages;
|
||||||
};
|
};
|
||||||
} // namespace Bigfoot
|
} // namespace Bigfoot
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
|||||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||||
FLATBUFFERS_VERSION_REVISION == 19,
|
FLATBUFFERS_VERSION_REVISION == 19,
|
||||||
"Non-compatible flatbuffers version included");
|
"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/unique_ptr.h"
|
||||||
#include "EASTL/string.h"
|
#include "EASTL/string.h"
|
||||||
|
|||||||
@@ -1,205 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* \file BigFile.cpp
|
|
||||||
*
|
|
||||||
* \author Romain BOULLARD
|
|
||||||
* \date December 2025
|
|
||||||
*********************************************************************/
|
|
||||||
#include <Engine/Asset/Asset.hpp>
|
|
||||||
|
|
||||||
#include <AssetsForTesting/Asset/AssetA.hpp>
|
|
||||||
#include <AssetsForTesting/Asset/AssetB.hpp>
|
|
||||||
#include <AssetsForTesting/Asset/AssetC.hpp>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
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<std::byte> 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> {assetA.GetHeader().uuid};
|
|
||||||
// assetB.GetAsset().asset_a_refs = {SoftReference<AssetA> {assetA.GetHeader().uuid},
|
|
||||||
// SoftReference<AssetA> {assetAA.GetHeader().uuid}};
|
|
||||||
|
|
||||||
const eastl::vector<std::byte> 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> {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>> {SoftReference<AssetA> {assetA.GetHeader().uuid},
|
|
||||||
// SoftReference<AssetA> {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> {assetA.GetHeader().uuid};
|
|
||||||
// assetB.GetAsset().asset_a_refs = {SoftReference<AssetA> {assetA.GetHeader().uuid},
|
|
||||||
// SoftReference<AssetA> {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> {assetA.GetHeader().uuid};
|
|
||||||
// assetC.GetAsset().inner_table->asset_a_refs = {HardReference<AssetA> {assetA.GetHeader().uuid},
|
|
||||||
// HardReference<AssetA> {assetAA.GetHeader().uuid}};
|
|
||||||
// assetC.GetAsset().asset_b_ref = HardReference<AssetB> {assetB.GetHeader().uuid};
|
|
||||||
// assetC.GetAsset().asset_b_refs = {SoftReference<AssetB> {assetB.GetHeader().uuid}};
|
|
||||||
|
|
||||||
const eastl::vector<std::byte> 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> {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>> {SoftReference<AssetB> {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> {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>> {HardReference<AssetA> {assetA.GetHeader().uuid},
|
|
||||||
// HardReference<AssetA> {assetAA.GetHeader().uuid}}));
|
|
||||||
// EXPECT_EQ(assetC.GetAsset().inner_table->asset_a_refs, assetC_dup.GetAsset().inner_table->asset_a_refs);
|
|
||||||
}
|
|
||||||
} // namespace Bigfoot
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* \file AssetContainer.cpp
|
|
||||||
*
|
|
||||||
* \author Romain BOULLARD
|
|
||||||
* \date December 2025
|
|
||||||
*********************************************************************/
|
|
||||||
#include <Engine/Asset/AssetContainer.hpp>
|
|
||||||
|
|
||||||
#include <AssetsForTesting/Asset/AssetA.hpp>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
namespace Bigfoot
|
|
||||||
{
|
|
||||||
class AssetContainerFixture: public ::testing::Test
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
AssetContainer<AssetA> 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
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* \file AssetLibrary.cpp
|
|
||||||
*
|
|
||||||
* \author Romain BOULLARD
|
|
||||||
* \date July 2026
|
|
||||||
*********************************************************************/
|
|
||||||
#include <Engine/Asset/AssetLibrary.hpp>
|
|
||||||
|
|
||||||
#include <AssetsForTesting/Asset/AssetA.hpp>
|
|
||||||
#include <AssetsForTesting/Asset/AssetB.hpp>
|
|
||||||
#include <AssetsForTesting/Asset/AssetC.hpp>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
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<AssetA> m_containerA;
|
|
||||||
AssetContainer<AssetB> m_containerB;
|
|
||||||
|
|
||||||
AssetLibrary m_library;
|
|
||||||
};
|
|
||||||
|
|
||||||
/****************************************************************************************/
|
|
||||||
|
|
||||||
TEST_F(AssetLibraryFixture, Insert_ShouldReturnTrueIfTheContainerHasBeenInserted)
|
|
||||||
{
|
|
||||||
AssetContainer<AssetC> 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<AssetA>* containerA = m_library.Get<AssetA>();
|
|
||||||
const AssetContainer<AssetB>* containerB = m_library.Get<AssetB>();
|
|
||||||
|
|
||||||
EXPECT_EQ(&m_containerA, containerA);
|
|
||||||
EXPECT_EQ(&m_containerB, containerB);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************************/
|
|
||||||
|
|
||||||
TEST_F(AssetLibraryFixture, Get_ShouldReturnNullptrIfTheContainersAreNotInTheLibrary)
|
|
||||||
{
|
|
||||||
const AssetContainer<AssetC>* containerC = m_library.Get<AssetC>();
|
|
||||||
|
|
||||||
EXPECT_EQ(nullptr, containerC);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************************/
|
|
||||||
|
|
||||||
TEST_F(AssetLibraryFixture, GlobalAssetLibraryShouldHaveAssetsRegistered)
|
|
||||||
{
|
|
||||||
EXPECT_NE(g_assetLibrary.Get<AssetA>(), nullptr);
|
|
||||||
EXPECT_NE(g_assetLibrary.Get<AssetB>(), nullptr);
|
|
||||||
EXPECT_NE(g_assetLibrary.Get<AssetC>(), nullptr);
|
|
||||||
}
|
|
||||||
} // namespace Bigfoot
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* \file BigFile.cpp
|
|
||||||
*
|
|
||||||
* \author Romain BOULLARD
|
|
||||||
* \date December 2025
|
|
||||||
*********************************************************************/
|
|
||||||
#include <Engine/BigFile/BigFile.hpp>
|
|
||||||
|
|
||||||
#include <System/Time/Time.hpp>
|
|
||||||
#include <System/UUID/UUID.hpp>
|
|
||||||
|
|
||||||
#include <EngineTests/BigFileInfo_generated.hpp>
|
|
||||||
|
|
||||||
#include <ankerl/unordered_dense.h>
|
|
||||||
#include <flatbuffers/reflection.h>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
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<std::byte, 4> blob {std::byte {1}, std::byte {2}, std::byte {3}, std::byte {4}};
|
|
||||||
constexpr eastl::array<std::byte, 4> blob2 {std::byte {1}, std::byte {2}, std::byte {3}, std::byte {5}};
|
|
||||||
constexpr eastl::array<std::byte, 4> blob3 {std::byte {1}, std::byte {2}, std::byte {3}, std::byte {6}};
|
|
||||||
constexpr eastl::array<std::byte, 4> blob4 {std::byte {10}, std::byte {11}, std::byte {12}, std::byte {13}};
|
|
||||||
|
|
||||||
constexpr std::uint64_t typeIDRef = std::numeric_limits<std::uint64_t>::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<eastl::string_view>(request.Get(0))};
|
|
||||||
EXPECT_STREQ(name.c_str(), "Test");
|
|
||||||
const std::uint64_t typeID = static_cast<std::uint64_t>(request.Get(1));
|
|
||||||
EXPECT_EQ(typeID, typeIDRef);
|
|
||||||
const eastl::string typeName {static_cast<eastl::string_view>(request.Get(2))};
|
|
||||||
EXPECT_STREQ(typeName.c_str(), "TypeTest");
|
|
||||||
|
|
||||||
const Time createTime = static_cast<std::uint64_t>(request.Get(3));
|
|
||||||
const Time modificationTime = static_cast<std::uint64_t>(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
|
|
||||||
@@ -8,4 +8,4 @@
|
|||||||
|
|
||||||
#include <Engine/Asset/AssetHelper.hpp>
|
#include <Engine/Asset/AssetHelper.hpp>
|
||||||
|
|
||||||
ASSET_CONTAINER(AssetA, ::Bigfoot::AssetA)
|
BIGFOOT_ASSET(AssetA, ::Bigfoot::AssetA)
|
||||||
|
|||||||
@@ -8,4 +8,4 @@
|
|||||||
|
|
||||||
#include <Engine/Asset/AssetHelper.hpp>
|
#include <Engine/Asset/AssetHelper.hpp>
|
||||||
|
|
||||||
ASSET_CONTAINER(AssetB, ::Bigfoot::AssetB)
|
BIGFOOT_ASSET(AssetB, ::Bigfoot::AssetB)
|
||||||
|
|||||||
@@ -8,4 +8,4 @@
|
|||||||
|
|
||||||
#include <Engine/Asset/AssetHelper.hpp>
|
#include <Engine/Asset/AssetHelper.hpp>
|
||||||
|
|
||||||
ASSET_CONTAINER(AssetC, ::Bigfoot::AssetC)
|
BIGFOOT_ASSET(AssetC, ::Bigfoot::AssetC)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ table AssetA
|
|||||||
health: uint = 0;
|
health: uint = 0;
|
||||||
mana: 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;
|
root_type AssetA;
|
||||||
@@ -30,7 +30,7 @@ class AssetA: public Asset<AssetATraits>
|
|||||||
AssetA(const AssetA& p_asset) = delete;
|
AssetA(const AssetA& p_asset) = delete;
|
||||||
AssetA(AssetA&& p_asset) = default;
|
AssetA(AssetA&& p_asset) = default;
|
||||||
|
|
||||||
~AssetA() override = default;
|
~AssetA() = default;
|
||||||
|
|
||||||
AssetA& operator=(const AssetA& p_asset) = delete;
|
AssetA& operator=(const AssetA& p_asset) = delete;
|
||||||
AssetA& operator=(AssetA&& p_asset) = default;
|
AssetA& operator=(AssetA&& p_asset) = default;
|
||||||
|
|||||||
+30
@@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
|||||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||||
FLATBUFFERS_VERSION_REVISION == 19,
|
FLATBUFFERS_VERSION_REVISION == 19,
|
||||||
"Non-compatible flatbuffers version included");
|
"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 "System/UUID/UUID.hpp"
|
||||||
#include "Engine/Asset/Reference.hpp"
|
#include "Engine/Asset/Reference.hpp"
|
||||||
@@ -28,6 +35,21 @@ struct AssetA;
|
|||||||
struct AssetABuilder;
|
struct AssetABuilder;
|
||||||
struct AssetAT;
|
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();
|
inline const ::flatbuffers::TypeTable *AssetATypeTable();
|
||||||
|
|
||||||
struct AssetAT : public ::flatbuffers::NativeTable {
|
struct AssetAT : public ::flatbuffers::NativeTable {
|
||||||
@@ -218,4 +240,12 @@ inline eastl::unique_ptr<Flat::Bigfoot::AssetAT> UnPackSizePrefixedAssetA(
|
|||||||
} // namespace Bigfoot
|
} // namespace Bigfoot
|
||||||
} // namespace Flat
|
} // 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_
|
#endif // FLATBUFFERS_GENERATED_ASSETA_FLAT_BIGFOOT_H_
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ namespace Flat.Bigfoot;
|
|||||||
|
|
||||||
table AssetB
|
table AssetB
|
||||||
{
|
{
|
||||||
ref_a: HardReference (native_inline, native_type_template_arg: "::Bigfoot::AssetA");
|
ref_a: HardReference (native_inline, bigfoot_ref: "::Bigfoot::AssetA");
|
||||||
refs_a: [SoftReference] (native_inline, native_type_template_arg: "::Bigfoot::AssetA");
|
refs_a: [SoftReference] (native_inline, bigfoot_ref: "::Bigfoot::AssetA");
|
||||||
}
|
}
|
||||||
|
|
||||||
root_type AssetB;
|
root_type AssetB;
|
||||||
@@ -30,7 +30,7 @@ class AssetB: public Asset<AssetBTraits>
|
|||||||
AssetB(const AssetB& p_asset) = delete;
|
AssetB(const AssetB& p_asset) = delete;
|
||||||
AssetB(AssetB&& p_asset) = default;
|
AssetB(AssetB&& p_asset) = default;
|
||||||
|
|
||||||
~AssetB() override = default;
|
~AssetB() = default;
|
||||||
|
|
||||||
AssetB& operator=(const AssetB& p_asset) = delete;
|
AssetB& operator=(const AssetB& p_asset) = delete;
|
||||||
AssetB& operator=(AssetB&& p_asset) = default;
|
AssetB& operator=(AssetB&& p_asset) = default;
|
||||||
|
|||||||
+37
@@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
|||||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||||
FLATBUFFERS_VERSION_REVISION == 19,
|
FLATBUFFERS_VERSION_REVISION == 19,
|
||||||
"Non-compatible flatbuffers version included");
|
"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 "System/UUID/UUID.hpp"
|
||||||
#include "Engine/Asset/Reference.hpp"
|
#include "Engine/Asset/Reference.hpp"
|
||||||
@@ -28,6 +35,23 @@ struct AssetB;
|
|||||||
struct AssetBBuilder;
|
struct AssetBBuilder;
|
||||||
struct AssetBT;
|
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();
|
inline const ::flatbuffers::TypeTable *AssetBTypeTable();
|
||||||
|
|
||||||
struct AssetBT : public ::flatbuffers::NativeTable {
|
struct AssetBT : public ::flatbuffers::NativeTable {
|
||||||
@@ -205,4 +229,17 @@ inline eastl::unique_ptr<Flat::Bigfoot::AssetBT> UnPackSizePrefixedAssetB(
|
|||||||
} // namespace Bigfoot
|
} // namespace Bigfoot
|
||||||
} // namespace Flat
|
} // 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_
|
#endif // FLATBUFFERS_GENERATED_ASSETB_FLAT_BIGFOOT_H_
|
||||||
|
|||||||
@@ -4,16 +4,19 @@ namespace Flat.Bigfoot;
|
|||||||
|
|
||||||
table InnerTable
|
table InnerTable
|
||||||
{
|
{
|
||||||
asset_a_ref: 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, native_type_template_arg: "::Bigfoot::AssetA");
|
asset_a_refs: [HardReference] (native_inline, bigfoot_ref: "::Bigfoot::AssetA");
|
||||||
|
|
||||||
|
any_asset: AnyHardReference (native_inline);
|
||||||
|
any_assets: [AnySoftReference] (native_inline);
|
||||||
}
|
}
|
||||||
|
|
||||||
table AssetC
|
table AssetC
|
||||||
{
|
{
|
||||||
inner_table: InnerTable (required);
|
inner_table: InnerTable (required);
|
||||||
|
|
||||||
asset_b_ref: HardReference (native_inline, native_type_template_arg: "::Bigfoot::AssetB");
|
asset_b_ref: HardReference (native_inline, bigfoot_ref: "::Bigfoot::AssetB");
|
||||||
asset_b_refs: [SoftReference] (native_inline, native_type_template_arg: "::Bigfoot::AssetB");
|
asset_b_refs: [SoftReference] (native_inline, bigfoot_ref: "::Bigfoot::AssetB");
|
||||||
}
|
}
|
||||||
|
|
||||||
root_type AssetC;
|
root_type AssetC;
|
||||||
@@ -33,7 +33,7 @@ class AssetC: public Asset<AssetCTraits>
|
|||||||
AssetC(const AssetC& p_asset) = delete;
|
AssetC(const AssetC& p_asset) = delete;
|
||||||
AssetC(AssetC&& p_asset) = default;
|
AssetC(AssetC&& p_asset) = default;
|
||||||
|
|
||||||
~AssetC() override = default;
|
~AssetC() = default;
|
||||||
|
|
||||||
AssetC& operator=(const AssetC& p_asset) = delete;
|
AssetC& operator=(const AssetC& p_asset) = delete;
|
||||||
AssetC& operator=(AssetC&& p_asset) = default;
|
AssetC& operator=(AssetC&& p_asset) = default;
|
||||||
|
|||||||
+87
-6
@@ -12,6 +12,13 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
|||||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||||
FLATBUFFERS_VERSION_REVISION == 19,
|
FLATBUFFERS_VERSION_REVISION == 19,
|
||||||
"Non-compatible flatbuffers version included");
|
"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 "System/UUID/UUID.hpp"
|
||||||
#include "Engine/Asset/Reference.hpp"
|
#include "Engine/Asset/Reference.hpp"
|
||||||
@@ -32,6 +39,29 @@ struct AssetC;
|
|||||||
struct AssetCBuilder;
|
struct AssetCBuilder;
|
||||||
struct AssetCT;
|
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 *InnerTableTypeTable();
|
||||||
|
|
||||||
inline const ::flatbuffers::TypeTable *AssetCTypeTable();
|
inline const ::flatbuffers::TypeTable *AssetCTypeTable();
|
||||||
@@ -43,6 +73,8 @@ struct InnerTableT : public ::flatbuffers::NativeTable {
|
|||||||
}
|
}
|
||||||
::Bigfoot::HardReference<::Bigfoot::AssetA> asset_a_ref{};
|
::Bigfoot::HardReference<::Bigfoot::AssetA> asset_a_ref{};
|
||||||
eastl::vector<::Bigfoot::HardReference<::Bigfoot::AssetA>> asset_a_refs{};
|
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 {
|
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 {
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
VT_ASSET_A_REF = 4,
|
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 {
|
const Flat::Bigfoot::HardReference *asset_a_ref() const {
|
||||||
return GetStruct<const Flat::Bigfoot::HardReference *>(VT_ASSET_A_REF);
|
return GetStruct<const Flat::Bigfoot::HardReference *>(VT_ASSET_A_REF);
|
||||||
@@ -65,12 +99,21 @@ struct InnerTable FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
|||||||
const ::flatbuffers::Vector<const Flat::Bigfoot::HardReference *> *asset_a_refs() const {
|
const ::flatbuffers::Vector<const Flat::Bigfoot::HardReference *> *asset_a_refs() const {
|
||||||
return GetPointer<const ::flatbuffers::Vector<const Flat::Bigfoot::HardReference *> *>(VT_ASSET_A_REFS);
|
return GetPointer<const ::flatbuffers::Vector<const Flat::Bigfoot::HardReference *> *>(VT_ASSET_A_REFS);
|
||||||
}
|
}
|
||||||
|
const Flat::Bigfoot::AnyHardReference *any_asset() const {
|
||||||
|
return GetStruct<const Flat::Bigfoot::AnyHardReference *>(VT_ANY_ASSET);
|
||||||
|
}
|
||||||
|
const ::flatbuffers::Vector<const Flat::Bigfoot::AnySoftReference *> *any_assets() const {
|
||||||
|
return GetPointer<const ::flatbuffers::Vector<const Flat::Bigfoot::AnySoftReference *> *>(VT_ANY_ASSETS);
|
||||||
|
}
|
||||||
template <bool B = false>
|
template <bool B = false>
|
||||||
bool Verify(::flatbuffers::VerifierTemplate<B> &verifier) const {
|
bool Verify(::flatbuffers::VerifierTemplate<B> &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyField<Flat::Bigfoot::HardReference>(verifier, VT_ASSET_A_REF, 1) &&
|
VerifyField<Flat::Bigfoot::HardReference>(verifier, VT_ASSET_A_REF, 1) &&
|
||||||
VerifyOffset(verifier, VT_ASSET_A_REFS) &&
|
VerifyOffset(verifier, VT_ASSET_A_REFS) &&
|
||||||
verifier.VerifyVector(asset_a_refs()) &&
|
verifier.VerifyVector(asset_a_refs()) &&
|
||||||
|
VerifyField<Flat::Bigfoot::AnyHardReference>(verifier, VT_ANY_ASSET, 1) &&
|
||||||
|
VerifyOffset(verifier, VT_ANY_ASSETS) &&
|
||||||
|
verifier.VerifyVector(any_assets()) &&
|
||||||
verifier.EndTable();
|
verifier.EndTable();
|
||||||
}
|
}
|
||||||
InnerTableT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
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<const Flat::Bigfoot::HardReference *>> asset_a_refs) {
|
void add_asset_a_refs(::flatbuffers::Offset<::flatbuffers::Vector<const Flat::Bigfoot::HardReference *>> asset_a_refs) {
|
||||||
fbb_.AddOffset(InnerTable::VT_ASSET_A_REFS, 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<const Flat::Bigfoot::AnySoftReference *>> any_assets) {
|
||||||
|
fbb_.AddOffset(InnerTable::VT_ANY_ASSETS, any_assets);
|
||||||
|
}
|
||||||
explicit InnerTableBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
explicit InnerTableBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
: fbb_(_fbb) {
|
: fbb_(_fbb) {
|
||||||
start_ = fbb_.StartTable();
|
start_ = fbb_.StartTable();
|
||||||
@@ -102,8 +151,12 @@ struct InnerTableBuilder {
|
|||||||
inline ::flatbuffers::Offset<InnerTable> CreateInnerTable(
|
inline ::flatbuffers::Offset<InnerTable> CreateInnerTable(
|
||||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
const Flat::Bigfoot::HardReference *asset_a_ref = nullptr,
|
const Flat::Bigfoot::HardReference *asset_a_ref = nullptr,
|
||||||
::flatbuffers::Offset<::flatbuffers::Vector<const Flat::Bigfoot::HardReference *>> asset_a_refs = 0) {
|
::flatbuffers::Offset<::flatbuffers::Vector<const Flat::Bigfoot::HardReference *>> asset_a_refs = 0,
|
||||||
|
const Flat::Bigfoot::AnyHardReference *any_asset = nullptr,
|
||||||
|
::flatbuffers::Offset<::flatbuffers::Vector<const Flat::Bigfoot::AnySoftReference *>> any_assets = 0) {
|
||||||
InnerTableBuilder builder_(_fbb);
|
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_refs(asset_a_refs);
|
||||||
builder_.add_asset_a_ref(asset_a_ref);
|
builder_.add_asset_a_ref(asset_a_ref);
|
||||||
return builder_.Finish();
|
return builder_.Finish();
|
||||||
@@ -224,6 +277,8 @@ inline void InnerTable::UnPackTo(InnerTableT *_o, const ::flatbuffers::resolver_
|
|||||||
(void)_resolver;
|
(void)_resolver;
|
||||||
{ auto _e = asset_a_ref(); if (_e) _o->asset_a_ref = ::flatbuffers::UnPackHardReferenceAssetA(*_e); }
|
{ 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 = 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<InnerTable> CreateInnerTable(::flatbuffers::FlatBufferBuilder &_fbb, const InnerTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
inline ::flatbuffers::Offset<InnerTable> CreateInnerTable(::flatbuffers::FlatBufferBuilder &_fbb, const InnerTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
||||||
@@ -236,10 +291,14 @@ inline ::flatbuffers::Offset<InnerTable> InnerTable::Pack(::flatbuffers::FlatBuf
|
|||||||
struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const InnerTableT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
|
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_ref = ::flatbuffers::PackHardReferenceAssetA(_o->asset_a_ref);
|
||||||
auto _asset_a_refs = _fbb.CreateVectorOfNativeStructs<Flat::Bigfoot::HardReference, ::Bigfoot::HardReference<::Bigfoot::AssetA>>(_o->asset_a_refs.data(), _o->asset_a_refs.size(), ::flatbuffers::PackHardReferenceAssetA);
|
auto _asset_a_refs = _fbb.CreateVectorOfNativeStructs<Flat::Bigfoot::HardReference, ::Bigfoot::HardReference<::Bigfoot::AssetA>>(_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<Flat::Bigfoot::AnySoftReference, ::Bigfoot::AnySoftReference>(_o->any_assets.data(), _o->any_assets.size());
|
||||||
return Flat::Bigfoot::CreateInnerTable(
|
return Flat::Bigfoot::CreateInnerTable(
|
||||||
_fbb,
|
_fbb,
|
||||||
&_asset_a_ref,
|
&_asset_a_ref,
|
||||||
_asset_a_refs);
|
_asset_a_refs,
|
||||||
|
&_any_asset,
|
||||||
|
_any_assets);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline AssetCT::AssetCT(const AssetCT &o)
|
inline AssetCT::AssetCT(const AssetCT &o)
|
||||||
@@ -290,13 +349,17 @@ inline ::flatbuffers::Offset<AssetC> AssetC::Pack(::flatbuffers::FlatBufferBuild
|
|||||||
inline const ::flatbuffers::TypeTable *InnerTableTypeTable() {
|
inline const ::flatbuffers::TypeTable *InnerTableTypeTable() {
|
||||||
static const ::flatbuffers::TypeCode type_codes[] = {
|
static const ::flatbuffers::TypeCode type_codes[] = {
|
||||||
{ ::flatbuffers::ET_SEQUENCE, 0, 0 },
|
{ ::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[] = {
|
static const ::flatbuffers::TypeFunction type_refs[] = {
|
||||||
Flat::Bigfoot::HardReferenceTypeTable
|
Flat::Bigfoot::HardReferenceTypeTable,
|
||||||
|
Flat::Bigfoot::AnyHardReferenceTypeTable,
|
||||||
|
Flat::Bigfoot::AnySoftReferenceTypeTable
|
||||||
};
|
};
|
||||||
static const ::flatbuffers::TypeTable tt = {
|
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;
|
return &tt;
|
||||||
}
|
}
|
||||||
@@ -369,4 +432,22 @@ inline eastl::unique_ptr<Flat::Bigfoot::AssetCT> UnPackSizePrefixedAssetC(
|
|||||||
} // namespace Bigfoot
|
} // namespace Bigfoot
|
||||||
} // namespace Flat
|
} // 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_
|
#endif // FLATBUFFERS_GENERATED_ASSETC_FLAT_BIGFOOT_H_
|
||||||
|
|||||||
@@ -1,539 +0,0 @@
|
|||||||
/*********************************************************************
|
|
||||||
* \file SlotMap.cpp
|
|
||||||
*
|
|
||||||
* \author Romain BOULLARD
|
|
||||||
* \date May 2026
|
|
||||||
*********************************************************************/
|
|
||||||
#include <Utils/Containers/SlotMap.hpp>
|
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
namespace Bigfoot
|
|
||||||
{
|
|
||||||
template<class VERSION_TYPE, class INDEX_TYPE>
|
|
||||||
struct SlotMapConfig
|
|
||||||
{
|
|
||||||
using Version = VERSION_TYPE;
|
|
||||||
using Index = INDEX_TYPE;
|
|
||||||
};
|
|
||||||
|
|
||||||
using SlotMapConfigs = ::testing::Types<SlotMapConfig<std::uint8_t, std::uint8_t>,
|
|
||||||
SlotMapConfig<std::uint8_t, std::uint16_t>,
|
|
||||||
SlotMapConfig<std::uint8_t, std::uint32_t>,
|
|
||||||
SlotMapConfig<std::uint16_t, std::uint8_t>,
|
|
||||||
SlotMapConfig<std::uint16_t, std::uint16_t>,
|
|
||||||
SlotMapConfig<std::uint16_t, std::uint32_t>,
|
|
||||||
SlotMapConfig<std::uint32_t, std::uint8_t>,
|
|
||||||
SlotMapConfig<std::uint32_t, std::uint16_t>,
|
|
||||||
SlotMapConfig<std::uint32_t, std::uint32_t>>;
|
|
||||||
|
|
||||||
struct SlotMapConfigNames
|
|
||||||
{
|
|
||||||
template<class T>
|
|
||||||
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 CONFIG>
|
|
||||||
class SlotKeyFixture: public ::testing::Test
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
using SlotMapVersionType = typename CONFIG::Version;
|
|
||||||
using SlotMapIndexType = typename CONFIG::Index;
|
|
||||||
|
|
||||||
using SlotMapType = SlotMap<std::uint32_t, SlotMapVersionType, SlotMapIndexType>;
|
|
||||||
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 CONFIG>
|
|
||||||
class SlotMapFixture: public ::testing::Test
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
using SlotMapVersionType = typename CONFIG::Version;
|
|
||||||
using SlotMapIndexType = typename CONFIG::Index;
|
|
||||||
|
|
||||||
using SlotMapType = SlotMap<std::uint32_t, SlotMapVersionType, SlotMapIndexType>;
|
|
||||||
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<typename TestFixture::SlotMapVersionType, std::uint32_t>)
|
|
||||||
{
|
|
||||||
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<typename TestFixture::SlotMapVersionType>::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<typename TestFixture::SlotMapVersionType>::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<std::uint32_t> 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<std::uint32_t> 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<std::uint32_t> 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<std::uint32_t> 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<std::uint32_t> 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<std::uint32_t> crValues;
|
|
||||||
for (auto it = this->m_slotMap.crbegin(); it != this->m_slotMap.crend(); ++it)
|
|
||||||
{
|
|
||||||
crValues.push_back(*it);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPECT_EQ(values, crValues);
|
|
||||||
}
|
|
||||||
} // namespace Bigfoot
|
|
||||||
Reference in New Issue
Block a user