Utilities

This commit is contained in:
2026-02-16 20:58:47 +01:00
committed by Romain BOULLARD
parent 9f32d230d5
commit 8fe1281cb7
16 changed files with 541 additions and 7 deletions

View File

@@ -20,13 +20,11 @@ target_sources(${PROJECT_NAME}
${SOURCES} ${SOURCES}
) )
target_link_libraries(${PROJECT_NAME} PUBLIC EASTL::EASTL mimalloc) target_link_libraries(${PROJECT_NAME} PUBLIC EASTL::EASTL mimalloc quill::quill $<$<CONFIG:Debug,RelWithDebInfo>:cpptrace::cpptrace>)
target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_DL_LIBS})
target_link_libraries(${PROJECT_NAME} PRIVATE $<$<CONFIG:Debug,RelWithDebInfo>:cpptrace::cpptrace> quill::quill)
target_compile_definitions(${PROJECT_NAME} target_compile_definitions(${PROJECT_NAME}
PUBLIC $<$<CONFIG:Debug,RelWithDebInfo>:QUILL_NO_EXCEPTIONS> PUBLIC QUILL_NO_EXCEPTIONS
PUBLIC $<$<CONFIG:Debug,RelWithDebInfo>:QUILL_DISABLE_NON_PREFIXED_MACROS> PUBLIC QUILL_DISABLE_NON_PREFIXED_MACROS
PUBLIC MI_SHARED_LIB) PUBLIC MI_SHARED_LIB)

View File

@@ -1,11 +1,11 @@
#ifndef {{GUARD_NAME}}
#define {{GUARD_NAME}}
/** /**
* Auto-generated header from: {{FILENAME}} * Auto-generated header from: {{FILENAME}}
* Generated by Bin2CPP * Generated by Bin2CPP
* *
* DO NOT TOUCH * DO NOT TOUCH
*/ */
#ifndef {{GUARD_NAME}}
#define {{GUARD_NAME}}
#include {{ARRAY_TYPE_INCLUDE}} #include {{ARRAY_TYPE_INCLUDE}}
#include <cstddef> #include <cstddef>

View File

@@ -0,0 +1,138 @@
/*********************************************************************
* \file Assert.hpp
*
* \author Romain BOULLARD
* \date October 2025
*********************************************************************/
#ifndef BIGFOOT_SYSTEM_ASSERT_HPP
#define BIGFOOT_SYSTEM_ASSERT_HPP
#include <Log.hpp>
#if defined BIN2CPP_NOT_OPTIMIZED
#include <cpptrace/cpptrace.hpp>
#include <source_location>
#include <string>
#if defined BIN2CPP_LINUX
#include <csignal>
#endif
namespace Bin2CPP
{
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_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)
{
BIN2CPP_LOG_FATAL("Assert: {} (File:{}, Line:{}, Function:{}\n{}",
std::format(p_format, std::forward<ARGS>(p_args)...),
p_location.file_name(),
p_location.line(),
p_location.function_name(),
p_stacktrace);
}
AssertHandler& operator=(const AssertHandler& p_handler) = delete;
AssertHandler& operator=(AssertHandler&& p_handler) = delete;
};
} // namespace Bin2CPP
#if defined BIN2CPP_WINDOWS
#define BIN2CPP_BREAK \
do \
{ \
__debugbreak(); \
} while (false)
#elif defined BIN2CPP_LINUX
#define BIN2CPP_BREAK \
do \
{ \
std::raise(SIGTRAP); \
} while (false)
#endif
#define BIN2CPP_ASSERT(p_assert, p_message, ...) \
do \
{ \
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(); \
}; \
\
Bin2CPP::AssertHandler::Handle(location, stacktrace(), p_message __VA_OPT__(, ) __VA_ARGS__); \
BIN2CPP_BREAK; \
} \
} while (false)
#define BIN2CPP_SOFT_ASSERT(p_assert, p_message, ...) \
do \
{ \
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(); \
}; \
\
Bin2CPP::AssertHandler::Handle(location, stacktrace(), p_message __VA_OPT__(, ) __VA_ARGS__); \
BIN2CPP_BREAK; \
} \
} while (false)
#define BIN2CPP_CRITICAL_ASSERT(p_assert, p_message, ...) \
do \
{ \
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(); \
}; \
\
Bin2CPP::AssertHandler::Handle(location, stacktrace(), p_message __VA_OPT__(, ) __VA_ARGS__); \
if (Bin2CPP::Singleton<Bin2CPP::Log>::HasInstance()) \
{ \
Bin2CPP::Singleton<Bin2CPP::Log>::Instance().Flush(); \
} \
BIN2CPP_BREAK; \
std::abort(); \
} \
} while (false)
#else
#define BIN2CPP_ASSERT(p_assert, p_message, ...)
#define BIN2CPP_SOFT_ASSERT(p_assert, p_message, ...)
#define BIN2CPP_CRITICAL_ASSERT(p_assert, p_message, ...)
#endif
#endif

