Compare commits
52
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e51afcbdf5 | ||
|
|
9ae55ac60f | ||
|
|
841ba38be8 | ||
|
|
6ccf56eb38 | ||
|
|
fc5794b5c7 | ||
|
|
3e3e3798ae | ||
|
|
ed5061dc52 | ||
|
|
f518bf7c8a | ||
|
|
eb2af20abd | ||
|
|
8f047767ae | ||
|
|
02e587bf86 | ||
|
|
fff7733cdb | ||
|
|
c6e801abb6 | ||
|
|
77e26cfa83 | ||
|
|
be85c650b9 | ||
|
|
d32d1d7229 | ||
|
|
65da7522ef | ||
|
|
2572922af9 | ||
|
|
03e501f1b2 | ||
|
|
e78d5378a4 | ||
|
|
1b9e17d6bc | ||
|
|
4b07aa7fa2 | ||
|
|
081e23360f | ||
|
|
eb22baacf9 | ||
|
|
0bee2c22ca | ||
|
|
1307273150 | ||
|
|
8b2ad9de35 | ||
|
|
1c2f9344b0 | ||
|
|
09014277a1 | ||
|
|
8e28f50e1d | ||
|
|
407401bea2 | ||
|
|
cbf4de6003 | ||
|
|
0ba9e062d4 | ||
|
|
33331ea529 | ||
|
|
8a36af6bcb | ||
|
|
c6ccdf8214 | ||
|
|
d9f4a0e896 | ||
|
|
1d572b9d09 | ||
|
|
870bfe57e6 | ||
|
|
9978ff358b | ||
|
|
8be97bacb5 | ||
|
|
cea3b8a904 | ||
|
|
1d2dafff48 | ||
|
|
17ab916b11 | ||
|
|
3c306dd2c7 | ||
|
|
a1e4119311 | ||
|
|
1bae20b79c | ||
|
|
39d2ddbe49 | ||
|
|
6bc25a776e | ||
|
|
96c4353a8a | ||
|
|
9733860ecd | ||
|
|
2062b8169f |
+28
-2
@@ -51,7 +51,7 @@ CompactNamespaces: false
|
||||
Cpp11BracedListStyle: true
|
||||
EmptyLineBeforeAccessModifier: Always
|
||||
FixNamespaceComments: true
|
||||
IncludeBlocks: Preserve
|
||||
IncludeBlocks: Regroup
|
||||
IndentCaseBlocks: true
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: None
|
||||
@@ -119,4 +119,30 @@ SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeCpp11BracedList: true
|
||||
SpaceInEmptyBlock: true
|
||||
PenaltyBreakAssignment: 200
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
IncludeCategories:
|
||||
- Regex: '^<Engine/'
|
||||
Priority: 1
|
||||
- Regex: '^<System/'
|
||||
Priority: 2
|
||||
- Regex: '^<Utils/'
|
||||
Priority: 3
|
||||
- Regex: '^<EngineTests/'
|
||||
Priority: 4
|
||||
- Regex: '^<SystemTests/'
|
||||
Priority: 5
|
||||
- Regex: '^<UtilsTests/'
|
||||
Priority: 6
|
||||
- Regex: '^<AssetsForTesting/'
|
||||
Priority: 7
|
||||
- Regex: '^<EngineBenchmarks/'
|
||||
Priority: 8
|
||||
- Regex: '^<AssetsForBenchmarking/'
|
||||
Priority: 9
|
||||
- Regex: '^<[a-zA-Z0-9_/]+\.h>'
|
||||
Priority: 10
|
||||
- Regex: '^<[a-zA-Z0-9_/]+\.hpp>'
|
||||
Priority: 10
|
||||
- Regex: '^<[a-zA-Z0-9_/]+>'
|
||||
Priority: 11
|
||||
MainIncludeChar: AngleBracket
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"name": "Bigfoot",
|
||||
"image": "git.romainboullard.com/bigfootdev/linuxbigfootbuilder:main"
|
||||
"image": "git.romainboullard.com/bigfootdev/linuxcppbuilder:development"
|
||||
}
|
||||
|
||||
+16
-16
@@ -6,20 +6,22 @@ on:
|
||||
- '**'
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
CCACHE_BASEDIR: ${{ github.workspace }}
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
container:
|
||||
image: git.romainboullard.com/bigfootdev/linuxbigfootbuilder:main
|
||||
image: git.romainboullard.com/bigfootdev/linuxcppbuilder:development
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
build_type: ["Debug", "RelWithDebInfo", "Release"]
|
||||
unity_build: ["ON", "OFF"]
|
||||
name: "Build & Test ${{ matrix.build_type }} (Unity Build: ${{ matrix.unity_build }})"
|
||||
conan_profile: ["./ConanProfiles/host/clang", "./ConanProfiles/host/clang_asan"]
|
||||
toolmode:
|
||||
- { value: "True", name: "toolmode" }
|
||||
- { value: "False", name: "game" }
|
||||
name: "Build & Test ${{ matrix.build_type }} with ${{ matrix.conan_profile }} (Unity Build: ${{ matrix.unity_build }}, Variant: ${{ matrix.toolmode.name }})"
|
||||
steps:
|
||||
- name: Install Node.js
|
||||
run: apt-get update && apt-get install -y nodejs
|
||||
@@ -29,28 +31,26 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Show ccache stats before
|
||||
run: ccache --zero-stats
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
conan install . --deployer=full_deploy --deployer-folder=build --remote=bigfootpackages -pr:h=clang -pr:b=clang --build=missing -s build_type=${{ matrix.build_type }} -o bigfoot/*:build_tests=True -o bigfoot/*:tracy=False -o bigfoot/*:build_tools=True -o bigfoot/*:vulkan=True -o bigfoot/*:build_benchmarks=True
|
||||
cmake -S . -B ./build/${{ matrix.build_type }} --toolchain ./build/${{ matrix.build_type }}/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_UNITY_BUILD=${{ matrix.unity_build }} -G "Ninja"
|
||||
cmake --build build/${{ matrix.build_type }} --parallel $(nproc)
|
||||
|
||||
- name: Show ccache stats after
|
||||
run: ccache --show-stats
|
||||
conan install . --remote=bigfootpackages -pr:h=${{ matrix.conan_profile }} -pr:b=./ConanProfiles/build/clang --build=missing -s build_type=${{ matrix.build_type }} -o bigfoot/*:build_tests=True -o bigfoot/*:build_benchmarks=True -o bigfoot/*:tracy=False -o bigfoot/*:vulkan=True -o bigfoot/*:toolmode=${{ matrix.toolmode.value }} -of build-${{ matrix.toolmode.name }}
|
||||
. ./build-${{ matrix.toolmode.name }}/build/${{ matrix.build_type }}/generators/conanbuild.sh
|
||||
cmake -S . -B ./build-${{ matrix.toolmode.name }}/${{ matrix.build_type }} --toolchain ./build-${{ matrix.toolmode.name }}/build/${{ matrix.build_type }}/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_UNITY_BUILD=${{ matrix.unity_build }} -G "Ninja"
|
||||
cmake --build build-${{ matrix.toolmode.name }}/${{ matrix.build_type }} --parallel $(nproc)
|
||||
. ./build-${{ matrix.toolmode.name }}/build/${{ matrix.build_type }}/generators/deactivate_conanbuild.sh
|
||||
|
||||
- name: Unit Tests
|
||||
run: |
|
||||
cd ./build/${{ matrix.build_type }}
|
||||
cd ./build-${{ matrix.toolmode.name }}/${{ matrix.build_type }}
|
||||
. ../../build-${{ matrix.toolmode.name }}/build/${{ matrix.build_type }}/generators/conanbuild.sh
|
||||
xvfb-run ctest . --output-on-failure
|
||||
. ../../build-${{ matrix.toolmode.name }}/build/${{ matrix.build_type }}/generators/deactivate_conanbuild.sh
|
||||
|
||||
clang-format:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
container:
|
||||
image: git.romainboullard.com/bigfootdev/linuxbigfootbuilder:main
|
||||
image: git.romainboullard.com/bigfootdev/linuxcppbuilder:main
|
||||
name: "Clang Format Checks"
|
||||
steps:
|
||||
- name: Install Node.js
|
||||
|
||||
@@ -11,7 +11,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
container:
|
||||
image: git.romainboullard.com/bigfootdev/linuxbigfootbuilder:main
|
||||
image: git.romainboullard.com/bigfootdev/linuxcppbuilder:development
|
||||
|
||||
name: "Sonarqube"
|
||||
steps:
|
||||
- name: Install Node.js
|
||||
@@ -23,11 +24,13 @@ jobs:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: Generate
|
||||
- name: Build
|
||||
run: |
|
||||
conan install . --deployer=full_deploy --deployer-folder=build --remote=bigfootpackages -pr:h=clang_coverage -pr:b=clang_coverage --build=missing -s build_type=Debug -o bigfoot/*:build_tests=True -o bigfoot/*:tracy=False -o bigfoot/*:build_tools=True -o bigfoot/*:vulkan=True -o bigfoot/*:build_benchmarks=True
|
||||
conan install . --remote=bigfootpackages -pr:h=./ConanProfiles/host/clang_coverage -pr:b=./ConanProfiles/build/clang --build=missing -s build_type=Debug -o bigfoot/*:build_tests=True -o bigfoot/*:build_benchmarks=True -o bigfoot/*:tracy=False -o bigfoot/*:build_tools=True -o bigfoot/*:vulkan=True
|
||||
. ./build/Debug/generators/conanbuild.sh
|
||||
cmake -S . -B ./build/Debug --toolchain ./build/Debug/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Debug -G "Ninja"
|
||||
cmake --build build/Debug --parallel $(nproc)
|
||||
. ./build/Debug/generators/deactivate_conanbuild.sh
|
||||
|
||||
- name: Clang-Tidy
|
||||
run: run-clang-tidy -p ./build/Debug/ >> tidy_result.txt
|
||||
|
||||
+3
-1
@@ -1,4 +1,6 @@
|
||||
[Bb]uild*
|
||||
!ConanProfiles/build/
|
||||
!ConanProfiles/build/**
|
||||
Environment/output
|
||||
*.generated.h
|
||||
|
||||
@@ -18,4 +20,4 @@ graph_info.json
|
||||
|
||||
test_package/Vendor
|
||||
|
||||
graphviz
|
||||
graphviz*
|
||||
@@ -0,0 +1,11 @@
|
||||
/*********************************************************************
|
||||
* \file BenchmarkAsset.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date August 2026
|
||||
*********************************************************************/
|
||||
#include <AssetsForBenchmarking/Asset/BenchmarkAsset.hpp>
|
||||
|
||||
#include <Engine/Asset/AssetHelper.hpp>
|
||||
|
||||
BIGFOOT_ASSET(BenchmarkAsset, ::Bigfoot::BenchmarkAsset)
|
||||
@@ -0,0 +1,17 @@
|
||||
get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
project(${PackageName})
|
||||
|
||||
set(PublicDependencies)
|
||||
set(PrivateDependencies)
|
||||
set(BigfootPublicDependencies)
|
||||
set(BigfootPrivateDependencies
|
||||
Engine)
|
||||
|
||||
bigfoot_create_package_lib(
|
||||
"${PublicDependencies}"
|
||||
"${PrivateDependencies}"
|
||||
"${BigfootPublicDependencies}"
|
||||
"${BigfootPrivateDependencies}"
|
||||
"")
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER Benchmarks/Bigfoot)
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
namespace Flat.Bigfoot;
|
||||
|
||||
table BenchmarkAsset
|
||||
{
|
||||
payload: [ubyte];
|
||||
}
|
||||
|
||||
root_type BenchmarkAsset;
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*********************************************************************
|
||||
* \file BenchmarkAsset.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date August 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_ASSETSFORBENCHMARKING_ASSET_BENCHMARKASSET_HPP
|
||||
#define BIGFOOT_ASSETSFORBENCHMARKING_ASSET_BENCHMARKASSET_HPP
|
||||
#include <Engine/Asset/Asset.hpp>
|
||||
|
||||
#include <AssetsForBenchmarking/Asset/BenchmarkAsset_generated.hpp>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
struct BenchmarkAssetTraits
|
||||
{
|
||||
using FLAT = ::Flat::Bigfoot::BenchmarkAsset;
|
||||
};
|
||||
|
||||
class BenchmarkAsset: public Asset<BenchmarkAssetTraits>
|
||||
{
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
|
||||
#endif
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
|
||||
#ifndef FLATBUFFERS_GENERATED_BENCHMARKASSET_FLAT_BIGFOOT_H_
|
||||
#define FLATBUFFERS_GENERATED_BENCHMARKASSET_FLAT_BIGFOOT_H_
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
|
||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||
// generated, otherwise it may not be compatible.
|
||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 19,
|
||||
"Non-compatible flatbuffers version included");
|
||||
// Ensure the included flatbuffers.h is Bigfoot's fork - stock
|
||||
// flatbuffers (or a differently versioned Bigfoot fork) is not compatible.
|
||||
#ifndef FLATBUFFERS_BIGFOOT_VERSION
|
||||
#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible"
|
||||
#endif
|
||||
static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1,
|
||||
"Non-compatible Bigfoot flatbuffers fork version included");
|
||||
|
||||
#include "EASTL/unique_ptr.h"
|
||||
#include "EASTL/string.h"
|
||||
#include "EASTL/vector.h"
|
||||
|
||||
namespace Flat {
|
||||
namespace Bigfoot {
|
||||
|
||||
struct BenchmarkAsset;
|
||||
struct BenchmarkAssetBuilder;
|
||||
struct BenchmarkAssetT;
|
||||
|
||||
inline const ::flatbuffers::TypeTable *BenchmarkAssetTypeTable();
|
||||
|
||||
struct BenchmarkAssetT : public ::flatbuffers::NativeTable {
|
||||
typedef BenchmarkAsset TableType;
|
||||
static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() {
|
||||
return "Flat.Bigfoot.BenchmarkAssetT";
|
||||
}
|
||||
eastl::vector<uint8_t> payload{};
|
||||
};
|
||||
|
||||
struct BenchmarkAsset FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||
typedef BenchmarkAssetT NativeTableType;
|
||||
typedef BenchmarkAssetBuilder Builder;
|
||||
struct Traits;
|
||||
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
return BenchmarkAssetTypeTable();
|
||||
}
|
||||
static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() {
|
||||
return "Flat.Bigfoot.BenchmarkAsset";
|
||||
}
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_PAYLOAD = 4
|
||||
};
|
||||
const ::flatbuffers::Vector<uint8_t> *payload() const {
|
||||
return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_PAYLOAD);
|
||||
}
|
||||
template <bool B = false>
|
||||
bool Verify(::flatbuffers::VerifierTemplate<B> &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyOffset(verifier, VT_PAYLOAD) &&
|
||||
verifier.VerifyVector(payload()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
BenchmarkAssetT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||
void UnPackTo(BenchmarkAssetT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||
static ::flatbuffers::Offset<BenchmarkAsset> Pack(::flatbuffers::FlatBufferBuilder &_fbb, const BenchmarkAssetT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
};
|
||||
|
||||
struct BenchmarkAssetBuilder {
|
||||
typedef BenchmarkAsset Table;
|
||||
::flatbuffers::FlatBufferBuilder &fbb_;
|
||||
::flatbuffers::uoffset_t start_;
|
||||
void add_payload(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> payload) {
|
||||
fbb_.AddOffset(BenchmarkAsset::VT_PAYLOAD, payload);
|
||||
}
|
||||
explicit BenchmarkAssetBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
::flatbuffers::Offset<BenchmarkAsset> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = ::flatbuffers::Offset<BenchmarkAsset>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline ::flatbuffers::Offset<BenchmarkAsset> CreateBenchmarkAsset(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> payload = 0) {
|
||||
BenchmarkAssetBuilder builder_(_fbb);
|
||||
builder_.add_payload(payload);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
struct BenchmarkAsset::Traits {
|
||||
using type = BenchmarkAsset;
|
||||
static auto constexpr Create = CreateBenchmarkAsset;
|
||||
};
|
||||
|
||||
::flatbuffers::Offset<BenchmarkAsset> CreateBenchmarkAsset(::flatbuffers::FlatBufferBuilder &_fbb, const BenchmarkAssetT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
|
||||
inline BenchmarkAssetT *BenchmarkAsset::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const {
|
||||
auto _o = std::make_unique<BenchmarkAssetT>();
|
||||
UnPackTo(_o.get(), _resolver);
|
||||
return _o.release();
|
||||
}
|
||||
|
||||
inline void BenchmarkAsset::UnPackTo(BenchmarkAssetT *_o, const ::flatbuffers::resolver_function_t *_resolver) const {
|
||||
(void)_o;
|
||||
(void)_resolver;
|
||||
{ auto _e = payload(); if (_e) { _o->payload.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->payload.begin()); } }
|
||||
}
|
||||
|
||||
inline ::flatbuffers::Offset<BenchmarkAsset> CreateBenchmarkAsset(::flatbuffers::FlatBufferBuilder &_fbb, const BenchmarkAssetT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
||||
return BenchmarkAsset::Pack(_fbb, _o, _rehasher);
|
||||
}
|
||||
|
||||
inline ::flatbuffers::Offset<BenchmarkAsset> BenchmarkAsset::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const BenchmarkAssetT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
||||
(void)_rehasher;
|
||||
(void)_o;
|
||||
struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const BenchmarkAssetT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
|
||||
auto _payload = _fbb.CreateVector(_o->payload.data(), _o->payload.size());
|
||||
return Flat::Bigfoot::CreateBenchmarkAsset(
|
||||
_fbb,
|
||||
_payload);
|
||||
}
|
||||
|
||||
inline const ::flatbuffers::TypeTable *BenchmarkAssetTypeTable() {
|
||||
static const ::flatbuffers::TypeCode type_codes[] = {
|
||||
{ ::flatbuffers::ET_UCHAR, 1, -1 }
|
||||
};
|
||||
static const ::flatbuffers::TypeTable tt = {
|
||||
::flatbuffers::ST_TABLE, 1, type_codes, nullptr, nullptr, nullptr, nullptr
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
|
||||
inline const Flat::Bigfoot::BenchmarkAsset *GetBenchmarkAsset(const void *buf) {
|
||||
return ::flatbuffers::GetRoot<Flat::Bigfoot::BenchmarkAsset>(buf);
|
||||
}
|
||||
|
||||
inline const Flat::Bigfoot::BenchmarkAsset *GetSizePrefixedBenchmarkAsset(const void *buf) {
|
||||
return ::flatbuffers::GetSizePrefixedRoot<Flat::Bigfoot::BenchmarkAsset>(buf);
|
||||
}
|
||||
|
||||
template <bool B = false>
|
||||
inline bool VerifyBenchmarkAssetBuffer(
|
||||
::flatbuffers::VerifierTemplate<B> &verifier) {
|
||||
return verifier.template VerifyBuffer<Flat::Bigfoot::BenchmarkAsset>(nullptr);
|
||||
}
|
||||
|
||||
template <bool B = false>
|
||||
inline bool VerifySizePrefixedBenchmarkAssetBuffer(
|
||||
::flatbuffers::VerifierTemplate<B> &verifier) {
|
||||
return verifier.template VerifySizePrefixedBuffer<Flat::Bigfoot::BenchmarkAsset>(nullptr);
|
||||
}
|
||||
|
||||
inline const char *BenchmarkAssetExtension() {
|
||||
return "bfbs";
|
||||
}
|
||||
|
||||
inline void FinishBenchmarkAssetBuffer(
|
||||
::flatbuffers::FlatBufferBuilder &fbb,
|
||||
::flatbuffers::Offset<Flat::Bigfoot::BenchmarkAsset> root) {
|
||||
fbb.Finish(root);
|
||||
}
|
||||
|
||||
inline void FinishSizePrefixedBenchmarkAssetBuffer(
|
||||
::flatbuffers::FlatBufferBuilder &fbb,
|
||||
::flatbuffers::Offset<Flat::Bigfoot::BenchmarkAsset> root) {
|
||||
fbb.FinishSizePrefixed(root);
|
||||
}
|
||||
|
||||
inline eastl::unique_ptr<Flat::Bigfoot::BenchmarkAssetT> UnPackBenchmarkAsset(
|
||||
const void *buf,
|
||||
const ::flatbuffers::resolver_function_t *res = nullptr) {
|
||||
return eastl::unique_ptr<Flat::Bigfoot::BenchmarkAssetT>(GetBenchmarkAsset(buf)->UnPack(res));
|
||||
}
|
||||
|
||||
inline eastl::unique_ptr<Flat::Bigfoot::BenchmarkAssetT> UnPackSizePrefixedBenchmarkAsset(
|
||||
const void *buf,
|
||||
const ::flatbuffers::resolver_function_t *res = nullptr) {
|
||||
return eastl::unique_ptr<Flat::Bigfoot::BenchmarkAssetT>(GetSizePrefixedBenchmarkAsset(buf)->UnPack(res));
|
||||
}
|
||||
|
||||
} // namespace Bigfoot
|
||||
} // namespace Flat
|
||||
|
||||
#endif // FLATBUFFERS_GENERATED_BENCHMARKASSET_FLAT_BIGFOOT_H_
|
||||
@@ -0,0 +1,4 @@
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/AssetsForBenchmarking)
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Engine)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Utils)
|
||||
@@ -0,0 +1,174 @@
|
||||
/*********************************************************************
|
||||
* \file AssetContainer.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date August 2026
|
||||
*********************************************************************/
|
||||
#include <Engine/Asset/AssetContainer.hpp>
|
||||
|
||||
#include <AssetsForBenchmarking/Asset/BenchmarkAsset.hpp>
|
||||
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <effolkronium/random.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
namespace
|
||||
{
|
||||
using Random = effolkronium::random_static;
|
||||
} // namespace
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void Insert(benchmark::State& state)
|
||||
{
|
||||
const auto count = static_cast<std::uint32_t>(state.range(0));
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
AssetContainer<BenchmarkAsset> container;
|
||||
for (std::uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
benchmark::DoNotOptimize(container.Insert());
|
||||
}
|
||||
benchmark::DoNotOptimize(container);
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * count);
|
||||
state.SetBytesProcessed(static_cast<std::int64_t>(state.iterations() * count * sizeof(BenchmarkAsset)));
|
||||
}
|
||||
|
||||
BENCHMARK(Insert)->Name("AssetContainer/Insert")->Arg(512)->Arg(8192)->Arg(131'072);
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void Get(benchmark::State& state)
|
||||
{
|
||||
const auto count = static_cast<std::uint32_t>(state.range(0));
|
||||
|
||||
AssetContainer<BenchmarkAsset> container;
|
||||
eastl::vector<SlotMapKey<>> keys;
|
||||
keys.reserve(count);
|
||||
for (std::uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
keys.push_back(container.Insert());
|
||||
}
|
||||
Random::shuffle(keys);
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
std::uint64_t sum = 0;
|
||||
for (const SlotMapKey<> key: keys)
|
||||
{
|
||||
if (const BenchmarkAsset* const asset = container.Get(key))
|
||||
{
|
||||
sum += asset->GetHeader().type_id;
|
||||
}
|
||||
}
|
||||
benchmark::DoNotOptimize(sum);
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * count);
|
||||
}
|
||||
|
||||
BENCHMARK(Get)->Name("AssetContainer/Get")->Arg(512)->Arg(8192)->Arg(131'072);
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void Has(benchmark::State& state)
|
||||
{
|
||||
const auto count = static_cast<std::uint32_t>(state.range(0));
|
||||
|
||||
AssetContainer<BenchmarkAsset> container;
|
||||
eastl::vector<UUID> uuids;
|
||||
uuids.reserve(count);
|
||||
for (std::uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
const SlotMapKey<> key = container.Insert();
|
||||
uuids.push_back(container.Get(key)->GetHeader().uuid);
|
||||
}
|
||||
Random::shuffle(uuids);
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
bool result = true;
|
||||
for (const UUID& uuid: uuids)
|
||||
{
|
||||
result = result && container.Has(uuid);
|
||||
}
|
||||
benchmark::DoNotOptimize(result);
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * count);
|
||||
}
|
||||
|
||||
BENCHMARK(Has)->Name("AssetContainer/Has")->Arg(512)->Arg(8192)->Arg(131'072);
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void AcquireContainerHandle(benchmark::State& state)
|
||||
{
|
||||
const auto count = static_cast<std::uint32_t>(state.range(0));
|
||||
|
||||
AssetContainer<BenchmarkAsset> container;
|
||||
eastl::vector<UUID> uuids;
|
||||
uuids.reserve(count);
|
||||
for (std::uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
const SlotMapKey<> key = container.Insert();
|
||||
uuids.push_back(container.Get(key)->GetHeader().uuid);
|
||||
}
|
||||
Random::shuffle(uuids);
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
std::uint64_t sum = 0;
|
||||
for (const UUID& uuid: uuids)
|
||||
{
|
||||
sum += container.AcquireContainerHandle(uuid)->GetHardRefCount();
|
||||
}
|
||||
benchmark::DoNotOptimize(sum);
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * count);
|
||||
}
|
||||
|
||||
BENCHMARK(AcquireContainerHandle)->Name("AssetContainer/AcquireContainerHandle")->Arg(512)->Arg(8192)->Arg(131'072);
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void Remove(benchmark::State& state)
|
||||
{
|
||||
const auto count = static_cast<std::uint32_t>(state.range(0));
|
||||
|
||||
AssetContainer<BenchmarkAsset> container;
|
||||
eastl::vector<UUID> uuids;
|
||||
uuids.reserve(count);
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
uuids.clear();
|
||||
for (std::uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
const SlotMapKey<> key = container.Insert();
|
||||
uuids.push_back(container.Get(key)->GetHeader().uuid);
|
||||
}
|
||||
Random::shuffle(uuids);
|
||||
state.ResumeTiming();
|
||||
|
||||
for (const UUID& uuid: uuids)
|
||||
{
|
||||
container.Remove(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * count);
|
||||
state.SetBytesProcessed(static_cast<std::int64_t>(state.iterations() * count * sizeof(BenchmarkAsset)));
|
||||
}
|
||||
|
||||
BENCHMARK(Remove)->Name("AssetContainer/Remove")->Arg(512)->Arg(8192)->Arg(131'072);
|
||||
} // namespace Bigfoot
|
||||
@@ -0,0 +1,136 @@
|
||||
/*********************************************************************
|
||||
* \file Reference.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date August 2026
|
||||
*********************************************************************/
|
||||
#include <Engine/Asset/Reference.hpp>
|
||||
|
||||
#include <Engine/Asset/AssetLibrary.hpp>
|
||||
|
||||
#include <AssetsForBenchmarking/Asset/BenchmarkAsset.hpp>
|
||||
|
||||
#include <EASTL/vector.h>
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
template<template<class> class REFERENCE>
|
||||
void Construct(benchmark::State& state)
|
||||
{
|
||||
AssetLibrary library;
|
||||
AssetContainer<BenchmarkAsset> container;
|
||||
std::ignore = library.Insert(&container);
|
||||
ScopedActiveAssetLibrary scopedLibrary {&library};
|
||||
|
||||
const SlotMapKey<> key = container.Insert();
|
||||
const UUID uuid = container.Get(key)->GetHeader().uuid;
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
REFERENCE<BenchmarkAsset> reference {uuid};
|
||||
benchmark::DoNotOptimize(reference);
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations());
|
||||
}
|
||||
|
||||
BENCHMARK_TEMPLATE(Construct, HardReference)->Name("Reference/HardReference/Construct");
|
||||
BENCHMARK_TEMPLATE(Construct, SoftReference)->Name("Reference/SoftReference/Construct");
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
template<template<class> class REFERENCE>
|
||||
void Get(benchmark::State& state)
|
||||
{
|
||||
AssetLibrary library;
|
||||
AssetContainer<BenchmarkAsset> container;
|
||||
std::ignore = library.Insert(&container);
|
||||
ScopedActiveAssetLibrary scopedLibrary {&library};
|
||||
|
||||
const SlotMapKey<> key = container.Insert();
|
||||
const UUID uuid = container.Get(key)->GetHeader().uuid;
|
||||
|
||||
REFERENCE<BenchmarkAsset> reference {uuid};
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
benchmark::DoNotOptimize(reference.Get());
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations());
|
||||
}
|
||||
|
||||
BENCHMARK_TEMPLATE(Get, HardReference)->Name("Reference/HardReference/Get");
|
||||
BENCHMARK_TEMPLATE(Get, SoftReference)->Name("Reference/SoftReference/Get");
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
template<template<class> class REFERENCE>
|
||||
void Copy(benchmark::State& state)
|
||||
{
|
||||
AssetLibrary library;
|
||||
AssetContainer<BenchmarkAsset> container;
|
||||
std::ignore = library.Insert(&container);
|
||||
ScopedActiveAssetLibrary scopedLibrary {&library};
|
||||
|
||||
const SlotMapKey<> key = container.Insert();
|
||||
const UUID uuid = container.Get(key)->GetHeader().uuid;
|
||||
|
||||
REFERENCE<BenchmarkAsset> reference {uuid};
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
REFERENCE<BenchmarkAsset> copy {reference};
|
||||
benchmark::DoNotOptimize(copy);
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations());
|
||||
}
|
||||
|
||||
BENCHMARK_TEMPLATE(Copy, HardReference)->Name("Reference/HardReference/Copy");
|
||||
BENCHMARK_TEMPLATE(Copy, SoftReference)->Name("Reference/SoftReference/Copy");
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
template<template<class> class REFERENCE>
|
||||
void Move(benchmark::State& state)
|
||||
{
|
||||
AssetLibrary library;
|
||||
AssetContainer<BenchmarkAsset> container;
|
||||
std::ignore = library.Insert(&container);
|
||||
ScopedActiveAssetLibrary scopedLibrary {&library};
|
||||
|
||||
const SlotMapKey<> key = container.Insert();
|
||||
const UUID uuid = container.Get(key)->GetHeader().uuid;
|
||||
|
||||
constexpr std::size_t BATCH_SIZE = 128;
|
||||
eastl::vector<REFERENCE<BenchmarkAsset>> batch;
|
||||
batch.reserve(BATCH_SIZE);
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
batch.clear();
|
||||
for (std::size_t i = 0; i < BATCH_SIZE; ++i)
|
||||
{
|
||||
batch.emplace_back(uuid);
|
||||
}
|
||||
state.ResumeTiming();
|
||||
|
||||
for (REFERENCE<BenchmarkAsset>& reference: batch)
|
||||
{
|
||||
REFERENCE<BenchmarkAsset> moved {std::move(reference)};
|
||||
benchmark::DoNotOptimize(moved);
|
||||
}
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * BATCH_SIZE);
|
||||
}
|
||||
|
||||
BENCHMARK_TEMPLATE(Move, HardReference)->Name("Reference/HardReference/Move");
|
||||
BENCHMARK_TEMPLATE(Move, SoftReference)->Name("Reference/SoftReference/Move");
|
||||
} // namespace Bigfoot
|
||||
@@ -0,0 +1,276 @@
|
||||
/*********************************************************************
|
||||
* \file BigFile.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date August 2026
|
||||
*********************************************************************/
|
||||
#include <Engine/BigFile/BigFile.hpp>
|
||||
|
||||
#include <System/File/File.hpp>
|
||||
#include <System/UUID/UUID.hpp>
|
||||
|
||||
#include <EngineBenchmarks/BigFileInfo_generated.hpp>
|
||||
|
||||
#include <AssetsForBenchmarking/Asset/BenchmarkAsset.hpp>
|
||||
|
||||
#include <EASTL/vector.h>
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <effolkronium/random.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
#ifdef BIGFOOT_TOOLMODE
|
||||
namespace
|
||||
{
|
||||
using Random = effolkronium::random_static;
|
||||
|
||||
constexpr std::uint32_t ASSET_COUNT = 20'000;
|
||||
constexpr std::size_t ASSET_PAYLOAD_SIZE = 256;
|
||||
|
||||
class Fixture: public benchmark::Fixture
|
||||
{
|
||||
public:
|
||||
void SetUp(benchmark::State&) override
|
||||
{
|
||||
BigFile::Request {m_bigFile, "DELETE FROM Asset;"}.Execute();
|
||||
BigFile::Request {m_bigFile, "DELETE FROM AssetMetadata;"}.Execute();
|
||||
|
||||
m_uuids.clear();
|
||||
m_uuids.reserve(ASSET_COUNT);
|
||||
|
||||
eastl::vector<AssetMetadata> metadatas;
|
||||
eastl::vector<eastl::vector<std::byte>> flatbuffers;
|
||||
metadatas.reserve(ASSET_COUNT);
|
||||
flatbuffers.reserve(ASSET_COUNT);
|
||||
|
||||
for (std::uint32_t i = 0; i < ASSET_COUNT; ++i)
|
||||
{
|
||||
BenchmarkAsset asset;
|
||||
asset.SetName(asset.GetHeader().uuid.ToString().c_str());
|
||||
asset.GetAsset().payload.assign(ASSET_PAYLOAD_SIZE, std::uint8_t {0xAB});
|
||||
|
||||
metadatas.push_back(AssetMetadata {.m_uuid = asset.GetHeader().uuid,
|
||||
.m_name = asset.GetHeader().name,
|
||||
.m_typeID = asset.GetHeader().type_id,
|
||||
.m_typeName = asset.GetHeader().type_name});
|
||||
flatbuffers.push_back(asset.Pack());
|
||||
m_uuids.push_back(asset.GetHeader().uuid);
|
||||
}
|
||||
|
||||
m_bigFile.SaveAssetFlatbuffers(metadatas, flatbuffers);
|
||||
}
|
||||
|
||||
protected:
|
||||
[[nodiscard]]
|
||||
eastl::vector<UUID> RandomBatch(const std::size_t p_batchSize) const
|
||||
{
|
||||
eastl::vector<UUID> batch;
|
||||
batch.reserve(p_batchSize);
|
||||
for (std::size_t i = 0; i < p_batchSize; ++i)
|
||||
{
|
||||
batch.push_back(m_uuids[Random::get<std::size_t>(0, m_uuids.size() - 1)]);
|
||||
}
|
||||
|
||||
return batch;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
eastl::vector<eastl::vector<UUID>> RandomBatchPool(const std::size_t p_batchSize,
|
||||
const std::size_t p_poolSize) const
|
||||
{
|
||||
eastl::vector<eastl::vector<UUID>> pool;
|
||||
pool.reserve(p_poolSize);
|
||||
for (std::size_t i = 0; i < p_poolSize; ++i)
|
||||
{
|
||||
pool.push_back(RandomBatch(p_batchSize));
|
||||
}
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
BigFile m_bigFile {File {BIGFILE_ENGINEBENCHMARKS_LOCATION}};
|
||||
eastl::vector<UUID> m_uuids;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BENCHMARK_DEFINE_F(Fixture, GetAssetFlatbuffer)(benchmark::State& state)
|
||||
{
|
||||
std::int64_t bytesProcessed = 0;
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
eastl::optional<eastl::vector<std::byte>> flatbuffer = m_bigFile.GetAssetFlatbuffer(
|
||||
m_uuids[Random::get<std::size_t>(0, m_uuids.size() - 1)]);
|
||||
benchmark::DoNotOptimize(flatbuffer);
|
||||
|
||||
if (flatbuffer.has_value())
|
||||
{
|
||||
bytesProcessed += static_cast<std::int64_t>(flatbuffer->size());
|
||||
}
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations());
|
||||
state.SetBytesProcessed(bytesProcessed);
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(Fixture, GetAssetFlatbuffer)->Name("BigFile/GetAssetFlatbuffer");
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BENCHMARK_DEFINE_F(Fixture, GetAssetFlatbuffers)(benchmark::State& state)
|
||||
{
|
||||
const auto batchSize = static_cast<std::size_t>(state.range(0));
|
||||
|
||||
constexpr std::size_t BATCH_POOL_SIZE = 64;
|
||||
const eastl::vector<eastl::vector<UUID>> batchPool = RandomBatchPool(batchSize, BATCH_POOL_SIZE);
|
||||
|
||||
std::int64_t bytesProcessed = 0;
|
||||
std::size_t batchIndex = 0;
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
eastl::vector<eastl::vector<std::byte>> flatbuffers = m_bigFile.GetAssetFlatbuffers(batchPool[batchIndex]);
|
||||
benchmark::DoNotOptimize(flatbuffers);
|
||||
|
||||
for (const eastl::vector<std::byte>& flatbuffer: flatbuffers)
|
||||
{
|
||||
bytesProcessed += static_cast<std::int64_t>(flatbuffer.size());
|
||||
}
|
||||
|
||||
batchIndex = (batchIndex + 1) % BATCH_POOL_SIZE;
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * batchSize);
|
||||
state.SetBytesProcessed(bytesProcessed);
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(Fixture, GetAssetFlatbuffers)
|
||||
->Name("BigFile/GetAssetFlatbuffers")
|
||||
->Arg(1)
|
||||
->Arg(8)
|
||||
->Arg(64)
|
||||
->Arg(512)
|
||||
->Arg(4096);
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BENCHMARK_DEFINE_F(Fixture, GetAssetMetadata)(benchmark::State& state)
|
||||
{
|
||||
for (auto _: state)
|
||||
{
|
||||
benchmark::DoNotOptimize(m_bigFile.GetAssetMetadata(m_uuids[Random::get<std::size_t>(0, m_uuids.size() - 1)]));
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations());
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(Fixture, GetAssetMetadata)->Name("BigFile/GetAssetMetadata");
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BENCHMARK_DEFINE_F(Fixture, GetAssetMetadatas)(benchmark::State& state)
|
||||
{
|
||||
const auto batchSize = static_cast<std::size_t>(state.range(0));
|
||||
|
||||
constexpr std::size_t BATCH_POOL_SIZE = 64;
|
||||
const eastl::vector<eastl::vector<UUID>> batchPool = RandomBatchPool(batchSize, BATCH_POOL_SIZE);
|
||||
|
||||
std::size_t batchIndex = 0;
|
||||
for (auto _: state)
|
||||
{
|
||||
benchmark::DoNotOptimize(m_bigFile.GetAssetMetadatas(batchPool[batchIndex]));
|
||||
batchIndex = (batchIndex + 1) % BATCH_POOL_SIZE;
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * batchSize);
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(Fixture, GetAssetMetadatas)
|
||||
->Name("BigFile/GetAssetMetadatas")
|
||||
->Arg(1)
|
||||
->Arg(8)
|
||||
->Arg(64)
|
||||
->Arg(512)
|
||||
->Arg(4096);
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BENCHMARK_DEFINE_F(Fixture, SaveAssetFlatbuffer)(benchmark::State& state)
|
||||
{
|
||||
std::int64_t bytesProcessed = 0;
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
BenchmarkAsset asset;
|
||||
asset.SetName(asset.GetHeader().uuid.ToString().c_str());
|
||||
asset.GetAsset().payload.assign(ASSET_PAYLOAD_SIZE, std::uint8_t {0xAB});
|
||||
|
||||
const AssetMetadata metadata {.m_uuid = asset.GetHeader().uuid,
|
||||
.m_name = asset.GetHeader().name,
|
||||
.m_typeID = asset.GetHeader().type_id,
|
||||
.m_typeName = asset.GetHeader().type_name};
|
||||
const eastl::vector<std::byte> flatbuffer = asset.Pack();
|
||||
bytesProcessed += static_cast<std::int64_t>(flatbuffer.size());
|
||||
state.ResumeTiming();
|
||||
|
||||
m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer);
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations());
|
||||
state.SetBytesProcessed(bytesProcessed);
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(Fixture, SaveAssetFlatbuffer)->Name("BigFile/SaveAssetFlatbuffer");
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BENCHMARK_DEFINE_F(Fixture, SaveAssetFlatbuffers)(benchmark::State& state)
|
||||
{
|
||||
const auto batchSize = static_cast<std::size_t>(state.range(0));
|
||||
std::int64_t bytesProcessed = 0;
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
eastl::vector<AssetMetadata> metadatas;
|
||||
eastl::vector<eastl::vector<std::byte>> flatbuffers;
|
||||
metadatas.reserve(batchSize);
|
||||
flatbuffers.reserve(batchSize);
|
||||
|
||||
for (std::size_t i = 0; i < batchSize; ++i)
|
||||
{
|
||||
BenchmarkAsset asset;
|
||||
asset.SetName(asset.GetHeader().uuid.ToString().c_str());
|
||||
asset.GetAsset().payload.assign(ASSET_PAYLOAD_SIZE, std::uint8_t {0xAB});
|
||||
|
||||
metadatas.push_back(AssetMetadata {.m_uuid = asset.GetHeader().uuid,
|
||||
.m_name = asset.GetHeader().name,
|
||||
.m_typeID = asset.GetHeader().type_id,
|
||||
.m_typeName = asset.GetHeader().type_name});
|
||||
flatbuffers.push_back(asset.Pack());
|
||||
bytesProcessed += static_cast<std::int64_t>(flatbuffers.back().size());
|
||||
}
|
||||
state.ResumeTiming();
|
||||
|
||||
m_bigFile.SaveAssetFlatbuffers(metadatas, flatbuffers);
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * batchSize);
|
||||
state.SetBytesProcessed(bytesProcessed);
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(Fixture, SaveAssetFlatbuffers)
|
||||
->Name("BigFile/SaveAssetFlatbuffers")
|
||||
->Arg(1)
|
||||
->Arg(8)
|
||||
->Arg(64)
|
||||
->Arg(512)
|
||||
->Arg(4096);
|
||||
#endif
|
||||
} // namespace Bigfoot
|
||||
@@ -0,0 +1,12 @@
|
||||
get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
project(${PackageName}Benchmarks)
|
||||
|
||||
bigfoot_create_package_benchmarks(
|
||||
"")
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
effolkronium_random
|
||||
$<LINK_LIBRARY:WHOLE_ARCHIVE,AssetsForBenchmarking>)
|
||||
|
||||
bigfoot_create_bigfile("Benchmarks/Bigfoot")
|
||||
@@ -0,0 +1,22 @@
|
||||
// AUTO-GENERATED DO NOT TOUCH
|
||||
|
||||
/*********************************************************************
|
||||
* \file BigFileInfo.generated.hpp
|
||||
*
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_ENGINEBENCHMARKS_BIGFILEINFO_GENERATED_HPP
|
||||
#define BIGFOOT_ENGINEBENCHMARKS_BIGFILEINFO_GENERATED_HPP
|
||||
|
||||
#include <EASTL/string_view.h>
|
||||
|
||||
#if defined BIGFOOT_TOOLMODE
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
/*
|
||||
* BigFile location
|
||||
*/
|
||||
constexpr eastl::string_view BIGFILE_ENGINEBENCHMARKS_LOCATION {"./EngineBenchmarks-bigfile.db"};
|
||||
} // namespace Bigfoot
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,5 @@
|
||||
get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
project(${PackageName}Benchmarks)
|
||||
|
||||
bigfoot_create_package_benchmarks(
|
||||
"")
|
||||
@@ -0,0 +1,262 @@
|
||||
#include <Utils/Containers/SlotMap.hpp>
|
||||
|
||||
#include <ankerl/unordered_dense.h>
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <effolkronium/random.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
namespace
|
||||
{
|
||||
using Random = effolkronium::random_static;
|
||||
} // namespace
|
||||
|
||||
struct MyComplexStruct
|
||||
{
|
||||
std::uint32_t m_actualValueForBench = 0; // field summed by the Iterate benchmark
|
||||
|
||||
float m_position[3] = {0.0f, 0.0f, 0.0f};
|
||||
float m_rotation[4] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
float m_scale[3] = {1.0f, 1.0f, 1.0f};
|
||||
|
||||
std::uint64_t m_entityId = 0;
|
||||
std::uint32_t m_parentSlot = 0;
|
||||
std::uint32_t m_flags = 0;
|
||||
|
||||
MyComplexStruct() = default;
|
||||
|
||||
explicit MyComplexStruct(const std::uint32_t p_value):
|
||||
m_actualValueForBench(p_value),
|
||||
m_entityId(p_value)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(MyComplexStruct) == 64, "Payload should be exactly one cache line.");
|
||||
static_assert(std::is_trivially_copyable_v<MyComplexStruct>,
|
||||
"Container moves should be a plain memcpy, not a heap-touching move.");
|
||||
|
||||
template<class SLOTMAP>
|
||||
class SlotMapAdaptor
|
||||
{
|
||||
public:
|
||||
using Key = SLOTMAP::SlotMapKey;
|
||||
|
||||
Key Add(MyComplexStruct&& p_value)
|
||||
{
|
||||
return m_container.Insert(std::move(p_value));
|
||||
}
|
||||
|
||||
const MyComplexStruct* Find(const Key p_key) const
|
||||
{
|
||||
return m_container.Get(p_key);
|
||||
}
|
||||
|
||||
void Remove(const Key p_key)
|
||||
{
|
||||
m_container.Remove(p_key);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
m_container.Reset();
|
||||
}
|
||||
|
||||
template<class FUNC>
|
||||
void ForEachValue(FUNC&& p_func) const
|
||||
{
|
||||
for (const MyComplexStruct& value: m_container)
|
||||
{
|
||||
p_func(value);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SLOTMAP m_container;
|
||||
};
|
||||
|
||||
template<class MAP>
|
||||
class HashMapHarnessAdaptor
|
||||
{
|
||||
public:
|
||||
using Key = typename MAP::key_type;
|
||||
|
||||
Key Add(MyComplexStruct&& p_value)
|
||||
{
|
||||
const Key key = m_nextKey++;
|
||||
m_container.emplace(key, std::move(p_value));
|
||||
return key;
|
||||
}
|
||||
|
||||
const MyComplexStruct* Find(const Key p_key) const
|
||||
{
|
||||
const auto it = m_container.find(p_key);
|
||||
return it != m_container.end() ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
void Remove(const Key p_key)
|
||||
{
|
||||
m_container.erase(p_key);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
m_container.clear();
|
||||
m_nextKey = 0;
|
||||
}
|
||||
|
||||
template<class FUNC>
|
||||
void ForEachValue(FUNC&& p_func) const
|
||||
{
|
||||
for (const auto& keyValue: m_container)
|
||||
{
|
||||
p_func(keyValue.second);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
MAP m_container;
|
||||
Key m_nextKey = 0;
|
||||
};
|
||||
|
||||
template<class ADAPTOR>
|
||||
void Insert(benchmark::State& state)
|
||||
{
|
||||
const auto count = static_cast<std::uint32_t>(state.range(0));
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
ADAPTOR adaptor;
|
||||
for (std::uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
benchmark::DoNotOptimize(adaptor.Add(MyComplexStruct {i}));
|
||||
}
|
||||
benchmark::DoNotOptimize(adaptor);
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * count);
|
||||
state.SetBytesProcessed(static_cast<std::int64_t>(state.iterations() * count * sizeof(MyComplexStruct)));
|
||||
}
|
||||
|
||||
template<class ADAPTOR>
|
||||
void Remove(benchmark::State& state)
|
||||
{
|
||||
const auto count = static_cast<std::uint32_t>(state.range(0));
|
||||
|
||||
ADAPTOR adaptor;
|
||||
std::vector<typename ADAPTOR::Key> keys;
|
||||
keys.reserve(count);
|
||||
Random::seed(0x5EEDU);
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
adaptor.Clear();
|
||||
keys.clear();
|
||||
for (std::uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
keys.push_back(adaptor.Add(MyComplexStruct {i}));
|
||||
}
|
||||
Random::shuffle(keys);
|
||||
state.ResumeTiming();
|
||||
|
||||
for (const typename ADAPTOR::Key key: keys)
|
||||
{
|
||||
adaptor.Remove(key);
|
||||
}
|
||||
benchmark::DoNotOptimize(adaptor);
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * count);
|
||||
state.SetBytesProcessed(static_cast<std::int64_t>(state.iterations() * count * sizeof(MyComplexStruct)));
|
||||
}
|
||||
|
||||
template<class ADAPTOR>
|
||||
void Get(benchmark::State& state)
|
||||
{
|
||||
const auto count = static_cast<std::uint32_t>(state.range(0));
|
||||
|
||||
ADAPTOR adaptor;
|
||||
std::vector<typename ADAPTOR::Key> keys;
|
||||
keys.reserve(count);
|
||||
for (std::uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
keys.push_back(adaptor.Add(MyComplexStruct {i}));
|
||||
}
|
||||
Random::seed(0x5EEDU);
|
||||
Random::shuffle(keys);
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
std::uint64_t sum = 0;
|
||||
for (const typename ADAPTOR::Key key: keys)
|
||||
{
|
||||
if (const MyComplexStruct* const value = adaptor.Find(key))
|
||||
{
|
||||
sum += value->m_actualValueForBench;
|
||||
}
|
||||
}
|
||||
benchmark::DoNotOptimize(sum);
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * count);
|
||||
state.SetBytesProcessed(static_cast<std::int64_t>(state.iterations() * count * sizeof(MyComplexStruct)));
|
||||
}
|
||||
|
||||
template<class ADAPTOR>
|
||||
void Iterate(benchmark::State& state)
|
||||
{
|
||||
const auto count = static_cast<std::uint32_t>(state.range(0));
|
||||
|
||||
ADAPTOR adaptor;
|
||||
for (std::uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
adaptor.Add(MyComplexStruct {i});
|
||||
}
|
||||
|
||||
for (auto _: state)
|
||||
{
|
||||
std::uint64_t sum = 0;
|
||||
adaptor.ForEachValue(
|
||||
[&sum](const MyComplexStruct& value)
|
||||
{
|
||||
sum += value.m_actualValueForBench;
|
||||
});
|
||||
benchmark::DoNotOptimize(sum);
|
||||
}
|
||||
|
||||
state.SetItemsProcessed(state.iterations() * count);
|
||||
state.SetBytesProcessed(static_cast<std::int64_t>(state.iterations() * count * sizeof(MyComplexStruct)));
|
||||
}
|
||||
|
||||
#define BIGFOOT_REGISTER_BENCHMARKS(ADAPTOR, NAME) \
|
||||
BENCHMARK_TEMPLATE(Insert, ADAPTOR)->Name(NAME "/Insert")->Arg(512)->Arg(8192)->Arg(262'144)->Arg(4'194'304); \
|
||||
BENCHMARK_TEMPLATE(Remove, ADAPTOR)->Name(NAME "/Remove")->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);
|
||||
|
||||
using DenseSlotMapHarness = SlotMapAdaptor<DenseSlotMap<MyComplexStruct>>;
|
||||
using StableSlotMapHarness = SlotMapAdaptor<StableSlotMap<MyComplexStruct>>;
|
||||
using UnorderedDenseMapHarness = HashMapHarnessAdaptor<ankerl::unordered_dense::map<std::uint64_t, MyComplexStruct>>;
|
||||
using UnorderedDenseSegementedMapHarness =
|
||||
HashMapHarnessAdaptor<ankerl::unordered_dense::segmented_map<std::uint64_t, MyComplexStruct>>;
|
||||
using UnorderedMapHarness = HashMapHarnessAdaptor<std::unordered_map<std::uint64_t, MyComplexStruct>>;
|
||||
using MapHarness = HashMapHarnessAdaptor<std::map<std::uint64_t, MyComplexStruct>>;
|
||||
|
||||
BIGFOOT_REGISTER_BENCHMARKS(DenseSlotMapHarness, "Bigfoot::DenseSlotMap");
|
||||
BIGFOOT_REGISTER_BENCHMARKS(StableSlotMapHarness, "Bigfoot::StableSlotMap");
|
||||
BIGFOOT_REGISTER_BENCHMARKS(UnorderedDenseMapHarness, "ankerl::unordered_dense::map");
|
||||
BIGFOOT_REGISTER_BENCHMARKS(UnorderedDenseSegementedMapHarness, "ankerl::unordered_dense::segmented_map");
|
||||
BIGFOOT_REGISTER_BENCHMARKS(UnorderedMapHarness, "std::unordered_map");
|
||||
BIGFOOT_REGISTER_BENCHMARKS(MapHarness, "std::map");
|
||||
|
||||
#undef BIGFOOT_REGISTER_BENCHMARKS
|
||||
#undef BIGFOOT_CACHE_TIER_ARGS
|
||||
} // namespace Bigfoot
|
||||
@@ -0,0 +1,15 @@
|
||||
/*********************************************************************
|
||||
* \file AssetLibrary.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date August 2026
|
||||
*********************************************************************/
|
||||
#include <Engine/Asset/AssetLibrary.hpp>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
void SetActiveAssetLibrary(AssetLibrary* p_assetLibrary)
|
||||
{
|
||||
g_activeAssetLibrary = p_assetLibrary;
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
@@ -0,0 +1,24 @@
|
||||
/*********************************************************************
|
||||
* \file AssetTypeID.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date May 2026
|
||||
*********************************************************************/
|
||||
#include <Engine/Asset/AssetTypeID.hpp>
|
||||
|
||||
#include <Engine/Asset/AssetTypeID_generated.hpp>
|
||||
|
||||
namespace flatbuffers
|
||||
{
|
||||
Flat::Bigfoot::AssetTypeID Pack(const Bigfoot::AssetTypeID& p_assetTypeID)
|
||||
{
|
||||
return Flat::Bigfoot::AssetTypeID {p_assetTypeID};
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
Bigfoot::AssetTypeID UnPack(const Flat::Bigfoot::AssetTypeID& p_flatAssetTypeID)
|
||||
{
|
||||
return Bigfoot::AssetTypeID {p_flatAssetTypeID.value()};
|
||||
}
|
||||
} // namespace flatbuffers
|
||||
@@ -0,0 +1,607 @@
|
||||
/*********************************************************************
|
||||
* \file BigFile.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date October 2025
|
||||
*********************************************************************/
|
||||
#include <Engine/BigFile/BigFile.hpp>
|
||||
|
||||
#include <Engine/EngineAssertHandler.hpp>
|
||||
|
||||
#include <EASTL/algorithm.h>
|
||||
#include <EASTL/sort.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
#ifdef BIGFOOT_TOOLMODE
|
||||
BigFile::BigFile(const File& p_file)
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_open_v2(p_file.ToAbsolute().GetPath().data(), &m_db, SQLITE_OPEN_READWRITE, nullptr);
|
||||
CRITICAL_ASSERT(EngineAssertHandler,
|
||||
result == SQLITE_OK,
|
||||
"Failed to open BigFile {} DB: {}",
|
||||
p_file.ToAbsolute().GetPath(),
|
||||
sqlite3_errmsg(m_db));
|
||||
|
||||
[[maybe_unused]]
|
||||
const int synchronousResult = sqlite3_exec(m_db, "PRAGMA synchronous = NORMAL;", nullptr, nullptr, nullptr);
|
||||
ASSERT(EngineAssertHandler,
|
||||
synchronousResult == SQLITE_OK,
|
||||
"Failed to set synchronous pragma: {}",
|
||||
sqlite3_errmsg(m_db));
|
||||
|
||||
[[maybe_unused]]
|
||||
const int foreignKeysResult = sqlite3_exec(m_db, "PRAGMA foreign_keys = ON;", nullptr, nullptr, nullptr);
|
||||
ASSERT(EngineAssertHandler,
|
||||
foreignKeysResult == SQLITE_OK,
|
||||
"Failed to set foreign_keys pragma: {}",
|
||||
sqlite3_errmsg(m_db));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void BigFile::BeginTransaction()
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_exec(m_db, "BEGIN TRANSACTION;", nullptr, nullptr, nullptr);
|
||||
ASSERT(EngineAssertHandler, result == SQLITE_OK, "Failed to begin transaction: {}", sqlite3_errmsg(m_db));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void BigFile::CommitTransaction()
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_exec(m_db, "COMMIT TRANSACTION;", nullptr, nullptr, nullptr);
|
||||
ASSERT(EngineAssertHandler, result == SQLITE_OK, "Failed to commit: {}", sqlite3_errmsg(m_db));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void BigFile::RollbackTransaction()
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_exec(m_db, "ROLLBACK TRANSACTION;", nullptr, nullptr, nullptr);
|
||||
ASSERT(EngineAssertHandler, result == SQLITE_OK, "Failed to rollback: {}", sqlite3_errmsg(m_db));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BigFile::~BigFile()
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_close_v2(m_db);
|
||||
CRITICAL_ASSERT(EngineAssertHandler, result == SQLITE_OK, "Failed to close BigFile DB: {}", sqlite3_errmsg(m_db));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
eastl::optional<eastl::vector<std::byte>> BigFile::GetAssetFlatbuffer(const UUID& p_uuid) const
|
||||
{
|
||||
BigFile::Request assetRequest {*this, "SELECT Asset FROM Asset WHERE UUID = ?1;"};
|
||||
assetRequest.Bind(1, p_uuid.ToBytes());
|
||||
|
||||
if (!assetRequest.Step())
|
||||
{
|
||||
return eastl::nullopt;
|
||||
}
|
||||
|
||||
const eastl::span<const std::byte> flatbuffer = assetRequest.Get(0);
|
||||
return eastl::vector<std::byte> {flatbuffer.begin(), flatbuffer.end()};
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
eastl::vector<eastl::vector<std::byte>> BigFile::GetAssetFlatbuffers(const eastl::span<const UUID> p_uuids) const
|
||||
{
|
||||
eastl::vector<eastl::vector<std::byte>> flatbuffers;
|
||||
if (p_uuids.empty())
|
||||
{
|
||||
return flatbuffers;
|
||||
}
|
||||
|
||||
flatbuffers.reserve(p_uuids.size());
|
||||
|
||||
if (p_uuids.size() == 1)
|
||||
{
|
||||
if (eastl::optional<eastl::vector<std::byte>> flatbuffer = GetAssetFlatbuffer(p_uuids[0]);
|
||||
flatbuffer.has_value())
|
||||
{
|
||||
flatbuffers.push_back(std::move(*flatbuffer));
|
||||
}
|
||||
|
||||
return flatbuffers;
|
||||
}
|
||||
|
||||
eastl::vector<UUID> uniqueUUIDs {p_uuids.begin(), p_uuids.end()};
|
||||
eastl::sort(uniqueUUIDs.begin(), uniqueUUIDs.end());
|
||||
uniqueUUIDs.erase(eastl::unique(uniqueUUIDs.begin(), uniqueUUIDs.end()), uniqueUUIDs.end());
|
||||
|
||||
eastl::string placeholders;
|
||||
placeholders.reserve(uniqueUUIDs.size() * 3);
|
||||
for (std::size_t i = 0; i < uniqueUUIDs.size(); ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
placeholders += ", ";
|
||||
}
|
||||
placeholders += "?";
|
||||
}
|
||||
|
||||
const std::string sqlRequest = fmt::format("SELECT Asset FROM Asset WHERE UUID IN ({});", placeholders);
|
||||
|
||||
BigFile::Request assetRequest {*this, sqlRequest.c_str()};
|
||||
for (std::size_t i = 0; i < uniqueUUIDs.size(); ++i)
|
||||
{
|
||||
assetRequest.Bind(static_cast<std::uint32_t>(i + 1), uniqueUUIDs[i].ToBytes());
|
||||
}
|
||||
|
||||
flatbuffers.reserve(uniqueUUIDs.size());
|
||||
for (std::size_t i = 0; i < uniqueUUIDs.size(); ++i)
|
||||
{
|
||||
if (!assetRequest.Step())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
const eastl::span<const std::byte> flatbuffer = assetRequest.Get(0);
|
||||
flatbuffers.emplace_back(flatbuffer.begin(), flatbuffer.end());
|
||||
}
|
||||
|
||||
return flatbuffers;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
eastl::optional<AssetMetadata> BigFile::GetAssetMetadata(const UUID& p_uuid) const
|
||||
{
|
||||
BigFile::Request assetRequest {
|
||||
*this,
|
||||
"SELECT UUID, Name, TypeID, TypeName, CreateTime, ModificationTime FROM AssetMetadata WHERE UUID = ?1;"};
|
||||
assetRequest.Bind(1, p_uuid.ToBytes());
|
||||
|
||||
if (!assetRequest.Step())
|
||||
{
|
||||
return eastl::nullopt;
|
||||
}
|
||||
|
||||
return AssetMetadata {.m_uuid = UUID {std::span<const std::byte, UUID::UUID_BYTE_SIZE> {
|
||||
static_cast<eastl::span<const std::byte>>(assetRequest.Get(0)).data(),
|
||||
UUID::UUID_BYTE_SIZE}},
|
||||
.m_name = eastl::string {static_cast<eastl::string_view>(assetRequest.Get(1))},
|
||||
.m_typeID = assetRequest.Get(2),
|
||||
.m_typeName = eastl::string {static_cast<eastl::string_view>(assetRequest.Get(3))},
|
||||
.m_creationTime = Time {static_cast<std::uint64_t>(assetRequest.Get(4))},
|
||||
.m_modificationTime = Time {static_cast<std::uint64_t>(assetRequest.Get(5))}};
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
eastl::vector<AssetMetadata> BigFile::GetAssetMetadatas(const eastl::span<const UUID> p_uuids) const
|
||||
{
|
||||
eastl::vector<AssetMetadata> metadatas;
|
||||
if (p_uuids.empty())
|
||||
{
|
||||
return metadatas;
|
||||
}
|
||||
|
||||
metadatas.reserve(p_uuids.size());
|
||||
|
||||
if (p_uuids.size() == 1)
|
||||
{
|
||||
if (eastl::optional<AssetMetadata> metadata = GetAssetMetadata(p_uuids[0]); metadata.has_value())
|
||||
{
|
||||
metadatas.push_back(std::move(*metadata));
|
||||
}
|
||||
|
||||
return metadatas;
|
||||
}
|
||||
|
||||
eastl::vector<UUID> uniqueUUIDs {p_uuids.begin(), p_uuids.end()};
|
||||
eastl::sort(uniqueUUIDs.begin(), uniqueUUIDs.end());
|
||||
uniqueUUIDs.erase(eastl::unique(uniqueUUIDs.begin(), uniqueUUIDs.end()), uniqueUUIDs.end());
|
||||
|
||||
eastl::string placeholders;
|
||||
placeholders.reserve(uniqueUUIDs.size() * 3);
|
||||
for (std::size_t i = 0; i < uniqueUUIDs.size(); ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
placeholders += ", ";
|
||||
}
|
||||
placeholders += "?";
|
||||
}
|
||||
|
||||
const std::string sqlRequest = fmt::format("SELECT UUID, Name, TypeID, TypeName, CreateTime, ModificationTime "
|
||||
"FROM AssetMetadata WHERE UUID IN ({});",
|
||||
placeholders);
|
||||
|
||||
BigFile::Request assetRequest {*this, sqlRequest.c_str()};
|
||||
for (std::size_t i = 0; i < uniqueUUIDs.size(); ++i)
|
||||
{
|
||||
assetRequest.Bind(static_cast<std::uint32_t>(i + 1), uniqueUUIDs[i].ToBytes());
|
||||
}
|
||||
|
||||
metadatas.reserve(uniqueUUIDs.size());
|
||||
for (std::size_t i = 0; i < uniqueUUIDs.size(); ++i)
|
||||
{
|
||||
if (!assetRequest.Step())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
metadatas.push_back(
|
||||
AssetMetadata {.m_uuid = UUID {std::span<const std::byte, UUID::UUID_BYTE_SIZE> {
|
||||
static_cast<eastl::span<const std::byte>>(assetRequest.Get(0)).data(),
|
||||
UUID::UUID_BYTE_SIZE}},
|
||||
.m_name = eastl::string {static_cast<eastl::string_view>(assetRequest.Get(1))},
|
||||
.m_typeID = assetRequest.Get(2),
|
||||
.m_typeName = eastl::string {static_cast<eastl::string_view>(assetRequest.Get(3))},
|
||||
.m_creationTime = Time {static_cast<std::uint64_t>(assetRequest.Get(4))},
|
||||
.m_modificationTime = Time {static_cast<std::uint64_t>(assetRequest.Get(5))}});
|
||||
}
|
||||
|
||||
return metadatas;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void BigFile::SaveAssetFlatbuffer(const AssetMetadata& p_metadata, const eastl::span<const std::byte> p_flatbuffer)
|
||||
{
|
||||
BeginTransaction();
|
||||
|
||||
BigFile::Request metadataRequest {
|
||||
*this,
|
||||
"INSERT INTO AssetMetadata (UUID, Name, TypeID, TypeName) VALUES (?1, ?2, ?3, ?4) "
|
||||
"ON CONFLICT(UUID) DO UPDATE SET Name = excluded.Name, TypeID = excluded.TypeID, TypeName = excluded.TypeName;"};
|
||||
metadataRequest.Bind(1, p_metadata.m_uuid.ToBytes());
|
||||
metadataRequest.Bind(2, p_metadata.m_name);
|
||||
metadataRequest.Bind(3, p_metadata.m_typeID);
|
||||
metadataRequest.Bind(4, p_metadata.m_typeName);
|
||||
metadataRequest.Execute();
|
||||
|
||||
BigFile::Request assetRequest {*this,
|
||||
"INSERT INTO Asset (UUID, Asset) VALUES (?1, ?2) "
|
||||
"ON CONFLICT(UUID) DO UPDATE SET Asset = excluded.Asset;"};
|
||||
assetRequest.Bind(1, p_metadata.m_uuid.ToBytes());
|
||||
assetRequest.Bind(2, p_flatbuffer);
|
||||
assetRequest.Execute();
|
||||
|
||||
CommitTransaction();
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void BigFile::SaveAssetFlatbuffers(const eastl::span<const AssetMetadata> p_metadatas,
|
||||
const eastl::span<const eastl::vector<std::byte>> p_flatbuffers)
|
||||
{
|
||||
ASSERT(EngineAssertHandler,
|
||||
p_metadatas.size() == p_flatbuffers.size(),
|
||||
"p_metadatas and p_flatbuffers must have the same size");
|
||||
|
||||
if (p_metadatas.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BeginTransaction();
|
||||
|
||||
constexpr std::size_t METADATA_PARAMS_PER_ROW = 4;
|
||||
const std::size_t maxRowsPerStatement = static_cast<std::size_t>(
|
||||
sqlite3_limit(m_db, SQLITE_LIMIT_VARIABLE_NUMBER, -1)) /
|
||||
METADATA_PARAMS_PER_ROW;
|
||||
|
||||
for (std::size_t chunkStart = 0; chunkStart < p_metadatas.size(); chunkStart += maxRowsPerStatement)
|
||||
{
|
||||
const std::size_t chunkSize = eastl::min(maxRowsPerStatement, p_metadatas.size() - chunkStart);
|
||||
|
||||
eastl::string metadataPlaceholders;
|
||||
metadataPlaceholders.reserve(chunkSize * 14);
|
||||
for (std::size_t i = 0; i < chunkSize; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
metadataPlaceholders += ", ";
|
||||
}
|
||||
metadataPlaceholders += "(?, ?, ?, ?)";
|
||||
}
|
||||
|
||||
const std::string metadataSQL = fmt::format(
|
||||
"INSERT INTO AssetMetadata (UUID, Name, TypeID, TypeName) VALUES {} "
|
||||
"ON CONFLICT(UUID) DO UPDATE SET Name = excluded.Name, TypeID = excluded.TypeID, TypeName = "
|
||||
"excluded.TypeName;",
|
||||
metadataPlaceholders);
|
||||
|
||||
BigFile::Request metadataRequest {*this, metadataSQL.c_str()};
|
||||
std::uint32_t metadataBindIndex = 1;
|
||||
for (std::size_t i = 0; i < chunkSize; ++i)
|
||||
{
|
||||
const AssetMetadata& metadata = p_metadatas[chunkStart + i];
|
||||
metadataRequest.Bind(metadataBindIndex++, metadata.m_uuid.ToBytes());
|
||||
metadataRequest.Bind(metadataBindIndex++, metadata.m_name);
|
||||
metadataRequest.Bind(metadataBindIndex++, metadata.m_typeID);
|
||||
metadataRequest.Bind(metadataBindIndex++, metadata.m_typeName);
|
||||
}
|
||||
metadataRequest.Execute();
|
||||
|
||||
eastl::string assetPlaceholders;
|
||||
assetPlaceholders.reserve(chunkSize * 8);
|
||||
for (std::size_t i = 0; i < chunkSize; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
assetPlaceholders += ", ";
|
||||
}
|
||||
assetPlaceholders += "(?, ?)";
|
||||
}
|
||||
|
||||
const std::string assetSQL = fmt::format(
|
||||
"INSERT INTO Asset (UUID, Asset) VALUES {} ON CONFLICT(UUID) DO UPDATE SET Asset = excluded.Asset;",
|
||||
assetPlaceholders);
|
||||
|
||||
BigFile::Request assetRequest {*this, assetSQL.c_str()};
|
||||
std::uint32_t assetBindIndex = 1;
|
||||
for (std::size_t i = 0; i < chunkSize; ++i)
|
||||
{
|
||||
assetRequest.Bind(assetBindIndex++, p_metadatas[chunkStart + i].m_uuid.ToBytes());
|
||||
assetRequest.Bind(assetBindIndex++, p_flatbuffers[chunkStart + i]);
|
||||
}
|
||||
assetRequest.Execute();
|
||||
}
|
||||
|
||||
CommitTransaction();
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool BigFile::Has(const UUID& p_uuid) const
|
||||
{
|
||||
BigFile::Request request {*this, "SELECT 1 FROM AssetMetadata WHERE UUID = ?1;"};
|
||||
request.Bind(1, p_uuid.ToBytes());
|
||||
|
||||
return request.Step();
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BigFile::Request::Request(const BigFile& p_bigFile, const eastl::string_view p_request):
|
||||
m_db(p_bigFile.m_db)
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_prepare_v2(m_db,
|
||||
p_request.data(),
|
||||
static_cast<std::uint32_t>(p_request.size()),
|
||||
&m_statement,
|
||||
nullptr);
|
||||
CRITICAL_ASSERT(EngineAssertHandler,
|
||||
result == SQLITE_OK,
|
||||
"Failed to create statement from BigFile DB: {}",
|
||||
sqlite3_errmsg(m_db));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void BigFile::Request::Bind(const std::uint32_t p_index, const std::int32_t p_value)
|
||||
{
|
||||
ASSERT(EngineAssertHandler,
|
||||
(p_index >= 1) && (p_index <= static_cast<std::uint32_t>(sqlite3_bind_parameter_count(m_statement))),
|
||||
"Invalid index for statement");
|
||||
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_bind_int(m_statement, p_index, p_value);
|
||||
ASSERT(EngineAssertHandler, result == SQLITE_OK, "Failed to bind value for statement: {}", sqlite3_errmsg(m_db));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void BigFile::Request::Bind(const std::uint32_t p_index, const std::uint32_t p_value)
|
||||
{
|
||||
ASSERT(EngineAssertHandler,
|
||||
(p_index >= 1) && (p_index <= static_cast<std::uint32_t>(sqlite3_bind_parameter_count(m_statement))),
|
||||
"Invalid index for statement");
|
||||
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_bind_int(m_statement, p_index, p_value);
|
||||
ASSERT(EngineAssertHandler, result == SQLITE_OK, "Failed to bind value for statement: {}", sqlite3_errmsg(m_db));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void BigFile::Request::Bind(const std::uint32_t p_index, const std::int64_t p_value)
|
||||
{
|
||||
ASSERT(EngineAssertHandler,
|
||||
(p_index >= 1) && (p_index <= static_cast<std::uint32_t>(sqlite3_bind_parameter_count(m_statement))),
|
||||
"Invalid index for statement");
|
||||
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_bind_int64(m_statement, p_index, p_value);
|
||||
ASSERT(EngineAssertHandler, result == SQLITE_OK, "Failed to bind value for statement: {}", sqlite3_errmsg(m_db));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void BigFile::Request::Bind(const std::uint32_t p_index, const std::uint64_t p_value)
|
||||
{
|
||||
ASSERT(EngineAssertHandler,
|
||||
(p_index >= 1) && (p_index <= static_cast<std::uint32_t>(sqlite3_bind_parameter_count(m_statement))),
|
||||
"Invalid index for statement");
|
||||
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_bind_int64(m_statement, p_index, std::bit_cast<std::int64_t>(p_value));
|
||||
ASSERT(EngineAssertHandler, result == SQLITE_OK, "Failed to bind value for statement: {}", sqlite3_errmsg(m_db));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void BigFile::Request::Bind(const std::uint32_t p_index, const float p_value)
|
||||
{
|
||||
ASSERT(EngineAssertHandler,
|
||||
(p_index >= 1) && (p_index <= static_cast<std::uint32_t>(sqlite3_bind_parameter_count(m_statement))),
|
||||
"Invalid index for statement");
|
||||
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_bind_double(m_statement, p_index, p_value);
|
||||
ASSERT(EngineAssertHandler, result == SQLITE_OK, "Failed to bind value for statement: {}", sqlite3_errmsg(m_db));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void BigFile::Request::Bind(const std::uint32_t p_index, const double p_value)
|
||||
{
|
||||
ASSERT(EngineAssertHandler,
|
||||
(p_index >= 1) && (p_index <= static_cast<std::uint32_t>(sqlite3_bind_parameter_count(m_statement))),
|
||||
"Invalid index for statement");
|
||||
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_bind_double(m_statement, p_index, p_value);
|
||||
ASSERT(EngineAssertHandler, result == SQLITE_OK, "Failed to bind value for statement: {}", sqlite3_errmsg(m_db));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void BigFile::Request::Bind(const std::uint32_t p_index, const eastl::string_view p_value, const CopyValue p_copy)
|
||||
{
|
||||
ASSERT(EngineAssertHandler,
|
||||
(p_index >= 1) && (p_index <= static_cast<std::uint32_t>(sqlite3_bind_parameter_count(m_statement))),
|
||||
"Invalid index for statement");
|
||||
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_bind_text(m_statement,
|
||||
p_index,
|
||||
p_value.data(),
|
||||
static_cast<std::uint32_t>(p_value.size()),
|
||||
p_copy ? SQLITE_TRANSIENT : SQLITE_STATIC);
|
||||
ASSERT(EngineAssertHandler, result == SQLITE_OK, "Failed to bind value for statement: {}", sqlite3_errmsg(m_db));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void BigFile::Request::Bind(const std::uint32_t p_index,
|
||||
const eastl::span<const std::byte> p_value,
|
||||
const CopyValue p_copy)
|
||||
{
|
||||
ASSERT(EngineAssertHandler,
|
||||
(p_index >= 1) && (p_index <= static_cast<std::uint32_t>(sqlite3_bind_parameter_count(m_statement))),
|
||||
"Invalid index for statement");
|
||||
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_bind_blob(m_statement,
|
||||
p_index,
|
||||
p_value.data(),
|
||||
static_cast<std::uint32_t>(p_value.size()),
|
||||
p_copy ? SQLITE_TRANSIENT : SQLITE_STATIC);
|
||||
ASSERT(EngineAssertHandler, result == SQLITE_OK, "Failed to bind value for statement: {}", sqlite3_errmsg(m_db));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool BigFile::Request::Step()
|
||||
{
|
||||
const int result = sqlite3_step(m_statement);
|
||||
ASSERT(EngineAssertHandler,
|
||||
(result == SQLITE_DONE) || (result == SQLITE_ROW),
|
||||
"Failed to step through the statement: {}",
|
||||
sqlite3_errmsg(m_db));
|
||||
|
||||
return result == SQLITE_ROW;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
std::uint32_t BigFile::Request::Execute()
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_step(m_statement);
|
||||
ASSERT(EngineAssertHandler, (result == SQLITE_DONE), "Failed to execute the statement: {}", sqlite3_errmsg(m_db));
|
||||
|
||||
return sqlite3_changes(m_db);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BigFile::Request::Column::Column(const Request& p_request, const std::uint32_t p_index):
|
||||
m_statement(p_request.m_statement),
|
||||
m_index(p_index)
|
||||
{
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BigFile::Request::Column::operator std::int32_t() const
|
||||
{
|
||||
return sqlite3_column_int(m_statement, m_index);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BigFile::Request::Column::operator std::uint32_t() const
|
||||
{
|
||||
return sqlite3_column_int(m_statement, m_index);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BigFile::Request::Column::operator std::int64_t() const
|
||||
{
|
||||
return sqlite3_column_int64(m_statement, m_index);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BigFile::Request::Column::operator std::uint64_t() const
|
||||
{
|
||||
return std::bit_cast<std::uint64_t>(sqlite3_column_int64(m_statement, m_index));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BigFile::Request::Column::operator float() const
|
||||
{
|
||||
return static_cast<float>(sqlite3_column_double(m_statement, m_index));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BigFile::Request::Column::operator double() const
|
||||
{
|
||||
return sqlite3_column_double(m_statement, m_index);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BigFile::Request::Column::operator eastl::string_view() const
|
||||
{
|
||||
return eastl::string_view {reinterpret_cast<const char*>(sqlite3_column_text(m_statement, m_index)),
|
||||
static_cast<std::size_t>(sqlite3_column_bytes(m_statement, m_index))};
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BigFile::Request::Column::operator eastl::span<const std::byte>() const
|
||||
{
|
||||
return eastl::span<const std::byte> {static_cast<const std::byte*>(sqlite3_column_blob(m_statement, m_index)),
|
||||
static_cast<std::size_t>(sqlite3_column_bytes(m_statement, m_index))};
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BigFile::Request::Column BigFile::Request::Get(const std::uint32_t p_index) const
|
||||
{
|
||||
ASSERT(EngineAssertHandler,
|
||||
p_index < static_cast<std::uint32_t>(sqlite3_column_count(m_statement)),
|
||||
"Invalid index for column!");
|
||||
return {*this, p_index};
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
BigFile::Request::~Request()
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_finalize(m_statement);
|
||||
CRITICAL_ASSERT(EngineAssertHandler, result == SQLITE_OK, "Failed to finalize statement: {}", sqlite3_errmsg(m_db));
|
||||
}
|
||||
#endif
|
||||
} // namespace Bigfoot
|
||||
@@ -1,41 +1,38 @@
|
||||
PRAGMA journal_mode=WAL;
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
DROP TABLE IF EXISTS AssetHeader;
|
||||
CREATE TABLE IF NOT EXISTS AssetHeader (
|
||||
UUID BLOB NOT NULL UNIQUE,
|
||||
CREATE TABLE IF NOT EXISTS AssetMetadata (
|
||||
UUID BLOB NOT NULL,
|
||||
Name TEXT NOT NULL UNIQUE,
|
||||
TypeID INTEGER NOT NULL,
|
||||
TypeName TEXT NOT NULL,
|
||||
|
||||
CreateTime INTEGER NOT NULL DEFAULT(CAST(unixepoch('subsec') AS INTEGER) * 1000000),
|
||||
ModificationTime INTEGER NOT NULL DEFAULT(CAST(unixepoch('subsec') AS INTEGER) * 1000000),
|
||||
CreateTime INTEGER NOT NULL DEFAULT(CAST(unixepoch('subsec') * 1000000 AS INTEGER)),
|
||||
ModificationTime INTEGER NOT NULL DEFAULT(CAST(unixepoch('subsec') * 1000000 AS INTEGER)),
|
||||
|
||||
PRIMARY KEY(UUID)
|
||||
);
|
||||
) WITHOUT ROWID;
|
||||
|
||||
CREATE TRIGGER IF NOT EXISTS AssetHeader_UpdateTime
|
||||
AFTER UPDATE OF Name, TypeID, TypeName ON AssetHeader FOR EACH ROW
|
||||
CREATE TRIGGER IF NOT EXISTS AssetMetadata_UpdateTime
|
||||
AFTER UPDATE OF Name, TypeID, TypeName ON AssetMetadata FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE AssetHeader
|
||||
SET ModificationTime = CAST(unixepoch('subsec') AS INTEGER) * 1000000
|
||||
UPDATE AssetMetadata
|
||||
SET ModificationTime = CAST(unixepoch('subsec') * 1000000 AS INTEGER)
|
||||
WHERE UUID = NEW.UUID;
|
||||
END;
|
||||
|
||||
DROP TABLE IF EXISTS Asset;
|
||||
CREATE TABLE IF NOT EXISTS Asset (
|
||||
UUID BLOB NOT NULL UNIQUE,
|
||||
UUID BLOB NOT NULL,
|
||||
|
||||
Asset BLOB NOT NULL,
|
||||
|
||||
PRIMARY KEY(UUID),
|
||||
FOREIGN KEY(UUID) REFERENCES AssetHeader(UUID) ON DELETE CASCADE
|
||||
);
|
||||
FOREIGN KEY(UUID) REFERENCES AssetMetadata(UUID) ON DELETE CASCADE
|
||||
) WITHOUT ROWID;
|
||||
|
||||
CREATE TRIGGER IF NOT EXISTS Asset_UpdateTime
|
||||
AFTER UPDATE OF Asset ON Asset FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE AssetHeader
|
||||
SET ModificationTime = CAST(unixepoch('subsec') AS INTEGER) * 1000000
|
||||
UPDATE AssetMetadata
|
||||
SET ModificationTime = CAST(unixepoch('subsec') * 1000000 AS INTEGER)
|
||||
WHERE UUID = NEW.UUID;
|
||||
END;
|
||||
@@ -5,8 +5,7 @@ set(PublicDependencies
|
||||
SQLite::SQLite3)
|
||||
set(PrivateDependencies)
|
||||
set(BigfootPublicDependencies
|
||||
System
|
||||
Utils)
|
||||
System)
|
||||
set(BigfootPrivateDependencies)
|
||||
|
||||
set(BIGFOOT_MAJOR 0)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/*********************************************************************
|
||||
* \file DataAccessor.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date August 2026
|
||||
*********************************************************************/
|
||||
#include <Engine/DataAccessor/DataAccessor.hpp>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
void SetDataAccessor(DataAccessor* p_dataAccessor)
|
||||
{
|
||||
g_dataAccessor = p_dataAccessor;
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
@@ -0,0 +1,22 @@
|
||||
include "Engine/Asset/AssetTypeID.fbs";
|
||||
|
||||
include "System/UUID/UUID.fbs";
|
||||
|
||||
namespace Flat.Bigfoot;
|
||||
|
||||
table AssetHeader
|
||||
{
|
||||
uuid: UUID (required, native_inline, id: 0);
|
||||
name: string (required, id: 1);
|
||||
type_id: AssetTypeID (required, native_inline, id: 2);
|
||||
type_name: string (required, id: 3);
|
||||
version: uint = 0 (id: 4);
|
||||
}
|
||||
|
||||
table Asset
|
||||
{
|
||||
header: AssetHeader (required, id: 0);
|
||||
inner_asset: [ubyte] (required, id: 1);
|
||||
}
|
||||
|
||||
root_type Asset;
|
||||
@@ -0,0 +1,189 @@
|
||||
/*********************************************************************
|
||||
* \file Asset.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date April 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_ENGINE_ASSET_ASSET_HPP
|
||||
#define BIGFOOT_ENGINE_ASSET_ASSET_HPP
|
||||
#include <Engine/Asset/AssetConcepts.hpp>
|
||||
#include <Engine/Asset/Asset_generated.hpp>
|
||||
#include <Engine/EngineAssertHandler.hpp>
|
||||
|
||||
#include <EASTL/span.h>
|
||||
#include <EASTL/vector.h>
|
||||
#include <ankerl/unordered_dense.h>
|
||||
#include <flatbuffers/reflection.h>
|
||||
#include <rapidhash.h>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
class AssetBase
|
||||
{
|
||||
public:
|
||||
virtual ~AssetBase() = default;
|
||||
|
||||
protected:
|
||||
AssetBase() = default;
|
||||
|
||||
AssetBase(const AssetBase& p_asset) = delete;
|
||||
AssetBase(AssetBase&& p_asset) = default;
|
||||
|
||||
AssetBase& operator=(const AssetBase& p_asset) = delete;
|
||||
AssetBase& operator=(AssetBase&& p_asset) = default;
|
||||
};
|
||||
|
||||
template<class ASSET>
|
||||
requires AssetTraits<ASSET>
|
||||
class Asset: public AssetBase
|
||||
{
|
||||
public:
|
||||
using FLAT_ASSET = typename ASSET::FLAT;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Will default initialize header
|
||||
*
|
||||
*/
|
||||
Asset()
|
||||
{
|
||||
m_header.type_id = GetTypeID();
|
||||
m_header.type_name = eastl::string {GetTypeName()};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the header of the asset
|
||||
*
|
||||
* \return The header of the asset
|
||||
*/
|
||||
[[nodiscard]]
|
||||
const ::Flat::Bigfoot::AssetHeaderT& GetHeader() const
|
||||
{
|
||||
return m_header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the asset
|
||||
*
|
||||
* \param p_name The name of the asset
|
||||
*/
|
||||
void SetName(const eastl::string_view p_name)
|
||||
{
|
||||
m_header.name = p_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the version of the asset
|
||||
*
|
||||
* \param p_name The version of the asset
|
||||
*/
|
||||
void SetVersion(const std::uint32_t p_version)
|
||||
{
|
||||
m_header.version = p_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the asset
|
||||
*
|
||||
* \return The asset
|
||||
*/
|
||||
[[nodiscard]]
|
||||
const typename FLAT_ASSET::NativeTableType& GetAsset() const
|
||||
{
|
||||
return m_asset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the asset
|
||||
*
|
||||
* \return The asset
|
||||
*/
|
||||
[[nodiscard]]
|
||||
typename FLAT_ASSET::NativeTableType& GetAsset()
|
||||
{
|
||||
return m_asset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpack a flatbuffer to the asset
|
||||
*
|
||||
* \param p_flatbuffer The flatbuffer to unpack
|
||||
*/
|
||||
void Unpack(const eastl::span<const std::byte> p_flatbuffer)
|
||||
{
|
||||
#ifdef BIGFOOT_NOT_OPTIMIZED
|
||||
flatbuffers::Verifier verifier {std::bit_cast<std::uint8_t*>(p_flatbuffer.data()), p_flatbuffer.size()};
|
||||
const bool assetVerified = ::Flat::Bigfoot::VerifyAssetBuffer(verifier);
|
||||
CRITICAL_ASSERT(EngineAssertHandler, assetVerified, "Given asset could not be verified!");
|
||||
|
||||
const ::Flat::Bigfoot::Asset* asset = flatbuffers::GetRoot<::Flat::Bigfoot::Asset>(p_flatbuffer.data());
|
||||
|
||||
flatbuffers::Verifier innerAssetVerifier {asset->inner_asset()->data(), asset->inner_asset()->size()};
|
||||
const bool innerAssetVerified = innerAssetVerifier.VerifyBuffer<FLAT_ASSET>();
|
||||
CRITICAL_ASSERT(EngineAssertHandler, innerAssetVerified, "Given asset could not be verified!");
|
||||
#else
|
||||
const ::Flat::Bigfoot::Asset* asset = flatbuffers::GetRoot<::Flat::Bigfoot::Asset>(p_flatbuffer.data());
|
||||
#endif
|
||||
|
||||
asset->header()->UnPackTo(&m_header);
|
||||
flatbuffers::GetRoot<FLAT_ASSET>(asset->inner_asset()->data())->UnPackTo(&m_asset, nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack the asset to a flatbuffer
|
||||
*
|
||||
* \return The packed asset
|
||||
*/
|
||||
[[nodiscard]]
|
||||
eastl::vector<std::byte> Pack() const
|
||||
{
|
||||
flatbuffers::FlatBufferBuilder innerAssetFbb;
|
||||
innerAssetFbb.Finish(FLAT_ASSET::Pack(innerAssetFbb, &m_asset));
|
||||
|
||||
flatbuffers::FlatBufferBuilder assetFbb;
|
||||
const auto header = ::Flat::Bigfoot::AssetHeader::Pack(assetFbb, &m_header);
|
||||
const auto innerAsset = assetFbb.CreateVector(innerAssetFbb.GetBufferPointer(), innerAssetFbb.GetSize());
|
||||
assetFbb.Finish(::Flat::Bigfoot::CreateAsset(assetFbb, header, innerAsset));
|
||||
|
||||
return eastl::vector<std::byte> {std::bit_cast<std::byte*>(assetFbb.GetBufferPointer()),
|
||||
std::bit_cast<std::byte*>(assetFbb.GetBufferPointer() + assetFbb.GetSize())};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the AssetTypeID
|
||||
*
|
||||
* \return The AssetTypeIPD
|
||||
*/
|
||||
[[nodiscard]]
|
||||
static AssetTypeID GetTypeID()
|
||||
{
|
||||
static const AssetTypeID typeID = rapidhash(FLAT_ASSET::GetFullyQualifiedName(),
|
||||
std::strlen(FLAT_ASSET::GetFullyQualifiedName()));
|
||||
return typeID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type name
|
||||
*
|
||||
* \return The type name
|
||||
*/
|
||||
[[nodiscard]]
|
||||
static eastl::string_view GetTypeName()
|
||||
{
|
||||
return FLAT_ASSET::GetFullyQualifiedName();
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* The asset
|
||||
*/
|
||||
typename FLAT_ASSET::NativeTableType m_asset;
|
||||
/**
|
||||
* The asset header
|
||||
*/
|
||||
::Flat::Bigfoot::AssetHeaderT m_header;
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
/*********************************************************************
|
||||
* \file AssetConcepts.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date August 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_ENGINE_ASSET_ASSETCONCEPTS_HPP
|
||||
#define BIGFOOT_ENGINE_ASSET_ASSETCONCEPTS_HPP
|
||||
#include <Engine/Asset/AssetTypeID.hpp>
|
||||
|
||||
#include <System/UUID/UUID.hpp>
|
||||
|
||||
#include <concepts>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
class AssetBase;
|
||||
|
||||
/**
|
||||
* The traits struct passed to Asset<TRAITS> (e.g. AssetATraits).
|
||||
* Must name the generated flatbuffers table type for the asset.
|
||||
*/
|
||||
template<class TRAITS>
|
||||
concept AssetTraits = requires {
|
||||
typename TRAITS::FLAT;
|
||||
typename TRAITS::FLAT::NativeTableType;
|
||||
{ TRAITS::FLAT::GetFullyQualifiedName() } -> std::convertible_to<const char*>;
|
||||
};
|
||||
|
||||
/**
|
||||
* A concrete Asset type (e.g. AssetA), usable with AssetContainer, AssetLibrary and References.
|
||||
*/
|
||||
template<class ASSET>
|
||||
concept AssetType = std::derived_from<ASSET, AssetBase> && !std::same_as<ASSET, AssetBase> &&
|
||||
requires(const ASSET& p_asset) {
|
||||
{ ASSET::GetTypeID() } -> std::convertible_to<AssetTypeID>;
|
||||
{ p_asset.GetHeader().uuid } -> std::convertible_to<UUID>;
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
#endif
|
||||
@@ -0,0 +1,355 @@
|
||||
/*********************************************************************
|
||||
* \file AssetContainer.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date May 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_ENGINE_ASSET_ASSETCONTAINER_HPP
|
||||
#define BIGFOOT_ENGINE_ASSET_ASSETCONTAINER_HPP
|
||||
#include <Engine/Asset/Asset.hpp>
|
||||
#include <Engine/Asset/AssetConcepts.hpp>
|
||||
#include <Engine/EngineAssertHandler.hpp>
|
||||
|
||||
#include <Utils/Containers/SlotMap.hpp>
|
||||
|
||||
#include <ankerl/unordered_dense.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
/**
|
||||
* An indirection that allows References to immediately get the asset, without fetching the actual container
|
||||
*/
|
||||
class ContainerHandle
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Get the HardRef count
|
||||
*
|
||||
* \return The HardRef count.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
std::uint32_t GetHardRefCount() const
|
||||
{
|
||||
return m_hardRefCount;
|
||||
}
|
||||
|
||||
/*
|
||||
* Increment the HardRef count
|
||||
*
|
||||
*/
|
||||
void IncrementHardRefCount()
|
||||
{
|
||||
++m_hardRefCount;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrement the HardRef count
|
||||
*
|
||||
*/
|
||||
void DecrementHardRefCount()
|
||||
{
|
||||
--m_hardRefCount;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the SoftRef count
|
||||
*
|
||||
* \return The SoftRef count.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
std::uint32_t GetSoftRefCount() const
|
||||
{
|
||||
return m_softRefCount;
|
||||
}
|
||||
|
||||
/*
|
||||
* Increment the SoftRef count
|
||||
*
|
||||
*/
|
||||
void IncrementSoftRefCount()
|
||||
{
|
||||
++m_softRefCount;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrement the SoftRef count
|
||||
*
|
||||
*/
|
||||
void DecrementSoftRefCount()
|
||||
{
|
||||
--m_softRefCount;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the Asset
|
||||
*
|
||||
* \return The asset, can be nullptr
|
||||
*/
|
||||
[[nodiscard]]
|
||||
AssetBase* GetAsset()
|
||||
{
|
||||
return m_asset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the Asset
|
||||
*
|
||||
* \return The asset
|
||||
*/
|
||||
[[nodiscard]]
|
||||
const AssetBase* GetAsset() const
|
||||
{
|
||||
return m_asset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the asset
|
||||
*
|
||||
* \param p_asset The asset
|
||||
*/
|
||||
void SetAsset(AssetBase* p_asset)
|
||||
{
|
||||
m_asset = p_asset;
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
* The HardRef count
|
||||
*/
|
||||
std::uint32_t m_hardRefCount = 0;
|
||||
|
||||
/*
|
||||
* The SoftRef count
|
||||
*/
|
||||
std::uint32_t m_softRefCount = 0;
|
||||
|
||||
/*
|
||||
* The asset
|
||||
*/
|
||||
AssetBase* m_asset = nullptr;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
class AssetContainerBase
|
||||
{
|
||||
using SlotMap = StableSlotMap<ContainerHandle>;
|
||||
using SlotMapKey = SlotMap::SlotMapKey;
|
||||
|
||||
public:
|
||||
virtual ~AssetContainerBase() = default;
|
||||
|
||||
/*
|
||||
* Check if an Asset is in the AssetContainer or not
|
||||
*
|
||||
* \param p_uuid The UUID to check
|
||||
* \return True if in AssetContainer, false otherwise
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool Has(const UUID& p_uuid) const
|
||||
{
|
||||
const Entry* entry = FindEntry(p_uuid);
|
||||
return entry != nullptr && entry->m_assetSlotKey.Valid();
|
||||
}
|
||||
|
||||
/*
|
||||
* Acquires a ContainerHandle for a given UUID
|
||||
* Will create it if it does not exists
|
||||
*
|
||||
* \param p_uuid The UUID to get ContainerHandle for
|
||||
* \return A ContainerHandle for the UUID
|
||||
*/
|
||||
[[nodiscard]]
|
||||
ContainerHandle* AcquireContainerHandle(const UUID& p_uuid)
|
||||
{
|
||||
return GetOrCreateEntry(p_uuid).m_handle;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove an Asset from the AssetContainer
|
||||
*
|
||||
* \param p_uuid The UUID to remove
|
||||
*/
|
||||
virtual void Remove(const UUID& p_uuid)
|
||||
{
|
||||
if (Entry* entry = FindEntry(p_uuid); entry != nullptr)
|
||||
{
|
||||
m_handles.Remove(entry->m_handleSlotKey);
|
||||
m_uuidToEntry.erase(p_uuid);
|
||||
}
|
||||
}
|
||||
|
||||
AssetContainerBase& operator=(AssetContainerBase&& p_container) = delete;
|
||||
|
||||
protected:
|
||||
struct Entry
|
||||
{
|
||||
/*
|
||||
* SlotMapKey to the handle
|
||||
*/
|
||||
SlotMapKey m_handleSlotKey;
|
||||
|
||||
/*
|
||||
* SlotMapKey to the asset
|
||||
*/
|
||||
SlotMapKey m_assetSlotKey;
|
||||
|
||||
/*
|
||||
* The handle itself, cached to avoid a SlotMap lookup on every access
|
||||
*/
|
||||
ContainerHandle* m_handle = nullptr;
|
||||
};
|
||||
|
||||
AssetContainerBase() = default;
|
||||
|
||||
AssetContainerBase(AssetContainerBase&& p_container) = delete;
|
||||
|
||||
/*
|
||||
* Finds an entry matching the Asset
|
||||
*
|
||||
* \param p_uuid The UUID to find
|
||||
* \return Pointer to an Entry, nullptr otherwise
|
||||
*/
|
||||
[[nodiscard]]
|
||||
Entry* FindEntry(const UUID& p_uuid)
|
||||
{
|
||||
const auto it = m_uuidToEntry.find(p_uuid);
|
||||
return it != m_uuidToEntry.end() ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds an entry matching the Asset
|
||||
*
|
||||
* \param p_uuid The UUID to find
|
||||
* \return Pointer to an Entry, nullptr otherwise
|
||||
*/
|
||||
[[nodiscard]]
|
||||
const Entry* FindEntry(const UUID& p_uuid) const
|
||||
{
|
||||
const auto it = m_uuidToEntry.find(p_uuid);
|
||||
return it != m_uuidToEntry.end() ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds an entry matching the Asset
|
||||
* Creates it if it does not exist
|
||||
*
|
||||
* \param p_uuid The UUID to find
|
||||
* \return The entry matching the Asset
|
||||
*/
|
||||
[[nodiscard]]
|
||||
Entry& GetOrCreateEntry(const UUID& p_uuid)
|
||||
{
|
||||
auto [it, inserted] = m_uuidToEntry.try_emplace(p_uuid);
|
||||
if (inserted)
|
||||
{
|
||||
it->second.m_handleSlotKey = m_handles.Insert();
|
||||
it->second.m_handle = m_handles.Get(it->second.m_handleSlotKey);
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
* HandleContainers
|
||||
*/
|
||||
SlotMap m_handles;
|
||||
|
||||
/*
|
||||
* Every Asset added to the map
|
||||
*/
|
||||
ankerl::unordered_dense::map<UUID, Entry> m_uuidToEntry;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
template<class ASSET>
|
||||
requires AssetType<ASSET>
|
||||
class AssetContainer: public AssetContainerBase
|
||||
{
|
||||
using SlotMap = StableSlotMap<ASSET>;
|
||||
using SlotMapKey = SlotMap::SlotMapKey;
|
||||
|
||||
public:
|
||||
/*
|
||||
* Inserts an Asset to the AssetContainer
|
||||
*
|
||||
* \tparam ARGS Arguments to construct the asset
|
||||
* \param p_args The arguments
|
||||
* \return The key to the inserted asset.
|
||||
*/
|
||||
template<class... ARGS>
|
||||
[[nodiscard]]
|
||||
SlotMapKey Insert(ARGS&&... p_args)
|
||||
{
|
||||
SlotMapKey slotKey = m_assets.Insert(std::forward<ARGS>(p_args)...);
|
||||
ASSET* asset = m_assets.Get(slotKey);
|
||||
|
||||
Entry& entry = GetOrCreateEntry(asset->GetHeader().uuid);
|
||||
if (entry.m_assetSlotKey.Valid())
|
||||
{
|
||||
m_assets.Remove(slotKey);
|
||||
slotKey = entry.m_assetSlotKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.m_assetSlotKey = slotKey;
|
||||
entry.m_handle->SetAsset(asset);
|
||||
}
|
||||
|
||||
return slotKey;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the Asset
|
||||
*
|
||||
* \param p_key The key to the asset
|
||||
* \return Pointer to the Asset
|
||||
*/
|
||||
[[nodiscard]]
|
||||
ASSET* Get(const SlotMapKey p_key)
|
||||
{
|
||||
return m_assets.Get(p_key);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the Asset
|
||||
*
|
||||
* \param p_key The key to the asset
|
||||
* \return Pointer to the Asset
|
||||
*/
|
||||
[[nodiscard]]
|
||||
const ASSET* Get(const SlotMapKey p_key) const
|
||||
{
|
||||
return m_assets.Get(p_key);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove an Asset from the AssetContainer
|
||||
*
|
||||
* \param p_uuid The UUID to remove
|
||||
*/
|
||||
void Remove(const UUID& p_uuid) override
|
||||
{
|
||||
if (Entry* entry = FindEntry(p_uuid); entry != nullptr && entry->m_assetSlotKey.Valid())
|
||||
{
|
||||
entry->m_handle->SetAsset(nullptr);
|
||||
m_assets.Remove(entry->m_assetSlotKey);
|
||||
entry->m_assetSlotKey = SlotMapKey {};
|
||||
}
|
||||
|
||||
AssetContainerBase::Remove(p_uuid);
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
* The assets
|
||||
*/
|
||||
SlotMap m_assets;
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
/*********************************************************************
|
||||
* \file AssetHelper.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date April 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_ENGINE_ASSET_ASSETHELPER_HPP
|
||||
#define BIGFOOT_ENGINE_ASSET_ASSETHELPER_HPP
|
||||
#include <Engine/Asset/AssetContainer.hpp>
|
||||
#include <Engine/Asset/AssetLibrary.hpp>
|
||||
#include <Engine/Asset/Reference.hpp>
|
||||
|
||||
#define BIGFOOT_ASSET(AssetName, AssetType) \
|
||||
namespace Bigfoot \
|
||||
{ \
|
||||
template<> \
|
||||
AssetTypeID GetAssetTypeID<AssetType>() \
|
||||
{ \
|
||||
return AssetType::GetTypeID(); \
|
||||
} \
|
||||
AssetContainer<AssetType> g_containerFor##AssetName; \
|
||||
const bool g_insertedContainerFor##AssetName = g_assetLibrary.Insert(&g_containerFor##AssetName); \
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,135 @@
|
||||
/*********************************************************************
|
||||
* \file AssetLibrary.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date July 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_ENGINE_ASSET_ASSETLIBRARY_HPP
|
||||
#define BIGFOOT_ENGINE_ASSET_ASSETLIBRARY_HPP
|
||||
#include <Engine/Asset/AssetConcepts.hpp>
|
||||
#include <Engine/Asset/AssetContainer.hpp>
|
||||
#include <Engine/Asset/AssetTypeID.hpp>
|
||||
|
||||
#include <ankerl/unordered_dense.h>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
class AssetLibrary
|
||||
{
|
||||
public:
|
||||
AssetLibrary() = default;
|
||||
|
||||
AssetLibrary(const AssetLibrary& p_library) = default;
|
||||
AssetLibrary(AssetLibrary&& p_library) = delete;
|
||||
|
||||
/**
|
||||
* Insert an AssetContainer pointer to the library
|
||||
*
|
||||
* \tparam ASSET The Asset type
|
||||
* \param p_assetContainer The asset container
|
||||
* \return The AssetContainer for the Asset type. Nullptr if not found
|
||||
*/
|
||||
template<class ASSET>
|
||||
requires AssetType<ASSET>
|
||||
[[nodiscard]]
|
||||
bool Insert(AssetContainer<ASSET>* p_assetContainer)
|
||||
{
|
||||
static const AssetTypeID typeID = ASSET::GetTypeID();
|
||||
if (m_assetContainers.contains(typeID))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto inserted = m_assetContainers.emplace(typeID, p_assetContainer);
|
||||
|
||||
return inserted.second;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the AssetContainer for a given AssetType
|
||||
*
|
||||
* \param p_typeID The asset type ID
|
||||
* \return The AssetContainer for the AssetType. Nullptr if not found
|
||||
*/
|
||||
[[nodiscard]]
|
||||
AssetContainerBase* GetAssetContainer(const AssetTypeID p_typeID)
|
||||
{
|
||||
if (const auto container = m_assetContainers.find(p_typeID); container != m_assetContainers.end())
|
||||
{
|
||||
return container->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the AssetContainer for a given AssetType
|
||||
*
|
||||
* \param p_typeID The asset type ID
|
||||
* \return The AssetContainer for the AssetType. Nullptr if not found
|
||||
*/
|
||||
[[nodiscard]]
|
||||
const AssetContainerBase* GetAssetContainer(const AssetTypeID p_typeID) const
|
||||
{
|
||||
if (const auto container = m_assetContainers.find(p_typeID); container != m_assetContainers.end())
|
||||
{
|
||||
return container->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AssetLibrary& operator=(const AssetLibrary& p_library) = default;
|
||||
AssetLibrary& operator=(AssetLibrary&& p_library) = delete;
|
||||
|
||||
private:
|
||||
// All the asset containers
|
||||
ankerl::unordered_dense::map<AssetTypeID, AssetContainerBase*> m_assetContainers;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
// The global asset library for Bigfoot
|
||||
inline AssetLibrary g_assetLibrary;
|
||||
inline AssetLibrary* g_activeAssetLibrary = &g_assetLibrary;
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
/*
|
||||
* Set the active asset library
|
||||
*
|
||||
* \param p_assetLibrary The asset library to set g_activeAssetLibrary to.
|
||||
*/
|
||||
void SetActiveAssetLibrary(AssetLibrary* p_assetLibrary);
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
class ScopedActiveAssetLibrary
|
||||
{
|
||||
public:
|
||||
ScopedActiveAssetLibrary(AssetLibrary* p_assetLibrary):
|
||||
m_previous(g_activeAssetLibrary)
|
||||
{
|
||||
SetActiveAssetLibrary(p_assetLibrary);
|
||||
}
|
||||
|
||||
ScopedActiveAssetLibrary(const ScopedActiveAssetLibrary& p_scopedActiveAssetLibrary) = delete;
|
||||
ScopedActiveAssetLibrary(ScopedActiveAssetLibrary&& p_scopedActiveAssetLibrary) = delete;
|
||||
|
||||
~ScopedActiveAssetLibrary()
|
||||
{
|
||||
SetActiveAssetLibrary(m_previous);
|
||||
}
|
||||
|
||||
ScopedActiveAssetLibrary& operator=(const ScopedActiveAssetLibrary& p_scopedActiveAssetLibrary) = delete;
|
||||
ScopedActiveAssetLibrary& operator=(ScopedActiveAssetLibrary&& p_scopedActiveAssetLibrary) = delete;
|
||||
|
||||
private:
|
||||
/*
|
||||
* The previously active asset library.
|
||||
*/
|
||||
AssetLibrary* m_previous = nullptr;
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
native_include "Engine/Asset/AssetTypeID.hpp";
|
||||
|
||||
namespace Flat.Bigfoot;
|
||||
|
||||
struct AssetTypeID (native_type: "::Bigfoot::AssetTypeID")
|
||||
{
|
||||
value: ulong;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*********************************************************************
|
||||
* \file AssetTypeID.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date February 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_ENGINE_ASSET_ASSETTYPEID_HPP
|
||||
#define BIGFOOT_ENGINE_ASSET_ASSETTYPEID_HPP
|
||||
#include <cstdint>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
using AssetTypeID = std::uint64_t;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
namespace Flat
|
||||
{
|
||||
namespace Bigfoot
|
||||
{
|
||||
struct AssetTypeID;
|
||||
}
|
||||
} // namespace Flat
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
namespace flatbuffers
|
||||
{
|
||||
Flat::Bigfoot::AssetTypeID Pack(const Bigfoot::AssetTypeID& p_assetTypeID);
|
||||
Bigfoot::AssetTypeID UnPack(const Flat::Bigfoot::AssetTypeID& p_flatAssetTypeID);
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
|
||||
#ifndef FLATBUFFERS_GENERATED_ASSETTYPEID_FLAT_BIGFOOT_H_
|
||||
#define FLATBUFFERS_GENERATED_ASSETTYPEID_FLAT_BIGFOOT_H_
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
|
||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||
// generated, otherwise it may not be compatible.
|
||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 19,
|
||||
"Non-compatible flatbuffers version included");
|
||||
// Ensure the included flatbuffers.h is Bigfoot's fork - stock
|
||||
// flatbuffers (or a differently versioned Bigfoot fork) is not compatible.
|
||||
#ifndef FLATBUFFERS_BIGFOOT_VERSION
|
||||
#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible"
|
||||
#endif
|
||||
static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1,
|
||||
"Non-compatible Bigfoot flatbuffers fork version included");
|
||||
|
||||
#include "Engine/Asset/AssetTypeID.hpp"
|
||||
|
||||
#include "EASTL/unique_ptr.h"
|
||||
#include "EASTL/string.h"
|
||||
#include "EASTL/vector.h"
|
||||
|
||||
namespace Flat {
|
||||
namespace Bigfoot {
|
||||
|
||||
struct AssetTypeID;
|
||||
|
||||
inline const ::flatbuffers::TypeTable *AssetTypeIDTypeTable();
|
||||
|
||||
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) AssetTypeID FLATBUFFERS_FINAL_CLASS {
|
||||
private:
|
||||
uint64_t value_;
|
||||
|
||||
public:
|
||||
struct Traits;
|
||||
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
return AssetTypeIDTypeTable();
|
||||
}
|
||||
static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() {
|
||||
return "Flat.Bigfoot.AssetTypeID";
|
||||
}
|
||||
AssetTypeID()
|
||||
: value_(0) {
|
||||
}
|
||||
AssetTypeID(uint64_t _value)
|
||||
: value_(::flatbuffers::EndianScalar(_value)) {
|
||||
}
|
||||
uint64_t value() const {
|
||||
return ::flatbuffers::EndianScalar(value_);
|
||||
}
|
||||
};
|
||||
FLATBUFFERS_STRUCT_END(AssetTypeID, 8);
|
||||
|
||||
struct AssetTypeID::Traits {
|
||||
using type = AssetTypeID;
|
||||
};
|
||||
|
||||
inline const ::flatbuffers::TypeTable *AssetTypeIDTypeTable() {
|
||||
static const ::flatbuffers::TypeCode type_codes[] = {
|
||||
{ ::flatbuffers::ET_ULONG, 0, -1 }
|
||||
};
|
||||
static const int64_t values[] = { 0, 8 };
|
||||
static const ::flatbuffers::TypeTable tt = {
|
||||
::flatbuffers::ST_STRUCT, 1, type_codes, nullptr, nullptr, values, nullptr
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
|
||||
} // namespace Bigfoot
|
||||
} // namespace Flat
|
||||
|
||||
#endif // FLATBUFFERS_GENERATED_ASSETTYPEID_FLAT_BIGFOOT_H_
|
||||
@@ -0,0 +1,413 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
|
||||
#ifndef FLATBUFFERS_GENERATED_ASSET_FLAT_BIGFOOT_H_
|
||||
#define FLATBUFFERS_GENERATED_ASSET_FLAT_BIGFOOT_H_
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
|
||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||
// generated, otherwise it may not be compatible.
|
||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 19,
|
||||
"Non-compatible flatbuffers version included");
|
||||
// Ensure the included flatbuffers.h is Bigfoot's fork - stock
|
||||
// flatbuffers (or a differently versioned Bigfoot fork) is not compatible.
|
||||
#ifndef FLATBUFFERS_BIGFOOT_VERSION
|
||||
#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible"
|
||||
#endif
|
||||
static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1,
|
||||
"Non-compatible Bigfoot flatbuffers fork version included");
|
||||
|
||||
#include "Engine/Asset/AssetTypeID.hpp"
|
||||
#include "System/UUID/UUID.hpp"
|
||||
#include "Engine/Asset/AssetTypeID_generated.hpp"
|
||||
#include "System/UUID/UUID_generated.hpp"
|
||||
|
||||
#include "EASTL/unique_ptr.h"
|
||||
#include "EASTL/string.h"
|
||||
#include "EASTL/vector.h"
|
||||
|
||||
namespace Flat {
|
||||
namespace Bigfoot {
|
||||
|
||||
struct AssetHeader;
|
||||
struct AssetHeaderBuilder;
|
||||
struct AssetHeaderT;
|
||||
|
||||
struct Asset;
|
||||
struct AssetBuilder;
|
||||
struct AssetT;
|
||||
|
||||
inline const ::flatbuffers::TypeTable *AssetHeaderTypeTable();
|
||||
|
||||
inline const ::flatbuffers::TypeTable *AssetTypeTable();
|
||||
|
||||
struct AssetHeaderT : public ::flatbuffers::NativeTable {
|
||||
typedef AssetHeader TableType;
|
||||
static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() {
|
||||
return "Flat.Bigfoot.AssetHeaderT";
|
||||
}
|
||||
::Bigfoot::UUID uuid{};
|
||||
eastl::string name{};
|
||||
::Bigfoot::AssetTypeID type_id{};
|
||||
eastl::string type_name{};
|
||||
uint32_t version = 0;
|
||||
};
|
||||
|
||||
struct AssetHeader FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||
typedef AssetHeaderT NativeTableType;
|
||||
typedef AssetHeaderBuilder Builder;
|
||||
struct Traits;
|
||||
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
return AssetHeaderTypeTable();
|
||||
}
|
||||
static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() {
|
||||
return "Flat.Bigfoot.AssetHeader";
|
||||
}
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_UUID = 4,
|
||||
VT_NAME = 6,
|
||||
VT_TYPE_ID = 8,
|
||||
VT_TYPE_NAME = 10,
|
||||
VT_VERSION = 12
|
||||
};
|
||||
const Flat::Bigfoot::UUID *uuid() const {
|
||||
return GetStruct<const Flat::Bigfoot::UUID *>(VT_UUID);
|
||||
}
|
||||
const ::flatbuffers::String *name() const {
|
||||
return GetPointer<const ::flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
const Flat::Bigfoot::AssetTypeID *type_id() const {
|
||||
return GetStruct<const Flat::Bigfoot::AssetTypeID *>(VT_TYPE_ID);
|
||||
}
|
||||
const ::flatbuffers::String *type_name() const {
|
||||
return GetPointer<const ::flatbuffers::String *>(VT_TYPE_NAME);
|
||||
}
|
||||
uint32_t version() const {
|
||||
return GetField<uint32_t>(VT_VERSION, 0);
|
||||
}
|
||||
template <bool B = false>
|
||||
bool Verify(::flatbuffers::VerifierTemplate<B> &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyFieldRequired<Flat::Bigfoot::UUID>(verifier, VT_UUID, 1) &&
|
||||
VerifyOffsetRequired(verifier, VT_NAME) &&
|
||||
verifier.VerifyString(name()) &&
|
||||
VerifyFieldRequired<Flat::Bigfoot::AssetTypeID>(verifier, VT_TYPE_ID, 8) &&
|
||||
VerifyOffsetRequired(verifier, VT_TYPE_NAME) &&
|
||||
verifier.VerifyString(type_name()) &&
|
||||
VerifyField<uint32_t>(verifier, VT_VERSION, 4) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
AssetHeaderT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||
void UnPackTo(AssetHeaderT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||
static ::flatbuffers::Offset<AssetHeader> Pack(::flatbuffers::FlatBufferBuilder &_fbb, const AssetHeaderT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
};
|
||||
|
||||
struct AssetHeaderBuilder {
|
||||
typedef AssetHeader Table;
|
||||
::flatbuffers::FlatBufferBuilder &fbb_;
|
||||
::flatbuffers::uoffset_t start_;
|
||||
void add_uuid(const Flat::Bigfoot::UUID *uuid) {
|
||||
fbb_.AddStruct(AssetHeader::VT_UUID, uuid);
|
||||
}
|
||||
void add_name(::flatbuffers::Offset<::flatbuffers::String> name) {
|
||||
fbb_.AddOffset(AssetHeader::VT_NAME, name);
|
||||
}
|
||||
void add_type_id(const Flat::Bigfoot::AssetTypeID *type_id) {
|
||||
fbb_.AddStruct(AssetHeader::VT_TYPE_ID, type_id);
|
||||
}
|
||||
void add_type_name(::flatbuffers::Offset<::flatbuffers::String> type_name) {
|
||||
fbb_.AddOffset(AssetHeader::VT_TYPE_NAME, type_name);
|
||||
}
|
||||
void add_version(uint32_t version) {
|
||||
fbb_.AddElement<uint32_t>(AssetHeader::VT_VERSION, version, 0);
|
||||
}
|
||||
explicit AssetHeaderBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
::flatbuffers::Offset<AssetHeader> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = ::flatbuffers::Offset<AssetHeader>(end);
|
||||
fbb_.Required(o, AssetHeader::VT_UUID);
|
||||
fbb_.Required(o, AssetHeader::VT_NAME);
|
||||
fbb_.Required(o, AssetHeader::VT_TYPE_ID);
|
||||
fbb_.Required(o, AssetHeader::VT_TYPE_NAME);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline ::flatbuffers::Offset<AssetHeader> CreateAssetHeader(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const Flat::Bigfoot::UUID *uuid = nullptr,
|
||||
::flatbuffers::Offset<::flatbuffers::String> name = 0,
|
||||
const Flat::Bigfoot::AssetTypeID *type_id = nullptr,
|
||||
::flatbuffers::Offset<::flatbuffers::String> type_name = 0,
|
||||
uint32_t version = 0) {
|
||||
AssetHeaderBuilder builder_(_fbb);
|
||||
builder_.add_version(version);
|
||||
builder_.add_type_name(type_name);
|
||||
builder_.add_type_id(type_id);
|
||||
builder_.add_name(name);
|
||||
builder_.add_uuid(uuid);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
struct AssetHeader::Traits {
|
||||
using type = AssetHeader;
|
||||
static auto constexpr Create = CreateAssetHeader;
|
||||
};
|
||||
|
||||
::flatbuffers::Offset<AssetHeader> CreateAssetHeader(::flatbuffers::FlatBufferBuilder &_fbb, const AssetHeaderT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
|
||||
struct AssetT : public ::flatbuffers::NativeTable {
|
||||
typedef Asset TableType;
|
||||
static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() {
|
||||
return "Flat.Bigfoot.AssetT";
|
||||
}
|
||||
eastl::unique_ptr<Flat::Bigfoot::AssetHeaderT> header{new Flat::Bigfoot::AssetHeaderT()};
|
||||
eastl::vector<uint8_t> inner_asset{};
|
||||
AssetT() = default;
|
||||
AssetT(const AssetT &o);
|
||||
AssetT(AssetT&&) FLATBUFFERS_NOEXCEPT = default;
|
||||
AssetT &operator=(AssetT o) FLATBUFFERS_NOEXCEPT;
|
||||
};
|
||||
|
||||
struct Asset FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||
typedef AssetT NativeTableType;
|
||||
typedef AssetBuilder Builder;
|
||||
struct Traits;
|
||||
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
return AssetTypeTable();
|
||||
}
|
||||
static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() {
|
||||
return "Flat.Bigfoot.Asset";
|
||||
}
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_HEADER = 4,
|
||||
VT_INNER_ASSET = 6
|
||||
};
|
||||
const Flat::Bigfoot::AssetHeader *header() const {
|
||||
return GetPointer<const Flat::Bigfoot::AssetHeader *>(VT_HEADER);
|
||||
}
|
||||
const ::flatbuffers::Vector<uint8_t> *inner_asset() const {
|
||||
return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_INNER_ASSET);
|
||||
}
|
||||
template <bool B = false>
|
||||
bool Verify(::flatbuffers::VerifierTemplate<B> &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyOffsetRequired(verifier, VT_HEADER) &&
|
||||
verifier.VerifyTable(header()) &&
|
||||
VerifyOffsetRequired(verifier, VT_INNER_ASSET) &&
|
||||
verifier.VerifyVector(inner_asset()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
AssetT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||
void UnPackTo(AssetT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||
static ::flatbuffers::Offset<Asset> Pack(::flatbuffers::FlatBufferBuilder &_fbb, const AssetT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
};
|
||||
|
||||
struct AssetBuilder {
|
||||
typedef Asset Table;
|
||||
::flatbuffers::FlatBufferBuilder &fbb_;
|
||||
::flatbuffers::uoffset_t start_;
|
||||
void add_header(::flatbuffers::Offset<Flat::Bigfoot::AssetHeader> header) {
|
||||
fbb_.AddOffset(Asset::VT_HEADER, header);
|
||||
}
|
||||
void add_inner_asset(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> inner_asset) {
|
||||
fbb_.AddOffset(Asset::VT_INNER_ASSET, inner_asset);
|
||||
}
|
||||
explicit AssetBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
::flatbuffers::Offset<Asset> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = ::flatbuffers::Offset<Asset>(end);
|
||||
fbb_.Required(o, Asset::VT_HEADER);
|
||||
fbb_.Required(o, Asset::VT_INNER_ASSET);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline ::flatbuffers::Offset<Asset> CreateAsset(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
::flatbuffers::Offset<Flat::Bigfoot::AssetHeader> header = 0,
|
||||
::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> inner_asset = 0) {
|
||||
AssetBuilder builder_(_fbb);
|
||||
builder_.add_inner_asset(inner_asset);
|
||||
builder_.add_header(header);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
struct Asset::Traits {
|
||||
using type = Asset;
|
||||
static auto constexpr Create = CreateAsset;
|
||||
};
|
||||
|
||||
::flatbuffers::Offset<Asset> CreateAsset(::flatbuffers::FlatBufferBuilder &_fbb, const AssetT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
|
||||
inline AssetHeaderT *AssetHeader::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const {
|
||||
auto _o = std::make_unique<AssetHeaderT>();
|
||||
UnPackTo(_o.get(), _resolver);
|
||||
return _o.release();
|
||||
}
|
||||
|
||||
inline void AssetHeader::UnPackTo(AssetHeaderT *_o, const ::flatbuffers::resolver_function_t *_resolver) const {
|
||||
(void)_o;
|
||||
(void)_resolver;
|
||||
{ auto _e = uuid(); if (_e) _o->uuid = ::flatbuffers::UnPack(*_e); }
|
||||
{ auto _e = name(); if (_e) _o->name = eastl::string(_e->c_str(), _e->size()); }
|
||||
{ auto _e = type_id(); if (_e) _o->type_id = ::flatbuffers::UnPack(*_e); }
|
||||
{ auto _e = type_name(); if (_e) _o->type_name = eastl::string(_e->c_str(), _e->size()); }
|
||||
{ auto _e = version(); _o->version = _e; }
|
||||
}
|
||||
|
||||
inline ::flatbuffers::Offset<AssetHeader> CreateAssetHeader(::flatbuffers::FlatBufferBuilder &_fbb, const AssetHeaderT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
||||
return AssetHeader::Pack(_fbb, _o, _rehasher);
|
||||
}
|
||||
|
||||
inline ::flatbuffers::Offset<AssetHeader> AssetHeader::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const AssetHeaderT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
||||
(void)_rehasher;
|
||||
(void)_o;
|
||||
struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const AssetHeaderT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
|
||||
auto _uuid = ::flatbuffers::Pack(_o->uuid);
|
||||
auto _name = _fbb.CreateString(_o->name);
|
||||
auto _type_id = ::flatbuffers::Pack(_o->type_id);
|
||||
auto _type_name = _fbb.CreateString(_o->type_name);
|
||||
auto _version = _o->version;
|
||||
return Flat::Bigfoot::CreateAssetHeader(
|
||||
_fbb,
|
||||
&_uuid,
|
||||
_name,
|
||||
&_type_id,
|
||||
_type_name,
|
||||
_version);
|
||||
}
|
||||
|
||||
inline AssetT::AssetT(const AssetT &o)
|
||||
: header((o.header) ? new Flat::Bigfoot::AssetHeaderT(*o.header) : nullptr),
|
||||
inner_asset(o.inner_asset) {
|
||||
}
|
||||
|
||||
inline AssetT &AssetT::operator=(AssetT o) FLATBUFFERS_NOEXCEPT {
|
||||
std::swap(header, o.header);
|
||||
std::swap(inner_asset, o.inner_asset);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline AssetT *Asset::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const {
|
||||
auto _o = std::make_unique<AssetT>();
|
||||
UnPackTo(_o.get(), _resolver);
|
||||
return _o.release();
|
||||
}
|
||||
|
||||
inline void Asset::UnPackTo(AssetT *_o, const ::flatbuffers::resolver_function_t *_resolver) const {
|
||||
(void)_o;
|
||||
(void)_resolver;
|
||||
{ auto _e = header(); if (_e) { if(_o->header) { _e->UnPackTo(_o->header.get(), _resolver); } else { _o->header = eastl::unique_ptr<Flat::Bigfoot::AssetHeaderT>(_e->UnPack(_resolver)); } } else if (_o->header) { _o->header.reset(); } }
|
||||
{ auto _e = inner_asset(); if (_e) { _o->inner_asset.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->inner_asset.begin()); } }
|
||||
}
|
||||
|
||||
inline ::flatbuffers::Offset<Asset> CreateAsset(::flatbuffers::FlatBufferBuilder &_fbb, const AssetT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
||||
return Asset::Pack(_fbb, _o, _rehasher);
|
||||
}
|
||||
|
||||
inline ::flatbuffers::Offset<Asset> Asset::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const AssetT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
||||
(void)_rehasher;
|
||||
(void)_o;
|
||||
struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const AssetT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
|
||||
auto _header = _o->header ? CreateAssetHeader(_fbb, _o->header.get(), _rehasher) : 0;
|
||||
auto _inner_asset = _fbb.CreateVector(_o->inner_asset.data(), _o->inner_asset.size());
|
||||
return Flat::Bigfoot::CreateAsset(
|
||||
_fbb,
|
||||
_header,
|
||||
_inner_asset);
|
||||
}
|
||||
|
||||
inline const ::flatbuffers::TypeTable *AssetHeaderTypeTable() {
|
||||
static const ::flatbuffers::TypeCode type_codes[] = {
|
||||
{ ::flatbuffers::ET_SEQUENCE, 0, 0 },
|
||||
{ ::flatbuffers::ET_STRING, 0, -1 },
|
||||
{ ::flatbuffers::ET_SEQUENCE, 0, 1 },
|
||||
{ ::flatbuffers::ET_STRING, 0, -1 },
|
||||
{ ::flatbuffers::ET_UINT, 0, -1 }
|
||||
};
|
||||
static const ::flatbuffers::TypeFunction type_refs[] = {
|
||||
Flat::Bigfoot::UUIDTypeTable,
|
||||
Flat::Bigfoot::AssetTypeIDTypeTable
|
||||
};
|
||||
static const ::flatbuffers::TypeTable tt = {
|
||||
::flatbuffers::ST_TABLE, 5, type_codes, type_refs, nullptr, nullptr, nullptr
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
|
||||
inline const ::flatbuffers::TypeTable *AssetTypeTable() {
|
||||
static const ::flatbuffers::TypeCode type_codes[] = {
|
||||
{ ::flatbuffers::ET_SEQUENCE, 0, 0 },
|
||||
{ ::flatbuffers::ET_UCHAR, 1, -1 }
|
||||
};
|
||||
static const ::flatbuffers::TypeFunction type_refs[] = {
|
||||
Flat::Bigfoot::AssetHeaderTypeTable
|
||||
};
|
||||
static const ::flatbuffers::TypeTable tt = {
|
||||
::flatbuffers::ST_TABLE, 2, type_codes, type_refs, nullptr, nullptr, nullptr
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
|
||||
inline const Flat::Bigfoot::Asset *GetAsset(const void *buf) {
|
||||
return ::flatbuffers::GetRoot<Flat::Bigfoot::Asset>(buf);
|
||||
}
|
||||
|
||||
inline const Flat::Bigfoot::Asset *GetSizePrefixedAsset(const void *buf) {
|
||||
return ::flatbuffers::GetSizePrefixedRoot<Flat::Bigfoot::Asset>(buf);
|
||||
}
|
||||
|
||||
template <bool B = false>
|
||||
inline bool VerifyAssetBuffer(
|
||||
::flatbuffers::VerifierTemplate<B> &verifier) {
|
||||
return verifier.template VerifyBuffer<Flat::Bigfoot::Asset>(nullptr);
|
||||
}
|
||||
|
||||
template <bool B = false>
|
||||
inline bool VerifySizePrefixedAssetBuffer(
|
||||
::flatbuffers::VerifierTemplate<B> &verifier) {
|
||||
return verifier.template VerifySizePrefixedBuffer<Flat::Bigfoot::Asset>(nullptr);
|
||||
}
|
||||
|
||||
inline const char *AssetExtension() {
|
||||
return "bfbs";
|
||||
}
|
||||
|
||||
inline void FinishAssetBuffer(
|
||||
::flatbuffers::FlatBufferBuilder &fbb,
|
||||
::flatbuffers::Offset<Flat::Bigfoot::Asset> root) {
|
||||
fbb.Finish(root);
|
||||
}
|
||||
|
||||
inline void FinishSizePrefixedAssetBuffer(
|
||||
::flatbuffers::FlatBufferBuilder &fbb,
|
||||
::flatbuffers::Offset<Flat::Bigfoot::Asset> root) {
|
||||
fbb.FinishSizePrefixed(root);
|
||||
}
|
||||
|
||||
inline eastl::unique_ptr<Flat::Bigfoot::AssetT> UnPackAsset(
|
||||
const void *buf,
|
||||
const ::flatbuffers::resolver_function_t *res = nullptr) {
|
||||
return eastl::unique_ptr<Flat::Bigfoot::AssetT>(GetAsset(buf)->UnPack(res));
|
||||
}
|
||||
|
||||
inline eastl::unique_ptr<Flat::Bigfoot::AssetT> UnPackSizePrefixedAsset(
|
||||
const void *buf,
|
||||
const ::flatbuffers::resolver_function_t *res = nullptr) {
|
||||
return eastl::unique_ptr<Flat::Bigfoot::AssetT>(GetSizePrefixedAsset(buf)->UnPack(res));
|
||||
}
|
||||
|
||||
} // namespace Bigfoot
|
||||
} // namespace Flat
|
||||
|
||||
#endif // FLATBUFFERS_GENERATED_ASSET_FLAT_BIGFOOT_H_
|
||||
@@ -0,0 +1,15 @@
|
||||
include "System/UUID/UUID.fbs";
|
||||
|
||||
native_include "Engine/Asset/Reference.hpp";
|
||||
|
||||
namespace Flat.Bigfoot;
|
||||
|
||||
struct HardReference (bigfoot_ref_wrapper: "::Bigfoot::HardReference")
|
||||
{
|
||||
uuid: UUID;
|
||||
}
|
||||
|
||||
struct SoftReference (bigfoot_ref_wrapper: "::Bigfoot::SoftReference")
|
||||
{
|
||||
uuid: UUID;
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*********************************************************************
|
||||
* \file Reference.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date April 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_ENGINE_ASSET_REFERENCE_HPP
|
||||
#define BIGFOOT_ENGINE_ASSET_REFERENCE_HPP
|
||||
#include <Engine/Asset/AssetConcepts.hpp>
|
||||
#include <Engine/Asset/AssetLibrary.hpp>
|
||||
|
||||
#include <System/UUID/UUID.hpp>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
template<class ASSET>
|
||||
AssetTypeID GetAssetTypeID();
|
||||
|
||||
template<>
|
||||
AssetTypeID GetAssetTypeID<AssetBase>() = delete;
|
||||
|
||||
template<class DERIVED, class ASSET>
|
||||
class ReferenceBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Get the UUID of the reference
|
||||
*
|
||||
* \return The UUID of the reference
|
||||
*/
|
||||
[[nodiscard]]
|
||||
const UUID& GetUUID() const
|
||||
{
|
||||
return m_uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the asset
|
||||
*
|
||||
* \return The asset, nullptr if it is not loaded
|
||||
*/
|
||||
[[nodiscard]]
|
||||
const ASSET* Get() const
|
||||
{
|
||||
static_assert(AssetType<ASSET>, "ASSET must derive from AssetBase (and not be AssetBase itself)");
|
||||
return m_handle ? static_cast<const ASSET*>(m_handle->GetAsset()) : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the asset
|
||||
*
|
||||
* \return The asset, nullptr if it is not loaded
|
||||
*/
|
||||
[[nodiscard]]
|
||||
ASSET* Get()
|
||||
{
|
||||
static_assert(AssetType<ASSET>, "ASSET must derive from AssetBase (and not be AssetBase itself)");
|
||||
return m_handle ? static_cast<ASSET*>(m_handle->GetAsset()) : nullptr;
|
||||
}
|
||||
|
||||
~ReferenceBase()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
ReferenceBase& operator=(const ReferenceBase& p_reference)
|
||||
{
|
||||
if (this != &p_reference)
|
||||
{
|
||||
Release();
|
||||
m_uuid = p_reference.m_uuid;
|
||||
m_handle = p_reference.m_handle;
|
||||
Acquire();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ReferenceBase& operator=(ReferenceBase&& p_reference) noexcept
|
||||
{
|
||||
if (this != &p_reference)
|
||||
{
|
||||
Release();
|
||||
m_uuid = std::exchange(p_reference.m_uuid, UUID::NULL_UUID);
|
||||
m_handle = std::exchange(p_reference.m_handle, nullptr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
bool operator==(const ReferenceBase& p_reference) const
|
||||
{
|
||||
return m_uuid == p_reference.m_uuid;
|
||||
}
|
||||
|
||||
protected:
|
||||
ReferenceBase() = default;
|
||||
|
||||
ReferenceBase(const UUID& p_uuid):
|
||||
m_uuid(p_uuid)
|
||||
{
|
||||
Acquire();
|
||||
}
|
||||
|
||||
ReferenceBase(const ReferenceBase& p_reference):
|
||||
m_uuid(p_reference.m_uuid),
|
||||
m_handle(p_reference.m_handle)
|
||||
{
|
||||
Acquire();
|
||||
}
|
||||
|
||||
ReferenceBase(ReferenceBase&& p_reference) noexcept:
|
||||
m_uuid(std::exchange(p_reference.m_uuid, UUID::NULL_UUID)),
|
||||
m_handle(std::exchange(p_reference.m_handle, nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Get the associated handle container for the asset
|
||||
* Register the reference inside the handle
|
||||
*
|
||||
*/
|
||||
void Acquire()
|
||||
{
|
||||
if (!m_uuid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (AssetContainerBase* assetContainer = g_activeAssetLibrary->GetAssetContainer(GetAssetTypeID<ASSET>()))
|
||||
{
|
||||
if (!m_handle)
|
||||
{
|
||||
m_handle = assetContainer->AcquireContainerHandle(m_uuid);
|
||||
}
|
||||
DERIVED::IncrementCount(*m_handle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister the reference from the handle
|
||||
*
|
||||
*/
|
||||
void Release()
|
||||
{
|
||||
if (m_handle)
|
||||
{
|
||||
DERIVED::DecrementCount(*m_handle);
|
||||
m_handle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* The UUID
|
||||
*/
|
||||
UUID m_uuid = UUID::NULL_UUID;
|
||||
|
||||
/**
|
||||
* Handle for the asset
|
||||
*/
|
||||
ContainerHandle* m_handle = nullptr;
|
||||
};
|
||||
|
||||
/*
|
||||
* Owning reference
|
||||
* Keeps the asset alive
|
||||
*/
|
||||
template<class ASSET>
|
||||
class HardReference: public ReferenceBase<HardReference<ASSET>, ASSET>
|
||||
{
|
||||
using Base = ReferenceBase<HardReference<ASSET>, ASSET>;
|
||||
|
||||
public:
|
||||
HardReference() = default;
|
||||
|
||||
HardReference(const UUID& p_uuid):
|
||||
Base(p_uuid)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Increment the hard ref count of the handle
|
||||
*
|
||||
* \param p_handle The handle for the asset
|
||||
*/
|
||||
static void IncrementCount(ContainerHandle& p_handle)
|
||||
{
|
||||
p_handle.IncrementHardRefCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement the hard ref count of the handle
|
||||
*
|
||||
* \param p_handle The handle for the asset
|
||||
*/
|
||||
static void DecrementCount(ContainerHandle& p_handle)
|
||||
{
|
||||
p_handle.DecrementHardRefCount();
|
||||
}
|
||||
|
||||
friend Base;
|
||||
};
|
||||
|
||||
template<class ASSET>
|
||||
class SoftReference: public ReferenceBase<SoftReference<ASSET>, ASSET>
|
||||
{
|
||||
using Base = ReferenceBase<SoftReference<ASSET>, ASSET>;
|
||||
|
||||
public:
|
||||
SoftReference() = default;
|
||||
|
||||
SoftReference(const UUID& p_uuid):
|
||||
Base(p_uuid)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Increment the soft ref count of the handle
|
||||
*
|
||||
* \param p_handle The handle for the asset
|
||||
*/
|
||||
static void IncrementCount(ContainerHandle& p_handle)
|
||||
{
|
||||
p_handle.IncrementSoftRefCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement the hard ref count of the handle
|
||||
*
|
||||
* \param p_handle The handle for the asset
|
||||
*/
|
||||
static void DecrementCount(ContainerHandle& p_handle)
|
||||
{
|
||||
p_handle.DecrementSoftRefCount();
|
||||
}
|
||||
|
||||
friend Base;
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
#endif
|
||||
@@ -0,0 +1,129 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
|
||||
#ifndef FLATBUFFERS_GENERATED_REFERENCE_FLAT_BIGFOOT_H_
|
||||
#define FLATBUFFERS_GENERATED_REFERENCE_FLAT_BIGFOOT_H_
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
|
||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||
// generated, otherwise it may not be compatible.
|
||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 19,
|
||||
"Non-compatible flatbuffers version included");
|
||||
// Ensure the included flatbuffers.h is Bigfoot's fork - stock
|
||||
// flatbuffers (or a differently versioned Bigfoot fork) is not compatible.
|
||||
#ifndef FLATBUFFERS_BIGFOOT_VERSION
|
||||
#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible"
|
||||
#endif
|
||||
static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1,
|
||||
"Non-compatible Bigfoot flatbuffers fork version included");
|
||||
|
||||
#include "System/UUID/UUID.hpp"
|
||||
#include "Engine/Asset/Reference.hpp"
|
||||
#include "System/UUID/UUID_generated.hpp"
|
||||
|
||||
#include "EASTL/unique_ptr.h"
|
||||
#include "EASTL/string.h"
|
||||
#include "EASTL/vector.h"
|
||||
|
||||
namespace Flat {
|
||||
namespace Bigfoot {
|
||||
|
||||
struct HardReference;
|
||||
|
||||
struct SoftReference;
|
||||
|
||||
inline const ::flatbuffers::TypeTable *HardReferenceTypeTable();
|
||||
|
||||
inline const ::flatbuffers::TypeTable *SoftReferenceTypeTable();
|
||||
|
||||
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(1) HardReference FLATBUFFERS_FINAL_CLASS {
|
||||
private:
|
||||
Flat::Bigfoot::UUID uuid_;
|
||||
|
||||
public:
|
||||
struct Traits;
|
||||
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
return HardReferenceTypeTable();
|
||||
}
|
||||
static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() {
|
||||
return "Flat.Bigfoot.HardReference";
|
||||
}
|
||||
HardReference()
|
||||
: uuid_() {
|
||||
}
|
||||
HardReference(const Flat::Bigfoot::UUID &_uuid)
|
||||
: uuid_(_uuid) {
|
||||
}
|
||||
const Flat::Bigfoot::UUID &uuid() const {
|
||||
return uuid_;
|
||||
}
|
||||
};
|
||||
FLATBUFFERS_STRUCT_END(HardReference, 16);
|
||||
|
||||
struct HardReference::Traits {
|
||||
using type = HardReference;
|
||||
};
|
||||
|
||||
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(1) SoftReference FLATBUFFERS_FINAL_CLASS {
|
||||
private:
|
||||
Flat::Bigfoot::UUID uuid_;
|
||||
|
||||
public:
|
||||
struct Traits;
|
||||
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
return SoftReferenceTypeTable();
|
||||
}
|
||||
static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() {
|
||||
return "Flat.Bigfoot.SoftReference";
|
||||
}
|
||||
SoftReference()
|
||||
: uuid_() {
|
||||
}
|
||||
SoftReference(const Flat::Bigfoot::UUID &_uuid)
|
||||
: uuid_(_uuid) {
|
||||
}
|
||||
const Flat::Bigfoot::UUID &uuid() const {
|
||||
return uuid_;
|
||||
}
|
||||
};
|
||||
FLATBUFFERS_STRUCT_END(SoftReference, 16);
|
||||
|
||||
struct SoftReference::Traits {
|
||||
using type = SoftReference;
|
||||
};
|
||||
|
||||
inline const ::flatbuffers::TypeTable *HardReferenceTypeTable() {
|
||||
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 *SoftReferenceTypeTable() {
|
||||
static const ::flatbuffers::TypeCode type_codes[] = {
|
||||
{ ::flatbuffers::ET_SEQUENCE, 0, 0 }
|
||||
};
|
||||
static const ::flatbuffers::TypeFunction type_refs[] = {
|
||||
Flat::Bigfoot::UUIDTypeTable
|
||||
};
|
||||
static const int64_t values[] = { 0, 16 };
|
||||
static const ::flatbuffers::TypeTable tt = {
|
||||
::flatbuffers::ST_STRUCT, 1, type_codes, type_refs, nullptr, values, nullptr
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
|
||||
} // namespace Bigfoot
|
||||
} // namespace Flat
|
||||
|
||||
#endif // FLATBUFFERS_GENERATED_REFERENCE_FLAT_BIGFOOT_H_
|
||||
@@ -0,0 +1,329 @@
|
||||
/*********************************************************************
|
||||
* \file BigFile.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date October 2025
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_ENGINE_BIGFILE_BIGFILE_HPP
|
||||
#define BIGFOOT_ENGINE_BIGFILE_BIGFILE_HPP
|
||||
#include <Engine/DataAccessor/DataAccessor.hpp>
|
||||
|
||||
#include <System/File/File.hpp>
|
||||
|
||||
#include <Utils/TaggedType.hpp>
|
||||
|
||||
#include <EASTL/span.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
#ifdef BIGFOOT_TOOLMODE
|
||||
class BigFile: public DataAccessor
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param p_file The file targetting the BigFile DB
|
||||
*/
|
||||
BigFile(const File& p_file);
|
||||
|
||||
BigFile(const BigFile& p_bigFile) = delete;
|
||||
BigFile(BigFile&& p_bigFile) = delete;
|
||||
|
||||
/**
|
||||
* Begin a transaction
|
||||
*
|
||||
*/
|
||||
void BeginTransaction();
|
||||
|
||||
/**
|
||||
* Commit a transaction
|
||||
*
|
||||
*/
|
||||
void CommitTransaction();
|
||||
|
||||
/**
|
||||
* Rollback a transaction
|
||||
*
|
||||
*/
|
||||
void RollbackTransaction();
|
||||
|
||||
~BigFile();
|
||||
|
||||
/**
|
||||
* Get an Asset flatbuffer
|
||||
*
|
||||
* \param p_uuid The asset to get the flatbuffer of
|
||||
* \return The flatbuffer, or nullopt if the asset was not found
|
||||
*/
|
||||
eastl::optional<eastl::vector<std::byte>> GetAssetFlatbuffer(const UUID& p_uuid) const override;
|
||||
|
||||
/**
|
||||
* Get several Asset flatbuffers
|
||||
*
|
||||
* \param p_uuids The assets to get the flatbuffers of
|
||||
* \return The flatbuffers that were found
|
||||
*/
|
||||
eastl::vector<eastl::vector<std::byte>> GetAssetFlatbuffers(eastl::span<const UUID> p_uuids) const override;
|
||||
|
||||
/**
|
||||
* Get an Asset metadata
|
||||
*
|
||||
* \param p_uuid The asset to get the metadata of
|
||||
* \return The metadata, or nullopt if the asset was not found
|
||||
*/
|
||||
eastl::optional<AssetMetadata> GetAssetMetadata(const UUID& p_uuid) const override;
|
||||
|
||||
/**
|
||||
* Get several Asset metadatas
|
||||
*
|
||||
* \param p_uuids The assets to get the metadatas of
|
||||
* \return The metadatas that were found
|
||||
*/
|
||||
eastl::vector<AssetMetadata> GetAssetMetadatas(eastl::span<const UUID> p_uuids) const override;
|
||||
|
||||
/**
|
||||
* Save an asset
|
||||
*
|
||||
* \p_metadata The metadata
|
||||
* \p_flatbuffer The flatbuffer of the asset
|
||||
*/
|
||||
void SaveAssetFlatbuffer(const AssetMetadata& p_metadata, const eastl::span<const std::byte> p_flatbuffer) override;
|
||||
|
||||
/**
|
||||
* Save several assets
|
||||
*
|
||||
* \p_metadatas The metadatas
|
||||
* \p_flatbuffers The flatbuffers of the assets, matching p_metadatas by index
|
||||
*/
|
||||
void SaveAssetFlatbuffers(eastl::span<const AssetMetadata> p_metadatas,
|
||||
eastl::span<const eastl::vector<std::byte>> p_flatbuffers) override;
|
||||
|
||||
/**
|
||||
* Check if the Asset exists
|
||||
*
|
||||
* \param p_uuid The asset to check
|
||||
* \param True if it exists, false otherwise
|
||||
*/
|
||||
bool Has(const UUID& p_uuid) const override;
|
||||
|
||||
BigFile& operator=(const BigFile& p_bigFile) = delete;
|
||||
BigFile& operator=(BigFile&& p_bigFile) = delete;
|
||||
|
||||
class Request
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Constructor
|
||||
*
|
||||
* \param p_bigFile The bigfile
|
||||
* \param p_request The SQL request
|
||||
*/
|
||||
Request(const BigFile& p_bigFile, const eastl::string_view p_request);
|
||||
|
||||
Request(const Request& p_request) = delete;
|
||||
Request(Request&& p_request) = delete;
|
||||
|
||||
using CopyValue = TaggedType<bool>;
|
||||
|
||||
/*
|
||||
* Bind a int32 value to the Request at index
|
||||
*
|
||||
* \param p_index The index to bind to
|
||||
* \param p_value The value
|
||||
*/
|
||||
void Bind(const std::uint32_t p_index, const std::int32_t p_value);
|
||||
|
||||
/*
|
||||
* Bind a uint32 value to the Request at index
|
||||
*
|
||||
* \param p_index The index to bind to
|
||||
* \param p_value The value
|
||||
*/
|
||||
void Bind(const std::uint32_t p_index, const std::uint32_t p_value);
|
||||
|
||||
/*
|
||||
* Bind a int64 value to the Request at index
|
||||
*
|
||||
* \param p_index The index to bind to
|
||||
* \param p_value The value
|
||||
*/
|
||||
void Bind(const std::uint32_t p_index, const std::int64_t p_value);
|
||||
|
||||
/*
|
||||
* Bind a uint64 value to the Request at index
|
||||
*
|
||||
* \param p_index The index to bind to
|
||||
* \param p_value The value
|
||||
*/
|
||||
void Bind(const std::uint32_t p_index, const std::uint64_t p_value);
|
||||
|
||||
/*
|
||||
* Bind a float value to the Request at index
|
||||
*
|
||||
* \param p_index The index to bind to
|
||||
* \param p_value The value
|
||||
*/
|
||||
void Bind(const std::uint32_t p_index, const float p_value);
|
||||
|
||||
/*
|
||||
* Bind a double value to the Request at index
|
||||
*
|
||||
* \param p_index The index to bind to
|
||||
* \param p_value The value
|
||||
*/
|
||||
void Bind(const std::uint32_t p_index, const double p_value);
|
||||
|
||||
/*
|
||||
* Bind a string value to the Request at index
|
||||
*
|
||||
* \param p_index The index to bind to
|
||||
* \param p_value The value
|
||||
* \param p_copy Should the memory be copied so that caller does not have to retain it
|
||||
*/
|
||||
void Bind(const std::uint32_t p_index,
|
||||
const eastl::string_view p_value,
|
||||
const CopyValue p_copy = CopyValue {false});
|
||||
|
||||
/*
|
||||
* Bind a blob value to the Request at index
|
||||
*
|
||||
* \param p_index The index to bind to
|
||||
* \param p_value The value
|
||||
* \param p_copy Should the memory be copied so that caller does not have to retain it
|
||||
*/
|
||||
void Bind(const std::uint32_t p_index,
|
||||
const eastl::span<const std::byte> p_value,
|
||||
const CopyValue p_copy = CopyValue {false});
|
||||
|
||||
/*
|
||||
* Step through the request
|
||||
*
|
||||
* \return True if a row is available to read via Get(), false once the statement is done
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool Step();
|
||||
|
||||
/*
|
||||
* Execute the request once
|
||||
*
|
||||
* \return The number of rows modified by the statement
|
||||
*/
|
||||
[[maybe_unused]]
|
||||
std::uint32_t Execute();
|
||||
|
||||
class Column
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Constructor
|
||||
*
|
||||
* \param p_request The request to get the column of
|
||||
* \param p_index Column index
|
||||
*/
|
||||
Column(const Request& p_request, const std::uint32_t p_index);
|
||||
|
||||
/*
|
||||
* Get value as a int32
|
||||
*
|
||||
* \return The value
|
||||
*/
|
||||
operator std::int32_t() const;
|
||||
|
||||
/*
|
||||
* Get value as a uint32
|
||||
*
|
||||
* \return The value
|
||||
*/
|
||||
operator std::uint32_t() const;
|
||||
|
||||
/*
|
||||
* Get value as a int64
|
||||
*
|
||||
* \return The value
|
||||
*/
|
||||
operator std::int64_t() const;
|
||||
|
||||
/*
|
||||
* Get value as a uint64
|
||||
*
|
||||
* \return The value
|
||||
*/
|
||||
operator std::uint64_t() const;
|
||||
|
||||
/*
|
||||
* Get value as a float
|
||||
*
|
||||
* \return The value
|
||||
*/
|
||||
operator float() const;
|
||||
|
||||
/*
|
||||
* Get value as a double
|
||||
*
|
||||
* \return The value
|
||||
*/
|
||||
operator double() const;
|
||||
|
||||
/*
|
||||
* Get value as a string
|
||||
*
|
||||
* \return The value
|
||||
*/
|
||||
operator eastl::string_view() const;
|
||||
|
||||
/*
|
||||
* Get value as a blob
|
||||
*
|
||||
* \return The value
|
||||
*/
|
||||
operator eastl::span<const std::byte>() const;
|
||||
|
||||
private:
|
||||
/*
|
||||
* The statement
|
||||
*/
|
||||
sqlite3_stmt* m_statement;
|
||||
|
||||
/*
|
||||
* The column index
|
||||
*/
|
||||
std::uint32_t m_index;
|
||||
};
|
||||
|
||||
/*
|
||||
* Get a column
|
||||
*
|
||||
* \param p_index Column index
|
||||
*/
|
||||
[[nodiscard]]
|
||||
Column Get(const std::uint32_t p_index) const;
|
||||
|
||||
~Request();
|
||||
|
||||
Request& operator=(const Request& p_request) = delete;
|
||||
Request& operator=(Request&& p_request) = delete;
|
||||
|
||||
private:
|
||||
/*
|
||||
* The database
|
||||
*/
|
||||
sqlite3* m_db;
|
||||
|
||||
/*
|
||||
* The statement
|
||||
*/
|
||||
sqlite3_stmt* m_statement;
|
||||
};
|
||||
|
||||
private:
|
||||
/**
|
||||
* The BigFile DB
|
||||
*/
|
||||
sqlite3* m_db;
|
||||
};
|
||||
#endif
|
||||
} // namespace Bigfoot
|
||||
|
||||
#endif
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <EASTL/string_view.h>
|
||||
|
||||
#if defined BIGFOOT_TOOLMODE
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
/*
|
||||
@@ -16,4 +18,5 @@ namespace Bigfoot
|
||||
*/
|
||||
constexpr eastl::string_view BIGFILE_@BIGFILE_NAME@_LOCATION {"@BIGFILE_LOCATION@"};
|
||||
} // namespace Bigfoot
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,149 @@
|
||||
/*********************************************************************
|
||||
* \file DataAccessor.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date August 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_ENGINE_DATAACCESSOR_DATAACCESSOR_HPP
|
||||
#define BIGFOOT_ENGINE_DATAACCESSOR_DATAACCESSOR_HPP
|
||||
#include <Engine/Asset/AssetTypeID.hpp>
|
||||
|
||||
#include <System/Time/Time.hpp>
|
||||
#include <System/UUID/UUID.hpp>
|
||||
|
||||
#include <EASTL/optional.h>
|
||||
#include <EASTL/span.h>
|
||||
#include <EASTL/string.h>
|
||||
#include <EASTL/vector.h>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
struct AssetMetadata
|
||||
{
|
||||
UUID m_uuid = UUID::NULL_UUID;
|
||||
eastl::string m_name {};
|
||||
|
||||
AssetTypeID m_typeID = 0;
|
||||
eastl::string m_typeName {};
|
||||
|
||||
Time m_creationTime = 0;
|
||||
Time m_modificationTime = 0;
|
||||
};
|
||||
|
||||
class DataAccessor
|
||||
{
|
||||
public:
|
||||
DataAccessor() = default;
|
||||
|
||||
DataAccessor(const DataAccessor& p_accessor) = default;
|
||||
DataAccessor(DataAccessor&& p_accessor) = default;
|
||||
|
||||
virtual ~DataAccessor() = default;
|
||||
|
||||
/**
|
||||
* Get an Asset flatbuffer
|
||||
*
|
||||
* \param p_uuid The asset to get the flatbuffer of
|
||||
* \return The flatbuffer, or nullopt if the asset was not found
|
||||
*/
|
||||
virtual eastl::optional<eastl::vector<std::byte>> GetAssetFlatbuffer(const UUID& p_uuid) const = 0;
|
||||
|
||||
/**
|
||||
* Get several Asset flatbuffers
|
||||
*
|
||||
* \param p_uuids The assets to get the flatbuffers of
|
||||
* \return The flatbuffers that were found
|
||||
*/
|
||||
virtual eastl::vector<eastl::vector<std::byte>> GetAssetFlatbuffers(eastl::span<const UUID> p_uuids) const = 0;
|
||||
|
||||
/**
|
||||
* Get an Asset metadata
|
||||
*
|
||||
* \param p_uuid The asset to get the metadata of
|
||||
* \return The metadata, or nullopt if the asset was not found
|
||||
*/
|
||||
virtual eastl::optional<AssetMetadata> GetAssetMetadata(const UUID& p_uuid) const = 0;
|
||||
|
||||
/**
|
||||
* Get several Asset metadatas
|
||||
*
|
||||
* \param p_uuids The assets to get the metadatas of
|
||||
* \return The metadatas that were found
|
||||
*/
|
||||
virtual eastl::vector<AssetMetadata> GetAssetMetadatas(eastl::span<const UUID> p_uuids) const = 0;
|
||||
|
||||
/**
|
||||
* Save an asset
|
||||
*
|
||||
* \p_metadata The metadata
|
||||
* \p_flatbuffer The flatbuffer of the asset
|
||||
*/
|
||||
virtual void SaveAssetFlatbuffer(const AssetMetadata& p_metadata,
|
||||
const eastl::span<const std::byte> p_flatbuffer) = 0;
|
||||
|
||||
/**
|
||||
* Save several assets
|
||||
*
|
||||
* \p_metadatas The metadatas
|
||||
* \p_flatbuffers The flatbuffers of the assets, matching p_metadatas by index
|
||||
*/
|
||||
virtual void SaveAssetFlatbuffers(eastl::span<const AssetMetadata> p_metadatas,
|
||||
eastl::span<const eastl::vector<std::byte>> p_flatbuffers) = 0;
|
||||
|
||||
/**
|
||||
* Check if the Asset exists
|
||||
*
|
||||
* \param p_uuid The asset to check
|
||||
* \param True if it exists, false otherwise
|
||||
*/
|
||||
virtual bool Has(const UUID& p_uuid) const = 0;
|
||||
|
||||
DataAccessor& operator=(const DataAccessor& p_accessor) = default;
|
||||
DataAccessor& operator=(DataAccessor&& p_accessor) = default;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
// The global data accessor for Bigfoot
|
||||
inline DataAccessor* g_dataAccessor = nullptr;
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
/*
|
||||
* Set the data accessor
|
||||
*
|
||||
* \param p_dataAccessor The data accessor to set g_dataAccessor to.
|
||||
*/
|
||||
void SetDataAccessor(DataAccessor* p_dataAccessor);
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
class ScopedDataAccessor
|
||||
{
|
||||
public:
|
||||
ScopedDataAccessor(DataAccessor* p_dataAccessor):
|
||||
m_previous(g_dataAccessor)
|
||||
{
|
||||
SetDataAccessor(p_dataAccessor);
|
||||
}
|
||||
|
||||
ScopedDataAccessor(const ScopedDataAccessor& p_scopedDataAccessor) = delete;
|
||||
ScopedDataAccessor(ScopedDataAccessor&& p_scopedDataAccessor) = delete;
|
||||
|
||||
~ScopedDataAccessor()
|
||||
{
|
||||
SetDataAccessor(m_previous);
|
||||
}
|
||||
|
||||
ScopedDataAccessor& operator=(const ScopedDataAccessor& p_scopedDataAccessor) = delete;
|
||||
ScopedDataAccessor& operator=(ScopedDataAccessor&& p_scopedDataAccessor) = delete;
|
||||
|
||||
private:
|
||||
/*
|
||||
* The previous data accessor.
|
||||
*/
|
||||
DataAccessor* m_previous = nullptr;
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
|
||||
#endif
|
||||
@@ -6,55 +6,15 @@
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_ENGINE_ENGINEASSERTHANDLER_HPP
|
||||
#define BIGFOOT_ENGINE_ENGINEASSERTHANDLER_HPP
|
||||
#include <Utils/Assert.hpp>
|
||||
|
||||
#include <Engine/EngineLogger_generated.hpp>
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
#include <EASTL/utility.h>
|
||||
#include <Utils/Assert/AssertHandler.hpp>
|
||||
|
||||
#include <format>
|
||||
#include <source_location>
|
||||
#include <string_view>
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
class EngineAssertHandler
|
||||
{
|
||||
public:
|
||||
EngineAssertHandler() = delete;
|
||||
|
||||
EngineAssertHandler(const EngineAssertHandler& p_handler) = delete;
|
||||
EngineAssertHandler(EngineAssertHandler&& p_handler) = delete;
|
||||
|
||||
~EngineAssertHandler() = delete;
|
||||
|
||||
/**
|
||||
* Handle an assertion.
|
||||
*
|
||||
* \param p_location Location of the assertion.
|
||||
* \param p_stacktrace The stack trace
|
||||
* \param p_format Format string for the assertion message.
|
||||
* \param p_args Arguments for the format string.
|
||||
*/
|
||||
template<typename... ARGS>
|
||||
static void Handle(const std::source_location& p_location,
|
||||
const std::string_view p_stacktrace,
|
||||
std::format_string<ARGS...> p_format,
|
||||
ARGS&&... p_args)
|
||||
{
|
||||
BIGFOOT_LOG_FATAL(ENGINE_LOGGER,
|
||||
"Assert: {} (File:{}, Line:{}, Function:{}\n{}",
|
||||
std::format(p_format, eastl::forward<ARGS>(p_args)...),
|
||||
p_location.file_name(),
|
||||
p_location.line(),
|
||||
p_location.function_name(),
|
||||
p_stacktrace);
|
||||
}
|
||||
|
||||
EngineAssertHandler& operator=(const EngineAssertHandler& p_handler) = delete;
|
||||
EngineAssertHandler& operator=(EngineAssertHandler&& p_handler) = delete;
|
||||
};
|
||||
using EngineAssertHandler = AssertHandler<ENGINE_LOGGER>;
|
||||
} // namespace Bigfoot
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_ENGINELOGGER_GENERATED_HPP
|
||||
#define BIGFOOT_ENGINELOGGER_GENERATED_HPP
|
||||
#include <System/Log/Log.hpp>
|
||||
#include <Utils/Log/LogMacros.hpp>
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
// to delete when an actual source is in Engine
|
||||
@@ -2,8 +2,6 @@ get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
project(${PackageName})
|
||||
|
||||
set(PublicDependencies
|
||||
$<$<CONFIG:Debug,RelWithDebInfo>:quill::quill>
|
||||
mimalloc
|
||||
stduuid::stduuid)
|
||||
set(PrivateDependencies)
|
||||
set(BigfootPublicDependencies
|
||||
@@ -18,11 +16,3 @@ bigfoot_create_package_lib(
|
||||
"")
|
||||
|
||||
bigfoot_create_logger()
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PUBLIC $<$<CONFIG:Debug,RelWithDebInfo>:QUILL_NO_EXCEPTIONS>
|
||||
PUBLIC $<$<CONFIG:Debug,RelWithDebInfo>:QUILL_DISABLE_NON_PREFIXED_MACROS>
|
||||
|
||||
PUBLIC MI_SHARED_LIB)
|
||||
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/MimallocImpl.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
|
||||
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*********************************************************************
|
||||
* \file File.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date December 2025
|
||||
*********************************************************************/
|
||||
#include <System/File/File.hpp>
|
||||
|
||||
#include <System/SystemAssertHandler.hpp>
|
||||
|
||||
#include <bit>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
File::File(const eastl::string_view p_path):
|
||||
m_path(p_path.data()),
|
||||
m_pathString(p_path)
|
||||
{
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool File::IsAbsolute() const
|
||||
{
|
||||
return m_path.is_absolute();
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool File::IsRelative() const
|
||||
{
|
||||
return m_path.is_relative();
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool File::Exists() const
|
||||
{
|
||||
return std::filesystem::exists(m_path);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
eastl::string_view File::GetPath() const
|
||||
{
|
||||
return m_pathString;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
File File::ToAbsolute() const
|
||||
{
|
||||
return File {std::filesystem::absolute(m_path)};
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
File File::ToRelative() const
|
||||
{
|
||||
return File {std::filesystem::relative(m_path)};
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
std::size_t File::GetSize() const
|
||||
{
|
||||
return static_cast<std::size_t>(std::filesystem::file_size(m_path));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
eastl::vector<std::byte> File::Read(const std::size_t p_offset, const std::size_t p_size) const
|
||||
{
|
||||
const File absoluteFile = ToAbsolute();
|
||||
const eastl::string_view path = absoluteFile.GetPath();
|
||||
|
||||
std::ifstream file {path.data(), std::ios::binary};
|
||||
CRITICAL_ASSERT(SystemAssertHandler, file.is_open(), "Failed to open file {} for reading", path);
|
||||
|
||||
file.seekg(static_cast<std::streamoff>(p_offset), std::ios::beg);
|
||||
|
||||
eastl::vector<std::byte> data;
|
||||
data.resize(p_size);
|
||||
file.read(std::bit_cast<char*>(data.data()), static_cast<std::streamsize>(data.size()));
|
||||
return data;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void File::Write(const eastl::span<const std::byte> p_data, const std::size_t p_offset) const
|
||||
{
|
||||
const File absoluteFile = ToAbsolute();
|
||||
const eastl::string_view path = absoluteFile.GetPath();
|
||||
|
||||
std::ofstream {path.data(), std::ios::binary | std::ios::app};
|
||||
|
||||
std::fstream file {path.data(), std::ios::binary | std::ios::in | std::ios::out};
|
||||
CRITICAL_ASSERT(SystemAssertHandler, file.is_open(), "Failed to open file {} for writing", path);
|
||||
|
||||
file.seekp(static_cast<std::streamoff>(p_offset), std::ios::beg);
|
||||
file.write(std::bit_cast<const char*>(p_data.data()), static_cast<std::streamsize>(p_data.size()));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void File::Delete() const
|
||||
{
|
||||
std::filesystem::remove(m_path);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
File::File(const std::filesystem::path& p_path):
|
||||
m_path(p_path),
|
||||
m_pathString(m_path.string().c_str())
|
||||
{
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
@@ -0,0 +1,234 @@
|
||||
/*********************************************************************
|
||||
* \file MemoryMappedFile.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date August 2026
|
||||
*********************************************************************/
|
||||
#include <System/File/MemoryMappedFile.hpp>
|
||||
|
||||
#include <System/SystemAssertHandler.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#if defined BIGFOOT_WINDOWS
|
||||
#include <Windows.h>
|
||||
#elif defined BIGFOOT_LINUX
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
MemoryMappedFile::MemoryMappedFile(const File& p_file)
|
||||
{
|
||||
const File absoluteFile = p_file.ToAbsolute();
|
||||
const eastl::string_view path = absoluteFile.GetPath();
|
||||
|
||||
#if defined BIGFOOT_WINDOWS
|
||||
m_fileHandle = CreateFileA(path.data(),
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
nullptr,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
||||
nullptr);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, m_fileHandle != INVALID_HANDLE_VALUE, "Failed to open file {}", path);
|
||||
|
||||
LARGE_INTEGER fileSize {};
|
||||
[[maybe_unused]]
|
||||
const BOOL gotFileSize = GetFileSizeEx(m_fileHandle, &fileSize);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, gotFileSize, "Failed to get the size of file {}", path);
|
||||
m_size = static_cast<std::size_t>(fileSize.QuadPart);
|
||||
|
||||
if (m_size != 0)
|
||||
{
|
||||
m_mappingHandle = CreateFileMappingA(m_fileHandle, nullptr, PAGE_READONLY, 0, 0, nullptr);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, m_mappingHandle != nullptr, "Failed create the file mapping {}", path);
|
||||
|
||||
m_data = static_cast<std::byte*>(MapViewOfFile(m_mappingHandle, FILE_MAP_READ, 0, 0, 0));
|
||||
CRITICAL_ASSERT(SystemAssertHandler, m_data != nullptr, "Failed to map the file {}", path);
|
||||
}
|
||||
#elif defined BIGFOOT_LINUX
|
||||
m_fileDescriptor = open(path.data(), O_RDONLY);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, m_fileDescriptor != -1, "Failed to open file {}", path);
|
||||
|
||||
struct stat fileStat {};
|
||||
[[maybe_unused]]
|
||||
const int statResult = fstat(m_fileDescriptor, &fileStat);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, statResult == 0, "Failed to get the size of file {}", path);
|
||||
m_size = static_cast<std::size_t>(fileStat.st_size);
|
||||
|
||||
if (m_size != 0)
|
||||
{
|
||||
void* const mapped = mmap(nullptr, m_size, PROT_READ, MAP_PRIVATE, m_fileDescriptor, 0);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, mapped != MAP_FAILED, "Failed to map file {}", path);
|
||||
m_data = static_cast<std::byte*>(mapped);
|
||||
|
||||
[[maybe_unused]]
|
||||
const int adviseResult = madvise(mapped, m_size, MADV_RANDOM);
|
||||
}
|
||||
#else
|
||||
CRITICAL_ASSERT(SystemAssertHandler, false, "MemoryMappedFileBase is not implemented on this platform");
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
MemoryMappedFile::~MemoryMappedFile()
|
||||
{
|
||||
#if defined BIGFOOT_WINDOWS
|
||||
if (m_data != nullptr)
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const BOOL unmapped = UnmapViewOfFile(m_data);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, unmapped, "Failed to unmap the file");
|
||||
}
|
||||
|
||||
if (m_mappingHandle != nullptr)
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const BOOL closedMapping = CloseHandle(m_mappingHandle);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, closedMapping, "Failed to close the file mapping");
|
||||
}
|
||||
|
||||
if (m_fileHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const BOOL closedFile = CloseHandle(m_fileHandle);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, closedFile, "Failed to close the file");
|
||||
}
|
||||
#elif defined BIGFOOT_LINUX
|
||||
if (m_data != nullptr)
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const int unmapped = munmap(m_data, m_size);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, unmapped == 0, "Failed to unmap the file");
|
||||
}
|
||||
|
||||
if (m_fileDescriptor != -1)
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const int closedFile = close(m_fileDescriptor);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, closedFile == 0, "Failed to close the file");
|
||||
}
|
||||
#else
|
||||
CRITICAL_ASSERT(SystemAssertHandler, false, "MemoryMappedFileBase is not implemented on this platform");
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
eastl::span<const std::byte> MemoryMappedFile::GetData() const
|
||||
{
|
||||
return eastl::span<const std::byte> {m_data, m_size};
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
WritableMemoryMappedFile::WritableMemoryMappedFile(const File& p_file, const std::size_t p_size):
|
||||
m_size(p_size)
|
||||
{
|
||||
const File absoluteFile = p_file.ToAbsolute();
|
||||
const eastl::string_view path = absoluteFile.GetPath();
|
||||
|
||||
#if defined BIGFOOT_WINDOWS
|
||||
m_fileHandle =
|
||||
CreateFileA(path.data(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, m_fileHandle != INVALID_HANDLE_VALUE, "Failed to create file {}", path);
|
||||
|
||||
const LARGE_INTEGER size {.QuadPart = static_cast<LONGLONG>(p_size)};
|
||||
m_mappingHandle = CreateFileMappingA(m_fileHandle, nullptr, PAGE_READWRITE, size.HighPart, size.LowPart, nullptr);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, m_mappingHandle != nullptr, "Failed create the file mapping {}", path);
|
||||
|
||||
m_data = static_cast<std::byte*>(MapViewOfFile(m_mappingHandle, FILE_MAP_WRITE, 0, 0, 0));
|
||||
CRITICAL_ASSERT(SystemAssertHandler, m_data != nullptr, "Failed to map the file {}", path);
|
||||
#elif defined BIGFOOT_LINUX
|
||||
m_fileDescriptor = open(path.data(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, m_fileDescriptor != -1, "Failed to create file {}", path);
|
||||
|
||||
struct stat fileStat {};
|
||||
fstat(m_fileDescriptor, &fileStat);
|
||||
if (static_cast<std::size_t>(fileStat.st_size) < p_size)
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const int truncateResult = ftruncate(m_fileDescriptor, static_cast<off_t>(p_size));
|
||||
CRITICAL_ASSERT(SystemAssertHandler, truncateResult == 0, "Failed to size file {}", path);
|
||||
}
|
||||
|
||||
void* const mapped = mmap(nullptr, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fileDescriptor, 0);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, mapped != MAP_FAILED, "Failed to map file {}", path);
|
||||
m_data = static_cast<std::byte*>(mapped);
|
||||
#else
|
||||
CRITICAL_ASSERT(SystemAssertHandler, false, "MemoryMappedFileBase is not implemented on this platform");
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
WritableMemoryMappedFile::~WritableMemoryMappedFile()
|
||||
{
|
||||
#if defined BIGFOOT_WINDOWS
|
||||
if (m_data != nullptr)
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const BOOL unmapped = UnmapViewOfFile(m_data);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, unmapped, "Failed to unmap the file");
|
||||
}
|
||||
|
||||
if (m_mappingHandle != nullptr)
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const BOOL closedMapping = CloseHandle(m_mappingHandle);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, closedMapping, "Failed to close the file mapping");
|
||||
}
|
||||
|
||||
if (m_fileHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const BOOL closedFile = CloseHandle(m_fileHandle);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, closedFile, "Failed to close the file");
|
||||
}
|
||||
#elif defined BIGFOOT_LINUX
|
||||
if (m_data != nullptr)
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const int unmapped = munmap(m_data, m_size);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, unmapped == 0, "Failed to unmap the file");
|
||||
}
|
||||
|
||||
if (m_fileDescriptor != -1)
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const int closedFile = close(m_fileDescriptor);
|
||||
CRITICAL_ASSERT(SystemAssertHandler, closedFile == 0, "Failed to close the file");
|
||||
}
|
||||
#else
|
||||
CRITICAL_ASSERT(SystemAssertHandler, false, "MemoryMappedFileBase is not implemented on this platform");
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
eastl::span<std::byte> WritableMemoryMappedFile::GetData() const
|
||||
{
|
||||
return eastl::span<std::byte> {m_data, m_size};
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void WritableMemoryMappedFile::Prefetch(const std::size_t p_offset, const std::size_t p_size) const
|
||||
{
|
||||
#if defined BIGFOOT_WINDOWS
|
||||
WIN32_MEMORY_RANGE_ENTRY range {.VirtualAddress = m_data + p_offset, .NumberOfBytes = p_size};
|
||||
[[maybe_unused]]
|
||||
const BOOL prefetched = PrefetchVirtualMemory(GetCurrentProcess(), 1, &range, 0);
|
||||
#elif defined BIGFOOT_LINUX
|
||||
[[maybe_unused]]
|
||||
const int adviseResult = madvise(m_data + p_offset, p_size, MADV_WILLNEED);
|
||||
#else
|
||||
CRITICAL_ASSERT(SystemAssertHandler, false, "MemoryMappedFileBase is not implemented on this platform");
|
||||
#endif
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
+35
-9
@@ -7,8 +7,10 @@
|
||||
#ifndef BIGFOOT_SYSTEM_FILE_HPP
|
||||
#define BIGFOOT_SYSTEM_FILE_HPP
|
||||
|
||||
#include <EASTL/span.h>
|
||||
#include <EASTL/string.h>
|
||||
#include <EASTL/string_view.h>
|
||||
#include <EASTL/vector.h>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
@@ -24,9 +26,6 @@ class File
|
||||
*/
|
||||
File(const eastl::string_view p_path);
|
||||
|
||||
File(const File& p_path) = default;
|
||||
File(File&& p_path) = default;
|
||||
|
||||
/**
|
||||
* Check if the file is relative to the current executable
|
||||
*
|
||||
@@ -57,7 +56,7 @@ class File
|
||||
* \return The path
|
||||
*/
|
||||
[[nodiscard]]
|
||||
eastl::string_view Path() const;
|
||||
eastl::string_view GetPath() const;
|
||||
|
||||
/**
|
||||
* Get the same file, relative to the current executable
|
||||
@@ -65,7 +64,7 @@ class File
|
||||
* \return The relative file
|
||||
*/
|
||||
[[nodiscard]]
|
||||
File Relative() const;
|
||||
File ToRelative() const;
|
||||
|
||||
/**
|
||||
* Get the same file, with an absolute path
|
||||
@@ -73,12 +72,39 @@ class File
|
||||
* \return The absolute file
|
||||
*/
|
||||
[[nodiscard]]
|
||||
File Absolute() const;
|
||||
File ToAbsolute() const;
|
||||
|
||||
~File() = default;
|
||||
/**
|
||||
* Get the size of the file
|
||||
*
|
||||
* \return The size in bytes
|
||||
*/
|
||||
[[nodiscard]]
|
||||
std::size_t GetSize() const;
|
||||
|
||||
File& operator=(const File& p_path) = default;
|
||||
File& operator=(File&& p_path) = default;
|
||||
/**
|
||||
* Read bytes from the file
|
||||
*
|
||||
* \param p_offset The offset in bytes
|
||||
* \param p_size The number of bytes to read
|
||||
* \return The bytes read
|
||||
*/
|
||||
[[nodiscard]]
|
||||
eastl::vector<std::byte> Read(std::size_t p_offset, std::size_t p_size) const;
|
||||
|
||||
/**
|
||||
* Write bytes to the file at a given offset, creating the file if needed. Content before
|
||||
* p_offset, or from past p_offset + p_data.size(), is left untouched.
|
||||
*
|
||||
* \param p_data The bytes to write
|
||||
* \param p_offset The offset, in bytes, to start writing at
|
||||
*/
|
||||
void Write(eastl::span<const std::byte> p_data, std::size_t p_offset) const;
|
||||
|
||||
/**
|
||||
* Delete the file
|
||||
*/
|
||||
void Delete() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -0,0 +1,150 @@
|
||||
/*********************************************************************
|
||||
* \file MemoryMappedFile.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date August 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_SYSTEM_MEMORYMAPPEDFILE_HPP
|
||||
#define BIGFOOT_SYSTEM_MEMORYMAPPEDFILE_HPP
|
||||
#include <System/File/File.hpp>
|
||||
|
||||
#include <EASTL/span.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
class MemoryMappedFile
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* Opens and maps the whole file
|
||||
*
|
||||
* \param p_file The file to map
|
||||
*/
|
||||
explicit MemoryMappedFile(const File& p_file);
|
||||
|
||||
MemoryMappedFile(const MemoryMappedFile& p_file) = delete;
|
||||
MemoryMappedFile(MemoryMappedFile&& p_file) = delete;
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
*/
|
||||
~MemoryMappedFile();
|
||||
|
||||
/**
|
||||
* Get the mapped content of the file
|
||||
*
|
||||
* \return The mapped bytes
|
||||
*/
|
||||
[[nodiscard]]
|
||||
eastl::span<const std::byte> GetData() const;
|
||||
|
||||
MemoryMappedFile& operator=(const MemoryMappedFile& p_file) = delete;
|
||||
MemoryMappedFile& operator=(MemoryMappedFile&& p_file) = delete;
|
||||
|
||||
private:
|
||||
#if defined BIGFOOT_WINDOWS
|
||||
/**
|
||||
* Handle to the file
|
||||
*/
|
||||
void* m_fileHandle = nullptr;
|
||||
|
||||
/**
|
||||
* Handle to the file mapping
|
||||
*/
|
||||
void* m_mappingHandle = nullptr;
|
||||
#elif defined BIGFOOT_LINUX
|
||||
/**
|
||||
* Handle to the file
|
||||
*/
|
||||
int m_fileDescriptor = -1;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The mapped size
|
||||
*/
|
||||
std::size_t m_size = 0;
|
||||
|
||||
/**
|
||||
* The mapped data
|
||||
*/
|
||||
std::byte* m_data = nullptr;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
class WritableMemoryMappedFile
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* Creates and maps the file
|
||||
*
|
||||
* \param p_file The file to create and map
|
||||
* \param p_size The size to map
|
||||
*/
|
||||
WritableMemoryMappedFile(const File& p_file, std::size_t p_size);
|
||||
|
||||
WritableMemoryMappedFile(const WritableMemoryMappedFile& p_file) = delete;
|
||||
WritableMemoryMappedFile(WritableMemoryMappedFile&& p_file) = delete;
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
*/
|
||||
~WritableMemoryMappedFile();
|
||||
|
||||
/**
|
||||
* Get the mapped content of the file
|
||||
*
|
||||
* \return The mapped bytes
|
||||
*/
|
||||
[[nodiscard]]
|
||||
eastl::span<std::byte> GetData() const;
|
||||
|
||||
/**
|
||||
* Hint the OS to prefetch a range of data, so writes into that range do not each pay a page fault
|
||||
*
|
||||
* \param p_offset The offset, in bytes, to start prefetching from
|
||||
* \param p_size The number of bytes to prefetch
|
||||
*/
|
||||
void Prefetch(std::size_t p_offset, std::size_t p_size) const;
|
||||
|
||||
WritableMemoryMappedFile& operator=(const WritableMemoryMappedFile& p_file) = delete;
|
||||
WritableMemoryMappedFile& operator=(WritableMemoryMappedFile&& p_file) = delete;
|
||||
|
||||
private:
|
||||
#if defined BIGFOOT_WINDOWS
|
||||
/**
|
||||
* Handle to the file
|
||||
*/
|
||||
void* m_fileHandle = nullptr;
|
||||
|
||||
/**
|
||||
* Handle to the file mapping
|
||||
*/
|
||||
void* m_mappingHandle = nullptr;
|
||||
#elif defined BIGFOOT_LINUX
|
||||
/**
|
||||
* Handle to the file
|
||||
*/
|
||||
int m_fileDescriptor = -1;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The mapped size
|
||||
*/
|
||||
std::size_t m_size = 0;
|
||||
|
||||
/**
|
||||
* The mapped data
|
||||
*/
|
||||
std::byte* m_data = nullptr;
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
|
||||
#endif
|
||||
@@ -1,95 +0,0 @@
|
||||
/*********************************************************************
|
||||
* \file EASTLFormatters.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date December 2025
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_SYSTEM_EASTLFORMATTERS_HPP
|
||||
#define BIGFOOT_SYSTEM_EASTLFORMATTERS_HPP
|
||||
#include <Utils/TargetMacros.h>
|
||||
|
||||
#if defined(BIGFOOT_NOT_OPTIMIZED)
|
||||
#include <quill/DeferredFormatCodec.h>
|
||||
#endif
|
||||
|
||||
#include <format>
|
||||
|
||||
#include <EASTL/string.h>
|
||||
#include <EASTL/string_view.h>
|
||||
|
||||
// STRING
|
||||
|
||||
template<>
|
||||
struct std::formatter<eastl::string>
|
||||
{
|
||||
constexpr auto parse(std::format_parse_context& ctx)
|
||||
{
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template<typename FormatContext>
|
||||
auto format(const eastl::string& p_string, FormatContext& ctx) const
|
||||
{
|
||||
return std::format_to(ctx.out(), "{}", p_string.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
template<>
|
||||
struct fmtquill::formatter<eastl::string>
|
||||
{
|
||||
constexpr auto parse(format_parse_context& ctx)
|
||||
{
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
auto format(const eastl::string& p_string, format_context& ctx) const
|
||||
{
|
||||
return fmtquill::format_to(ctx.out(), "{}", p_string.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct quill::Codec<eastl::string>: quill::DeferredFormatCodec<eastl::string>
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
// STRING_VIEW
|
||||
|
||||
template<>
|
||||
struct std::formatter<eastl::string_view>
|
||||
{
|
||||
constexpr auto parse(std::format_parse_context& ctx)
|
||||
{
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template<typename FormatContext>
|
||||
auto format(const eastl::string_view& p_stringView, FormatContext& ctx) const
|
||||
{
|
||||
return std::format_to(ctx.out(), "{}", p_stringView.data());
|
||||
}
|
||||
};
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
template<>
|
||||
struct fmtquill::formatter<eastl::string_view>
|
||||
{
|
||||
constexpr auto parse(format_parse_context& ctx)
|
||||
{
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
auto format(const eastl::string_view& p_stringView, format_context& ctx) const
|
||||
{
|
||||
return fmtquill::format_to(ctx.out(), "{}", p_stringView.data());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct quill::Codec<eastl::string_view>: quill::DeferredFormatCodec<eastl::string_view>
|
||||
{
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
@@ -6,55 +6,15 @@
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_SYSTEM_SYSTEMASSERTHANDLER_HPP
|
||||
#define BIGFOOT_SYSTEM_SYSTEMASSERTHANDLER_HPP
|
||||
#include <Utils/Assert.hpp>
|
||||
|
||||
#include <System/SystemLogger_generated.hpp>
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
#include <EASTL/utility.h>
|
||||
#include <Utils/Assert/AssertHandler.hpp>
|
||||
|
||||
#include <format>
|
||||
#include <source_location>
|
||||
#include <string_view>
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
class SystemAssertHandler
|
||||
{
|
||||
public:
|
||||
SystemAssertHandler() = delete;
|
||||
|
||||
SystemAssertHandler(const SystemAssertHandler& p_handler) = delete;
|
||||
SystemAssertHandler(SystemAssertHandler&& p_handler) = delete;
|
||||
|
||||
~SystemAssertHandler() = delete;
|
||||
|
||||
/**
|
||||
* Handle an assertion.
|
||||
*
|
||||
* \param p_location Location of the assertion.
|
||||
* \param p_stacktrace The stack trace
|
||||
* \param p_format Format string for the assertion message.
|
||||
* \param p_args Arguments for the format string.
|
||||
*/
|
||||
template<typename... ARGS>
|
||||
static void Handle(const std::source_location& p_location,
|
||||
const std::string_view p_stacktrace,
|
||||
std::format_string<ARGS...> p_format,
|
||||
ARGS&&... p_args)
|
||||
{
|
||||
BIGFOOT_LOG_FATAL(SYSTEM_LOGGER,
|
||||
"Assert: {} (File:{}, Line:{}, Function:{}\n{}",
|
||||
std::format(p_format, eastl::forward<ARGS>(p_args)...),
|
||||
p_location.file_name(),
|
||||
p_location.line(),
|
||||
p_location.function_name(),
|
||||
p_stacktrace);
|
||||
}
|
||||
|
||||
SystemAssertHandler& operator=(const SystemAssertHandler& p_handler) = delete;
|
||||
SystemAssertHandler& operator=(SystemAssertHandler&& p_handler) = delete;
|
||||
};
|
||||
using SystemAssertHandler = AssertHandler<SYSTEM_LOGGER>;
|
||||
} // namespace Bigfoot
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_SYSTEMLOGGER_GENERATED_HPP
|
||||
#define BIGFOOT_SYSTEMLOGGER_GENERATED_HPP
|
||||
#include <System/Log/Log.hpp>
|
||||
#include <Utils/Log/LogMacros.hpp>
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
native_include "System/Time/Time.hpp";
|
||||
|
||||
namespace Flat.Bigfoot;
|
||||
|
||||
struct Time (native_type: "::Bigfoot::Time")
|
||||
{
|
||||
epoch:ulong;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*********************************************************************
|
||||
* \file Time.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date December 2025
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_SYSTEM_TIME_TIME_HPP
|
||||
#define BIGFOOT_SYSTEM_TIME_TIME_HPP
|
||||
#include <chrono>
|
||||
#include <compare>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
class Time
|
||||
{
|
||||
public:
|
||||
Time(const std::uint64_t p_epoch);
|
||||
|
||||
[[nodiscard]]
|
||||
std::uint32_t GetYear() const;
|
||||
|
||||
[[nodiscard]]
|
||||
std::uint32_t GetMonth() const;
|
||||
|
||||
[[nodiscard]]
|
||||
std::uint32_t GetDay() const;
|
||||
|
||||
[[nodiscard]]
|
||||
std::uint32_t GetHour() const;
|
||||
|
||||
[[nodiscard]]
|
||||
std::uint32_t GetMinute() const;
|
||||
|
||||
[[nodiscard]]
|
||||
std::uint32_t GetSecond() const;
|
||||
|
||||
[[nodiscard]]
|
||||
std::uint32_t GetMicrosecond() const;
|
||||
|
||||
[[nodiscard]]
|
||||
std::uint64_t GetEpoch() const;
|
||||
|
||||
[[nodiscard]]
|
||||
bool operator==(const Time& p_other) const
|
||||
{
|
||||
return m_epoch == p_other.m_epoch;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto operator<=>(const Time& p_other) const
|
||||
{
|
||||
return m_epoch <=> p_other.m_epoch;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static Time Now();
|
||||
|
||||
private:
|
||||
std::uint64_t m_epoch;
|
||||
std::tm m_timeInfo;
|
||||
std::chrono::microseconds m_microseconds;
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
namespace Flat
|
||||
{
|
||||
namespace Bigfoot
|
||||
{
|
||||
struct Time;
|
||||
}
|
||||
} // namespace Flat
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
namespace flatbuffers
|
||||
{
|
||||
Flat::Bigfoot::Time Pack(const Bigfoot::Time& p_time);
|
||||
Bigfoot::Time UnPack(const Flat::Bigfoot::Time& p_flatTime);
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
|
||||
#ifndef FLATBUFFERS_GENERATED_TIME_FLAT_BIGFOOT_H_
|
||||
#define FLATBUFFERS_GENERATED_TIME_FLAT_BIGFOOT_H_
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
|
||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||
// generated, otherwise it may not be compatible.
|
||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 19,
|
||||
"Non-compatible flatbuffers version included");
|
||||
// Ensure the included flatbuffers.h is Bigfoot's fork - stock
|
||||
// flatbuffers (or a differently versioned Bigfoot fork) is not compatible.
|
||||
#ifndef FLATBUFFERS_BIGFOOT_VERSION
|
||||
#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible"
|
||||
#endif
|
||||
static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1,
|
||||
"Non-compatible Bigfoot flatbuffers fork version included");
|
||||
|
||||
#include "System/Time/Time.hpp"
|
||||
|
||||
#include "EASTL/unique_ptr.h"
|
||||
#include "EASTL/string.h"
|
||||
#include "EASTL/vector.h"
|
||||
|
||||
namespace Flat {
|
||||
namespace Bigfoot {
|
||||
|
||||
struct Time;
|
||||
|
||||
inline const ::flatbuffers::TypeTable *TimeTypeTable();
|
||||
|
||||
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Time FLATBUFFERS_FINAL_CLASS {
|
||||
private:
|
||||
uint64_t epoch_;
|
||||
|
||||
public:
|
||||
struct Traits;
|
||||
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
return TimeTypeTable();
|
||||
}
|
||||
static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() {
|
||||
return "Flat.Bigfoot.Time";
|
||||
}
|
||||
Time()
|
||||
: epoch_(0) {
|
||||
}
|
||||
Time(uint64_t _epoch)
|
||||
: epoch_(::flatbuffers::EndianScalar(_epoch)) {
|
||||
}
|
||||
uint64_t epoch() const {
|
||||
return ::flatbuffers::EndianScalar(epoch_);
|
||||
}
|
||||
};
|
||||
FLATBUFFERS_STRUCT_END(Time, 8);
|
||||
|
||||
struct Time::Traits {
|
||||
using type = Time;
|
||||
};
|
||||
|
||||
inline const ::flatbuffers::TypeTable *TimeTypeTable() {
|
||||
static const ::flatbuffers::TypeCode type_codes[] = {
|
||||
{ ::flatbuffers::ET_ULONG, 0, -1 }
|
||||
};
|
||||
static const int64_t values[] = { 0, 8 };
|
||||
static const ::flatbuffers::TypeTable tt = {
|
||||
::flatbuffers::ST_STRUCT, 1, type_codes, nullptr, nullptr, values, nullptr
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
|
||||
} // namespace Bigfoot
|
||||
} // namespace Flat
|
||||
|
||||
#endif // FLATBUFFERS_GENERATED_TIME_FLAT_BIGFOOT_H_
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
namespace flatbuffers
|
||||
{
|
||||
Bigfoot::Flat::UUID Pack(const Bigfoot::UUID& p_uuid);
|
||||
Bigfoot::UUID UnPack(const Bigfoot::Flat::UUID& p_flatUUID);
|
||||
Flat::Bigfoot::UUID Pack(const Bigfoot::UUID& p_uuid);
|
||||
Bigfoot::UUID UnPack(const Flat::Bigfoot::UUID& p_flatUUID);
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
native_include "System/UUID/FlatUUID.hpp";
|
||||
native_include "System/UUID/UUID.hpp";
|
||||
|
||||
namespace Bigfoot.Flat;
|
||||
namespace Flat.Bigfoot;
|
||||
|
||||
struct UUID (native_type: "::Bigfoot::UUID")
|
||||
{
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
* \author Romain BOULLARD
|
||||
* \date October 2025
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_SYSTEM_UUID_HPP
|
||||
#define BIGFOOT_SYSTEM_UUID_HPP
|
||||
|
||||
#ifndef BIGFOOT_SYSTEM_UUID_UUID_HPP
|
||||
#define BIGFOOT_SYSTEM_UUID_UUID_HPP
|
||||
#include <ankerl/unordered_dense.h>
|
||||
#include <fmt/format.h>
|
||||
#include <uuid.h>
|
||||
|
||||
namespace Bigfoot
|
||||
@@ -16,6 +17,11 @@ class UUID
|
||||
public:
|
||||
static constexpr std::uint32_t UUID_BYTE_SIZE = 16;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Will default initialize an UUID to a valid value
|
||||
*
|
||||
*/
|
||||
UUID();
|
||||
|
||||
/**
|
||||
@@ -32,22 +38,26 @@ class UUID
|
||||
*/
|
||||
explicit UUID(const std::span<const std::byte, UUID_BYTE_SIZE> p_raw);
|
||||
|
||||
UUID(const UUID& p_uuid) = default;
|
||||
UUID(UUID&& p_uuid) noexcept = default;
|
||||
/**
|
||||
* Gets the raw bytes of a UUID
|
||||
*
|
||||
* \return A view to the raw bytes
|
||||
*/
|
||||
[[nodiscard]]
|
||||
std::span<const std::byte, UUID_BYTE_SIZE> ToBytes() const;
|
||||
|
||||
~UUID() = default;
|
||||
/**
|
||||
* Gets the string representation of a UUID
|
||||
*
|
||||
* \return A string representing the UUID
|
||||
*/
|
||||
[[nodiscard]]
|
||||
std::string ToString() const;
|
||||
|
||||
operator std::span<const std::byte, UUID_BYTE_SIZE>() const;
|
||||
operator std::string() const;
|
||||
operator bool() const;
|
||||
|
||||
UUID& operator=(const UUID& p_uuid) = default;
|
||||
UUID& operator=(UUID&& p_uuid) noexcept = default;
|
||||
|
||||
[[nodiscard]]
|
||||
bool operator==(const UUID& p_uuid) const = default;
|
||||
[[nodiscard]]
|
||||
bool operator!=(const UUID& p_uuid) const = default;
|
||||
bool operator==(const UUID& p_uuid) const;
|
||||
[[nodiscard]]
|
||||
bool operator<(const UUID& p_uuid) const;
|
||||
|
||||
@@ -73,8 +83,6 @@ class UUID
|
||||
static UUID NULL_UUID;
|
||||
|
||||
private:
|
||||
friend struct std::hash<UUID>;
|
||||
|
||||
/**
|
||||
* The uuid.
|
||||
*/
|
||||
@@ -97,27 +105,34 @@ class UUID
|
||||
template<>
|
||||
struct std::hash<Bigfoot::UUID>
|
||||
{
|
||||
using is_avalanching = void;
|
||||
|
||||
[[nodiscard]]
|
||||
std::size_t operator()(const Bigfoot::UUID& p_uuid) const noexcept
|
||||
{
|
||||
return std::hash<uuids::uuid>()(p_uuid.m_uuid);
|
||||
const auto bytes = p_uuid.ToBytes();
|
||||
return ankerl::unordered_dense::detail::wyhash::hash(bytes.data(), bytes.size());
|
||||
}
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
template<>
|
||||
struct std::formatter<Bigfoot::UUID, char>
|
||||
struct fmt::formatter<Bigfoot::UUID>
|
||||
{
|
||||
constexpr auto parse(std::format_parse_context& ctx)
|
||||
constexpr auto parse(format_parse_context& ctx)
|
||||
{
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template<typename FormatContext>
|
||||
auto format(const Bigfoot::UUID& p_uuid, FormatContext& ctx) const
|
||||
auto format(const Bigfoot::UUID& p_uuid, format_context& ctx) const
|
||||
{
|
||||
return std::format_to(ctx.out(), "{}", static_cast<std::string>(p_uuid));
|
||||
return fmt::format_to(ctx.out(), "{}", p_uuid.ToString());
|
||||
}
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
#include <quill/DeferredFormatCodec.h>
|
||||
|
||||
@@ -131,7 +146,7 @@ struct fmtquill::formatter<Bigfoot::UUID>
|
||||
|
||||
auto format(const Bigfoot::UUID& p_uuid, format_context& ctx) const
|
||||
{
|
||||
return fmtquill::format_to(ctx.out(), "{}", static_cast<std::string>(p_uuid));
|
||||
return fmtquill::format_to(ctx.out(), "{}", p_uuid.ToString());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -141,4 +156,22 @@ struct quill::Codec<Bigfoot::UUID>: quill::DeferredFormatCodec<Bigfoot::UUID>
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
namespace Flat
|
||||
{
|
||||
namespace Bigfoot
|
||||
{
|
||||
struct UUID;
|
||||
}
|
||||
} // namespace Flat
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
namespace flatbuffers
|
||||
{
|
||||
Flat::Bigfoot::UUID Pack(const Bigfoot::UUID& p_uuid);
|
||||
Bigfoot::UUID UnPack(const Flat::Bigfoot::UUID& p_flatUUID);
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
|
||||
#ifndef FLATBUFFERS_GENERATED_UUID_BIGFOOT_FLAT_H_
|
||||
#define FLATBUFFERS_GENERATED_UUID_BIGFOOT_FLAT_H_
|
||||
#ifndef FLATBUFFERS_GENERATED_UUID_FLAT_BIGFOOT_H_
|
||||
#define FLATBUFFERS_GENERATED_UUID_FLAT_BIGFOOT_H_
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
|
||||
@@ -12,14 +12,22 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 19,
|
||||
"Non-compatible flatbuffers version included");
|
||||
// Ensure the included flatbuffers.h is Bigfoot's fork - stock
|
||||
// flatbuffers (or a differently versioned Bigfoot fork) is not compatible.
|
||||
#ifndef FLATBUFFERS_BIGFOOT_VERSION
|
||||
#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible"
|
||||
#endif
|
||||
static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1,
|
||||
"Non-compatible Bigfoot flatbuffers fork version included");
|
||||
|
||||
#include "System/UUID/FlatUUID.hpp"
|
||||
#include "System/UUID/UUID.hpp"
|
||||
|
||||
#include "EASTL/unique_ptr.h"
|
||||
#include "EASTL/string.h"
|
||||
#include "EASTL/vector.h"
|
||||
|
||||
namespace Bigfoot {
|
||||
namespace Flat {
|
||||
namespace Bigfoot {
|
||||
|
||||
struct UUID;
|
||||
|
||||
@@ -35,7 +43,7 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(1) UUID FLATBUFFERS_FINAL_CLASS {
|
||||
return UUIDTypeTable();
|
||||
}
|
||||
static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() {
|
||||
return "Bigfoot.Flat.UUID";
|
||||
return "Flat.Bigfoot.UUID";
|
||||
}
|
||||
UUID()
|
||||
: bytes_() {
|
||||
@@ -59,16 +67,13 @@ inline const ::flatbuffers::TypeTable *UUIDTypeTable() {
|
||||
};
|
||||
static const int16_t array_sizes[] = { 16, };
|
||||
static const int64_t values[] = { 0, 16 };
|
||||
static const char * const names[] = {
|
||||
"bytes"
|
||||
};
|
||||
static const ::flatbuffers::TypeTable tt = {
|
||||
::flatbuffers::ST_STRUCT, 1, type_codes, nullptr, array_sizes, values, names
|
||||
::flatbuffers::ST_STRUCT, 1, type_codes, nullptr, array_sizes, values, nullptr
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
|
||||
} // namespace Flat
|
||||
} // namespace Bigfoot
|
||||
} // namespace Flat
|
||||
|
||||
#endif // FLATBUFFERS_GENERATED_UUID_BIGFOOT_FLAT_H_
|
||||
#endif // FLATBUFFERS_GENERATED_UUID_FLAT_BIGFOOT_H_
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
* \author Romain BOULLARD
|
||||
* \date December 2025
|
||||
*********************************************************************/
|
||||
#include <System/Time.hpp>
|
||||
#include <System/Time/Time.hpp>
|
||||
|
||||
#include <System/SystemAssertHandler.hpp>
|
||||
#include <System/Time/Time_generated.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -54,56 +55,56 @@ Time::Time(const std::uint64_t p_epoch):
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
std::uint32_t Time::Year() const
|
||||
std::uint32_t Time::GetYear() const
|
||||
{
|
||||
return m_timeInfo.tm_year + 1900;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
std::uint32_t Time::Month() const
|
||||
std::uint32_t Time::GetMonth() const
|
||||
{
|
||||
return m_timeInfo.tm_mon + 1;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
std::uint32_t Time::Day() const
|
||||
std::uint32_t Time::GetDay() const
|
||||
{
|
||||
return m_timeInfo.tm_mday;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
std::uint32_t Time::Hour() const
|
||||
std::uint32_t Time::GetHour() const
|
||||
{
|
||||
return m_timeInfo.tm_hour;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
std::uint32_t Time::Minute() const
|
||||
std::uint32_t Time::GetMinute() const
|
||||
{
|
||||
return m_timeInfo.tm_min;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
std::uint32_t Time::Second() const
|
||||
std::uint32_t Time::GetSecond() const
|
||||
{
|
||||
return m_timeInfo.tm_sec;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
std::uint32_t Time::Microsecond() const
|
||||
std::uint32_t Time::GetMicrosecond() const
|
||||
{
|
||||
return static_cast<std::uint32_t>(m_microseconds.count());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
std::uint64_t Time::Epoch() const
|
||||
std::uint64_t Time::GetEpoch() const
|
||||
{
|
||||
return m_epoch;
|
||||
}
|
||||
@@ -119,3 +120,20 @@ Time Time::Now()
|
||||
return Time {epochInMicroSeconds};
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
namespace flatbuffers
|
||||
{
|
||||
Flat::Bigfoot::Time Pack(const Bigfoot::Time& p_time)
|
||||
{
|
||||
return Flat::Bigfoot::Time {p_time.GetEpoch()};
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
Bigfoot::Time UnPack(const Flat::Bigfoot::Time& p_flatTime)
|
||||
{
|
||||
return Bigfoot::Time {p_flatTime.epoch()};
|
||||
}
|
||||
} // namespace flatbuffers
|
||||
@@ -1,27 +0,0 @@
|
||||
/*********************************************************************
|
||||
* \file FlatUUID.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date December 2025
|
||||
*********************************************************************/
|
||||
#include <System/UUID/FlatUUID.hpp>
|
||||
|
||||
namespace flatbuffers
|
||||
{
|
||||
Bigfoot::Flat::UUID Pack(const Bigfoot::UUID& p_uuid)
|
||||
{
|
||||
const std::span<const std::byte, Bigfoot::UUID::UUID_BYTE_SIZE> bytes = p_uuid;
|
||||
return Bigfoot::Flat::UUID {
|
||||
std::span<const std::uint8_t, Bigfoot::UUID::UUID_BYTE_SIZE> {reinterpret_cast<const std::uint8_t*>(bytes.data()),
|
||||
bytes.size()}};
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
Bigfoot::UUID UnPack(const Bigfoot::Flat::UUID& p_flatUUID)
|
||||
{
|
||||
const std::span<const std::uint8_t, Bigfoot::UUID::UUID_BYTE_SIZE> bytesView {p_flatUUID.bytes()->data(),
|
||||
p_flatUUID.bytes()->size()};
|
||||
return Bigfoot::UUID {std::as_bytes(bytesView)};
|
||||
}
|
||||
} // namespace flatbuffers
|
||||
@@ -6,6 +6,8 @@
|
||||
*********************************************************************/
|
||||
#include <System/UUID/UUID.hpp>
|
||||
|
||||
#include <System/UUID/UUID_generated.hpp>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
UUID UUID::NULL_UUID {"00000000-0000-0000-0000-000000000000"};
|
||||
@@ -41,14 +43,14 @@ UUID::UUID(const std::span<const std::byte, UUID_BYTE_SIZE> p_raw)
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
UUID::operator std::span<const std::byte, UUID::UUID_BYTE_SIZE>() const
|
||||
std::span<const std::byte, UUID::UUID_BYTE_SIZE> UUID::ToBytes() const
|
||||
{
|
||||
return m_uuid.as_bytes();
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
UUID::operator std::string() const
|
||||
std::string UUID::ToString() const
|
||||
{
|
||||
return uuids::to_string(m_uuid);
|
||||
}
|
||||
@@ -60,6 +62,11 @@ UUID::operator bool() const
|
||||
return *this != NULL_UUID;
|
||||
}
|
||||
|
||||
bool UUID::operator==(const UUID& p_uuid) const
|
||||
{
|
||||
return m_uuid == p_uuid.m_uuid;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
bool UUID::operator<(const UUID& p_uuid) const
|
||||
@@ -85,3 +92,25 @@ uuids::uuid_random_generator UUID::GetUUIDGenerator()
|
||||
return uuids::uuid_random_generator {ms_randomGenerator};
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
namespace flatbuffers
|
||||
{
|
||||
Flat::Bigfoot::UUID Pack(const Bigfoot::UUID& p_uuid)
|
||||
{
|
||||
const std::span<const std::byte, Bigfoot::UUID::UUID_BYTE_SIZE> bytes = p_uuid.ToBytes();
|
||||
return Flat::Bigfoot::UUID {
|
||||
std::span<const std::uint8_t, Bigfoot::UUID::UUID_BYTE_SIZE> {reinterpret_cast<const std::uint8_t*>(bytes.data()),
|
||||
bytes.size()}};
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
Bigfoot::UUID UnPack(const Flat::Bigfoot::UUID& p_flatUUID)
|
||||
{
|
||||
const std::span<const std::uint8_t, Bigfoot::UUID::UUID_BYTE_SIZE> bytesView {p_flatUUID.bytes()->data(),
|
||||
p_flatUUID.bytes()->size()};
|
||||
return Bigfoot::UUID {std::as_bytes(bytesView)};
|
||||
}
|
||||
} // namespace flatbuffers
|
||||
|
||||
@@ -2,7 +2,15 @@ get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
project(${PackageName})
|
||||
|
||||
set(PublicDependencies
|
||||
$<$<CONFIG:Debug,RelWithDebInfo>:cpptrace::cpptrace>)
|
||||
$<$<CONFIG:Debug,RelWithDebInfo>:quill::quill>
|
||||
$<IF:$<BOOL:${ASAN}>,mimalloc-asan,mimalloc-static>
|
||||
unordered_dense::unordered_dense
|
||||
EASTL::EASTL
|
||||
EAStdC::EAStdC
|
||||
fmt::fmt
|
||||
flatbuffers::flatbuffers
|
||||
rapidhash::rapidhash
|
||||
effolkronium_random)
|
||||
set(PrivateDependencies)
|
||||
set(BigfootPublicDependencies)
|
||||
set(BigfootPrivateDependencies)
|
||||
@@ -12,4 +20,13 @@ bigfoot_create_package_lib(
|
||||
"${PrivateLibraries}"
|
||||
"${BigfootPublicDependencies}"
|
||||
"${BigfootPrivateDependencies}"
|
||||
"")
|
||||
"")
|
||||
set_source_files_properties(../Utils/MimallocImpl.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
|
||||
set_source_files_properties(../Utils/EASTLVsnprintfImpl.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
|
||||
|
||||
bigfoot_create_logger()
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
$<$<CONFIG:Debug,RelWithDebInfo>:QUILL_NO_EXCEPTIONS>
|
||||
$<$<CONFIG:Debug,RelWithDebInfo>:QUILL_DISABLE_NON_PREFIXED_MACROS>)
|
||||
+15
-23
@@ -6,11 +6,10 @@
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_UTILS_ASSERT_HPP
|
||||
#define BIGFOOT_UTILS_ASSERT_HPP
|
||||
#include <Utils/Log/LogMacros.hpp>
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
|
||||
#include <cpptrace/cpptrace.hpp>
|
||||
|
||||
#include <source_location>
|
||||
#include <string>
|
||||
|
||||
@@ -18,16 +17,27 @@
|
||||
#include <csignal>
|
||||
#endif
|
||||
|
||||
#define BIGFOOT_FLUSH_LOG \
|
||||
do \
|
||||
{ \
|
||||
if (Bigfoot::Singleton<Bigfoot::Log>::HasInstance()) \
|
||||
{ \
|
||||
Bigfoot::Singleton<Bigfoot::Log>::GetInstance().Flush(); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#if defined BIGFOOT_WINDOWS
|
||||
#define BREAK \
|
||||
do \
|
||||
{ \
|
||||
BIGFOOT_FLUSH_LOG; \
|
||||
__debugbreak(); \
|
||||
} while (false)
|
||||
#elif defined BIGFOOT_LINUX
|
||||
#define BREAK \
|
||||
do \
|
||||
{ \
|
||||
BIGFOOT_FLUSH_LOG; \
|
||||
std::raise(SIGTRAP); \
|
||||
} while (false)
|
||||
#endif
|
||||
@@ -38,13 +48,7 @@
|
||||
constexpr std::source_location location = std::source_location::current(); \
|
||||
if (!(p_assert)) [[unlikely]] \
|
||||
{ \
|
||||
constexpr auto stacktrace = []() -> std::string \
|
||||
{ \
|
||||
const cpptrace::stacktrace stacktrace = cpptrace::generate_trace(); \
|
||||
return stacktrace.to_string(); \
|
||||
}; \
|
||||
\
|
||||
HANDLER::Handle(location, stacktrace(), p_message __VA_OPT__(, ) __VA_ARGS__); \
|
||||
HANDLER::Handle(location, p_message __VA_OPT__(, ) __VA_ARGS__); \
|
||||
BREAK; \
|
||||
} \
|
||||
} while (false)
|
||||
@@ -55,13 +59,7 @@
|
||||
constexpr std::source_location location = std::source_location::current(); \
|
||||
if (!(p_assert)) [[unlikely]] \
|
||||
{ \
|
||||
constexpr auto stacktrace = []() -> std::string \
|
||||
{ \
|
||||
const cpptrace::stacktrace stacktrace = cpptrace::generate_trace(); \
|
||||
return stacktrace.to_string(); \
|
||||
}; \
|
||||
\
|
||||
HANDLER::Handle(location, stacktrace(), p_message __VA_OPT__(, ) __VA_ARGS__); \
|
||||
HANDLER::Handle(location, p_message __VA_OPT__(, ) __VA_ARGS__); \
|
||||
BREAK; \
|
||||
} \
|
||||
} while (false)
|
||||
@@ -72,13 +70,7 @@
|
||||
constexpr std::source_location location = std::source_location::current(); \
|
||||
if (!(p_assert)) [[unlikely]] \
|
||||
{ \
|
||||
constexpr auto stacktrace = []() -> std::string \
|
||||
{ \
|
||||
const cpptrace::stacktrace stacktrace = cpptrace::generate_trace(); \
|
||||
return stacktrace.to_string(); \
|
||||
}; \
|
||||
\
|
||||
HANDLER::Handle(location, stacktrace(), p_message __VA_OPT__(, ) __VA_ARGS__); \
|
||||
HANDLER::Handle(location, p_message __VA_OPT__(, ) __VA_ARGS__); \
|
||||
BREAK; \
|
||||
std::abort(); \
|
||||
} \
|
||||
@@ -0,0 +1,54 @@
|
||||
/*********************************************************************
|
||||
* \file AssertHandler.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date August 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_UTILS_ASSERTHANDLER_HPP
|
||||
#define BIGFOOT_UTILS_ASSERTHANDLER_HPP
|
||||
#include <Utils/Assert/Assert.hpp>
|
||||
#include <Utils/Log/Log.hpp>
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <source_location>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
template<Log::LoggerInfo& LOGGER>
|
||||
class AssertHandler
|
||||
{
|
||||
public:
|
||||
AssertHandler() = delete;
|
||||
|
||||
AssertHandler(const AssertHandler& p_handler) = delete;
|
||||
AssertHandler(AssertHandler&& p_handler) = delete;
|
||||
|
||||
~AssertHandler() = delete;
|
||||
|
||||
/**
|
||||
* Handle an assertion.
|
||||
*
|
||||
* \param p_location Location of the assertion.
|
||||
* \param p_format Format string for the assertion message.
|
||||
* \param p_args Arguments for the format string.
|
||||
*/
|
||||
template<typename... ARGS>
|
||||
static void Handle(const std::source_location& p_location, fmt::format_string<ARGS...> p_format, ARGS&&... p_args)
|
||||
{
|
||||
BIGFOOT_LOG_FATAL(LOGGER,
|
||||
"Assert: {} (File:{}, Line:{}, Function:{}\n",
|
||||
fmt::format(p_format, std::forward<ARGS>(p_args)...),
|
||||
p_location.file_name(),
|
||||
p_location.line(),
|
||||
p_location.function_name());
|
||||
}
|
||||
|
||||
AssertHandler& operator=(const AssertHandler& p_handler) = delete;
|
||||
AssertHandler& operator=(AssertHandler&& p_handler) = delete;
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
#endif
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,115 @@
|
||||
/*********************************************************************
|
||||
* \file EASTLFormatters.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date December 2025
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_UTILS_LOG_EASTLFORMATTERS_HPP
|
||||
#define BIGFOOT_UTILS_LOG_EASTLFORMATTERS_HPP
|
||||
#include <Utils/TargetMacros.h>
|
||||
|
||||
#if defined(BIGFOOT_NOT_OPTIMIZED)
|
||||
#include <quill/core/Codec.h>
|
||||
#endif
|
||||
|
||||
#include <EASTL/string.h>
|
||||
#include <EASTL/string_view.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
// STRING
|
||||
|
||||
template<>
|
||||
struct fmt::formatter<eastl::string>
|
||||
{
|
||||
constexpr auto parse(format_parse_context& ctx)
|
||||
{
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
auto format(const eastl::string& p_string, format_context& ctx) const
|
||||
{
|
||||
return fmt::format_to(ctx.out(), "{}", p_string.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
template<>
|
||||
struct fmtquill::formatter<eastl::string>
|
||||
{
|
||||
constexpr auto parse(format_parse_context& ctx)
|
||||
{
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
auto format(const eastl::string& p_string, format_context& ctx) const
|
||||
{
|
||||
return fmtquill::format_to(ctx.out(), "{}", p_string.c_str());
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// STRING_VIEW
|
||||
|
||||
template<>
|
||||
struct fmt::formatter<eastl::string_view>
|
||||
{
|
||||
constexpr auto parse(format_parse_context& ctx)
|
||||
{
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
auto format(const eastl::string_view& p_stringView, format_context& ctx) const
|
||||
{
|
||||
return fmt::format_to(ctx.out(), "{}", p_stringView.data());
|
||||
}
|
||||
};
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
template<>
|
||||
struct fmtquill::formatter<eastl::string_view>
|
||||
{
|
||||
constexpr auto parse(format_parse_context& ctx)
|
||||
{
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
auto format(const eastl::string_view& p_stringView, format_context& ctx) const
|
||||
{
|
||||
return fmtquill::format_to(ctx.out(), "{}", p_stringView.data());
|
||||
}
|
||||
};
|
||||
|
||||
namespace Bigfoot::Codec
|
||||
{
|
||||
template<class STRING>
|
||||
struct string_view: quill::Codec<std::string_view>
|
||||
{
|
||||
using Base = quill::Codec<std::string_view>;
|
||||
|
||||
[[nodiscard]]
|
||||
static size_t compute_encoded_size(quill::detail::SizeCacheVector& p_cache, const STRING& p_arg) noexcept
|
||||
{
|
||||
return Base::compute_encoded_size(p_cache, std::string_view {p_arg.data(), p_arg.size()});
|
||||
}
|
||||
|
||||
static void encode(std::byte*& p_buffer,
|
||||
const quill::detail::SizeCacheVector& p_cache,
|
||||
std::uint32_t& p_cacheIndex,
|
||||
const STRING& p_arg) noexcept
|
||||
{
|
||||
Base::encode(p_buffer, p_cache, p_cacheIndex, std::string_view {p_arg.data(), p_arg.size()});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<>
|
||||
struct quill::Codec<eastl::string>: Bigfoot::Codec::string_view<eastl::string>
|
||||
{
|
||||
};
|
||||
|
||||
template<>
|
||||
struct quill::Codec<eastl::string_view>: Bigfoot::Codec::string_view<eastl::string_view>
|
||||
{
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,102 @@
|
||||
/*********************************************************************
|
||||
* \file Log.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date October 2025
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_UTILS_LOG_LOG_HPP
|
||||
#define BIGFOOT_UTILS_LOG_LOG_HPP
|
||||
#include <Utils/Log/EASTLFormatters.hpp>
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
#include <Utils/Log/Log_generated.hpp>
|
||||
|
||||
#include <EASTL/array.h>
|
||||
|
||||
#ifdef BIGFOOT_WINDOWS
|
||||
#pragma warning(disable: 4702)
|
||||
#endif
|
||||
#include <quill/Backend.h>
|
||||
#include <quill/Frontend.h>
|
||||
#include <quill/LogMacros.h>
|
||||
#include <quill/Logger.h>
|
||||
#include <quill/sinks/ConsoleSink.h>
|
||||
#if defined BIGFOOT_WINDOWS
|
||||
#pragma warning(default: 4702)
|
||||
#endif
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
class Log
|
||||
{
|
||||
public:
|
||||
struct LoggerInfo
|
||||
{
|
||||
std::string m_name;
|
||||
Flat::LogLevel m_level;
|
||||
};
|
||||
|
||||
Log();
|
||||
|
||||
Log(const Log& p_logger) = delete;
|
||||
Log(Log&& p_logger) = delete;
|
||||
|
||||
/**
|
||||
* Register a logger.
|
||||
*
|
||||
* \param p_loggerInfo The logger to register
|
||||
*/
|
||||
[[nodiscard]]
|
||||
quill::Logger* RegisterLogger(const LoggerInfo& p_loggerInfo);
|
||||
|
||||
/**
|
||||
* Unregister a logger.
|
||||
*
|
||||
* \param p_loggerInfo The logger to unregister
|
||||
*/
|
||||
void UnregisterLogger(const LoggerInfo& p_loggerInfo);
|
||||
|
||||
/**
|
||||
* Register a logger.
|
||||
*
|
||||
* \param p_loggerInfo The logger to get
|
||||
* \return The logger, nullptr if it does not exist
|
||||
*/
|
||||
[[nodiscard]]
|
||||
quill::Logger* GetLogger(const LoggerInfo& p_loggerInfo);
|
||||
|
||||
/**
|
||||
* Changes the loglevel of a Logger.
|
||||
*
|
||||
* \param p_loggerInfo The logger to change
|
||||
* \param p_level The new level
|
||||
*/
|
||||
void ChangeLoggerLogLevel(LoggerInfo& p_loggerInfo, const Flat::LogLevel p_level);
|
||||
|
||||
/*
|
||||
* Flush all the loggers
|
||||
*
|
||||
*/
|
||||
void Flush();
|
||||
|
||||
~Log();
|
||||
|
||||
Log& operator=(const Log& p_logger) = delete;
|
||||
Log& operator=(Log&& p_logger) = delete;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Set the LogLevel of a logger
|
||||
*
|
||||
* \param p_loggerInfo The logger to set
|
||||
*/
|
||||
void SetLoggerLevel(const LoggerInfo& p_loggerInfo);
|
||||
|
||||
/*
|
||||
* The sinks
|
||||
*/
|
||||
eastl::array<std::shared_ptr<quill::Sink>, 1> m_sinks;
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
#endif
|
||||
#endif
|
||||
+18
-96
@@ -1,103 +1,25 @@
|
||||
/*********************************************************************
|
||||
* \file Log.hpp
|
||||
* \file LogMacros.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date October 2025
|
||||
* \date May 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_SYSTEM_LOG_HPP
|
||||
#define BIGFOOT_SYSTEM_LOG_HPP
|
||||
#include <System/Log/EASTLFormatters.hpp>
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
#include <System/Log/Log_generated.hpp>
|
||||
|
||||
#ifndef BIGFOOT_UTILS_LOG_LOGMACROS_HPP
|
||||
#define BIGFOOT_UTILS_LOG_LOGMACROS_HPP
|
||||
#include <Utils/Log/Log.hpp>
|
||||
#include <Utils/Singleton.hpp>
|
||||
|
||||
#include <EASTL/array.h>
|
||||
|
||||
#ifdef BIGFOOT_WINDOWS
|
||||
#pragma warning(disable: 4702)
|
||||
#endif
|
||||
#include <quill/Backend.h>
|
||||
#include <quill/Frontend.h>
|
||||
#include <quill/LogMacros.h>
|
||||
#include <quill/Logger.h>
|
||||
#include <quill/sinks/ConsoleSink.h>
|
||||
#if defined BIGFOOT_WINDOWS
|
||||
#pragma warning(default: 4702)
|
||||
#endif
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
class Log
|
||||
{
|
||||
public:
|
||||
struct LoggerInfo
|
||||
{
|
||||
std::string m_name;
|
||||
Flat::LogLevel m_level;
|
||||
};
|
||||
|
||||
Log();
|
||||
|
||||
Log(const Log& p_logger) = delete;
|
||||
Log(Log&& p_logger) = delete;
|
||||
|
||||
/**
|
||||
* Register a logger.
|
||||
*
|
||||
* \param p_loggerInfo The logger to register
|
||||
*/
|
||||
[[nodiscard]]
|
||||
quill::Logger* RegisterLogger(const LoggerInfo& p_loggerInfo);
|
||||
|
||||
/**
|
||||
* Register a logger.
|
||||
*
|
||||
* \param p_loggerInfo The logger to get
|
||||
* \return The logger, nullptr if it does not exist
|
||||
*/
|
||||
[[nodiscard]]
|
||||
quill::Logger* GetLogger(const LoggerInfo& p_loggerInfo);
|
||||
|
||||
/**
|
||||
* Changes the loglevel of a Logger.
|
||||
*
|
||||
* \param p_loggerInfo The logger to change
|
||||
* \param p_level The new level
|
||||
*/
|
||||
void ChangeLoggerLogLevel(LoggerInfo& p_loggerInfo, const Flat::LogLevel p_level);
|
||||
|
||||
~Log();
|
||||
|
||||
Log& operator=(const Log& p_logger) = delete;
|
||||
Log& operator=(Log&& p_logger) = delete;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Set the LogLevel of a logger
|
||||
*
|
||||
* \param p_loggerInfo The logger to set
|
||||
*/
|
||||
void SetLoggerLevel(const LoggerInfo& p_loggerInfo);
|
||||
|
||||
/*
|
||||
* The sinks
|
||||
*/
|
||||
eastl::array<std::shared_ptr<quill::Sink>, 1> m_sinks;
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
#define BIGFOOT_LOG_DEBUG(loggerName, fmt, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (quill::Logger* logger = Bigfoot::Singleton<Bigfoot::Log>::Instance().GetLogger(loggerName)) \
|
||||
if (::quill::Logger* logger = ::Bigfoot::Singleton<::Bigfoot::Log>::GetInstance().GetLogger(loggerName)) \
|
||||
{ \
|
||||
QUILL_LOG_DEBUG(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
QUILL_LOG_DEBUG(Bigfoot::Singleton<Bigfoot::Log>::Instance().RegisterLogger(loggerName), \
|
||||
QUILL_LOG_DEBUG(::Bigfoot::Singleton<::Bigfoot::Log>::GetInstance().RegisterLogger(loggerName), \
|
||||
fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -105,13 +27,13 @@ class Log
|
||||
#define BIGFOOT_LOG_TRACE(loggerName, fmt, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (quill::Logger* logger = Bigfoot::Singleton<Bigfoot::Log>::Instance().GetLogger(loggerName)) \
|
||||
if (::quill::Logger* logger = ::Bigfoot::Singleton<::Bigfoot::Log>::GetInstance().GetLogger(loggerName)) \
|
||||
{ \
|
||||
QUILL_LOG_TRACE_L3(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
QUILL_LOG_TRACE_L3(Bigfoot::Singleton<Bigfoot::Log>::Instance().RegisterLogger(loggerName), \
|
||||
QUILL_LOG_TRACE_L3(::Bigfoot::Singleton<::Bigfoot::Log>::GetInstance().RegisterLogger(loggerName), \
|
||||
fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -119,13 +41,13 @@ class Log
|
||||
#define BIGFOOT_LOG_INFO(loggerName, fmt, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (quill::Logger* logger = Bigfoot::Singleton<Bigfoot::Log>::Instance().GetLogger(loggerName)) \
|
||||
if (::quill::Logger* logger = ::Bigfoot::Singleton<::Bigfoot::Log>::GetInstance().GetLogger(loggerName)) \
|
||||
{ \
|
||||
QUILL_LOG_INFO(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
QUILL_LOG_INFO(Bigfoot::Singleton<Bigfoot::Log>::Instance().RegisterLogger(loggerName), \
|
||||
QUILL_LOG_INFO(::Bigfoot::Singleton<::Bigfoot::Log>::GetInstance().RegisterLogger(loggerName), \
|
||||
fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -133,13 +55,13 @@ class Log
|
||||
#define BIGFOOT_LOG_WARN(loggerName, fmt, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (quill::Logger* logger = Bigfoot::Singleton<Bigfoot::Log>::Instance().GetLogger(loggerName)) \
|
||||
if (::quill::Logger* logger = ::Bigfoot::Singleton<::Bigfoot::Log>::GetInstance().GetLogger(loggerName)) \
|
||||
{ \
|
||||
QUILL_LOG_WARNING(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
QUILL_LOG_WARNING(Bigfoot::Singleton<Bigfoot::Log>::Instance().RegisterLogger(loggerName), \
|
||||
QUILL_LOG_WARNING(::Bigfoot::Singleton<::Bigfoot::Log>::GetInstance().RegisterLogger(loggerName), \
|
||||
fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -147,13 +69,13 @@ class Log
|
||||
#define BIGFOOT_LOG_ERROR(loggerName, fmt, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (quill::Logger* logger = Bigfoot::Singleton<Bigfoot::Log>::Instance().GetLogger(loggerName)) \
|
||||
if (::quill::Logger* logger = ::Bigfoot::Singleton<::Bigfoot::Log>::GetInstance().GetLogger(loggerName)) \
|
||||
{ \
|
||||
QUILL_LOG_ERROR(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
QUILL_LOG_ERROR(Bigfoot::Singleton<Bigfoot::Log>::Instance().RegisterLogger(loggerName), \
|
||||
QUILL_LOG_ERROR(::Bigfoot::Singleton<::Bigfoot::Log>::GetInstance().RegisterLogger(loggerName), \
|
||||
fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -161,13 +83,13 @@ class Log
|
||||
#define BIGFOOT_LOG_FATAL(loggerName, fmt, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (quill::Logger* logger = Bigfoot::Singleton<Bigfoot::Log>::Instance().GetLogger(loggerName)) \
|
||||
if (::quill::Logger* logger = ::Bigfoot::Singleton<::Bigfoot::Log>::GetInstance().GetLogger(loggerName)) \
|
||||
{ \
|
||||
QUILL_LOG_CRITICAL(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
QUILL_LOG_CRITICAL(Bigfoot::Singleton<Bigfoot::Log>::Instance().RegisterLogger(loggerName), \
|
||||
QUILL_LOG_CRITICAL(::Bigfoot::Singleton<::Bigfoot::Log>::GetInstance().RegisterLogger(loggerName), \
|
||||
fmt __VA_OPT__(, ) __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
+10
-13
@@ -12,9 +12,17 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 19,
|
||||
"Non-compatible flatbuffers version included");
|
||||
// Ensure the included flatbuffers.h is Bigfoot's fork - stock
|
||||
// flatbuffers (or a differently versioned Bigfoot fork) is not compatible.
|
||||
#ifndef FLATBUFFERS_BIGFOOT_VERSION
|
||||
#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible"
|
||||
#endif
|
||||
static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1,
|
||||
"Non-compatible Bigfoot flatbuffers fork version included");
|
||||
|
||||
#include "EASTL/unique_ptr.h"
|
||||
#include "EASTL/string.h"
|
||||
#include "EASTL/vector.h"
|
||||
|
||||
namespace Bigfoot {
|
||||
namespace Flat {
|
||||
@@ -95,11 +103,8 @@ inline const ::flatbuffers::TypeTable *LogSinkTypeTypeTable() {
|
||||
static const ::flatbuffers::TypeFunction type_refs[] = {
|
||||
Bigfoot::Flat::LogSinkTypeTypeTable
|
||||
};
|
||||
static const char * const names[] = {
|
||||
"Console"
|
||||
};
|
||||
static const ::flatbuffers::TypeTable tt = {
|
||||
::flatbuffers::ST_ENUM, 1, type_codes, type_refs, nullptr, nullptr, names
|
||||
::flatbuffers::ST_ENUM, 1, type_codes, type_refs, nullptr, nullptr, nullptr
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
@@ -116,16 +121,8 @@ inline const ::flatbuffers::TypeTable *LogLevelTypeTable() {
|
||||
static const ::flatbuffers::TypeFunction type_refs[] = {
|
||||
Bigfoot::Flat::LogLevelTypeTable
|
||||
};
|
||||
static const char * const names[] = {
|
||||
"Debug",
|
||||
"Trace",
|
||||
"Info",
|
||||
"Warn",
|
||||
"Error",
|
||||
"Critical"
|
||||
};
|
||||
static const ::flatbuffers::TypeTable tt = {
|
||||
::flatbuffers::ST_ENUM, 6, type_codes, type_refs, nullptr, nullptr, names
|
||||
::flatbuffers::ST_ENUM, 6, type_codes, type_refs, nullptr, nullptr, nullptr
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_@LOGGER_FILENAME_UPPER@_GENERATED_HPP
|
||||
#define BIGFOOT_@LOGGER_FILENAME_UPPER@_GENERATED_HPP
|
||||
#include <System/Log/Log.hpp>
|
||||
#include <Utils/Log/LogMacros.hpp>
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@
|
||||
* \author Romain BOULLARD
|
||||
* \date October 2025
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_CONCAT_PROFILER_HPP
|
||||
#define BIGFOOT_CONCAT_PROFILER_HPP
|
||||
#ifndef BIGFOOT_UTILS_PROFILER_HPP
|
||||
#define BIGFOOT_UTILS_PROFILER_HPP
|
||||
|
||||
#ifdef TRACY
|
||||
#include <tracy/Tracy.hpp>
|
||||
@@ -6,12 +6,7 @@
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_UTILS_SINGLETON_HPP
|
||||
#define BIGFOOT_UTILS_SINGLETON_HPP
|
||||
|
||||
#include <EASTL/array.h>
|
||||
#include <EASTL/bit.h>
|
||||
#include <EASTL/optional.h>
|
||||
#include <EASTL/type_traits.h>
|
||||
#include <EASTL/utility.h>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
@@ -31,11 +26,21 @@ class Singleton
|
||||
*
|
||||
* \return The instance
|
||||
*/
|
||||
static constexpr TYPE& Instance()
|
||||
static constexpr TYPE& GetInstance()
|
||||
{
|
||||
return ms_instance.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the instance initialized
|
||||
*
|
||||
* \return True if initialized, false otherwise
|
||||
*/
|
||||
static constexpr bool HasInstance()
|
||||
{
|
||||
return ms_instance.has_value();
|
||||
}
|
||||
|
||||
class Lifetime
|
||||
{
|
||||
public:
|
||||
@@ -44,11 +49,10 @@ class Singleton
|
||||
*
|
||||
* \param p_args Arguments for the singleton
|
||||
*/
|
||||
template<typename... ARGS,
|
||||
typename = eastl::enable_if_t<!(eastl::is_same_v<Lifetime, eastl::decay_t<ARGS>> || ...)>>
|
||||
template<typename... ARGS>
|
||||
explicit Lifetime(ARGS&&... p_args)
|
||||
{
|
||||
Initialize(eastl::forward<ARGS>(p_args)...);
|
||||
Initialize(std::forward<ARGS>(p_args)...);
|
||||
}
|
||||
|
||||
Lifetime(const Lifetime& p_lifetime) = delete;
|
||||
@@ -59,15 +63,11 @@ class Singleton
|
||||
Finalize();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
Lifetime& operator=(const Lifetime& p_lifetime) = delete;
|
||||
[[nodiscard]]
|
||||
Lifetime& operator=(Lifetime&& p_lifetime) = delete;
|
||||
Lifetime& operator=(Lifetime&& p_lifetime) noexcept = delete;
|
||||
};
|
||||
|
||||
[[nodiscard]]
|
||||
Singleton& operator=(const Singleton& p_singleton) = delete;
|
||||
[[nodiscard]]
|
||||
Singleton& operator=(Singleton&& p_singleton) = delete;
|
||||
|
||||
private:
|
||||
@@ -79,7 +79,7 @@ class Singleton
|
||||
template<typename... ARGS>
|
||||
static void Initialize(ARGS&&... p_args)
|
||||
{
|
||||
ms_instance.emplace(eastl::forward<ARGS>(p_args)...);
|
||||
ms_instance.emplace(std::forward<ARGS>(p_args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
* \author Romain BOULLARD
|
||||
* \date December 2025
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_UTILS_TAGGEDTYPE_H
|
||||
#define BIGFOOT_UTILS_TAGGEDTYPE_H
|
||||
#ifndef BIGFOOT_UTILS_TAGGEDTYPE_HPP
|
||||
#define BIGFOOT_UTILS_TAGGEDTYPE_HPP
|
||||
|
||||
#include <compare>
|
||||
|
||||
@@ -22,14 +22,6 @@ class TaggedType
|
||||
{
|
||||
}
|
||||
|
||||
constexpr TaggedType(const TaggedType& p_taggedType) = default;
|
||||
constexpr TaggedType(TaggedType&& p_taggedType) noexcept = default;
|
||||
|
||||
~TaggedType() = default;
|
||||
|
||||
constexpr TaggedType& operator=(const TaggedType& p_taggedType) = default;
|
||||
constexpr TaggedType& operator=(TaggedType&& p_taggedType) noexcept = default;
|
||||
|
||||
constexpr TaggedType& operator=(const TYPE& p_value)
|
||||
{
|
||||
m_value = p_value;
|
||||
|
||||
@@ -7,6 +7,14 @@
|
||||
#ifndef BIGFOOT_UTILS_TARGETMACROS_H
|
||||
#define BIGFOOT_UTILS_TARGETMACROS_H
|
||||
|
||||
#if defined BIGFOOT_WINDOWS
|
||||
#define BIGFOOT_WINDOWS_OR_LINUX(p_windows, p_linux) p_windows
|
||||
#endif
|
||||
|
||||
#if defined BIGFOOT_LINUX
|
||||
#define BIGFOOT_WINDOWS_OR_LINUX(p_windows, p_linux) p_linux
|
||||
#endif
|
||||
|
||||
#if defined BIGFOOT_OPTIMIZED
|
||||
#define BIGFOOT_OPTIMIZED_ONLY(...) __VA_ARGS__
|
||||
#define BIGFOOT_NOT_OPTIMIZED_ONLY(...)
|
||||
@@ -18,4 +26,16 @@
|
||||
#define BIGFOOT_NOT_OPTIMIZED_ONLY(...) __VA_ARGS__
|
||||
#define BIGFOOT_OPTIMIZED_OR_NOT(p_optimized, p_notOptimized) p_notOptimized
|
||||
#endif
|
||||
|
||||
#if defined BIGFOOT_TOOLMODE
|
||||
#define BIGFOOT_TOOLMODE_ONLY(...) __VA_ARGS__
|
||||
#define BIGFOOT_GAME_ONLY(...)
|
||||
#define BIGFOOT_GAME_OR_TOOLMODE(p_game, p_toolmode) p_toolmode
|
||||
#endif
|
||||
|
||||
#if defined BIGFOOT_GAME
|
||||
#define BIGFOOT_TOOLMODE_ONLY(...)
|
||||
#define BIGFOOT_GAME_ONLY(...) __VA_ARGS__
|
||||
#define BIGFOOT_GAME_OR_TOOLMODE(p_game, p_toolmode) p_game
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*********************************************************************
|
||||
* \file UtilsAssertHandler.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date May 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_UTILS_UTILSASSERTHANDLER_HPP
|
||||
#define BIGFOOT_UTILS_UTILSASSERTHANDLER_HPP
|
||||
#include <Utils/Assert/AssertHandler.hpp>
|
||||
#include <Utils/UtilsLogger_generated.hpp>
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
using UtilsAssertHandler = AssertHandler<UTILS_LOGGER>;
|
||||
} // namespace Bigfoot
|
||||
#endif
|
||||
#endif
|
||||
+5
-5
@@ -1,12 +1,12 @@
|
||||
// AUTO-GENERATED DO NOT TOUCH
|
||||
|
||||
/*********************************************************************
|
||||
* \file SystemTestsLogger.generated.hpp
|
||||
* \file UtilsLogger.generated.hpp
|
||||
*
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_SYSTEMTESTSLOGGER_GENERATED_HPP
|
||||
#define BIGFOOT_SYSTEMTESTSLOGGER_GENERATED_HPP
|
||||
#include <System/Log/Log.hpp>
|
||||
#ifndef BIGFOOT_UTILSLOGGER_GENERATED_HPP
|
||||
#define BIGFOOT_UTILSLOGGER_GENERATED_HPP
|
||||
#include <Utils/Log/LogMacros.hpp>
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Bigfoot
|
||||
/*
|
||||
* Logger
|
||||
*/
|
||||
inline Log::LoggerInfo SYSTEMTESTS_LOGGER {"SYSTEMTESTS_LOGGER", Flat::LogLevel::Trace};
|
||||
inline Log::LoggerInfo UTILS_LOGGER {"UTILS_LOGGER", Flat::LogLevel::Trace};
|
||||
} // namespace Bigfoot
|
||||
#endif
|
||||
#endif
|
||||
@@ -9,8 +9,9 @@
|
||||
#include <Utils/Caster.hpp>
|
||||
#include <Utils/TargetMacros.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <format>
|
||||
#include <string>
|
||||
|
||||
namespace Bigfoot
|
||||
@@ -42,18 +43,13 @@ class Version
|
||||
{
|
||||
}
|
||||
|
||||
Version(const Version& p_version) = default;
|
||||
Version(Version&& p_version) = default;
|
||||
|
||||
~Version() = default;
|
||||
|
||||
/**
|
||||
* Get the major part of the version.
|
||||
*
|
||||
* \return The major part of the version.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr std::uint8_t Major() const
|
||||
constexpr std::uint8_t GetMajor() const
|
||||
{
|
||||
constexpr std::uint32_t mask = 0b00000000111111110000000000000000;
|
||||
|
||||
@@ -66,7 +62,7 @@ class Version
|
||||
* \return The minor part of the version.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr std::uint8_t Minor() const
|
||||
constexpr std::uint8_t GetMinor() const
|
||||
{
|
||||
constexpr std::uint32_t mask = 0b00000000000000001111111100000000;
|
||||
|
||||
@@ -79,54 +75,34 @@ class Version
|
||||
* \return The patch part of the version.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr std::uint8_t Patch() const
|
||||
constexpr std::uint8_t GetPatch() const
|
||||
{
|
||||
constexpr std::uint32_t mask = 0b00000000000000000000000011111111;
|
||||
|
||||
return static_cast<std::uint8_t>(m_combined & mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw Version
|
||||
*
|
||||
* \return the raw version
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr operator std::uint32_t() const
|
||||
constexpr std::uint32_t Raw() const
|
||||
{
|
||||
return m_combined;
|
||||
}
|
||||
|
||||
operator std::string() const;
|
||||
|
||||
constexpr Version& operator=(const Version& p_version) = default;
|
||||
|
||||
constexpr Version& operator=(Version&& p_version) = default;
|
||||
/**
|
||||
* Gets the string representation of the Version
|
||||
*
|
||||
* \return The string
|
||||
*/
|
||||
[[nodiscard]]
|
||||
std::string ToString() const;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool operator>(const Version& p_version) const
|
||||
{
|
||||
return m_combined > p_version.m_combined;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool operator<(const Version& p_version) const
|
||||
{
|
||||
return m_combined < p_version.m_combined;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool operator>=(const Version& p_version) const
|
||||
{
|
||||
return m_combined >= p_version.m_combined;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool operator<=(const Version& p_version) const
|
||||
{
|
||||
return m_combined <= p_version.m_combined;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool operator==(const Version& p_version) const = default;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool operator!=(const Version& p_version) const = default;
|
||||
constexpr auto operator<=>(const Version& p_version) const = default;
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -140,7 +116,7 @@ class Version
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
template<>
|
||||
struct std::formatter<Bigfoot::Version>
|
||||
struct fmt::formatter<Bigfoot::Version>
|
||||
{
|
||||
template<typename ParseContext>
|
||||
constexpr auto parse(ParseContext& p_context)
|
||||
@@ -151,7 +127,7 @@ struct std::formatter<Bigfoot::Version>
|
||||
template<typename FormatContext>
|
||||
auto format(const Bigfoot::Version& p_version, FormatContext& p_context) const
|
||||
{
|
||||
return std::format_to(p_context.out(), "{}", static_cast<std::string>(p_version));
|
||||
return fmt::format_to(p_context.out(), "{}", p_version.ToString());
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* \author Romain BOULLARD
|
||||
* \date October 2025
|
||||
*********************************************************************/
|
||||
#include <System/Log/Log.hpp>
|
||||
#include <Utils/Log/Log.hpp>
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
|
||||
@@ -33,6 +33,16 @@ quill::Logger* Log::RegisterLogger(const LoggerInfo& p_loggerInfo)
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
void Log::UnregisterLogger(const LoggerInfo& p_loggerInfo)
|
||||
{
|
||||
if (quill::Logger* logger = quill::Frontend::get_logger(p_loggerInfo.m_name))
|
||||
{
|
||||
quill::Frontend::remove_logger_blocking(logger);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
quill::Logger* Log::GetLogger(const LoggerInfo& p_loggerInfo)
|
||||
{
|
||||
return quill::Frontend::get_logger(p_loggerInfo.m_name);
|
||||
@@ -79,13 +89,23 @@ void Log::SetLoggerLevel(const LoggerInfo& p_loggerInfo)
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
Log::~Log()
|
||||
void Log::Flush()
|
||||
{
|
||||
for (quill::Logger* logger: quill::Frontend::get_all_loggers())
|
||||
{
|
||||
quill::Frontend::remove_logger(logger);
|
||||
logger->flush_log();
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
Log::~Log()
|
||||
{
|
||||
Flush();
|
||||
for (quill::Logger* logger: quill::Frontend::get_all_loggers())
|
||||
{
|
||||
quill::Frontend::remove_logger_blocking(logger);
|
||||
}
|
||||
quill::Backend::stop();
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
@@ -4,7 +4,7 @@
|
||||
* \author Romain BOULLARD
|
||||
* \date October 2025
|
||||
*********************************************************************/
|
||||
#include <System/Profiler.hpp>
|
||||
#include <Utils/Profiler.hpp>
|
||||
|
||||
#if defined BIGFOOT_WINDOWS
|
||||
#pragma comment(linker, "/include:mi_version")
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
Version::operator std::string() const
|
||||
std::string Version::ToString() const
|
||||
{
|
||||
return std::format("{}.{}.{}", Major(), Minor(), Patch());
|
||||
return fmt::format("{}.{}.{}", GetMajor(), GetMinor(), GetPatch());
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/System)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Misc)
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Utils)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/System)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Engine)
|
||||
@@ -0,0 +1,102 @@
|
||||
/*********************************************************************
|
||||
* \file Asset.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date August 2026
|
||||
*********************************************************************/
|
||||
#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:
|
||||
AssetA m_asset;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetFixture, Constructor_ShouldInitializeHeaderTypeIdAndTypeName)
|
||||
{
|
||||
EXPECT_EQ(m_asset.GetHeader().type_id, AssetA::GetTypeID());
|
||||
EXPECT_EQ(m_asset.GetHeader().type_name, eastl::string {AssetA::GetTypeName()});
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetFixture, SetName_ShouldSetTheName)
|
||||
{
|
||||
m_asset.SetName("MyAsset");
|
||||
|
||||
EXPECT_STREQ(m_asset.GetHeader().name.c_str(), "MyAsset");
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetFixture, SetVersion_ShouldSetTheVersion)
|
||||
{
|
||||
m_asset.SetVersion(5);
|
||||
|
||||
EXPECT_EQ(m_asset.GetHeader().version, 5);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetFixture, GetAsset_ShouldReturnAMutableReferenceToTheUnderlyingAsset)
|
||||
{
|
||||
m_asset.GetAsset().health = 10;
|
||||
|
||||
EXPECT_EQ(m_asset.GetAsset().health, 10);
|
||||
EXPECT_EQ(std::as_const(m_asset).GetAsset().health, 10);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetFixture, GetTypeID_ShouldBeStableAcrossCalls)
|
||||
{
|
||||
EXPECT_EQ(AssetA::GetTypeID(), AssetA::GetTypeID());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetFixture, GetTypeID_ShouldBeDifferentForDifferentAssetTypes)
|
||||
{
|
||||
EXPECT_NE(AssetA::GetTypeID(), AssetB::GetTypeID());
|
||||
EXPECT_NE(AssetA::GetTypeID(), AssetC::GetTypeID());
|
||||
EXPECT_NE(AssetB::GetTypeID(), AssetC::GetTypeID());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetFixture, GetTypeName_ShouldReturnTheFlatbufferFullyQualifiedName)
|
||||
{
|
||||
EXPECT_EQ(AssetA::GetTypeName(), eastl::string_view {AssetA::FLAT_ASSET::GetFullyQualifiedName()});
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetFixture, PackThenUnpack_ShouldRoundTripTheHeaderAndTheAsset)
|
||||
{
|
||||
m_asset.SetName("MyAsset");
|
||||
m_asset.SetVersion(3);
|
||||
m_asset.GetAsset().health = 42;
|
||||
m_asset.GetAsset().mana = 7;
|
||||
|
||||
AssetA unpacked;
|
||||
unpacked.Unpack(m_asset.Pack());
|
||||
|
||||
EXPECT_EQ(unpacked.GetHeader().uuid, m_asset.GetHeader().uuid);
|
||||
EXPECT_STREQ(unpacked.GetHeader().name.c_str(), m_asset.GetHeader().name.c_str());
|
||||
EXPECT_EQ(unpacked.GetHeader().version, m_asset.GetHeader().version);
|
||||
EXPECT_EQ(unpacked.GetHeader().type_id, m_asset.GetHeader().type_id);
|
||||
EXPECT_STREQ(unpacked.GetHeader().type_name.c_str(), m_asset.GetHeader().type_name.c_str());
|
||||
EXPECT_EQ(unpacked.GetAsset().health, m_asset.GetAsset().health);
|
||||
EXPECT_EQ(unpacked.GetAsset().mana, m_asset.GetAsset().mana);
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
@@ -0,0 +1,182 @@
|
||||
/*********************************************************************
|
||||
* \file AssetContainer.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date July 2026
|
||||
*********************************************************************/
|
||||
#include <Engine/Asset/AssetContainer.hpp>
|
||||
|
||||
#include <AssetsForTesting/Asset/AssetA.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
class ContainerHandleFixture: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
const auto key = m_containerA.Insert();
|
||||
|
||||
m_uuid = m_containerA.Get(key)->GetHeader().uuid;
|
||||
|
||||
m_handle = m_containerA.AcquireContainerHandle(m_uuid);
|
||||
}
|
||||
|
||||
AssetContainer<AssetA> m_containerA;
|
||||
|
||||
UUID m_uuid;
|
||||
|
||||
ContainerHandle* m_handle;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(ContainerHandleFixture, GetAsset_ShouldReturnTheAsset)
|
||||
{
|
||||
EXPECT_NE(m_handle->GetAsset(), nullptr);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(ContainerHandleFixture, GetAsset_ShouldReturnNullptrIfTheAssetHasBeenRemoved)
|
||||
{
|
||||
m_containerA.Remove(m_uuid);
|
||||
EXPECT_EQ(m_handle->GetAsset(), nullptr);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(ContainerHandleFixture, IncrementHardRefCount_ShouldIncrementTheHardRefCount)
|
||||
{
|
||||
const std::uint32_t original = m_handle->GetHardRefCount();
|
||||
m_handle->IncrementHardRefCount();
|
||||
EXPECT_EQ(original + 1, m_handle->GetHardRefCount());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(ContainerHandleFixture, IncrementSoftRefCount_ShouldIncrementTheSoftRefCount)
|
||||
{
|
||||
const std::uint32_t original = m_handle->GetSoftRefCount();
|
||||
m_handle->IncrementSoftRefCount();
|
||||
EXPECT_EQ(original + 1, m_handle->GetSoftRefCount());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(ContainerHandleFixture, DecrementHardRefCount_ShouldDecrementTheHardRefCount)
|
||||
{
|
||||
m_handle->IncrementHardRefCount();
|
||||
|
||||
const std::uint32_t original = m_handle->GetHardRefCount();
|
||||
m_handle->DecrementHardRefCount();
|
||||
EXPECT_EQ(original - 1, m_handle->GetHardRefCount());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(ContainerHandleFixture, DecrementSoftRefCount_ShouldDecrementTheSoftRefCount)
|
||||
{
|
||||
m_handle->IncrementSoftRefCount();
|
||||
|
||||
const std::uint32_t original = m_handle->GetSoftRefCount();
|
||||
m_handle->DecrementSoftRefCount();
|
||||
EXPECT_EQ(original - 1, m_handle->GetSoftRefCount());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
class AssetContainerFixture: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
AssetContainer<AssetA> m_containerA;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetContainerFixture, Has_ShouldReturnTrueIfTheContainerHasTheAsset)
|
||||
{
|
||||
const auto key = m_containerA.Insert();
|
||||
EXPECT_TRUE(m_containerA.Has(m_containerA.Get(key)->GetHeader().uuid));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetContainerFixture, Has_ShouldReturnFalseIfTheContainerDoesNotHaveTheAsset)
|
||||
{
|
||||
EXPECT_FALSE(m_containerA.Has(UUID {}));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetContainerFixture, AcquireHandle_ShouldReturnTheAssociatedContainerHandle)
|
||||
{
|
||||
const auto key = m_containerA.Insert();
|
||||
|
||||
const ContainerHandle* handle = m_containerA.AcquireContainerHandle(m_containerA.Get(key)->GetHeader().uuid);
|
||||
EXPECT_EQ(static_cast<const AssetA*>(handle->GetAsset())->GetHeader().uuid,
|
||||
m_containerA.Get(key)->GetHeader().uuid);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetContainerFixture, AcquireHandle_ShouldCreateTheAssociatedContainerHandleIfItDoesNotExists)
|
||||
{
|
||||
const ContainerHandle* handle = m_containerA.AcquireContainerHandle(UUID {});
|
||||
EXPECT_EQ(handle->GetAsset(), nullptr);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetContainerFixture, Insert_ShouldReturnValidAndUniqueSlotKeyOnInsert)
|
||||
{
|
||||
const SlotMapKey slotKey = m_containerA.Insert();
|
||||
EXPECT_TRUE(slotKey.Valid());
|
||||
EXPECT_NE(slotKey, m_containerA.Insert());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetContainerFixture, Insert_ShouldReturnTheSameSlotKeyInCaseOfDuplicatedUUID)
|
||||
{
|
||||
const SlotMapKey slotKey = m_containerA.Insert();
|
||||
|
||||
AssetA duplicate;
|
||||
duplicate.Unpack(m_containerA.Get(slotKey)->Pack());
|
||||
|
||||
EXPECT_EQ(slotKey, m_containerA.Insert(std::move(duplicate)));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetContainerFixture, Get_ShouldReturnTheAssetWithTheSlotKey)
|
||||
{
|
||||
const SlotMapKey slotKey = m_containerA.Insert();
|
||||
|
||||
EXPECT_NE(m_containerA.Get(slotKey), nullptr);
|
||||
EXPECT_NE(std::as_const(m_containerA).Get(slotKey), nullptr);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetContainerFixture, Get_ShouldReturnNullptrIfSlotKeyNotInContainer)
|
||||
{
|
||||
EXPECT_EQ(m_containerA.Get(SlotMapKey<> {1, 0}), nullptr);
|
||||
EXPECT_EQ(std::as_const(m_containerA).Get(SlotMapKey<> {1, 0}), nullptr);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetContainerFixture, Remove_ShouldRemoveTheAsset)
|
||||
{
|
||||
const SlotMapKey slotKey = m_containerA.Insert();
|
||||
const UUID uuid = m_containerA.Get(slotKey)->GetHeader().uuid;
|
||||
|
||||
m_containerA.Remove(uuid);
|
||||
|
||||
EXPECT_EQ(m_containerA.Get(slotKey), nullptr);
|
||||
EXPECT_FALSE(m_containerA.Has(uuid));
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
@@ -0,0 +1,94 @@
|
||||
/*********************************************************************
|
||||
* \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:
|
||||
AssetContainer<AssetA> m_containerA;
|
||||
AssetContainer<AssetB> m_containerB;
|
||||
AssetContainer<AssetC> m_containerC;
|
||||
|
||||
AssetLibrary m_library;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetLibraryFixture, Insert_ShouldReturnTrueOnSuccess)
|
||||
{
|
||||
EXPECT_TRUE(m_library.Insert(&m_containerA));
|
||||
EXPECT_TRUE(m_library.Insert(&m_containerB));
|
||||
EXPECT_TRUE(m_library.Insert(&m_containerC));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetLibraryFixture, Insert_ShouldReturnFalseOnDuplicate)
|
||||
{
|
||||
std::ignore = m_library.Insert(&m_containerA);
|
||||
EXPECT_FALSE(m_library.Insert(&m_containerA));
|
||||
|
||||
AssetContainer<AssetA> m_containerAA;
|
||||
EXPECT_FALSE(m_library.Insert(&m_containerAA));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetLibraryFixture, GetAssetContainer_ShouldReturnTheAssetContainerIfAvailable)
|
||||
{
|
||||
std::ignore = m_library.Insert(&m_containerA);
|
||||
std::ignore = m_library.Insert(&m_containerB);
|
||||
std::ignore = m_library.Insert(&m_containerC);
|
||||
|
||||
EXPECT_EQ(m_library.GetAssetContainer(GetAssetTypeID<AssetA>()), &m_containerA);
|
||||
EXPECT_EQ(m_library.GetAssetContainer(GetAssetTypeID<AssetB>()), &m_containerB);
|
||||
EXPECT_EQ(m_library.GetAssetContainer(GetAssetTypeID<AssetC>()), &m_containerC);
|
||||
|
||||
EXPECT_EQ(std::as_const(m_library).GetAssetContainer(GetAssetTypeID<AssetA>()), &m_containerA);
|
||||
EXPECT_EQ(std::as_const(m_library).GetAssetContainer(GetAssetTypeID<AssetB>()), &m_containerB);
|
||||
EXPECT_EQ(std::as_const(m_library).GetAssetContainer(GetAssetTypeID<AssetC>()), &m_containerC);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetLibraryFixture, GetAssetContainer_ShouldReturnNullptrIfTheContainerDoesNotExist)
|
||||
{
|
||||
std::ignore = m_library.Insert(&m_containerB);
|
||||
|
||||
EXPECT_EQ(m_library.GetAssetContainer(GetAssetTypeID<AssetA>()), nullptr);
|
||||
EXPECT_EQ(std::as_const(m_library).GetAssetContainer(GetAssetTypeID<AssetA>()), nullptr);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetLibraryFixture, SetActiveAssetLibrary_ShouldSetTheActiveAssetLibraryToTheGivenLibrary)
|
||||
{
|
||||
SetActiveAssetLibrary(&m_library);
|
||||
EXPECT_EQ(g_activeAssetLibrary, &m_library);
|
||||
SetActiveAssetLibrary(&g_assetLibrary);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(AssetLibraryFixture, ScopedActiveAssetLibrary_ShouldChangeTheActiveAssetLibraryInAScopedWay)
|
||||
{
|
||||
EXPECT_EQ(g_activeAssetLibrary, &g_assetLibrary);
|
||||
{
|
||||
ScopedActiveAssetLibrary activeAssetLibraryScoped {&m_library};
|
||||
EXPECT_EQ(g_activeAssetLibrary, &m_library);
|
||||
}
|
||||
EXPECT_EQ(g_activeAssetLibrary, &g_assetLibrary);
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
@@ -0,0 +1,480 @@
|
||||
/*********************************************************************
|
||||
* \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 HardReferenceFixture: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
SetActiveAssetLibrary(&m_library);
|
||||
|
||||
std::ignore = m_library.Insert(&m_containerA);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
SetActiveAssetLibrary(&g_assetLibrary);
|
||||
}
|
||||
|
||||
AssetContainer<AssetA> m_containerA;
|
||||
|
||||
AssetLibrary m_library;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(HardReferenceFixture, GetUUID_ShouldReturnTheUUID)
|
||||
{
|
||||
UUID uuid;
|
||||
HardReference<AssetA> hardRef {uuid};
|
||||
|
||||
EXPECT_EQ(hardRef.GetUUID(), uuid);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(HardReferenceFixture, Get_ShouldReturnTheAsset)
|
||||
{
|
||||
const auto key = m_containerA.Insert();
|
||||
const UUID uuid = m_containerA.Get(key)->GetHeader().uuid;
|
||||
|
||||
HardReference<AssetA> hardRef {uuid};
|
||||
|
||||
EXPECT_EQ(hardRef.Get(), m_containerA.Get(key));
|
||||
EXPECT_EQ(std::as_const(hardRef).Get(), std::as_const(m_containerA).Get(key));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(HardReferenceFixture, Get_ShouldReturnNullptrIfTheAssetDoesNotExist)
|
||||
{
|
||||
UUID uuid;
|
||||
HardReference<AssetA> hardRef {uuid};
|
||||
|
||||
EXPECT_EQ(hardRef.Get(), nullptr);
|
||||
EXPECT_EQ(std::as_const(hardRef).Get(), nullptr);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(HardReferenceFixture, Get_ShouldReturnNullptrAfterTheAssetIsRemovedFromTheContainer)
|
||||
{
|
||||
const auto key = m_containerA.Insert();
|
||||
const UUID uuid = m_containerA.Get(key)->GetHeader().uuid;
|
||||
|
||||
HardReference<AssetA> hardRef {uuid};
|
||||
|
||||
m_containerA.Remove(uuid);
|
||||
|
||||
EXPECT_EQ(hardRef.Get(), nullptr);
|
||||
EXPECT_EQ(std::as_const(hardRef).Get(), nullptr);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(HardReferenceFixture, ShouldTouchTheHardRefCountOfTheHandle)
|
||||
{
|
||||
UUID uuid;
|
||||
const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid);
|
||||
|
||||
EXPECT_EQ(handle->GetHardRefCount(), 0);
|
||||
|
||||
{
|
||||
HardReference<AssetA> hardRef1 {uuid};
|
||||
EXPECT_EQ(handle->GetHardRefCount(), 1);
|
||||
{
|
||||
HardReference<AssetA> hardRef2 {uuid};
|
||||
EXPECT_EQ(handle->GetHardRefCount(), 2);
|
||||
}
|
||||
EXPECT_EQ(handle->GetHardRefCount(), 1);
|
||||
}
|
||||
|
||||
EXPECT_EQ(handle->GetHardRefCount(), 0);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(HardReferenceFixture, CopyConstructor_ShouldIncrementTheHardRefCountAndCopyTheState)
|
||||
{
|
||||
const auto key = m_containerA.Insert();
|
||||
const UUID uuid = m_containerA.Get(key)->GetHeader().uuid;
|
||||
const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid);
|
||||
|
||||
HardReference<AssetA> hardRef1 {uuid};
|
||||
EXPECT_EQ(handle->GetHardRefCount(), 1);
|
||||
|
||||
HardReference<AssetA> hardRef2 {hardRef1};
|
||||
|
||||
EXPECT_EQ(handle->GetHardRefCount(), 2);
|
||||
EXPECT_EQ(hardRef2.GetUUID(), uuid);
|
||||
EXPECT_EQ(hardRef2.Get(), m_containerA.Get(key));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(HardReferenceFixture, MoveConstructor_ShouldTransferTheStateWithoutChangingTheHardRefCount)
|
||||
{
|
||||
const auto key = m_containerA.Insert();
|
||||
const UUID uuid = m_containerA.Get(key)->GetHeader().uuid;
|
||||
const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid);
|
||||
|
||||
HardReference<AssetA> hardRef1 {uuid};
|
||||
EXPECT_EQ(handle->GetHardRefCount(), 1);
|
||||
|
||||
HardReference<AssetA> hardRef2 {std::move(hardRef1)};
|
||||
|
||||
EXPECT_EQ(handle->GetHardRefCount(), 1);
|
||||
EXPECT_EQ(hardRef2.GetUUID(), uuid);
|
||||
EXPECT_EQ(hardRef2.Get(), m_containerA.Get(key));
|
||||
EXPECT_EQ(hardRef1.GetUUID(), UUID::NULL_UUID);
|
||||
EXPECT_EQ(hardRef1.Get(), nullptr);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(HardReferenceFixture, CopyAssignment_ShouldReleaseThePreviousHandleAndAcquireTheNewOne)
|
||||
{
|
||||
UUID uuidA;
|
||||
UUID uuidB;
|
||||
const ContainerHandle* handleA = m_containerA.AcquireContainerHandle(uuidA);
|
||||
const ContainerHandle* handleB = m_containerA.AcquireContainerHandle(uuidB);
|
||||
|
||||
HardReference<AssetA> hardRefA {uuidA};
|
||||
HardReference<AssetA> hardRefB {uuidB};
|
||||
EXPECT_EQ(handleA->GetHardRefCount(), 1);
|
||||
EXPECT_EQ(handleB->GetHardRefCount(), 1);
|
||||
|
||||
hardRefB = hardRefA;
|
||||
|
||||
EXPECT_EQ(handleA->GetHardRefCount(), 2);
|
||||
EXPECT_EQ(handleB->GetHardRefCount(), 0);
|
||||
EXPECT_EQ(hardRefB.GetUUID(), uuidA);
|
||||
EXPECT_EQ(hardRefB.Get(), hardRefA.Get());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(HardReferenceFixture, CopyAssignment_SelfAssignment_ShouldNotChangeTheHardRefCount)
|
||||
{
|
||||
UUID uuid;
|
||||
const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid);
|
||||
|
||||
HardReference<AssetA> hardRef {uuid};
|
||||
EXPECT_EQ(handle->GetHardRefCount(), 1);
|
||||
|
||||
HardReference<AssetA>* selfPtr = &hardRef;
|
||||
hardRef = *selfPtr;
|
||||
|
||||
EXPECT_EQ(handle->GetHardRefCount(), 1);
|
||||
EXPECT_EQ(hardRef.GetUUID(), uuid);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(HardReferenceFixture, MoveAssignment_ShouldReleaseThePreviousHandleAndTransferTheNewOne)
|
||||
{
|
||||
UUID uuidA;
|
||||
UUID uuidB;
|
||||
const ContainerHandle* handleA = m_containerA.AcquireContainerHandle(uuidA);
|
||||
const ContainerHandle* handleB = m_containerA.AcquireContainerHandle(uuidB);
|
||||
|
||||
HardReference<AssetA> hardRefA {uuidA};
|
||||
HardReference<AssetA> hardRefB {uuidB};
|
||||
EXPECT_EQ(handleA->GetHardRefCount(), 1);
|
||||
EXPECT_EQ(handleB->GetHardRefCount(), 1);
|
||||
|
||||
hardRefB = std::move(hardRefA);
|
||||
|
||||
EXPECT_EQ(handleA->GetHardRefCount(), 1);
|
||||
EXPECT_EQ(handleB->GetHardRefCount(), 0);
|
||||
EXPECT_EQ(hardRefB.GetUUID(), uuidA);
|
||||
EXPECT_EQ(hardRefA.GetUUID(), UUID::NULL_UUID);
|
||||
EXPECT_EQ(hardRefA.Get(), nullptr);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(HardReferenceFixture, MoveAssignment_SelfAssignment_ShouldNotChangeTheHardRefCount)
|
||||
{
|
||||
UUID uuid;
|
||||
const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid);
|
||||
|
||||
HardReference<AssetA> hardRef {uuid};
|
||||
EXPECT_EQ(handle->GetHardRefCount(), 1);
|
||||
|
||||
HardReference<AssetA>* selfPtr = &hardRef;
|
||||
hardRef = std::move(*selfPtr);
|
||||
|
||||
EXPECT_EQ(handle->GetHardRefCount(), 1);
|
||||
EXPECT_EQ(hardRef.GetUUID(), uuid);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(HardReferenceFixture, EqualityOperator_ShouldReturnTrueForReferencesWithTheSameUUID)
|
||||
{
|
||||
UUID uuid;
|
||||
HardReference<AssetA> hardRef1 {uuid};
|
||||
HardReference<AssetA> hardRef2 {uuid};
|
||||
|
||||
EXPECT_EQ(hardRef1, hardRef2);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(HardReferenceFixture, EqualityOperator_ShouldReturnFalseForReferencesWithDifferentUUIDs)
|
||||
{
|
||||
UUID uuid1;
|
||||
UUID uuid2;
|
||||
HardReference<AssetA> hardRef1 {uuid1};
|
||||
HardReference<AssetA> hardRef2 {uuid2};
|
||||
|
||||
EXPECT_NE(hardRef1, hardRef2);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
class SoftReferenceFixture: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
SetActiveAssetLibrary(&m_library);
|
||||
|
||||
std::ignore = m_library.Insert(&m_containerA);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
SetActiveAssetLibrary(&g_assetLibrary);
|
||||
}
|
||||
|
||||
AssetContainer<AssetA> m_containerA;
|
||||
|
||||
AssetLibrary m_library;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SoftReferenceFixture, GetUUID_ShouldReturnTheUUID)
|
||||
{
|
||||
UUID uuid;
|
||||
SoftReference<AssetA> hardRef {uuid};
|
||||
|
||||
EXPECT_EQ(hardRef.GetUUID(), uuid);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SoftReferenceFixture, Get_ShouldReturnTheAsset)
|
||||
{
|
||||
const auto key = m_containerA.Insert();
|
||||
const UUID uuid = m_containerA.Get(key)->GetHeader().uuid;
|
||||
|
||||
SoftReference<AssetA> hardRef {uuid};
|
||||
|
||||
EXPECT_EQ(hardRef.Get(), m_containerA.Get(key));
|
||||
EXPECT_EQ(std::as_const(hardRef).Get(), std::as_const(m_containerA).Get(key));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SoftReferenceFixture, Get_ShouldReturnNullptrIfTheAssetDoesNotExist)
|
||||
{
|
||||
UUID uuid;
|
||||
SoftReference<AssetA> hardRef {uuid};
|
||||
|
||||
EXPECT_EQ(hardRef.Get(), nullptr);
|
||||
EXPECT_EQ(std::as_const(hardRef).Get(), nullptr);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SoftReferenceFixture, Get_ShouldReturnNullptrAfterTheAssetIsRemovedFromTheContainer)
|
||||
{
|
||||
const auto key = m_containerA.Insert();
|
||||
const UUID uuid = m_containerA.Get(key)->GetHeader().uuid;
|
||||
|
||||
SoftReference<AssetA> hardRef {uuid};
|
||||
|
||||
m_containerA.Remove(uuid);
|
||||
|
||||
EXPECT_EQ(hardRef.Get(), nullptr);
|
||||
EXPECT_EQ(std::as_const(hardRef).Get(), nullptr);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SoftReferenceFixture, ShouldTouchTheSoftRefCountOfTheHandle)
|
||||
{
|
||||
UUID uuid;
|
||||
const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid);
|
||||
|
||||
EXPECT_EQ(handle->GetSoftRefCount(), 0);
|
||||
|
||||
{
|
||||
SoftReference<AssetA> softRef1 {uuid};
|
||||
EXPECT_EQ(handle->GetSoftRefCount(), 1);
|
||||
{
|
||||
SoftReference<AssetA> softRef2 {uuid};
|
||||
EXPECT_EQ(handle->GetSoftRefCount(), 2);
|
||||
}
|
||||
EXPECT_EQ(handle->GetSoftRefCount(), 1);
|
||||
}
|
||||
|
||||
EXPECT_EQ(handle->GetSoftRefCount(), 0);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SoftReferenceFixture, CopyConstructor_ShouldIncrementTheSoftRefCountAndCopyTheState)
|
||||
{
|
||||
const auto key = m_containerA.Insert();
|
||||
const UUID uuid = m_containerA.Get(key)->GetHeader().uuid;
|
||||
const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid);
|
||||
|
||||
SoftReference<AssetA> softRef1 {uuid};
|
||||
EXPECT_EQ(handle->GetSoftRefCount(), 1);
|
||||
|
||||
SoftReference<AssetA> softRef2 {softRef1};
|
||||
|
||||
EXPECT_EQ(handle->GetSoftRefCount(), 2);
|
||||
EXPECT_EQ(softRef2.GetUUID(), uuid);
|
||||
EXPECT_EQ(softRef2.Get(), m_containerA.Get(key));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SoftReferenceFixture, MoveConstructor_ShouldTransferTheStateWithoutChangingTheSoftRefCount)
|
||||
{
|
||||
const auto key = m_containerA.Insert();
|
||||
const UUID uuid = m_containerA.Get(key)->GetHeader().uuid;
|
||||
const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid);
|
||||
|
||||
SoftReference<AssetA> softRef1 {uuid};
|
||||
EXPECT_EQ(handle->GetSoftRefCount(), 1);
|
||||
|
||||
SoftReference<AssetA> softRef2 {std::move(softRef1)};
|
||||
|
||||
EXPECT_EQ(handle->GetSoftRefCount(), 1);
|
||||
EXPECT_EQ(softRef2.GetUUID(), uuid);
|
||||
EXPECT_EQ(softRef2.Get(), m_containerA.Get(key));
|
||||
EXPECT_EQ(softRef1.GetUUID(), UUID::NULL_UUID);
|
||||
EXPECT_EQ(softRef1.Get(), nullptr);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SoftReferenceFixture, CopyAssignment_ShouldReleaseThePreviousHandleAndAcquireTheNewOne)
|
||||
{
|
||||
UUID uuidA;
|
||||
UUID uuidB;
|
||||
const ContainerHandle* handleA = m_containerA.AcquireContainerHandle(uuidA);
|
||||
const ContainerHandle* handleB = m_containerA.AcquireContainerHandle(uuidB);
|
||||
|
||||
SoftReference<AssetA> softRefA {uuidA};
|
||||
SoftReference<AssetA> softRefB {uuidB};
|
||||
EXPECT_EQ(handleA->GetSoftRefCount(), 1);
|
||||
EXPECT_EQ(handleB->GetSoftRefCount(), 1);
|
||||
|
||||
softRefB = softRefA;
|
||||
|
||||
EXPECT_EQ(handleA->GetSoftRefCount(), 2);
|
||||
EXPECT_EQ(handleB->GetSoftRefCount(), 0);
|
||||
EXPECT_EQ(softRefB.GetUUID(), uuidA);
|
||||
EXPECT_EQ(softRefB.Get(), softRefA.Get());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SoftReferenceFixture, CopyAssignment_SelfAssignment_ShouldNotChangeTheSoftRefCount)
|
||||
{
|
||||
UUID uuid;
|
||||
const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid);
|
||||
|
||||
SoftReference<AssetA> softRef {uuid};
|
||||
EXPECT_EQ(handle->GetSoftRefCount(), 1);
|
||||
|
||||
SoftReference<AssetA>* selfPtr = &softRef;
|
||||
softRef = *selfPtr;
|
||||
|
||||
EXPECT_EQ(handle->GetSoftRefCount(), 1);
|
||||
EXPECT_EQ(softRef.GetUUID(), uuid);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SoftReferenceFixture, MoveAssignment_ShouldReleaseThePreviousHandleAndTransferTheNewOne)
|
||||
{
|
||||
UUID uuidA;
|
||||
UUID uuidB;
|
||||
const ContainerHandle* handleA = m_containerA.AcquireContainerHandle(uuidA);
|
||||
const ContainerHandle* handleB = m_containerA.AcquireContainerHandle(uuidB);
|
||||
|
||||
SoftReference<AssetA> softRefA {uuidA};
|
||||
SoftReference<AssetA> softRefB {uuidB};
|
||||
EXPECT_EQ(handleA->GetSoftRefCount(), 1);
|
||||
EXPECT_EQ(handleB->GetSoftRefCount(), 1);
|
||||
|
||||
softRefB = std::move(softRefA);
|
||||
|
||||
EXPECT_EQ(handleA->GetSoftRefCount(), 1);
|
||||
EXPECT_EQ(handleB->GetSoftRefCount(), 0);
|
||||
EXPECT_EQ(softRefB.GetUUID(), uuidA);
|
||||
EXPECT_EQ(softRefA.GetUUID(), UUID::NULL_UUID);
|
||||
EXPECT_EQ(softRefA.Get(), nullptr);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SoftReferenceFixture, MoveAssignment_SelfAssignment_ShouldNotChangeTheSoftRefCount)
|
||||
{
|
||||
UUID uuid;
|
||||
const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid);
|
||||
|
||||
SoftReference<AssetA> softRef {uuid};
|
||||
EXPECT_EQ(handle->GetSoftRefCount(), 1);
|
||||
|
||||
SoftReference<AssetA>* selfPtr = &softRef;
|
||||
softRef = std::move(*selfPtr);
|
||||
|
||||
EXPECT_EQ(handle->GetSoftRefCount(), 1);
|
||||
EXPECT_EQ(softRef.GetUUID(), uuid);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SoftReferenceFixture, EqualityOperator_ShouldReturnTrueForReferencesWithTheSameUUID)
|
||||
{
|
||||
UUID uuid;
|
||||
SoftReference<AssetA> softRef1 {uuid};
|
||||
SoftReference<AssetA> softRef2 {uuid};
|
||||
|
||||
EXPECT_EQ(softRef1, softRef2);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(SoftReferenceFixture, EqualityOperator_ShouldReturnFalseForReferencesWithDifferentUUIDs)
|
||||
{
|
||||
UUID uuid1;
|
||||
UUID uuid2;
|
||||
SoftReference<AssetA> softRef1 {uuid1};
|
||||
SoftReference<AssetA> softRef2 {uuid2};
|
||||
|
||||
EXPECT_NE(softRef1, softRef2);
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
@@ -0,0 +1,369 @@
|
||||
/*********************************************************************
|
||||
* \file BigFile.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date August 2026
|
||||
*********************************************************************/
|
||||
#include <Engine/BigFile/BigFile.hpp>
|
||||
|
||||
#include <System/File/File.hpp>
|
||||
|
||||
#include <EngineTests/BigFileInfo_generated.hpp>
|
||||
|
||||
#include <AssetsForTesting/Asset/AssetA.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
#ifdef BIGFOOT_TOOLMODE
|
||||
class BigFileFixture: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
BigFile::Request {m_bigFile, "DELETE FROM Asset;"}.Execute();
|
||||
BigFile::Request {m_bigFile, "DELETE FROM AssetMetadata;"}.Execute();
|
||||
}
|
||||
|
||||
BigFile m_bigFile {File {BIGFILE_ENGINETESTS_LOCATION}};
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(BigFileFixture, GetAssetFlatbuffer_ShouldReturnNulloptForNonExistentUUID)
|
||||
{
|
||||
const UUID uuid;
|
||||
|
||||
EXPECT_FALSE(m_bigFile.GetAssetFlatbuffer(uuid).has_value());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(BigFileFixture, GetAssetFlatbuffer_ShouldGetTheAssetFlatbuffer)
|
||||
{
|
||||
AssetA asset;
|
||||
asset.SetName("hello");
|
||||
asset.GetAsset().health = 42;
|
||||
asset.GetAsset().mana = 7;
|
||||
const eastl::vector<std::byte> flatbuffer = asset.Pack();
|
||||
|
||||
const AssetMetadata metadata {.m_uuid = asset.GetHeader().uuid,
|
||||
.m_name = asset.GetHeader().name,
|
||||
.m_typeID = asset.GetHeader().type_id,
|
||||
.m_typeName = asset.GetHeader().type_name};
|
||||
|
||||
m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer);
|
||||
|
||||
const eastl::optional<eastl::vector<std::byte>> savedFlatbuffer = m_bigFile.GetAssetFlatbuffer(
|
||||
asset.GetHeader().uuid);
|
||||
ASSERT_TRUE(savedFlatbuffer.has_value());
|
||||
EXPECT_EQ(*savedFlatbuffer, flatbuffer);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(BigFileFixture, GetAssetFlatbuffers_ShouldOmitUUIDsThatDoNotExist)
|
||||
{
|
||||
AssetA assetA;
|
||||
assetA.SetName("hello");
|
||||
const eastl::vector<std::byte> flatbufferA = assetA.Pack();
|
||||
m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetA.GetHeader().uuid,
|
||||
.m_name = assetA.GetHeader().name,
|
||||
.m_typeID = assetA.GetHeader().type_id,
|
||||
.m_typeName = assetA.GetHeader().type_name},
|
||||
flatbufferA);
|
||||
|
||||
AssetA assetB;
|
||||
assetB.SetName("world");
|
||||
const eastl::vector<std::byte> flatbufferB = assetB.Pack();
|
||||
m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetB.GetHeader().uuid,
|
||||
.m_name = assetB.GetHeader().name,
|
||||
.m_typeID = assetB.GetHeader().type_id,
|
||||
.m_typeName = assetB.GetHeader().type_name},
|
||||
flatbufferB);
|
||||
|
||||
const eastl::vector<UUID> uuids {assetA.GetHeader().uuid, UUID {}, assetB.GetHeader().uuid};
|
||||
|
||||
const eastl::vector<eastl::vector<std::byte>> flatbuffers = m_bigFile.GetAssetFlatbuffers(uuids);
|
||||
|
||||
ASSERT_EQ(flatbuffers.size(), 2);
|
||||
EXPECT_TRUE((flatbuffers[0] == flatbufferA && flatbuffers[1] == flatbufferB) ||
|
||||
(flatbuffers[0] == flatbufferB && flatbuffers[1] == flatbufferA));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(BigFileFixture, GetAssetFlatbuffers_ShouldNotDuplicateResultsForADuplicateUUID)
|
||||
{
|
||||
AssetA assetA;
|
||||
assetA.SetName("hello");
|
||||
const eastl::vector<std::byte> flatbufferA = assetA.Pack();
|
||||
m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetA.GetHeader().uuid,
|
||||
.m_name = assetA.GetHeader().name,
|
||||
.m_typeID = assetA.GetHeader().type_id,
|
||||
.m_typeName = assetA.GetHeader().type_name},
|
||||
flatbufferA);
|
||||
|
||||
const eastl::vector<UUID> uuids {assetA.GetHeader().uuid, assetA.GetHeader().uuid};
|
||||
|
||||
const eastl::vector<eastl::vector<std::byte>> flatbuffers = m_bigFile.GetAssetFlatbuffers(uuids);
|
||||
|
||||
ASSERT_EQ(flatbuffers.size(), 1);
|
||||
EXPECT_EQ(flatbuffers[0], flatbufferA);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(BigFileFixture, GetAssetMetadata_ShouldReturnNulloptForNonExistentUUID)
|
||||
{
|
||||
const UUID uuid;
|
||||
|
||||
EXPECT_FALSE(m_bigFile.GetAssetMetadata(uuid).has_value());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(BigFileFixture, GetAssetMetadata_ShouldGetTheAssetMetadata)
|
||||
{
|
||||
AssetA asset;
|
||||
asset.SetName("hello");
|
||||
asset.GetAsset().health = 42;
|
||||
asset.GetAsset().mana = 7;
|
||||
const eastl::vector<std::byte> flatbuffer = asset.Pack();
|
||||
|
||||
const AssetMetadata metadata {.m_uuid = asset.GetHeader().uuid,
|
||||
.m_name = asset.GetHeader().name,
|
||||
.m_typeID = asset.GetHeader().type_id,
|
||||
.m_typeName = asset.GetHeader().type_name};
|
||||
|
||||
m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer);
|
||||
|
||||
const eastl::optional<AssetMetadata> savedMetadata = m_bigFile.GetAssetMetadata(asset.GetHeader().uuid);
|
||||
ASSERT_TRUE(savedMetadata.has_value());
|
||||
|
||||
EXPECT_EQ(savedMetadata->m_uuid, metadata.m_uuid);
|
||||
EXPECT_EQ(savedMetadata->m_name, metadata.m_name);
|
||||
EXPECT_EQ(savedMetadata->m_typeID, metadata.m_typeID);
|
||||
EXPECT_EQ(savedMetadata->m_typeName, metadata.m_typeName);
|
||||
EXPECT_GT(savedMetadata->m_creationTime, Time {0});
|
||||
EXPECT_GT(savedMetadata->m_modificationTime, Time {0});
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(BigFileFixture, GetAssetMetadatas_ShouldOmitUUIDsThatDoNotExist)
|
||||
{
|
||||
AssetA assetA;
|
||||
assetA.SetName("hello");
|
||||
m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetA.GetHeader().uuid,
|
||||
.m_name = assetA.GetHeader().name,
|
||||
.m_typeID = assetA.GetHeader().type_id,
|
||||
.m_typeName = assetA.GetHeader().type_name},
|
||||
assetA.Pack());
|
||||
|
||||
AssetA assetB;
|
||||
assetB.SetName("world");
|
||||
m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetB.GetHeader().uuid,
|
||||
.m_name = assetB.GetHeader().name,
|
||||
.m_typeID = assetB.GetHeader().type_id,
|
||||
.m_typeName = assetB.GetHeader().type_name},
|
||||
assetB.Pack());
|
||||
|
||||
const UUID missingUUID;
|
||||
const eastl::vector<UUID> uuids {assetA.GetHeader().uuid, missingUUID, assetB.GetHeader().uuid};
|
||||
|
||||
const eastl::vector<AssetMetadata> metadatas = m_bigFile.GetAssetMetadatas(uuids);
|
||||
|
||||
ASSERT_EQ(metadatas.size(), 2);
|
||||
EXPECT_TRUE((metadatas[0].m_uuid == assetA.GetHeader().uuid && metadatas[0].m_name == "hello" &&
|
||||
metadatas[1].m_uuid == assetB.GetHeader().uuid && metadatas[1].m_name == "world") ||
|
||||
(metadatas[0].m_uuid == assetB.GetHeader().uuid && metadatas[0].m_name == "world" &&
|
||||
metadatas[1].m_uuid == assetA.GetHeader().uuid && metadatas[1].m_name == "hello"));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(BigFileFixture, SaveAssetFlatbuffer_ShouldSaveTheAsset)
|
||||
{
|
||||
AssetA asset;
|
||||
asset.SetName("hello");
|
||||
asset.GetAsset().health = 42;
|
||||
asset.GetAsset().mana = 7;
|
||||
const eastl::vector<std::byte> flatbuffer = asset.Pack();
|
||||
|
||||
const AssetMetadata metadata {.m_uuid = asset.GetHeader().uuid,
|
||||
.m_name = asset.GetHeader().name,
|
||||
.m_typeID = asset.GetHeader().type_id,
|
||||
.m_typeName = asset.GetHeader().type_name};
|
||||
|
||||
m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer);
|
||||
|
||||
EXPECT_TRUE(m_bigFile.Has(asset.GetHeader().uuid));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(BigFileFixture, SaveAssetFlatbuffer_ShouldUpdateTheDataWhenCalledTwice)
|
||||
{
|
||||
const UUID uuid;
|
||||
|
||||
AssetA asset;
|
||||
asset.GetAsset().health = 1;
|
||||
m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = uuid,
|
||||
.m_name = "hello",
|
||||
.m_typeID = AssetA::GetTypeID(),
|
||||
.m_typeName = eastl::string {AssetA::GetTypeName()}},
|
||||
asset.Pack());
|
||||
|
||||
const eastl::optional<AssetMetadata> savedMetadata1 = m_bigFile.GetAssetMetadata(uuid);
|
||||
ASSERT_TRUE(savedMetadata1.has_value());
|
||||
EXPECT_EQ(savedMetadata1->m_name, "hello");
|
||||
EXPECT_EQ(savedMetadata1->m_typeID, AssetA::GetTypeID());
|
||||
EXPECT_EQ(savedMetadata1->m_typeName, eastl::string {AssetA::GetTypeName()});
|
||||
EXPECT_EQ(savedMetadata1->m_modificationTime, savedMetadata1->m_creationTime);
|
||||
|
||||
const eastl::optional<eastl::vector<std::byte>> savedFlatbuffer1 = m_bigFile.GetAssetFlatbuffer(uuid);
|
||||
ASSERT_TRUE(savedFlatbuffer1.has_value());
|
||||
|
||||
AssetA savedAsset1;
|
||||
savedAsset1.Unpack(*savedFlatbuffer1);
|
||||
EXPECT_EQ(savedAsset1.GetAsset().health, 1);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
|
||||
asset.GetAsset().health = 2;
|
||||
m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = uuid,
|
||||
.m_name = "world",
|
||||
.m_typeID = AssetA::GetTypeID(),
|
||||
.m_typeName = eastl::string {AssetA::GetTypeName()}},
|
||||
asset.Pack());
|
||||
|
||||
const eastl::optional<AssetMetadata> savedMetadata2 = m_bigFile.GetAssetMetadata(uuid);
|
||||
ASSERT_TRUE(savedMetadata2.has_value());
|
||||
EXPECT_EQ(savedMetadata2->m_name, "world");
|
||||
EXPECT_EQ(savedMetadata2->m_typeID, AssetA::GetTypeID());
|
||||
EXPECT_EQ(savedMetadata2->m_typeName, eastl::string {AssetA::GetTypeName()});
|
||||
EXPECT_GT(savedMetadata2->m_modificationTime, savedMetadata2->m_creationTime);
|
||||
|
||||
EXPECT_LT(savedMetadata1->m_modificationTime, savedMetadata2->m_modificationTime);
|
||||
|
||||
const eastl::optional<eastl::vector<std::byte>> savedFlatbuffer2 = m_bigFile.GetAssetFlatbuffer(uuid);
|
||||
ASSERT_TRUE(savedFlatbuffer2.has_value());
|
||||
|
||||
AssetA savedAsset2;
|
||||
savedAsset2.Unpack(*savedFlatbuffer2);
|
||||
EXPECT_EQ(savedAsset2.GetAsset().health, 2);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(BigFileFixture, SaveAssetFlatbuffers_ShouldSaveTheAssets)
|
||||
{
|
||||
AssetA assetA;
|
||||
assetA.SetName("hello");
|
||||
assetA.GetAsset().health = 42;
|
||||
|
||||
AssetA assetB;
|
||||
assetB.SetName("world");
|
||||
assetB.GetAsset().health = 7;
|
||||
|
||||
const eastl::vector<AssetMetadata> metadatas {AssetMetadata {.m_uuid = assetA.GetHeader().uuid,
|
||||
.m_name = assetA.GetHeader().name,
|
||||
.m_typeID = assetA.GetHeader().type_id,
|
||||
.m_typeName = assetA.GetHeader().type_name},
|
||||
AssetMetadata {.m_uuid = assetB.GetHeader().uuid,
|
||||
.m_name = assetB.GetHeader().name,
|
||||
.m_typeID = assetB.GetHeader().type_id,
|
||||
.m_typeName = assetB.GetHeader().type_name}};
|
||||
const eastl::vector<eastl::vector<std::byte>> flatbuffers {assetA.Pack(), assetB.Pack()};
|
||||
|
||||
m_bigFile.SaveAssetFlatbuffers(metadatas, flatbuffers);
|
||||
|
||||
EXPECT_TRUE(m_bigFile.Has(assetA.GetHeader().uuid));
|
||||
EXPECT_TRUE(m_bigFile.Has(assetB.GetHeader().uuid));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(BigFileFixture, SaveAssetFlatbuffers_ShouldUpdateTheDataWhenCalledTwice)
|
||||
{
|
||||
const UUID uuid;
|
||||
|
||||
AssetA asset;
|
||||
asset.GetAsset().health = 1;
|
||||
const eastl::vector<AssetMetadata> metadatas1 {AssetMetadata {.m_uuid = uuid,
|
||||
.m_name = "hello",
|
||||
.m_typeID = AssetA::GetTypeID(),
|
||||
.m_typeName = eastl::string {AssetA::GetTypeName()}}};
|
||||
const eastl::vector<eastl::vector<std::byte>> flatbuffers1 {asset.Pack()};
|
||||
m_bigFile.SaveAssetFlatbuffers(metadatas1, flatbuffers1);
|
||||
|
||||
const eastl::optional<AssetMetadata> savedMetadata1 = m_bigFile.GetAssetMetadata(uuid);
|
||||
ASSERT_TRUE(savedMetadata1.has_value());
|
||||
EXPECT_EQ(savedMetadata1->m_name, "hello");
|
||||
EXPECT_EQ(savedMetadata1->m_modificationTime, savedMetadata1->m_creationTime);
|
||||
|
||||
const eastl::optional<eastl::vector<std::byte>> savedFlatbuffer1 = m_bigFile.GetAssetFlatbuffer(uuid);
|
||||
ASSERT_TRUE(savedFlatbuffer1.has_value());
|
||||
|
||||
AssetA savedAsset1;
|
||||
savedAsset1.Unpack(*savedFlatbuffer1);
|
||||
EXPECT_EQ(savedAsset1.GetAsset().health, 1);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
|
||||
asset.GetAsset().health = 2;
|
||||
const eastl::vector<AssetMetadata> metadatas2 {AssetMetadata {.m_uuid = uuid,
|
||||
.m_name = "world",
|
||||
.m_typeID = AssetA::GetTypeID(),
|
||||
.m_typeName = eastl::string {AssetA::GetTypeName()}}};
|
||||
const eastl::vector<eastl::vector<std::byte>> flatbuffers2 {asset.Pack()};
|
||||
m_bigFile.SaveAssetFlatbuffers(metadatas2, flatbuffers2);
|
||||
|
||||
const eastl::optional<AssetMetadata> savedMetadata2 = m_bigFile.GetAssetMetadata(uuid);
|
||||
ASSERT_TRUE(savedMetadata2.has_value());
|
||||
EXPECT_EQ(savedMetadata2->m_name, "world");
|
||||
EXPECT_GT(savedMetadata2->m_modificationTime, savedMetadata2->m_creationTime);
|
||||
|
||||
EXPECT_LT(savedMetadata1->m_modificationTime, savedMetadata2->m_modificationTime);
|
||||
|
||||
const eastl::optional<eastl::vector<std::byte>> savedFlatbuffer2 = m_bigFile.GetAssetFlatbuffer(uuid);
|
||||
ASSERT_TRUE(savedFlatbuffer2.has_value());
|
||||
|
||||
AssetA savedAsset2;
|
||||
savedAsset2.Unpack(*savedFlatbuffer2);
|
||||
EXPECT_EQ(savedAsset2.GetAsset().health, 2);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(BigFileFixture, Has_ShouldReturnTrueIfTheAssetExists)
|
||||
{
|
||||
AssetA asset;
|
||||
asset.SetName("hello");
|
||||
asset.GetAsset().health = 42;
|
||||
asset.GetAsset().mana = 7;
|
||||
const eastl::vector<std::byte> flatbuffer = asset.Pack();
|
||||
|
||||
const AssetMetadata metadata {.m_uuid = asset.GetHeader().uuid,
|
||||
.m_name = asset.GetHeader().name,
|
||||
.m_typeID = asset.GetHeader().type_id,
|
||||
.m_typeName = asset.GetHeader().type_name};
|
||||
|
||||
m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer);
|
||||
|
||||
EXPECT_TRUE(m_bigFile.Has(asset.GetHeader().uuid));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(BigFileFixture, Has_ShouldReturnFalseIfTheAssetDoesNotExist)
|
||||
{
|
||||
EXPECT_FALSE(m_bigFile.Has(UUID {}));
|
||||
}
|
||||
#endif
|
||||
} // namespace Bigfoot
|
||||
@@ -1,15 +1,13 @@
|
||||
get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
project(${PackageName}Tests)
|
||||
|
||||
set(Dependencies)
|
||||
set(BigfootDependencies
|
||||
Engine
|
||||
System
|
||||
Utils)
|
||||
|
||||
bigfoot_create_bigfile("Tests/Bigfoot")
|
||||
AssetsForTesting)
|
||||
|
||||
bigfoot_create_package_tests(
|
||||
""
|
||||
"${BigfootDependencies}")
|
||||
"${Dependencies}"
|
||||
"${BigfootDependencies}"
|
||||
"")
|
||||
|
||||
bigfoot_setup_dependencies("Tests/Bigfoot")
|
||||
bigfoot_create_bigfile("Tests/Bigfoot")
|
||||
@@ -0,0 +1,78 @@
|
||||
/*********************************************************************
|
||||
* \file DataAccessor.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date August 2026
|
||||
*********************************************************************/
|
||||
#include <Engine/DataAccessor/DataAccessor.hpp>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
class DataAccessorFixture: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
class DataAccessorMock: public DataAccessor
|
||||
{
|
||||
public:
|
||||
MOCK_METHOD(eastl::optional<eastl::vector<std::byte>>,
|
||||
GetAssetFlatbuffer,
|
||||
(const UUID& p_uuid),
|
||||
(const, override));
|
||||
MOCK_METHOD(eastl::vector<eastl::vector<std::byte>>,
|
||||
GetAssetFlatbuffers,
|
||||
(eastl::span<const UUID> p_uuids),
|
||||
(const, override));
|
||||
MOCK_METHOD(eastl::optional<AssetMetadata>, GetAssetMetadata, (const UUID& p_uuid), (const, override));
|
||||
MOCK_METHOD(eastl::vector<AssetMetadata>,
|
||||
GetAssetMetadatas,
|
||||
(eastl::span<const UUID> p_uuids),
|
||||
(const, override));
|
||||
MOCK_METHOD(void,
|
||||
SaveAssetFlatbuffer,
|
||||
(const AssetMetadata& p_metaData, const eastl::span<const std::byte> p_flatbuffer),
|
||||
(override));
|
||||
MOCK_METHOD(void,
|
||||
SaveAssetFlatbuffers,
|
||||
(eastl::span<const AssetMetadata> p_metadatas,
|
||||
eastl::span<const eastl::vector<std::byte>> p_flatbuffers),
|
||||
(override));
|
||||
MOCK_METHOD(bool, Has, (const UUID& p_uuid), (const, override));
|
||||
};
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
m_original = g_dataAccessor;
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
SetDataAccessor(m_original);
|
||||
}
|
||||
|
||||
DataAccessorMock m_accessor;
|
||||
DataAccessor* m_original;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(DataAccessorFixture, SetDataAccessor_ShouldSetTheDataAccessor)
|
||||
{
|
||||
SetDataAccessor(&m_accessor);
|
||||
EXPECT_EQ(g_dataAccessor, &m_accessor);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(DataAccessorFixture, ScopedDataAccessor_ShouldChangeTheDataAccessorInAScopedWay)
|
||||
{
|
||||
EXPECT_EQ(g_dataAccessor, nullptr);
|
||||
{
|
||||
ScopedDataAccessor dataAccessor {&m_accessor};
|
||||
EXPECT_EQ(g_dataAccessor, &m_accessor);
|
||||
}
|
||||
EXPECT_EQ(g_dataAccessor, nullptr);
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
@@ -0,0 +1,19 @@
|
||||
/*********************************************************************
|
||||
* \file main.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date May 2026
|
||||
*********************************************************************/
|
||||
#include <Utils/Log/LogMacros.hpp>
|
||||
#include <Utils/TargetMacros.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
BIGFOOT_NOT_OPTIMIZED_ONLY(::Bigfoot::Singleton<::Bigfoot::Log>::Lifetime m_lifetime);
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <EASTL/string_view.h>
|
||||
|
||||
#if defined BIGFOOT_TOOLMODE
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
/*
|
||||
@@ -17,3 +19,4 @@ namespace Bigfoot
|
||||
constexpr eastl::string_view BIGFILE_ENGINETESTS_LOCATION {"./EngineTests-bigfile.db"};
|
||||
} // namespace Bigfoot
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
// to delete when an actual test is in EngineTests
|
||||
@@ -0,0 +1,11 @@
|
||||
/*********************************************************************
|
||||
* \file AssetA.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date July 2026
|
||||
*********************************************************************/
|
||||
#include <AssetsForTesting/Asset/AssetA.hpp>
|
||||
|
||||
#include <Engine/Asset/AssetHelper.hpp>
|
||||
|
||||
BIGFOOT_ASSET(AssetA, ::Bigfoot::AssetA)
|
||||
@@ -0,0 +1,11 @@
|
||||
/*********************************************************************
|
||||
* \file AssetB.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date July 2026
|
||||
*********************************************************************/
|
||||
#include <AssetsForTesting/Asset/AssetB.hpp>
|
||||
|
||||
#include <Engine/Asset/AssetHelper.hpp>
|
||||
|
||||
BIGFOOT_ASSET(AssetB, ::Bigfoot::AssetB)
|
||||
@@ -0,0 +1,11 @@
|
||||
/*********************************************************************
|
||||
* \file AssetC.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date July 2026
|
||||
*********************************************************************/
|
||||
#include <AssetsForTesting/Asset/AssetC.hpp>
|
||||
|
||||
#include <Engine/Asset/AssetHelper.hpp>
|
||||
|
||||
BIGFOOT_ASSET(AssetC, ::Bigfoot::AssetC)
|
||||
@@ -0,0 +1,15 @@
|
||||
get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
project(${PackageName})
|
||||
|
||||
set(PublicDependencies)
|
||||
set(PrivateDependencies)
|
||||
set(BigfootPublicDependencies)
|
||||
set(BigfootPrivateDependencies
|
||||
Engine)
|
||||
|
||||
bigfoot_create_package_tests_helper_lib(
|
||||
"${PublicDependencies}"
|
||||
"${PrivateDependencies}"
|
||||
"${BigfootPublicDependencies}"
|
||||
"${BigfootPrivateDependencies}"
|
||||
"")
|
||||
@@ -0,0 +1,13 @@
|
||||
include "Engine/Asset/Reference.fbs";
|
||||
|
||||
namespace Flat.Bigfoot;
|
||||
|
||||
table AssetA
|
||||
{
|
||||
health: uint = 0;
|
||||
mana: uint = 0;
|
||||
|
||||
ref_a: SoftReference (native_inline, bigfoot_ref: "::Bigfoot::AssetA");
|
||||
}
|
||||
|
||||
root_type AssetA;
|
||||
@@ -0,0 +1,25 @@
|
||||
/*********************************************************************
|
||||
* \file AssetA.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date April 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_ASSETSFORTESTING_ASSET_ASSETA_HPP
|
||||
#define BIGFOOT_ASSETSFORTESTING_ASSET_ASSETA_HPP
|
||||
#include <Engine/Asset/Asset.hpp>
|
||||
|
||||
#include <AssetsForTesting/Asset/AssetA_generated.hpp>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
struct AssetATraits
|
||||
{
|
||||
using FLAT = ::Flat::Bigfoot::AssetA;
|
||||
};
|
||||
|
||||
class AssetA: public Asset<AssetATraits>
|
||||
{
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
|
||||
#endif
|
||||
+251
@@ -0,0 +1,251 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
|
||||
#ifndef FLATBUFFERS_GENERATED_ASSETA_FLAT_BIGFOOT_H_
|
||||
#define FLATBUFFERS_GENERATED_ASSETA_FLAT_BIGFOOT_H_
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
|
||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||
// generated, otherwise it may not be compatible.
|
||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 19,
|
||||
"Non-compatible flatbuffers version included");
|
||||
// Ensure the included flatbuffers.h is Bigfoot's fork - stock
|
||||
// flatbuffers (or a differently versioned Bigfoot fork) is not compatible.
|
||||
#ifndef FLATBUFFERS_BIGFOOT_VERSION
|
||||
#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible"
|
||||
#endif
|
||||
static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1,
|
||||
"Non-compatible Bigfoot flatbuffers fork version included");
|
||||
|
||||
#include "System/UUID/UUID.hpp"
|
||||
#include "Engine/Asset/Reference.hpp"
|
||||
#include "Engine/Asset/Reference_generated.hpp"
|
||||
|
||||
#include "EASTL/unique_ptr.h"
|
||||
#include "EASTL/string.h"
|
||||
#include "EASTL/vector.h"
|
||||
|
||||
namespace Flat {
|
||||
namespace Bigfoot {
|
||||
|
||||
struct AssetA;
|
||||
struct AssetABuilder;
|
||||
struct AssetAT;
|
||||
|
||||
} // namespace Bigfoot
|
||||
} // namespace Flat
|
||||
|
||||
namespace Bigfoot {
|
||||
class AssetA;
|
||||
} // namespace Bigfoot
|
||||
|
||||
namespace flatbuffers {
|
||||
Flat::Bigfoot::SoftReference PackSoftReferenceAssetA(const ::Bigfoot::SoftReference<::Bigfoot::AssetA>& p_asset);
|
||||
::Bigfoot::SoftReference<::Bigfoot::AssetA> UnPackSoftReferenceAssetA(const Flat::Bigfoot::SoftReference& p_asset);
|
||||
} // namespace flatbuffers
|
||||
|
||||
namespace Flat {
|
||||
namespace Bigfoot {
|
||||
|
||||
inline const ::flatbuffers::TypeTable *AssetATypeTable();
|
||||
|
||||
struct AssetAT : public ::flatbuffers::NativeTable {
|
||||
typedef AssetA TableType;
|
||||
static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() {
|
||||
return "Flat.Bigfoot.AssetAT";
|
||||
}
|
||||
uint32_t health = 0;
|
||||
uint32_t mana = 0;
|
||||
::Bigfoot::SoftReference<::Bigfoot::AssetA> ref_a{};
|
||||
};
|
||||
|
||||
struct AssetA FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||
typedef AssetAT NativeTableType;
|
||||
typedef AssetABuilder Builder;
|
||||
struct Traits;
|
||||
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
return AssetATypeTable();
|
||||
}
|
||||
static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() {
|
||||
return "Flat.Bigfoot.AssetA";
|
||||
}
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_HEALTH = 4,
|
||||
VT_MANA = 6,
|
||||
VT_REF_A = 8
|
||||
};
|
||||
uint32_t health() const {
|
||||
return GetField<uint32_t>(VT_HEALTH, 0);
|
||||
}
|
||||
uint32_t mana() const {
|
||||
return GetField<uint32_t>(VT_MANA, 0);
|
||||
}
|
||||
const Flat::Bigfoot::SoftReference *ref_a() const {
|
||||
return GetStruct<const Flat::Bigfoot::SoftReference *>(VT_REF_A);
|
||||
}
|
||||
template <bool B = false>
|
||||
bool Verify(::flatbuffers::VerifierTemplate<B> &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint32_t>(verifier, VT_HEALTH, 4) &&
|
||||
VerifyField<uint32_t>(verifier, VT_MANA, 4) &&
|
||||
VerifyField<Flat::Bigfoot::SoftReference>(verifier, VT_REF_A, 1) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
AssetAT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||
void UnPackTo(AssetAT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||
static ::flatbuffers::Offset<AssetA> Pack(::flatbuffers::FlatBufferBuilder &_fbb, const AssetAT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
};
|
||||
|
||||
struct AssetABuilder {
|
||||
typedef AssetA Table;
|
||||
::flatbuffers::FlatBufferBuilder &fbb_;
|
||||
::flatbuffers::uoffset_t start_;
|
||||
void add_health(uint32_t health) {
|
||||
fbb_.AddElement<uint32_t>(AssetA::VT_HEALTH, health, 0);
|
||||
}
|
||||
void add_mana(uint32_t mana) {
|
||||
fbb_.AddElement<uint32_t>(AssetA::VT_MANA, mana, 0);
|
||||
}
|
||||
void add_ref_a(const Flat::Bigfoot::SoftReference *ref_a) {
|
||||
fbb_.AddStruct(AssetA::VT_REF_A, ref_a);
|
||||
}
|
||||
explicit AssetABuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
::flatbuffers::Offset<AssetA> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = ::flatbuffers::Offset<AssetA>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline ::flatbuffers::Offset<AssetA> CreateAssetA(
|
||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint32_t health = 0,
|
||||
uint32_t mana = 0,
|
||||
const Flat::Bigfoot::SoftReference *ref_a = nullptr) {
|
||||
AssetABuilder builder_(_fbb);
|
||||
builder_.add_ref_a(ref_a);
|
||||
builder_.add_mana(mana);
|
||||
builder_.add_health(health);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
struct AssetA::Traits {
|
||||
using type = AssetA;
|
||||
static auto constexpr Create = CreateAssetA;
|
||||
};
|
||||
|
||||
::flatbuffers::Offset<AssetA> CreateAssetA(::flatbuffers::FlatBufferBuilder &_fbb, const AssetAT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
|
||||
inline AssetAT *AssetA::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const {
|
||||
auto _o = std::make_unique<AssetAT>();
|
||||
UnPackTo(_o.get(), _resolver);
|
||||
return _o.release();
|
||||
}
|
||||
|
||||
inline void AssetA::UnPackTo(AssetAT *_o, const ::flatbuffers::resolver_function_t *_resolver) const {
|
||||
(void)_o;
|
||||
(void)_resolver;
|
||||
{ auto _e = health(); _o->health = _e; }
|
||||
{ auto _e = mana(); _o->mana = _e; }
|
||||
{ auto _e = ref_a(); if (_e) _o->ref_a = ::flatbuffers::UnPackSoftReferenceAssetA(*_e); }
|
||||
}
|
||||
|
||||
inline ::flatbuffers::Offset<AssetA> CreateAssetA(::flatbuffers::FlatBufferBuilder &_fbb, const AssetAT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
||||
return AssetA::Pack(_fbb, _o, _rehasher);
|
||||
}
|
||||
|
||||
inline ::flatbuffers::Offset<AssetA> AssetA::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const AssetAT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
||||
(void)_rehasher;
|
||||
(void)_o;
|
||||
struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const AssetAT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
|
||||
auto _health = _o->health;
|
||||
auto _mana = _o->mana;
|
||||
auto _ref_a = ::flatbuffers::PackSoftReferenceAssetA(_o->ref_a);
|
||||
return Flat::Bigfoot::CreateAssetA(
|
||||
_fbb,
|
||||
_health,
|
||||
_mana,
|
||||
&_ref_a);
|
||||
}
|
||||
|
||||
inline const ::flatbuffers::TypeTable *AssetATypeTable() {
|
||||
static const ::flatbuffers::TypeCode type_codes[] = {
|
||||
{ ::flatbuffers::ET_UINT, 0, -1 },
|
||||
{ ::flatbuffers::ET_UINT, 0, -1 },
|
||||
{ ::flatbuffers::ET_SEQUENCE, 0, 0 }
|
||||
};
|
||||
static const ::flatbuffers::TypeFunction type_refs[] = {
|
||||
Flat::Bigfoot::SoftReferenceTypeTable
|
||||
};
|
||||
static const ::flatbuffers::TypeTable tt = {
|
||||
::flatbuffers::ST_TABLE, 3, type_codes, type_refs, nullptr, nullptr, nullptr
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
|
||||
inline const Flat::Bigfoot::AssetA *GetAssetA(const void *buf) {
|
||||
return ::flatbuffers::GetRoot<Flat::Bigfoot::AssetA>(buf);
|
||||
}
|
||||
|
||||
inline const Flat::Bigfoot::AssetA *GetSizePrefixedAssetA(const void *buf) {
|
||||
return ::flatbuffers::GetSizePrefixedRoot<Flat::Bigfoot::AssetA>(buf);
|
||||
}
|
||||
|
||||
template <bool B = false>
|
||||
inline bool VerifyAssetABuffer(
|
||||
::flatbuffers::VerifierTemplate<B> &verifier) {
|
||||
return verifier.template VerifyBuffer<Flat::Bigfoot::AssetA>(nullptr);
|
||||
}
|
||||
|
||||
template <bool B = false>
|
||||
inline bool VerifySizePrefixedAssetABuffer(
|
||||
::flatbuffers::VerifierTemplate<B> &verifier) {
|
||||
return verifier.template VerifySizePrefixedBuffer<Flat::Bigfoot::AssetA>(nullptr);
|
||||
}
|
||||
|
||||
inline const char *AssetAExtension() {
|
||||
return "bfbs";
|
||||
}
|
||||
|
||||
inline void FinishAssetABuffer(
|
||||
::flatbuffers::FlatBufferBuilder &fbb,
|
||||
::flatbuffers::Offset<Flat::Bigfoot::AssetA> root) {
|
||||
fbb.Finish(root);
|
||||
}
|
||||
|
||||
inline void FinishSizePrefixedAssetABuffer(
|
||||
::flatbuffers::FlatBufferBuilder &fbb,
|
||||
::flatbuffers::Offset<Flat::Bigfoot::AssetA> root) {
|
||||
fbb.FinishSizePrefixed(root);
|
||||
}
|
||||
|
||||
inline eastl::unique_ptr<Flat::Bigfoot::AssetAT> UnPackAssetA(
|
||||
const void *buf,
|
||||
const ::flatbuffers::resolver_function_t *res = nullptr) {
|
||||
return eastl::unique_ptr<Flat::Bigfoot::AssetAT>(GetAssetA(buf)->UnPack(res));
|
||||
}
|
||||
|
||||
inline eastl::unique_ptr<Flat::Bigfoot::AssetAT> UnPackSizePrefixedAssetA(
|
||||
const void *buf,
|
||||
const ::flatbuffers::resolver_function_t *res = nullptr) {
|
||||
return eastl::unique_ptr<Flat::Bigfoot::AssetAT>(GetSizePrefixedAssetA(buf)->UnPack(res));
|
||||
}
|
||||
|
||||
} // namespace Bigfoot
|
||||
} // namespace Flat
|
||||
|
||||
namespace flatbuffers {
|
||||
#ifndef FLATBUFFERS_BIGFOOT_REF_SOFTREFERENCEASSETA
|
||||
#define FLATBUFFERS_BIGFOOT_REF_SOFTREFERENCEASSETA
|
||||
inline Flat::Bigfoot::SoftReference PackSoftReferenceAssetA(const ::Bigfoot::SoftReference<::Bigfoot::AssetA>& p_asset) { return {Pack(p_asset.GetUUID())}; }
|
||||
inline ::Bigfoot::SoftReference<::Bigfoot::AssetA> UnPackSoftReferenceAssetA(const Flat::Bigfoot::SoftReference& p_asset) { return {UnPack(p_asset.uuid())}; }
|
||||
#endif // FLATBUFFERS_BIGFOOT_REF_SOFTREFERENCEASSETA
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_GENERATED_ASSETA_FLAT_BIGFOOT_H_
|
||||
@@ -0,0 +1,11 @@
|
||||
include "Engine/Asset/Reference.fbs";
|
||||
|
||||
namespace Flat.Bigfoot;
|
||||
|
||||
table AssetB
|
||||
{
|
||||
ref_a: HardReference (native_inline, bigfoot_ref: "::Bigfoot::AssetA");
|
||||
refs_a: [SoftReference] (native_inline, bigfoot_ref: "::Bigfoot::AssetA");
|
||||
}
|
||||
|
||||
root_type AssetB;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user