StableSlotMap
Bigfoot / Sonarqube (push) Skipped
Bigfoot / Build & Test Debug with ./ConanProfiles/clang (Unity Build: OFF) (push) Failing after 2m4s
Bigfoot / Build & Test Debug with ./ConanProfiles/clang (Unity Build: ON) (push) Failing after 2m34s
Bigfoot / Build & Test Debug with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Failing after 8m3s
Bigfoot / Build & Test Debug with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Failing after 6m46s
Bigfoot / Build & Test Release with ./ConanProfiles/clang (Unity Build: OFF) (push) Canceled after 0s
Bigfoot / Build & Test Release with ./ConanProfiles/clang (Unity Build: ON) (push) Canceled after 0s
Bigfoot / Build & Test Release with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Canceled after 0s
Bigfoot / Build & Test Release with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Canceled after 0s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang (Unity Build: ON) (push) Canceled after 0s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang_asan (Unity Build: OFF) (push) Canceled after 0s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang_asan (Unity Build: ON) (push) Canceled after 0s
Bigfoot / Clang Format Checks (push) Canceled after 0s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/clang (Unity Build: OFF) (push) Canceled after 1m18s

This commit is contained in:
2026-08-17 17:25:49 +02:00
parent 9733860ecd
commit 96c4353a8a
21 changed files with 564 additions and 1138 deletions
@@ -41,19 +41,19 @@ template<class SLOTMAP>
class SlotMapAdaptor
{
public:
using Key = SlotMapKey;
using Key = SLOTMAP::SlotMapKey;
SlotMapKey Add(MyComplexStruct&& p_value)
Key Add(MyComplexStruct&& p_value)
{
return m_container.Insert(std::move(p_value));
}
const MyComplexStruct* Find(const SlotMapKey p_key) const
const MyComplexStruct* Find(const Key p_key) const
{
return m_container.Get(p_key);
}
void Remove(const SlotMapKey p_key)
void Remove(const Key p_key)
{
m_container.Remove(p_key);
}
@@ -119,6 +119,8 @@ class ContainerHandle
class AssetContainerBase
{
using SlotMap = StableSlotMap<ContainerHandle>;
using SlotMapKey = SlotMap::SlotMapKey;
public:
virtual ~AssetContainerBase() = default;
@@ -245,7 +247,7 @@ class AssetContainerBase
/*
* HandleContainers
*/
StableSlotMap<ContainerHandle> m_handles;
SlotMap m_handles;
/*
* Every Asset added to the map
@@ -258,6 +260,8 @@ class AssetContainerBase
template<class ASSET>
class AssetContainer: public AssetContainerBase
{
using SlotMap = StableSlotMap<ASSET>;
using SlotMapKey = SlotMap::SlotMapKey;
public:
AssetContainer() = default;
@@ -343,7 +347,7 @@ class AssetContainer: public AssetContainerBase
/*
* The assets
*/
StableSlotMap<ASSET> m_assets;
SlotMap m_assets;
};
} // namespace Bigfoot
-1
View File
@@ -1 +0,0 @@
// to delete when an actual source is in Engine
@@ -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
@@ -1,16 +0,0 @@
namespace Bigfoot.Flat;
enum LogSinkType: byte
{
Console
}
enum LogLevel: byte
{
Debug,
Trace,
Info,
Warn,
Error,
Critical
}
@@ -1,182 +0,0 @@
/*********************************************************************
* \file Log.hpp
*
* \author Romain BOULLARD
* \date October 2025
*********************************************************************/
#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>
#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
#define BIGFOOT_LOG_DEBUG(loggerName, fmt, ...) \
do \
{ \
if (quill::Logger* logger = Bigfoot::Singleton<Bigfoot::Log>::Instance().GetLogger(loggerName)) \
{ \
QUILL_LOG_DEBUG(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
else \
{ \
QUILL_LOG_DEBUG(Bigfoot::Singleton<Bigfoot::Log>::Instance().RegisterLogger(loggerName), \
fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
#define BIGFOOT_LOG_TRACE(loggerName, fmt, ...) \
do \
{ \
if (quill::Logger* logger = Bigfoot::Singleton<Bigfoot::Log>::Instance().GetLogger(loggerName)) \
{ \
QUILL_LOG_TRACE_L3(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
else \
{ \
QUILL_LOG_TRACE_L3(Bigfoot::Singleton<Bigfoot::Log>::Instance().RegisterLogger(loggerName), \
fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
#define BIGFOOT_LOG_INFO(loggerName, fmt, ...) \
do \
{ \
if (quill::Logger* logger = Bigfoot::Singleton<Bigfoot::Log>::Instance().GetLogger(loggerName)) \
{ \
QUILL_LOG_INFO(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
else \
{ \
QUILL_LOG_INFO(Bigfoot::Singleton<Bigfoot::Log>::Instance().RegisterLogger(loggerName), \
fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
#define BIGFOOT_LOG_WARN(loggerName, fmt, ...) \
do \
{ \
if (quill::Logger* logger = Bigfoot::Singleton<Bigfoot::Log>::Instance().GetLogger(loggerName)) \
{ \
QUILL_LOG_WARNING(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
else \
{ \
QUILL_LOG_WARNING(Bigfoot::Singleton<Bigfoot::Log>::Instance().RegisterLogger(loggerName), \
fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
#define BIGFOOT_LOG_ERROR(loggerName, fmt, ...) \
do \
{ \
if (quill::Logger* logger = Bigfoot::Singleton<Bigfoot::Log>::Instance().GetLogger(loggerName)) \
{ \
QUILL_LOG_ERROR(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
else \
{ \
QUILL_LOG_ERROR(Bigfoot::Singleton<Bigfoot::Log>::Instance().RegisterLogger(loggerName), \
fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
#define BIGFOOT_LOG_FATAL(loggerName, fmt, ...) \
do \
{ \
if (quill::Logger* logger = Bigfoot::Singleton<Bigfoot::Log>::Instance().GetLogger(loggerName)) \
{ \
QUILL_LOG_CRITICAL(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
else \
{ \
QUILL_LOG_CRITICAL(Bigfoot::Singleton<Bigfoot::Log>::Instance().RegisterLogger(loggerName), \
fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
#else
#define BIGFOOT_LOG_DEBUG(loggerName, fmt, ...)
#define BIGFOOT_LOG_TRACE(loggerName, fmt, ...)
#define BIGFOOT_LOG_INFO(loggerName, fmt, ...)
#define BIGFOOT_LOG_WARN(loggerName, fmt, ...)
#define BIGFOOT_LOG_ERROR(loggerName, fmt, ...)
#define BIGFOOT_LOG_FATAL(loggerName, fmt, ...)
#endif
#endif
@@ -1,133 +0,0 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_LOG_BIGFOOT_FLAT_H_
#define FLATBUFFERS_GENERATED_LOG_BIGFOOT_FLAT_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 Bigfoot {
namespace Flat {
enum class LogSinkType : int8_t {
Console = 0,
MIN = Console,
MAX = Console
};
inline const LogSinkType (&EnumValuesLogSinkType())[1] {
static const LogSinkType values[] = {
LogSinkType::Console
};
return values;
}
inline const char * const *EnumNamesLogSinkType() {
static const char * const names[2] = {
"Console",
nullptr
};
return names;
}
inline const char *EnumNameLogSinkType(LogSinkType e) {
if (::flatbuffers::IsOutRange(e, LogSinkType::Console, LogSinkType::Console)) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesLogSinkType()[index];
}
enum class LogLevel : int8_t {
Debug = 0,
Trace = 1,
Info = 2,
Warn = 3,
Error = 4,
Critical = 5,
MIN = Debug,
MAX = Critical
};
inline const LogLevel (&EnumValuesLogLevel())[6] {
static const LogLevel values[] = {
LogLevel::Debug,
LogLevel::Trace,
LogLevel::Info,
LogLevel::Warn,
LogLevel::Error,
LogLevel::Critical
};
return values;
}
inline const char * const *EnumNamesLogLevel() {
static const char * const names[7] = {
"Debug",
"Trace",
"Info",
"Warn",
"Error",
"Critical",
nullptr
};
return names;
}
inline const char *EnumNameLogLevel(LogLevel e) {
if (::flatbuffers::IsOutRange(e, LogLevel::Debug, LogLevel::Critical)) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesLogLevel()[index];
}
inline const ::flatbuffers::TypeTable *LogSinkTypeTypeTable() {
static const ::flatbuffers::TypeCode type_codes[] = {
{ ::flatbuffers::ET_CHAR, 0, 0 }
};
static const ::flatbuffers::TypeFunction type_refs[] = {
Bigfoot::Flat::LogSinkTypeTypeTable
};
static const ::flatbuffers::TypeTable tt = {
::flatbuffers::ST_ENUM, 1, type_codes, type_refs, nullptr, nullptr, nullptr
};
return &tt;
}
inline const ::flatbuffers::TypeTable *LogLevelTypeTable() {
static const ::flatbuffers::TypeCode type_codes[] = {
{ ::flatbuffers::ET_CHAR, 0, 0 },
{ ::flatbuffers::ET_CHAR, 0, 0 },
{ ::flatbuffers::ET_CHAR, 0, 0 },
{ ::flatbuffers::ET_CHAR, 0, 0 },
{ ::flatbuffers::ET_CHAR, 0, 0 },
{ ::flatbuffers::ET_CHAR, 0, 0 }
};
static const ::flatbuffers::TypeFunction type_refs[] = {
Bigfoot::Flat::LogLevelTypeTable
};
static const ::flatbuffers::TypeTable tt = {
::flatbuffers::ST_ENUM, 6, type_codes, type_refs, nullptr, nullptr, nullptr
};
return &tt;
}
} // namespace Flat
} // namespace Bigfoot
#endif // FLATBUFFERS_GENERATED_LOG_BIGFOOT_FLAT_H_
@@ -1,21 +0,0 @@
@AUTO_GENERATED_COMMENT@
/*********************************************************************
* \file @LOGGER_FILENAME@.generated.hpp
*
*********************************************************************/
#ifndef BIGFOOT_@LOGGER_FILENAME_UPPER@_GENERATED_HPP
#define BIGFOOT_@LOGGER_FILENAME_UPPER@_GENERATED_HPP
#include <System/Log/Log.hpp>
#if defined BIGFOOT_NOT_OPTIMIZED
namespace Bigfoot
{
/*
* Logger
*/
inline Log::LoggerInfo @LOGGER_NAME@ {"@LOGGER_NAME@", Flat::LogLevel::Trace};
} // namespace Bigfoot
#endif
#endif
@@ -1,64 +0,0 @@
/*********************************************************************
* \file Profiler.hpp
*
* \author Romain BOULLARD
* \date October 2025
*********************************************************************/
#ifndef BIGFOOT_CONCAT_PROFILER_HPP
#define BIGFOOT_CONCAT_PROFILER_HPP
#ifdef TRACY
#include <tracy/Tracy.hpp>
#define BIGFOOT_PROFILER_THREADNAME(p_name) tracy::SetThreadName(p_name)
#define BIGFOOT_PROFILER_FRAME() FrameMark
#define BIGFOOT_PROFILER_FRAME_START(p_name) FrameMarkStart(p_name)
#define BIGFOOT_PROFILER_FRAME_STOP(p_name) FrameMarkEnd(p_name)
#define BIGFOOT_PROFILER_PROFILE_FUNCTION() ZoneScoped
#define BIGFOOT_PROFILER_PROFILE(p_name) ZoneScopedN(p_name)
#define BIGFOOT_PROFILER_TEXT(p_text, p_size) ZoneText(p_text, p_size)
#define BIGFOOT_PROFILER_MEMORY_ALLOC(p_ptr, p_size) TracyAlloc(p_ptr, p_size)
#define BIGFOOT_PROFILER_MEMORY_FREE(p_ptr) TracyFree(p_ptr)
#define BIGFOOT_PROFILER_LOCKABLE(p_type, p_name) TracyLockable(p_type, p_name)
#define BIGFOOT_PROFILER_LOCK(p_name) LockMark(p_name)
#define BIGFOOT_PROFILER_APPINFO(p_text, p_size) TracyAppInfo(p_text, p_size)
#define BIGFOOT_PROFILER_ATTACH_FRAME_IMAGE(p_imageData, p_width, p_height, p_offset) \
FrameImage(p_imageData, p_width, p_height, p_offset, false)
#define BIGFOOT_PROFILER
#define BIGFOOT_PROFILER_ONLY(...) __VA_ARGS__
// TODO: profile GPU
#else
#define BIGFOOT_PROFILER_THREADNAME(p_name)
#define BIGFOOT_PROFILER_FRAME()
#define BIGFOOT_PROFILER_FRAME_START(p_name)
#define BIGFOOT_PROFILER_FRAME_STOP(p_name)
#define BIGFOOT_PROFILER_PROFILE_FUNCTION()
#define BIGFOOT_PROFILER_PROFILE(p_name)
#define BIGFOOT_PROFILER_TEXT_FUNCTION(p_text, p_size)
#define BIGFOOT_PROFILER_TEXT(p_text, p_size)
#define BIGFOOT_PROFILER_MEMORY_ALLOC(p_ptr, p_size)
#define BIGFOOT_PROFILER_MEMORY_FREE(p_ptr)
#define BIGFOOT_PROFILER_LOCKABLE(p_type, p_name) p_type p_name
#define BIGFOOT_PROFILER_LOCK(p_name)
#define BIGFOOT_PROFILER_APPINFO(p_text, p_size)
#define BIGFOOT_PROFILER_ATTACH_FRAME_IMAGE(p_imageData, p_width, p_height, p_offset)
#define BIGFOOT_PROFILER_ONLY(...)
// TODO: profile GPU
#endif
#endif
@@ -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
-92
View File
@@ -1,92 +0,0 @@
/*******************************************************************
* \file Log.cpp
*
* \author Romain BOULLARD
* \date October 2025
*********************************************************************/
#include <System/Log/Log.hpp>
#if defined BIGFOOT_NOT_OPTIMIZED
namespace Bigfoot
{
Log::Log()
{
quill::Backend::start();
m_sinks[static_cast<std::size_t>(Flat::LogSinkType::Console)] =
quill::Frontend::create_or_get_sink<quill::ConsoleSink>(
std::string {Flat::EnumNameLogSinkType(Flat::LogSinkType::Console)});
}
/****************************************************************************************/
quill::Logger* Log::RegisterLogger(const LoggerInfo& p_loggerInfo)
{
quill::Logger* logger = quill::Frontend::create_or_get_logger(
p_loggerInfo.m_name,
m_sinks[static_cast<std::size_t>(Flat::LogSinkType::Console)]);
SetLoggerLevel(p_loggerInfo);
return logger;
}
/****************************************************************************************/
quill::Logger* Log::GetLogger(const LoggerInfo& p_loggerInfo)
{
return quill::Frontend::get_logger(p_loggerInfo.m_name);
}
/****************************************************************************************/
void Log::ChangeLoggerLogLevel(LoggerInfo& p_loggerInfo, const Flat::LogLevel p_level)
{
p_loggerInfo.m_level = p_level;
SetLoggerLevel(p_loggerInfo);
}
/****************************************************************************************/
void Log::SetLoggerLevel(const LoggerInfo& p_loggerInfo)
{
constexpr auto logLevelToQuillLogLevel = [](const Flat::LogLevel p_level) constexpr -> quill::LogLevel
{
switch (p_level)
{
case Flat::LogLevel::Debug:
return quill::LogLevel::Debug;
case Flat::LogLevel::Trace:
return quill::LogLevel::TraceL3;
case Flat::LogLevel::Info:
return quill::LogLevel::Info;
case Flat::LogLevel::Warn:
return quill::LogLevel::Warning;
case Flat::LogLevel::Error:
return quill::LogLevel::Error;
case Flat::LogLevel::Critical:
return quill::LogLevel::Critical;
}
return quill::LogLevel::TraceL3;
};
if (quill::Logger* logger = GetLogger(p_loggerInfo))
{
logger->set_log_level(logLevelToQuillLogLevel(p_loggerInfo.m_level));
}
}
/****************************************************************************************/
Log::~Log()
{
for (quill::Logger* logger: quill::Frontend::get_all_loggers())
{
quill::Frontend::remove_logger(logger);
}
quill::Backend::stop();
}
} // namespace Bigfoot
#endif
-98
View File
@@ -1,98 +0,0 @@
/*********************************************************************
* \file MimallocImpl.cpp
*
* \author Romain BOULLARD
* \date October 2025
*********************************************************************/
#include <System/Profiler.hpp>
#if defined BIGFOOT_WINDOWS
#pragma comment(linker, "/include:mi_version")
#pragma warning(disable: 4100 4559)
#elif defined BIGFOOT_LINUX
#if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#else
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#endif
#endif
// Taken from mimalloc-new-delete.h
// clang-format off
// ----------------------------------------------------------------------------
// This header provides convenient overrides for the new and
// delete operations in C++.
//
// This header should be included in only one source file!
//
// On Windows, or when linking dynamically with mimalloc, these
// can be more performant than the standard new-delete operations.
// See <https://en.cppreference.com/w/cpp/memory/new/operator_new>
// ---------------------------------------------------------------------------
#if defined(__cplusplus)
#include <new>
#include <mimalloc.h>
#if defined(_MSC_VER) && defined(_Ret_notnull_) && defined(_Post_writable_byte_size_)
// stay consistent with VCRT definitions
#define mi_decl_new(n) mi_decl_nodiscard mi_decl_restrict _Ret_notnull_ _Post_writable_byte_size_(n)
#define mi_decl_new_nothrow(n) mi_decl_nodiscard mi_decl_restrict _Ret_maybenull_ _Success_(return != NULL) _Post_writable_byte_size_(n)
#else
#define mi_decl_new(n) mi_decl_nodiscard mi_decl_restrict
#define mi_decl_new_nothrow(n) mi_decl_nodiscard mi_decl_restrict
#endif
void operator delete(void* p) noexcept { mi_free(p); BIGFOOT_PROFILER_MEMORY_FREE(p); };
void operator delete[](void* p) noexcept { mi_free(p); BIGFOOT_PROFILER_MEMORY_FREE(p); };
void operator delete (void* p, const std::nothrow_t&) noexcept { mi_free(p); BIGFOOT_PROFILER_MEMORY_FREE(p); }
void operator delete[](void* p, const std::nothrow_t&) noexcept { mi_free(p); BIGFOOT_PROFILER_MEMORY_FREE(p); }
mi_decl_new(n) void* operator new(std::size_t n) noexcept(false) { void* p = mi_new(n); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; }
mi_decl_new(n) void* operator new[](std::size_t n) noexcept(false) { void* p = mi_new(n); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; }
mi_decl_new_nothrow(n) void* operator new (std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); void* p = mi_new_nothrow(n); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; }
mi_decl_new_nothrow(n) void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); void* p = mi_new_nothrow(n); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; }
// Not from mimalloc-new-delete.h, but necessary for EASTL
void* operator new[](size_t size, const char* name, int flags, unsigned debugFlags, const char* file, int line) noexcept(false) { void* p = mi_new(size); BIGFOOT_PROFILER_MEMORY_ALLOC(p, size); return p; }
#if (__cplusplus >= 201402L || _MSC_VER >= 1916)
void operator delete (void* p, std::size_t n) noexcept { mi_free_size(p,n); BIGFOOT_PROFILER_MEMORY_FREE(p); };
void operator delete[](void* p, std::size_t n) noexcept { mi_free_size(p,n); BIGFOOT_PROFILER_MEMORY_FREE(p); };
#endif
#if (__cplusplus > 201402L || defined(__cpp_aligned_new))
void operator delete (void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); BIGFOOT_PROFILER_MEMORY_FREE(p); }
void operator delete[](void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); BIGFOOT_PROFILER_MEMORY_FREE(p); }
void operator delete (void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast<size_t>(al)); BIGFOOT_PROFILER_MEMORY_FREE(p); };
void operator delete[](void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast<size_t>(al)); BIGFOOT_PROFILER_MEMORY_FREE(p); };
void operator delete (void* p, std::align_val_t al, const std::nothrow_t&) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); BIGFOOT_PROFILER_MEMORY_FREE(p); }
void operator delete[](void* p, std::align_val_t al, const std::nothrow_t&) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); BIGFOOT_PROFILER_MEMORY_FREE(p); }
void* operator new (std::size_t n, std::align_val_t al) noexcept(false) { void* p = mi_new_aligned(n, static_cast<size_t>(al)); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; }
void* operator new[](std::size_t n, std::align_val_t al) noexcept(false) { void* p = mi_new_aligned(n, static_cast<size_t>(al)); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; }
void* operator new (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { void* p = mi_new_aligned_nothrow(n, static_cast<size_t>(al)); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; }
void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { void* p = mi_new_aligned_nothrow(n, static_cast<size_t>(al)); BIGFOOT_PROFILER_MEMORY_ALLOC(p, n); return p; }
// Not from mimalloc-new-delete.h, but necessary for EASTL
void* operator new[](size_t size, size_t alignment, size_t alignmentOffset, const char* pName, int flags, unsigned debugFlags, const char* file, int line) noexcept(false) { void* p = mi_new_aligned(size, alignment); BIGFOOT_PROFILER_MEMORY_ALLOC(p, size); return p; }
#endif
#endif
// clang-format on
#if defined BIGFOOT_WINDOWS
#pragma warning(default: 4100 4559)
#elif defined BIGFOOT_LINUX
#if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER)
#pragma GCC diagnostic pop
#else
#pragma clang diagnostic pop
#endif
#endif
-121
View File
@@ -1,121 +0,0 @@
/*********************************************************************
* \file Time.cpp
*
* \author Romain BOULLARD
* \date December 2025
*********************************************************************/
#include <System/Time.hpp>
#include <System/SystemAssertHandler.hpp>
namespace
{
[[nodiscard]]
std::tm GetTimeInfo(const std::time_t& p_time)
{
std::tm timeInfo {};
#ifdef BIGFOOT_WINDOWS
[[maybe_unused]]
const errno_t error = gmtime_s(&timeInfo, &p_time);
if (error != 0)
{
char errnoStr[256];
strerror_s(errnoStr, error);
CRITICAL_ASSERT(Bigfoot::SystemAssertHandler,
false,
"Failed to convert epoch time to calendar time. {}",
errnoStr);
}
#elif BIGFOOT_LINUX
[[maybe_unused]]
const std::tm* error = gmtime_r(&p_time, &timeInfo);
CRITICAL_ASSERT(Bigfoot::SystemAssertHandler, error, "Failed to convert epoch time to calendar time");
#else
static_assert(false, "not implemented");
#endif
return timeInfo;
}
} // namespace
namespace Bigfoot
{
Time::Time(const std::uint64_t p_epoch):
m_epoch(p_epoch),
m_timeInfo(GetTimeInfo(std::chrono::system_clock::to_time_t(
std::chrono::time_point<std::chrono::system_clock> {std::chrono::microseconds {m_epoch}}))),
m_microseconds(std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::time_point<std::chrono::system_clock> {
std::chrono::microseconds {m_epoch}}.time_since_epoch()) %
std::chrono::seconds(1)))
{
}
/****************************************************************************************/
std::uint32_t Time::Year() const
{
return m_timeInfo.tm_year + 1900;
}
/****************************************************************************************/
std::uint32_t Time::Month() const
{
return m_timeInfo.tm_mon + 1;
}
/****************************************************************************************/
std::uint32_t Time::Day() const
{
return m_timeInfo.tm_mday;
}
/****************************************************************************************/
std::uint32_t Time::Hour() const
{
return m_timeInfo.tm_hour;
}
/****************************************************************************************/
std::uint32_t Time::Minute() const
{
return m_timeInfo.tm_min;
}
/****************************************************************************************/
std::uint32_t Time::Second() const
{
return m_timeInfo.tm_sec;
}
/****************************************************************************************/
std::uint32_t Time::Microsecond() const
{
return static_cast<std::uint32_t>(m_microseconds.count());
}
/****************************************************************************************/
std::uint64_t Time::Epoch() const
{
return m_epoch;
}
/****************************************************************************************/
Time Time::Now()
{
const std::chrono::time_point<std::chrono::system_clock> time = std::chrono::system_clock::now();
const std::uint64_t epochInMicroSeconds =
std::chrono::duration_cast<std::chrono::microseconds>(time.time_since_epoch()).count();
return Time {epochInMicroSeconds};
}
} // namespace Bigfoot
-27
View File
@@ -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
@@ -13,12 +13,15 @@
#include <EASTL/iterator.h>
#include <EASTL/unique_ptr.h>
#include <EASTL/vector.h>
#include <EASTL/numeric.h>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
namespace Bigfoot
{
@@ -331,12 +334,506 @@ class DenseSlotMap
std::size_t m_freeListHead = SlotMapKey::MAX_INDEX;
};
template<class T, class SLOT_MAP_KEY = SlotMapKey<>>
template<class T, class SLOT_MAP_KEY_TYPE = SlotMapKey<>>
class StableSlotMap
{
private:
static constexpr std::size_t PAGE_SIZE = 64;
struct AlignedSlot
{
alignas(T) std::byte m_bytes[sizeof(T)];
};
struct Page
{
Page() = default;
Page(const Page& p_page) = delete;
Page(Page&& p_page) = delete;
~Page()
{
for (std::size_t offset = m_occupied.find_first(); offset != PAGE_SIZE;
offset = m_occupied.find_next(offset))
{
std::destroy_at(Get(offset));
}
}
Page& operator=(const Page& p_page) = delete;
Page& operator=(Page&& p_page) = delete;
[[nodiscard]]
T* Get(const std::size_t p_offset)
{
return std::launder(reinterpret_cast<T*>(m_data[p_offset].m_bytes));
}
[[nodiscard]]
const T* Get(const std::size_t p_offset) const
{
return std::launder(reinterpret_cast<const T*>(m_data[p_offset].m_bytes));
}
[[nodiscard]]
std::size_t Size() const
{
return m_occupied.count();
}
eastl::array<AlignedSlot, PAGE_SIZE> m_data;
eastl::bitset<PAGE_SIZE> m_occupied;
};
public:
using SlotMapKey = SLOT_MAP_KEY_TYPE;
template<class VALUE_TYPE>
class IteratorImpl
{
private:
using PagesVector = eastl::vector<eastl::unique_ptr<Page>>;
using PageIterator =
std::conditional_t<std::is_const_v<VALUE_TYPE>, typename PagesVector::const_iterator, typename PagesVector::iterator>;
using MapType = std::conditional_t<std::is_const_v<VALUE_TYPE>, const StableSlotMap, StableSlotMap>;
using PageType = std::conditional_t<std::is_const_v<VALUE_TYPE>, const Page, Page>;
public:
using iterator_category = eastl::bidirectional_iterator_tag;
using value_type = std::remove_const_t<VALUE_TYPE>;
using difference_type = std::ptrdiff_t;
using pointer = VALUE_TYPE*;
using reference = VALUE_TYPE&;
IteratorImpl() = default;
// Allows an iterator to be implicitly used as a const_iterator.
template<class OTHER_VALUE_TYPE, class = std::enable_if_t<std::is_same_v<VALUE_TYPE, const OTHER_VALUE_TYPE>>>
IteratorImpl(const IteratorImpl<OTHER_VALUE_TYPE>& p_other):
m_map(p_other.m_map),
m_pageIt(p_other.m_pageIt),
m_page(p_other.m_page),
m_offset(p_other.m_offset),
m_current(p_other.m_current)
{
}
[[nodiscard]]
reference operator*() const
{
return *m_current;
}
[[nodiscard]]
pointer operator->() const
{
return m_current;
}
IteratorImpl& operator++()
{
Increment();
return *this;
}
IteratorImpl operator++(int)
{
const IteratorImpl temp = *this;
++(*this);
return temp;
}
IteratorImpl& operator--()
{
Decrement();
return *this;
}
IteratorImpl operator--(int)
{
const IteratorImpl temp = *this;
--(*this);
return temp;
}
[[nodiscard]]
bool operator==(const IteratorImpl& p_other) const
{
return m_map == p_other.m_map && m_current == p_other.m_current;
}
private:
friend class StableSlotMap;
template<class>
friend class IteratorImpl;
explicit IteratorImpl(MapType* p_map):
m_map(p_map)
{
}
void SeekFirstFrom(PageIterator p_pageIt)
{
for (; p_pageIt != m_map->m_pages.end(); ++p_pageIt)
{
PageType* const page = p_pageIt->get();
const std::size_t offset = page->m_occupied.find_first();
if (offset != PAGE_SIZE)
{
m_pageIt = p_pageIt;
m_page = page;
m_offset = offset;
m_current = page->Get(offset);
return;
}
}
m_pageIt = p_pageIt;
m_page = nullptr;
m_offset = 0;
m_current = nullptr;
}
void SeekLastFrom(PageIterator p_pageIt)
{
for (;;)
{
PageType* const page = p_pageIt->get();
const std::size_t offset = page->m_occupied.find_last();
if (offset != PAGE_SIZE)
{
m_pageIt = p_pageIt;
m_page = page;
m_offset = offset;
m_current = page->Get(offset);
return;
}
if (p_pageIt == m_map->m_pages.begin())
{
return;
}
--p_pageIt;
}
}
void Increment()
{
const std::size_t offset = m_page->m_occupied.find_next(m_offset);
if (offset != PAGE_SIZE)
{
m_offset = offset;
m_current = m_page->Get(offset);
return;
}
SeekFirstFrom(eastl::next(m_pageIt));
}
void Decrement()
{
if (m_current == nullptr)
{
SeekLastFrom(eastl::prev(m_map->m_pages.end()));
return;
}
const std::size_t offset = m_page->m_occupied.find_prev(m_offset);
if (offset != PAGE_SIZE)
{
m_offset = offset;
m_current = m_page->Get(offset);
return;
}
if (m_pageIt == m_map->m_pages.begin())
{
return;
}
SeekLastFrom(eastl::prev(m_pageIt));
}
MapType* m_map = nullptr;
PageIterator m_pageIt {};
PageType* m_page = nullptr;
std::size_t m_offset = 0;
pointer m_current = nullptr;
};
using iterator = IteratorImpl<T>;
using const_iterator = IteratorImpl<const T>;
using reverse_iterator = eastl::reverse_iterator<iterator>;
using const_reverse_iterator = eastl::reverse_iterator<const_iterator>;
StableSlotMap() = default;
StableSlotMap(const StableSlotMap& p_map) = default;
StableSlotMap(StableSlotMap&& p_map) = default;
~StableSlotMap() = default;
[[nodiscard]]
bool Has(const SlotMapKey p_key) const
{
return p_key.Valid() &&
(p_key.GetIndex() < m_keys.size() && p_key.GetVersion() == m_keys[p_key.GetIndex()].GetVersion());
}
[[nodiscard]]
std::size_t Size() const
{
return eastl::accumulate(m_pages.begin(),
m_pages.end(),
0,
[](const std::size_t p_value, const eastl::unique_ptr<Page>& p_page)
{
return p_value + p_page->Size();
});
}
[[nodiscard]]
std::size_t Capacity() const
{
return m_pages.size() * PAGE_SIZE;
}
[[nodiscard]]
bool Empty() const
{
return Size() == 0;
}
template<class... ARGS>
[[nodiscard]]
SlotMapKey Insert(ARGS&&... p_args)
{
ASSERT(UtilsAssertHandler,
Size() < SlotMapKey::MAX_INDEX,
"Can't store more than {} elements",
SlotMapKey::MAX_INDEX);
SlotMapKey key;
if (HasFreeSlots())
{
const std::size_t indexToRecyclingKey = m_freeListHead;
m_freeListHead = m_keys[indexToRecyclingKey].GetIndex();
m_keys[indexToRecyclingKey] = SlotMapKey {m_keys[indexToRecyclingKey].GetVersion(),
static_cast<SlotMapKey::IndexType>(indexToRecyclingKey)};
key = m_keys[indexToRecyclingKey];
}
else
{
m_keys.emplace_back(1, static_cast<SlotMapKey::IndexType>(m_keys.size()));
key = m_keys.back();
}
const std::size_t pageIndex = GetPageIndex(key);
if (pageIndex >= m_pages.size())
{
m_pages.push_back(eastl::make_unique<Page>());
}
Page* const page = GetPageAt(pageIndex);
const std::size_t offsetInPage = GetDataOffset(key);
new (page->m_data[offsetInPage].m_bytes) T(std::forward<ARGS>(p_args)...);
page->m_occupied.set(offsetInPage);
return key;
}
void Remove(const SlotMapKey p_key)
{
if (!Has(p_key))
{
return;
}
Page* const page = GetPageAt(GetPageIndex(p_key));
const std::size_t offsetInPage = GetDataOffset(p_key);
std::destroy_at(page->Get(offsetInPage));
page->m_occupied.reset(offsetInPage);
RecycleKey(p_key);
}
void Reset()
{
for (eastl::unique_ptr<Page>& page: m_pages)
{
page = eastl::make_unique<Page>();
}
m_keys.clear();
m_freeListHead = SlotMapKey::MAX_INDEX;
}
void Clear()
{
std::size_t pageIndex = 0;
for (const eastl::unique_ptr<Page>& page: m_pages)
{
for (std::size_t offset = page->m_occupied.find_first(); offset != PAGE_SIZE;
offset = page->m_occupied.find_next(offset))
{
std::destroy_at(page->Get(offset));
const std::size_t keyIndex = pageIndex * PAGE_SIZE + offset;
RecycleKey(SlotMapKey {m_keys[keyIndex].GetVersion(), static_cast<SlotMapKey::IndexType>(keyIndex)});
}
page->m_occupied.reset();
++pageIndex;
}
}
[[nodiscard]]
const T* Get(const SlotMapKey p_key) const
{
return Has(p_key) ? GetPageAt(GetPageIndex(p_key))->Get(GetDataOffset(p_key)) : nullptr;
}
[[nodiscard]]
T* Get(const SlotMapKey p_key)
{
return const_cast<T*>(std::as_const(*this).Get(p_key));
}
[[nodiscard]]
iterator begin()
{
iterator it {this};
it.SeekFirstFrom(m_pages.begin());
return it;
}
[[nodiscard]]
iterator end()
{
return iterator {this};
}
[[nodiscard]]
const_iterator begin() const
{
const_iterator it {this};
it.SeekFirstFrom(m_pages.begin());
return it;
}
[[nodiscard]]
const_iterator end() const
{
return const_iterator {this};
}
[[nodiscard]]
reverse_iterator rbegin()
{
return reverse_iterator {end()};
}
[[nodiscard]]
reverse_iterator rend()
{
return reverse_iterator {begin()};
}
[[nodiscard]]
const_reverse_iterator rbegin() const
{
return const_reverse_iterator {end()};
}
[[nodiscard]]
const_reverse_iterator rend() const
{
return const_reverse_iterator {begin()};
}
[[nodiscard]]
const_iterator cbegin() const
{
return begin();
}
[[nodiscard]]
const_iterator cend() const
{
return end();
}
[[nodiscard]]
const_reverse_iterator crbegin() const
{
return rbegin();
}
[[nodiscard]]
const_reverse_iterator crend() const
{
return rend();
}
StableSlotMap& operator=(const StableSlotMap& p_map) = default;
StableSlotMap& operator=(StableSlotMap&& p_map) = default;
private:
[[nodiscard]]
bool HasFreeSlots() const
{
return m_freeListHead != SlotMapKey::MAX_INDEX;
}
void RecycleKey(const SlotMapKey p_key)
{
const typename SlotMapKey::VersionType nextVersion = static_cast<SlotMapKey::VersionType>(p_key.GetVersion() +
1);
if (nextVersion == SlotMapKey::INVALID_VERSION)
{
// Mark it dead, we've exhausted all versions for this key
m_keys[p_key.GetIndex()] = SlotMapKey {SlotMapKey::INVALID_VERSION, 0};
return;
}
m_keys[p_key.GetIndex()] = SlotMapKey {nextVersion, static_cast<SlotMapKey::IndexType>(m_freeListHead)};
m_freeListHead = p_key.GetIndex();
}
[[nodiscard]]
static std::size_t GetPageIndex(const SlotMapKey p_key)
{
return p_key.GetIndex() / PAGE_SIZE;
}
[[nodiscard]]
static std::size_t GetDataOffset(const SlotMapKey p_key)
{
return p_key.GetIndex() % PAGE_SIZE;
}
[[nodiscard]]
const Page* GetPageAt(const std::size_t p_pageIndex) const
{
return m_pages[p_pageIndex].get();
}
[[nodiscard]]
Page* GetPageAt(const std::size_t p_pageIndex)
{
return m_pages[p_pageIndex].get();
}
private:
eastl::vector<eastl::unique_ptr<Page>> m_pages;
eastl::vector<SlotMapKey> m_keys;
/**
* Index to a key that can be recycled
*/
std::size_t m_freeListHead = SlotMapKey::MAX_INDEX;
};
} // namespace Bigfoot
@@ -90,8 +90,8 @@ TEST_F(AssetContainerFixture, Get_ShouldReturnTheAssetWithTheSlotKey)
TEST_F(AssetContainerFixture, Get_ShouldReturnNullptrIfSlotKeyNotInContainer)
{
EXPECT_EQ(m_containerA.Get(SlotMapKey {1, 0}), nullptr);
EXPECT_EQ(const_cast<const AssetContainer<AssetA>&>(m_containerA).Get(SlotMapKey {1, 0}), nullptr);
EXPECT_EQ(m_containerA.Get(SlotMapKey<> {1, 0}), nullptr);
EXPECT_EQ(const_cast<const AssetContainer<AssetA>&>(m_containerA).Get(SlotMapKey<> {1, 0}), nullptr);
}
/****************************************************************************************/
-1
View File
@@ -1 +0,0 @@
// to delete when an actual test is in EngineTests
@@ -1,21 +0,0 @@
// AUTO-GENERATED DO NOT TOUCH
/*********************************************************************
* \file SystemTestsLogger.generated.hpp
*
*********************************************************************/
#ifndef BIGFOOT_SYSTEMTESTSLOGGER_GENERATED_HPP
#define BIGFOOT_SYSTEMTESTSLOGGER_GENERATED_HPP
#include <System/Log/Log.hpp>
#if defined BIGFOOT_NOT_OPTIMIZED
namespace Bigfoot
{
/*
* Logger
*/
inline Log::LoggerInfo SYSTEMTESTS_LOGGER {"SYSTEMTESTS_LOGGER", Flat::LogLevel::Trace};
} // namespace Bigfoot
#endif
#endif
-138
View File
@@ -1,138 +0,0 @@
/*********************************************************************
* \file Log.cpp
*
* \author Romain BOULLARD
* \date December 2022
*********************************************************************/
#include <System/Log/Log.hpp>
#include <Utils/Singleton.hpp>
#include <SystemTests/SystemTestsLogger_generated.hpp>
#if defined BIGFOOT_NOT_OPTIMIZED
#include <gtest/gtest.h>
namespace Bigfoot
{
class LogFixture: public ::testing::Test
{
protected:
void SetUp() override
{
SYSTEMTESTS_LOGGER = {"UTILSTESTS_LOGGER", Flat::LogLevel::Trace};
}
static constexpr Flat::LogLevel QuillLogLevelToLogLevel(const quill::LogLevel p_level)
{
switch (p_level)
{
case quill::LogLevel::Debug:
return Flat::LogLevel::Debug;
case quill::LogLevel::TraceL3:
return Flat::LogLevel::Trace;
case quill::LogLevel::Info:
return Flat::LogLevel::Info;
case quill::LogLevel::Warning:
return Flat::LogLevel::Warn;
case quill::LogLevel::Error:
return Flat::LogLevel::Error;
case quill::LogLevel::Critical:
return Flat::LogLevel::Critical;
default:
break;
}
return Flat::LogLevel::Trace;
}
Log m_log;
};
/****************************************************************************************/
TEST_F(LogFixture, RegisterLogger_ShouldRegisterTheLogger)
{
const quill::Logger* logger = m_log.RegisterLogger(SYSTEMTESTS_LOGGER);
EXPECT_TRUE(logger);
EXPECT_EQ(logger, m_log.GetLogger(SYSTEMTESTS_LOGGER));
EXPECT_EQ(logger->get_logger_name(), SYSTEMTESTS_LOGGER.m_name);
EXPECT_EQ(QuillLogLevelToLogLevel(logger->get_log_level()), SYSTEMTESTS_LOGGER.m_level);
}
/****************************************************************************************/
TEST_F(LogFixture, GetLogger_ShouldReturnNullptrIfTheLoggerDoesNotExist)
{
EXPECT_FALSE(m_log.GetLogger(SYSTEMTESTS_LOGGER));
}
/****************************************************************************************/
TEST_F(LogFixture, GetLogger_ShouldReturnTheLoggerIfItExists)
{
[[maybe_unused]]
const quill::Logger* logger = m_log.RegisterLogger(SYSTEMTESTS_LOGGER);
EXPECT_TRUE(m_log.GetLogger(SYSTEMTESTS_LOGGER));
}
/****************************************************************************************/
TEST_F(LogFixture, ChangeLoggerLogLevel_ShouldChangeTheLoggerLogLevel)
{
const quill::Logger* logger = m_log.RegisterLogger(SYSTEMTESTS_LOGGER);
m_log.ChangeLoggerLogLevel(SYSTEMTESTS_LOGGER, Flat::LogLevel::Critical);
EXPECT_EQ(QuillLogLevelToLogLevel(logger->get_log_level()), Flat::LogLevel::Critical);
}
/****************************************************************************************/
TEST_F(LogFixture, LogDebug)
{
Singleton<Log>::Lifetime singletonLifetime;
BIGFOOT_LOG_DEBUG(SYSTEMTESTS_LOGGER, "Hello");
}
/****************************************************************************************/
TEST_F(LogFixture, LogTrace)
{
Singleton<Log>::Lifetime singletonLifetime;
BIGFOOT_LOG_TRACE(SYSTEMTESTS_LOGGER, "Hello");
}
/****************************************************************************************/
TEST_F(LogFixture, LogInfo)
{
Singleton<Log>::Lifetime singletonLifetime;
BIGFOOT_LOG_INFO(SYSTEMTESTS_LOGGER, "Hello");
}
/****************************************************************************************/
TEST_F(LogFixture, LogWarn)
{
Singleton<Log>::Lifetime singletonLifetime;
BIGFOOT_LOG_WARN(SYSTEMTESTS_LOGGER, "Hello");
}
/****************************************************************************************/
TEST_F(LogFixture, LogError)
{
Singleton<Log>::Lifetime singletonLifetime;
BIGFOOT_LOG_ERROR(SYSTEMTESTS_LOGGER, "Hello");
}
/****************************************************************************************/
TEST_F(LogFixture, LogFatal)
{
Singleton<Log>::Lifetime singletonLifetime;
BIGFOOT_LOG_FATAL(SYSTEMTESTS_LOGGER, "Hello");
}
} // namespace Bigfoot
#endif
-67
View File
@@ -1,67 +0,0 @@
/*********************************************************************
* \file Time.cpp
*
* \author Romain BOULLARD
* \date December 2025
*********************************************************************/
#include <System/Time.hpp>
#include <gtest/gtest.h>
namespace Bigfoot
{
class TimeFixture: public ::testing::Test
{
public:
Time m_time {1'767'643'746'680'609};
};
/****************************************************************************************/
TEST_F(TimeFixture, Year_ShouldReturnTheYear)
{
EXPECT_EQ(m_time.Year(), 2026);
}
/****************************************************************************************/
TEST_F(TimeFixture, Month_ShouldReturnTheMonth)
{
EXPECT_EQ(m_time.Month(), 1);
}
/****************************************************************************************/
TEST_F(TimeFixture, Day_ShouldReturnTheDay)
{
EXPECT_EQ(m_time.Day(), 5);
}
/****************************************************************************************/
TEST_F(TimeFixture, Hour_ShouldReturnTheHour)
{
EXPECT_EQ(m_time.Hour(), 20);
}
/****************************************************************************************/
TEST_F(TimeFixture, Minute_ShouldReturnTheMinute)
{
EXPECT_EQ(m_time.Minute(), 9);
}
/****************************************************************************************/
TEST_F(TimeFixture, Second_ShouldReturnTheSecond)
{
EXPECT_EQ(m_time.Second(), 6);
}
/****************************************************************************************/
TEST_F(TimeFixture, Microsecond_ShouldReturnTheMicrosecond)
{
EXPECT_EQ(m_time.Microsecond(), 680'609);
}
} // namespace Bigfoot
+52 -50
View File
@@ -148,14 +148,14 @@ class SlotMapNameGenerator
{
return "DenseSlotMap";
}
// if constexpr (std::is_same_v<T, StableSlotMap<SlotMapValue>>)
// {
// return "StableSlotMap";
// }
if constexpr (std::is_same_v<T, StableSlotMap<SlotMapValue, SlotMapKey<std::uint8_t, std::uint8_t>>>)
{
return "StableSlotMap";
}
}
};
using SlotMapTypes = ::testing::Types<DenseSlotMap<SlotMapValue, SlotMapKey<std::uint8_t, std::uint8_t>>>;
using SlotMapTypes = ::testing::Types<DenseSlotMap<SlotMapValue, SlotMapKey<std::uint8_t, std::uint8_t>>, StableSlotMap<SlotMapValue, SlotMapKey<std::uint8_t, std::uint8_t>>>;
TYPED_TEST_SUITE(SlotMapFixture, SlotMapTypes, SlotMapNameGenerator);
/****************************************************************************************/
@@ -1114,49 +1114,51 @@ TYPED_TEST(SlotMapFixture, ConstReverseIterator)
/****************************************************************************************/
// class StableSlotMapFixture: public ::testing::Test
// {
// protected:
// StableSlotMap<std::uint32_t> m_slotMap;
// };
//
// /****************************************************************************************/
//
// TEST_F(StableSlotMapFixture, PointersAreStable)
// {
// const SlotMapKey key = m_slotMap.Insert(42);
// const std::uint32_t* const pointer = m_slotMap.Get(key);
//
// // Inserting enough elements to span multiple pages (PAGE_SIZE is 64) must not move already
// // -inserted data: unlike DenseSlotMap's contiguous eastl::vector, growth only appends new
// // Page objects (each individually heap-allocated), it never reallocates existing ones.
// constexpr std::uint32_t elementCount = 200;
// eastl::array<SlotMapKey, elementCount> keys;
// for (std::uint32_t value = 0; value < elementCount; ++value)
// {
// keys[value] = m_slotMap.Insert(value);
// }
//
// EXPECT_EQ(m_slotMap.Get(key), pointer);
// EXPECT_EQ(*pointer, 42);
//
// // Removing unrelated elements, including ones sharing the same page as key, must not move it
// // either: Remove() only destroys that slot in place, it never compacts the page's array.
// for (std::uint32_t value = 0; value < elementCount; value += 2)
// {
// m_slotMap.Remove(keys[value]);
// }
//
// EXPECT_EQ(m_slotMap.Get(key), pointer);
// EXPECT_EQ(*pointer, 42);
//
// // Re-inserting into the freed slots must not move it either
// for (std::uint32_t value = 0; value < elementCount / 2; ++value)
// {
// std::ignore = m_slotMap.Insert(value);
// }
//
// EXPECT_EQ(m_slotMap.Get(key), pointer);
// EXPECT_EQ(*pointer, 42);
// }
class StableSlotMapFixture: public ::testing::Test
{
protected:
StableSlotMap<std::uint32_t> m_slotMap;
using SlotMapKey = StableSlotMap<std::uint32_t>::SlotMapKey;
};
/****************************************************************************************/
TEST_F(StableSlotMapFixture, PointersAreStable)
{
const SlotMapKey key = m_slotMap.Insert(42);
const std::uint32_t* const pointer = m_slotMap.Get(key);
// Inserting enough elements to span multiple pages (PAGE_SIZE is 64) must not move already
// -inserted data: unlike DenseSlotMap's contiguous eastl::vector, growth only appends new
// Page objects (each individually heap-allocated), it never reallocates existing ones.
constexpr std::uint32_t elementCount = 200;
eastl::array<SlotMapKey, elementCount> keys;
for (std::uint32_t value = 0; value < elementCount; ++value)
{
keys[value] = m_slotMap.Insert(value);
}
EXPECT_EQ(m_slotMap.Get(key), pointer);
EXPECT_EQ(*pointer, 42);
// Removing unrelated elements, including ones sharing the same page as key, must not move it
// either: Remove() only destroys that slot in place, it never compacts the page's array.
for (std::uint32_t value = 0; value < elementCount; value += 2)
{
m_slotMap.Remove(keys[value]);
}
EXPECT_EQ(m_slotMap.Get(key), pointer);
EXPECT_EQ(*pointer, 42);
// Re-inserting into the freed slots must not move it either
for (std::uint32_t value = 0; value < elementCount / 2; ++value)
{
std::ignore = m_slotMap.Insert(value);
}
EXPECT_EQ(m_slotMap.Get(key), pointer);
EXPECT_EQ(*pointer, 42);
}
} // namespace Bigfoot