Compare commits
17 Commits
main
...
6317604bd2
| Author | SHA1 | Date | |
|---|---|---|---|
| 6317604bd2 | |||
| b2f3b095be | |||
| 5829530652 | |||
| a062a058cd | |||
| 46b8095c6a | |||
| 63fd92c584 | |||
| 3466469440 | |||
| b5c2e4936b | |||
| 02a08012d0 | |||
| 063645fae3 | |||
| 6c8979684d | |||
| c6b84168d8 | |||
| b638b2c223 | |||
| 3a890069de | |||
| 1775e864b4 | |||
| e78d648178 | |||
| 6cd9801ef7 |
@@ -15,7 +15,6 @@ Checks: >
|
||||
-cppcoreguidelines-macro-usage,
|
||||
-cppcoreguidelines-avoid-do-while
|
||||
|
||||
HeaderFilterRegex: '^(Bigfoot)/'
|
||||
ExcludeHeaderFilterRegex: '_generated.*'
|
||||
|
||||
CheckOptions:
|
||||
|
||||
@@ -3,8 +3,8 @@ name: Bigfoot
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
workflow_dispatch:
|
||||
- main
|
||||
- Development
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
@@ -25,14 +25,23 @@ jobs:
|
||||
|
||||
- name: Generate
|
||||
run: |
|
||||
conan install . --deployer=full_deploy --deployer-folder=build --remote=bigfootpackages -pr:h=clang -pr:b=clang --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
|
||||
cmake -S . -B ./build/Debug --toolchain ./build/Debug/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_UNITY_BUILD=Debug -G "Ninja"
|
||||
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
|
||||
cmake -S . -B ./build/Debug --toolchain ./build/Debug/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Debug -G "Ninja"
|
||||
cmake --build build/Debug --parallel $(nproc)
|
||||
|
||||
- name: Clang-Tidy
|
||||
run: run-clang-tidy -p ./build/Debug/ >> tidy_result.txt
|
||||
|
||||
- name: Infer
|
||||
run: infer run --compilation-database build/Debug/compile_commands.json
|
||||
|
||||
- name: SonarQube Scan
|
||||
if: github.head_ref == 'main' || github.ref_name == 'main'
|
||||
uses: SonarSource/sonarqube-scan-action@v7.0.0
|
||||
with:
|
||||
args: >
|
||||
-Dsonar.cxx.jsonCompilationDatabase=./build/Debug/compile_commands.json
|
||||
-Dsonar.verbose=true
|
||||
env:
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
SONAR_HOST_URL: ${{ secrets.SONAR_HOST }}
|
||||
3
.inferconfig
Normal file
3
.inferconfig
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
275
Bigfoot/Sources/Engine/BigFile/BigFile.cpp
Normal file
275
Bigfoot/Sources/Engine/BigFile/BigFile.cpp
Normal file
@@ -0,0 +1,275 @@
|
||||
/*********************************************************************
|
||||
* \file BigFile.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date October 2025
|
||||
*********************************************************************/
|
||||
#include <Engine/BigFile/BigFile.hpp>
|
||||
|
||||
#include <Engine/EngineAssertHandler.hpp>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
BigFile::BigFile(const File& p_file)
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const int result = sqlite3_open_v2(p_file.Absolute().Path().data(), &m_db, SQLITE_OPEN_READWRITE, nullptr);
|
||||
CRITICAL_ASSERT(EngineAssertHandler, result == SQLITE_OK, "Failed to open BigFile DB: {}", 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));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
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 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 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));
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
262
Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFile.hpp
Normal file
262
Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFile.hpp
Normal file
@@ -0,0 +1,262 @@
|
||||
/*********************************************************************
|
||||
* \file BigFile.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date October 2025
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_ENGINE_BIGFILE_HPP
|
||||
#define BIGFOOT_ENGINE_BIGFILE_HPP
|
||||
#include <System/File.hpp>
|
||||
|
||||
#include <Utils/TaggedType.hpp>
|
||||
|
||||
#include <EASTL/span.h>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
class BigFile
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param p_file The file targetting the BigFile DB
|
||||
*/
|
||||
BigFile(const File& p_file);
|
||||
|
||||
BigFile(const BigFile& p_bigFile) = default;
|
||||
BigFile(BigFile&& p_bigFile) = default;
|
||||
|
||||
/**
|
||||
* Begin a transaction
|
||||
*
|
||||
*/
|
||||
void BeginTransaction();
|
||||
|
||||
/**
|
||||
* Commit a transaction
|
||||
*
|
||||
*/
|
||||
void CommitTransaction();
|
||||
|
||||
/**
|
||||
* Rollback a transaction
|
||||
*
|
||||
*/
|
||||
void RollbackTransaction();
|
||||
|
||||
~BigFile();
|
||||
|
||||
BigFile& operator=(const BigFile& p_bigFile) = default;
|
||||
BigFile& operator=(BigFile&& p_bigFile) = default;
|
||||
|
||||
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) = default;
|
||||
Request(Request&& p_request) = default;
|
||||
|
||||
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 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 the request can continue (get next row), false otherwise
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool Step();
|
||||
|
||||
/*
|
||||
* Execute the request once
|
||||
*
|
||||
* The number of modified rows
|
||||
*/
|
||||
[[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);
|
||||
|
||||
Column(const Column& p_column) = default;
|
||||
Column(Column&& p_column) = default;
|
||||
|
||||
~Column() = default;
|
||||
|
||||
Column& operator=(const Column& p_column) = default;
|
||||
Column& operator=(Column&& p_column) = default;
|
||||
|
||||
/*
|
||||
* 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 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) = default;
|
||||
Request& operator=(Request&& p_request) = default;
|
||||
|
||||
private:
|
||||
/*
|
||||
* The database
|
||||
*/
|
||||
sqlite3* m_db;
|
||||
|
||||
/*
|
||||
* The statement
|
||||
*/
|
||||
sqlite3_stmt* m_statement;
|
||||
};
|
||||
|
||||
private:
|
||||
/**
|
||||
* The BigFile DB
|
||||
*/
|
||||
sqlite3* m_db;
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
|
||||
#endif
|
||||
@@ -45,7 +45,7 @@ class EngineAssertHandler
|
||||
{
|
||||
BIGFOOT_LOG_FATAL(ENGINE_LOGGER,
|
||||
"Assert: {} (File:{}, Line:{}, Function:{}\n{}",
|
||||
std::format(p_format, eastl::forward<ARGS>(p_args)...),
|
||||
std::format(p_format, std::forward<ARGS>(p_args)...),
|
||||
p_location.file_name(),
|
||||
p_location.line(),
|
||||
p_location.function_name(),
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
// to delete when an actual source is in Engine
|
||||
@@ -68,6 +68,12 @@ class Log
|
||||
*/
|
||||
void ChangeLoggerLogLevel(LoggerInfo& p_loggerInfo, const Flat::LogLevel p_level);
|
||||
|
||||
/*
|
||||
* Flush all the loggers
|
||||
*
|
||||
*/
|
||||
void Flush();
|
||||
|
||||
~Log();
|
||||
|
||||
Log& operator=(const Log& p_logger) = delete;
|
||||
|
||||
@@ -45,7 +45,7 @@ class SystemAssertHandler
|
||||
{
|
||||
BIGFOOT_LOG_FATAL(SYSTEM_LOGGER,
|
||||
"Assert: {} (File:{}, Line:{}, Function:{}\n{}",
|
||||
std::format(p_format, eastl::forward<ARGS>(p_args)...),
|
||||
std::format(p_format, std::forward<ARGS>(p_args)...),
|
||||
p_location.file_name(),
|
||||
p_location.line(),
|
||||
p_location.function_name(),
|
||||
|
||||
@@ -79,6 +79,16 @@ void Log::SetLoggerLevel(const LoggerInfo& p_loggerInfo)
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
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())
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
* \author Romain BOULLARD
|
||||
* \date October 2025
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_UTILS_ASSERT_HPP
|
||||
#define BIGFOOT_UTILS_ASSERT_HPP
|
||||
#ifndef BIGFOOT_SYSTEM_ASSERT_HPP
|
||||
#define BIGFOOT_SYSTEM_ASSERT_HPP
|
||||
#include <System/Log/Log.hpp>
|
||||
|
||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||
|
||||
@@ -79,6 +80,10 @@
|
||||
}; \
|
||||
\
|
||||
HANDLER::Handle(location, stacktrace(), p_message __VA_OPT__(, ) __VA_ARGS__); \
|
||||
if (Bigfoot::Singleton<Bigfoot::Log>::HasInstance()) \
|
||||
{ \
|
||||
Bigfoot::Singleton<Bigfoot::Log>::Instance().Flush(); \
|
||||
} \
|
||||
BREAK; \
|
||||
std::abort(); \
|
||||
} \
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <EASTL/array.h>
|
||||
#include <EASTL/bit.h>
|
||||
#include <EASTL/optional.h>
|
||||
#include <EASTL/type_traits.h>
|
||||
#include <EASTL/utility.h>
|
||||
|
||||
@@ -32,7 +33,17 @@ class Singleton
|
||||
*/
|
||||
static constexpr TYPE& Instance()
|
||||
{
|
||||
return *eastl::bit_cast<TYPE*>(ms_instance.data());
|
||||
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
|
||||
@@ -43,11 +54,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;
|
||||
@@ -78,9 +88,7 @@ class Singleton
|
||||
template<typename... ARGS>
|
||||
static void Initialize(ARGS&&... p_args)
|
||||
{
|
||||
new (ms_instance.data()) TYPE(eastl::forward<ARGS>(p_args)...);
|
||||
|
||||
ms_initialized = true;
|
||||
ms_instance.emplace(std::forward<ARGS>(p_args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,20 +97,13 @@ class Singleton
|
||||
*/
|
||||
static void Finalize()
|
||||
{
|
||||
eastl::bit_cast<TYPE*>(ms_instance.data())->~TYPE();
|
||||
|
||||
ms_initialized = false;
|
||||
ms_instance.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* The singleton.
|
||||
*/
|
||||
alignas(alignof(TYPE)) inline static eastl::array<std::byte, sizeof(TYPE)> ms_instance;
|
||||
|
||||
/**
|
||||
* Is the singleton initialized?
|
||||
*/
|
||||
inline static bool ms_initialized = false;
|
||||
inline static eastl::optional<TYPE> ms_instance;
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
#endif
|
||||
|
||||
158
Bigfoot/Tests/Engine/BigFile/BigFile.cpp
Normal file
158
Bigfoot/Tests/Engine/BigFile/BigFile.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
/*********************************************************************
|
||||
* \file BigFile.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date December 2025
|
||||
*********************************************************************/
|
||||
#include <Engine/BigFile/BigFile.hpp>
|
||||
|
||||
#include <System/Log/Log.hpp>
|
||||
#include <System/Time.hpp>
|
||||
#include <System/UUID/UUID.hpp>
|
||||
|
||||
#include <Utils/Singleton.hpp>
|
||||
#include <Utils/TargetMacros.h>
|
||||
|
||||
#include <EngineTests/BigFileInfo_generated.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
class BigFileFixture: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
BigFile::Request deleteHeader {m_bigFile, "DELETE FROM AssetHeader"};
|
||||
BigFile::Request deleteAsset {m_bigFile, "DELETE FROM AssetHeader"};
|
||||
|
||||
m_bigFile.BeginTransaction();
|
||||
deleteHeader.Execute();
|
||||
deleteAsset.Execute();
|
||||
m_bigFile.CommitTransaction();
|
||||
}
|
||||
|
||||
BIGFOOT_NOT_OPTIMIZED_ONLY(Singleton<Log>::Lifetime m_loggerLifetime;)
|
||||
|
||||
BigFile m_bigFile {File {BIGFILE_ENGINETESTS_LOCATION}};
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(BigFileFixture, Lol)
|
||||
{
|
||||
UUID uuid;
|
||||
UUID uuid2;
|
||||
|
||||
eastl::array<std::byte, 4> blob {std::byte {1}, std::byte {2}, std::byte {3}, std::byte {4}};
|
||||
eastl::array<std::byte, 4> blob2 {std::byte {1}, std::byte {2}, std::byte {3}, std::byte {5}};
|
||||
eastl::array<std::byte, 4> blob3 {std::byte {1}, std::byte {2}, std::byte {3}, std::byte {6}};
|
||||
|
||||
{
|
||||
BigFile::Request assetHeaderRequest {
|
||||
m_bigFile,
|
||||
"INSERT INTO AssetHeader (UUID, Name, TypeID, TypeName) VALUES(?, ?, ?, ?)"};
|
||||
assetHeaderRequest.Bind(1, static_cast<std::span<const std::byte, UUID::UUID_BYTE_SIZE>>(uuid));
|
||||
assetHeaderRequest.Bind(2, "Test");
|
||||
assetHeaderRequest.Bind(3, 42);
|
||||
assetHeaderRequest.Bind(4, "TypeTest");
|
||||
|
||||
BigFile::Request assetRequest {m_bigFile, "INSERT INTO Asset (UUID, Asset) VALUES(?, ?)"};
|
||||
assetRequest.Bind(1, static_cast<std::span<const std::byte, UUID::UUID_BYTE_SIZE>>(uuid));
|
||||
assetRequest.Bind(2, blob);
|
||||
|
||||
BigFile::Request assetHeaderRequest2 {
|
||||
m_bigFile,
|
||||
"INSERT INTO AssetHeader (UUID, Name, TypeID, TypeName) VALUES(?, ?, ?, ?)"};
|
||||
assetHeaderRequest2.Bind(1, static_cast<std::span<const std::byte, UUID::UUID_BYTE_SIZE>>(uuid2));
|
||||
assetHeaderRequest2.Bind(2, "Test2");
|
||||
assetHeaderRequest2.Bind(3, 42);
|
||||
assetHeaderRequest2.Bind(4, "TypeTest");
|
||||
|
||||
BigFile::Request assetRequest2 {m_bigFile, "INSERT INTO Asset (UUID, Asset) VALUES(?, ?)"};
|
||||
assetRequest2.Bind(1, static_cast<std::span<const std::byte, UUID::UUID_BYTE_SIZE>>(uuid2));
|
||||
assetRequest2.Bind(2, blob3);
|
||||
|
||||
m_bigFile.BeginTransaction();
|
||||
[[maybe_unused]]
|
||||
std::uint32_t assetHeaderChangedCount = assetHeaderRequest.Execute();
|
||||
[[maybe_unused]]
|
||||
std::uint32_t assetChangedCount = assetRequest.Execute();
|
||||
|
||||
[[maybe_unused]]
|
||||
std::uint32_t assetHeaderChangedCount2 = assetHeaderRequest2.Execute();
|
||||
[[maybe_unused]]
|
||||
std::uint32_t assetChangedCount2 = assetRequest2.Execute();
|
||||
|
||||
m_bigFile.CommitTransaction();
|
||||
}
|
||||
|
||||
{
|
||||
BigFile::Request updateAsset {m_bigFile, "UPDATE Asset SET Asset = ? WHERE UUID = ?"};
|
||||
updateAsset.Bind(1, blob2);
|
||||
updateAsset.Bind(2, static_cast<std::span<const std::byte, UUID::UUID_BYTE_SIZE>>(uuid));
|
||||
|
||||
m_bigFile.BeginTransaction();
|
||||
[[maybe_unused]]
|
||||
std::uint32_t updateAssetChangedCount = updateAsset.Execute();
|
||||
m_bigFile.CommitTransaction();
|
||||
}
|
||||
|
||||
{
|
||||
BigFile::Request request {
|
||||
m_bigFile,
|
||||
"SELECT Name, TypeID, TypeName, CreateTime, ModificationTime FROM AssetHeader WHERE UUID = ?"};
|
||||
request.Bind(1, static_cast<std::span<const std::byte, UUID::UUID_BYTE_SIZE>>(uuid));
|
||||
|
||||
[[maybe_unused]]
|
||||
const bool get = request.Step();
|
||||
|
||||
[[maybe_unused]]
|
||||
const eastl::string name {static_cast<eastl::string_view>(request.Get(0))};
|
||||
[[maybe_unused]]
|
||||
const std::uint32_t typeId = request.Get(1);
|
||||
[[maybe_unused]]
|
||||
const eastl::string typeName {static_cast<eastl::string_view>(request.Get(2))};
|
||||
[[maybe_unused]]
|
||||
const Time createTime = static_cast<std::int64_t>(request.Get(3));
|
||||
[[maybe_unused]]
|
||||
const Time modificationTime = static_cast<std::int64_t>(request.Get(4));
|
||||
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const std::uint32_t year = createTime.Year();
|
||||
[[maybe_unused]]
|
||||
const std::uint32_t month = createTime.Month();
|
||||
[[maybe_unused]]
|
||||
const std::uint32_t day = createTime.Day();
|
||||
[[maybe_unused]]
|
||||
const std::uint32_t hour = createTime.Hour();
|
||||
[[maybe_unused]]
|
||||
const std::uint32_t minute = createTime.Minute();
|
||||
[[maybe_unused]]
|
||||
const std::uint32_t second = createTime.Second();
|
||||
[[maybe_unused]]
|
||||
const std::uint32_t microsecond = createTime.Microsecond();
|
||||
}
|
||||
|
||||
{
|
||||
[[maybe_unused]]
|
||||
const std::uint32_t year = modificationTime.Year();
|
||||
[[maybe_unused]]
|
||||
const std::uint32_t month = modificationTime.Month();
|
||||
[[maybe_unused]]
|
||||
const std::uint32_t day = modificationTime.Day();
|
||||
[[maybe_unused]]
|
||||
const std::uint32_t hour = modificationTime.Hour();
|
||||
[[maybe_unused]]
|
||||
const std::uint32_t minute = modificationTime.Minute();
|
||||
[[maybe_unused]]
|
||||
const std::uint32_t second = modificationTime.Second();
|
||||
[[maybe_unused]]
|
||||
const std::uint32_t microsecond = modificationTime.Microsecond();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Bigfoot
|
||||
@@ -1 +0,0 @@
|
||||
// to delete when an actual test is in EngineTests
|
||||
@@ -22,6 +22,8 @@ function(bigfoot_create_package_lib PackagePublicDependencies PackagePrivateDepe
|
||||
${_BF_SOURCES}
|
||||
)
|
||||
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE ${BIGFOOT_CXX_FLAGS})
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC unordered_dense::unordered_dense EASTL::EASTL flatbuffers::flatbuffers rapidhash::rapidhash)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_DL_LIBS})
|
||||
|
||||
@@ -55,6 +57,9 @@ function(bigfoot_create_package_tests ParentFolder BigfootDependencies)
|
||||
${_BF_TEST_SOURCES}
|
||||
)
|
||||
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE ${BIGFOOT_CXX_FLAGS})
|
||||
target_link_options(${PROJECT_NAME} PRIVATE ${BIGFOOT_EXE_LINK_FLAGS})
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Include)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE $<LINK_LIBRARY:WHOLE_ARCHIVE,${PackageName}>)
|
||||
@@ -89,5 +94,4 @@ function(bigfoot_create_package_tests ParentFolder BigfootDependencies)
|
||||
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}Fixture)
|
||||
|
||||
set_target_properties(${PROJECT_NAME}Fixture PROPERTIES FOLDER UtilityTargets/Tests/Bigfoot/${ParentFolder})
|
||||
|
||||
endfunction()
|
||||
@@ -1,5 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.24)
|
||||
|
||||
# CMake sets this flag by default, we don't use exception in bigfoot, we can remove it
|
||||
string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
|
||||
project(Bigfoot VERSION 0.1.0
|
||||
|
||||
@@ -8,4 +8,7 @@ sonar.sources=Bigfoot/Sources
|
||||
sonar.tests=Bigfoot/Tests
|
||||
|
||||
sonar.cxx.file.suffixes=.hpp,.cpp,.h
|
||||
sonar.cxx.clangtidy.reportPaths=tidy_result.txt
|
||||
sonar.cxx.clangtidy.reportPaths=tidy_result.txt
|
||||
sonar.cxx.infer.reportPaths=infer-out/report.json
|
||||
|
||||
sonar.cxx.jsonCompilationDatabase.analyzeOnlyContainedFiles=True
|
||||
|
||||
Reference in New Issue
Block a user