View File

@@ -0,0 +1,87 @@
/*********************************************************************
* \file EASTLFormatters.hpp
*
* \author Romain BOULLARD
* \date February 2026
*********************************************************************/
#ifndef BIN2CPP_EASTLFORMATTERS_HPP
#define BIN2CPP_EASTLFORMATTERS_HPP
#include <quill/DeferredFormatCodec.h>
#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());
}
};
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>
{
};
// 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());
}
};
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

View File

@@ -0,0 +1,116 @@
/*********************************************************************
* \file Log.hpp
*
* \author Romain BOULLARD
* \date February 2026
*********************************************************************/
#ifndef BIN2CPP_LOG_HPP
#define BIN2CPP_LOG_HPP
#include <EASTLFormatters.hpp>
#include <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 Bin2CPP
{
class Log
{
public:
Log();
Log(const Log& p_logger) = delete;
Log(Log&& p_logger) = delete;
/**
* Register a logger.
*
* \return The logger, nullptr if it does not exist
*/
[[nodiscard]]
quill::Logger* GetLogger();
/*
* Flush all the loggers
*
*/
void Flush();
~Log();
Log& operator=(const Log& p_logger) = delete;
Log& operator=(Log&& p_logger) = delete;
private:
/*
* The sinks
*/
eastl::array<std::shared_ptr<quill::Sink>, 1> m_sinks;
};
} // namespace Bin2CPP
#define BIN2CPP_LOG_DEBUG(fmt, ...) \
do \
{ \
if (quill::Logger* logger = Bin2CPP::Singleton<Bin2CPP::Log>::Instance().GetLogger()) \
{ \
QUILL_LOG_DEBUG(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
#define BIN2CPP_LOG_TRACE(fmt, ...) \
do \
{ \
if (quill::Logger* logger = Bin2CPP::Singleton<Bin2CPP::Log>::Instance().GetLogger()) \
{ \
QUILL_LOG_TRACE_L3(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
#define BIN2CPP_LOG_INFO(fmt, ...) \
do \
{ \
if (quill::Logger* logger = Bin2CPP::Singleton<Bin2CPP::Log>::Instance().GetLogger()) \
{ \
QUILL_LOG_INFO(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
#define BIN2CPP_LOG_WARN(fmt, ...) \
do \
{ \
if (quill::Logger* logger = Bin2CPP::Singleton<Bin2CPP::Log>::Instance().GetLogger()) \
{ \
QUILL_LOG_WARNING(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
#define BIN2CPP_LOG_ERROR(fmt, ...) \
do \
{ \
if (quill::Logger* logger = Bin2CPP::Singleton<Bin2CPP::Log>::Instance().GetLogger()) \
{ \
QUILL_LOG_ERROR(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
#define BIN2CPP_LOG_FATAL(fmt, ...) \
do \
{ \
if (quill::Logger* logger = Bin2CPP::Singleton<Bin2CPP::Log>::Instance().GetLogger()) \
{ \
QUILL_LOG_CRITICAL(logger, fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
} while (0)
#endif

View File

@@ -0,0 +1,104 @@
/*********************************************************************
* \file Singleton.hpp
*
* \author Romain BOULLARD
* \date February 2026
*********************************************************************/
#ifndef BIN2CPP_SINGLETON_HPP
#define BIN2CPP_SINGLETON_HPP
#include <EASTL/optional.h>
namespace Bin2CPP
{
template<class TYPE>
class Singleton
{
public:
Singleton() = delete;
Singleton(const Singleton& p_singleton) = delete;
Singleton(Singleton&& p_singleton) = delete;
~Singleton() = delete;
/**
* Get the instance.
*
* \return The instance
*/
static constexpr TYPE& Instance()
{
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:
/**
* Constructor.
*
* \param p_args Arguments for the singleton
*/
template<typename... ARGS>
explicit Lifetime(ARGS&&... p_args)
{
Initialize(std::forward<ARGS>(p_args)...);
}
Lifetime(const Lifetime& p_lifetime) = delete;
Lifetime(Lifetime&& p_lifetime) = delete;
~Lifetime()
{
Finalize();
}
[[nodiscard]]
Lifetime& operator=(const Lifetime& p_lifetime) = delete;
[[nodiscard]]
Lifetime& operator=(Lifetime&& p_lifetime) = delete;
};
[[nodiscard]]
Singleton& operator=(const Singleton& p_singleton) = delete;
[[nodiscard]]
Singleton& operator=(Singleton&& p_singleton) = delete;
private:
/**
* Initialize the singleton.
*
* \param p_args Arguments for the singleton
*/
template<typename... ARGS>
static void Initialize(ARGS&&... p_args)
{
ms_instance.emplace(std::forward<ARGS>(p_args)...);
}
/**
* Finalize the singleton.
*
*/
static void Finalize()
{
ms_instance.reset();
}
/**
* The singleton.
*/
inline static eastl::optional<TYPE> ms_instance;
};
} // namespace Bin2CPP
#endif

View File

@@ -0,0 +1,49 @@
/*******************************************************************
* \file Log.cpp
*
* \author Romain BOULLARD
* \date February 2026
*********************************************************************/
#include <Log.hpp>
namespace Bin2CPP
{
Log::Log()
{
quill::Backend::start();
m_sinks[0] = quill::Frontend::create_or_get_sink<quill::ConsoleSink>("ConsoleSink");
quill::Logger* logger = quill::Frontend::create_or_get_logger("Bin2CPP", m_sinks[0]);
logger->set_log_level(quill::LogLevel::TraceL3);
}
/****************************************************************************************/
quill::Logger* Log::GetLogger()
{
return quill::Frontend::get_logger("Bin2CPP");
}
/****************************************************************************************/
void Log::Flush()
{
for (quill::Logger* logger: quill::Frontend::get_all_loggers())
{
logger->flush_log();
}
}
/****************************************************************************************/
Log::~Log()
{
for (quill::Logger* logger: quill::Frontend::get_all_loggers())
{
quill::Frontend::remove_logger(logger);
}
quill::Backend::stop();
}
} // namespace Bin2CPP

View File

@@ -0,0 +1,39 @@
/*********************************************************************
* \file Singleton.cpp
*
* \author Romain BOULLARD
* \date February 2026
*********************************************************************/
#include <Singleton.hpp>
#include <gtest/gtest.h>
namespace Bin2CPP
{
class SingletonFixture: public ::testing::Test
{
protected:
Singleton<std::uint8_t>::Lifetime m_lifetime{8};
};
/****************************************************************************************/
TEST_F(SingletonFixture, HasInstance_ShouldReturnTrueIfSingletonIsInitialized)
{
EXPECT_TRUE(Singleton<std::uint8_t>::HasInstance());
}
/****************************************************************************************/
TEST_F(SingletonFixture, HasInstance_ShouldReturnFaleIfSingletonIsNotInitialized)
{
EXPECT_FALSE(Singleton<std::uint32_t>::HasInstance());
}
/****************************************************************************************/
TEST_F(SingletonFixture, Instance_ShouldReturnTheInstance)
{
EXPECT_EQ(Singleton<std::uint8_t>::Instance(), 8);
}
} // namespace Bin2CPP

View File

@@ -0,0 +1,3 @@
//
// Created by romain on 16/02/2026.
//

0
format.sh Normal file → Executable file
View File

0
generate_bin2cpp.sh Normal file → Executable file
View File

0
generate_dependencies.sh Normal file → Executable file
View File