Compare commits
11 Commits
StaticAnal
...
6317604bd2
| Author | SHA1 | Date | |
|---|---|---|---|
| 6317604bd2 | |||
| b2f3b095be | |||
| 5829530652 | |||
| a062a058cd | |||
| 46b8095c6a | |||
| 63fd92c584 | |||
| 3466469440 | |||
| b5c2e4936b | |||
| 3d4394765b | |||
| 3a890069de | |||
| 1775e864b4 |
@@ -1,9 +1,10 @@
|
|||||||
name: Bigfoot
|
name: Bigfoot
|
||||||
|
|
||||||
pull_request:
|
on:
|
||||||
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
types: [opened, synchronize, reopened]
|
- Development
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-test:
|
build-and-test:
|
||||||
@@ -35,7 +36,7 @@ jobs:
|
|||||||
run: infer run --compilation-database build/Debug/compile_commands.json
|
run: infer run --compilation-database build/Debug/compile_commands.json
|
||||||
|
|
||||||
- name: SonarQube Scan
|
- name: SonarQube Scan
|
||||||
if: github.event_name == 'push'
|
if: github.head_ref == 'main' || github.ref_name == 'main'
|
||||||
uses: SonarSource/sonarqube-scan-action@v7.0.0
|
uses: SonarSource/sonarqube-scan-action@v7.0.0
|
||||||
with:
|
with:
|
||||||
args: >
|
args: >
|
||||||
|
|||||||
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,
|
BIGFOOT_LOG_FATAL(ENGINE_LOGGER,
|
||||||
"Assert: {} (File:{}, Line:{}, Function:{}\n{}",
|
"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.file_name(),
|
||||||
p_location.line(),
|
p_location.line(),
|
||||||
p_location.function_name(),
|
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);
|
void ChangeLoggerLogLevel(LoggerInfo& p_loggerInfo, const Flat::LogLevel p_level);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flush all the loggers
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void Flush();
|
||||||
|
|
||||||
~Log();
|
~Log();
|
||||||
|
|
||||||
Log& operator=(const Log& p_logger) = delete;
|
Log& operator=(const Log& p_logger) = delete;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class SystemAssertHandler
|
|||||||
{
|
{
|
||||||
BIGFOOT_LOG_FATAL(SYSTEM_LOGGER,
|
BIGFOOT_LOG_FATAL(SYSTEM_LOGGER,
|
||||||
"Assert: {} (File:{}, Line:{}, Function:{}\n{}",
|
"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.file_name(),
|
||||||
p_location.line(),
|
p_location.line(),
|
||||||
p_location.function_name(),
|
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()
|
Log::~Log()
|
||||||
{
|
{
|
||||||
for (quill::Logger* logger: quill::Frontend::get_all_loggers())
|
for (quill::Logger* logger: quill::Frontend::get_all_loggers())
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
* \author Romain BOULLARD
|
* \author Romain BOULLARD
|
||||||
* \date October 2025
|
* \date October 2025
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
#ifndef BIGFOOT_UTILS_ASSERT_HPP
|
#ifndef BIGFOOT_SYSTEM_ASSERT_HPP
|
||||||
#define BIGFOOT_UTILS_ASSERT_HPP
|
#define BIGFOOT_SYSTEM_ASSERT_HPP
|
||||||
|
#include <System/Log/Log.hpp>
|
||||||
|
|
||||||
#if defined BIGFOOT_NOT_OPTIMIZED
|
#if defined BIGFOOT_NOT_OPTIMIZED
|
||||||
|
|
||||||
@@ -79,6 +80,10 @@
|
|||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
HANDLER::Handle(location, stacktrace(), p_message __VA_OPT__(, ) __VA_ARGS__); \
|
HANDLER::Handle(location, stacktrace(), p_message __VA_OPT__(, ) __VA_ARGS__); \
|
||||||
|
if (Bigfoot::Singleton<Bigfoot::Log>::HasInstance()) \
|
||||||
|
{ \
|
||||||
|
Bigfoot::Singleton<Bigfoot::Log>::Instance().Flush(); \
|
||||||
|
} \
|
||||||
BREAK; \
|
BREAK; \
|
||||||
std::abort(); \
|
std::abort(); \
|
||||||
} \
|
} \
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <EASTL/array.h>
|
#include <EASTL/array.h>
|
||||||
#include <EASTL/bit.h>
|
#include <EASTL/bit.h>
|
||||||
|
#include <EASTL/optional.h>
|
||||||
#include <EASTL/type_traits.h>
|
#include <EASTL/type_traits.h>
|
||||||
#include <EASTL/utility.h>
|
#include <EASTL/utility.h>
|
||||||
|
|
||||||
@@ -32,7 +33,17 @@ class Singleton
|
|||||||
*/
|
*/
|
||||||
static constexpr TYPE& Instance()
|
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
|
class Lifetime
|
||||||
@@ -43,11 +54,10 @@ class Singleton
|
|||||||
*
|
*
|
||||||
* \param p_args Arguments for the singleton
|
* \param p_args Arguments for the singleton
|
||||||
*/
|
*/
|
||||||
template<typename... ARGS,
|
template<typename... ARGS>
|
||||||
typename = eastl::enable_if_t<!(eastl::is_same_v<Lifetime, eastl::decay_t<ARGS>> || ...)>>
|
|
||||||
explicit Lifetime(ARGS&&... p_args)
|
explicit Lifetime(ARGS&&... p_args)
|
||||||
{
|
{
|
||||||
Initialize(eastl::forward<ARGS>(p_args)...);
|
Initialize(std::forward<ARGS>(p_args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lifetime(const Lifetime& p_lifetime) = delete;
|
Lifetime(const Lifetime& p_lifetime) = delete;
|
||||||
@@ -78,9 +88,7 @@ class Singleton
|
|||||||
template<typename... ARGS>
|
template<typename... ARGS>
|
||||||
static void Initialize(ARGS&&... p_args)
|
static void Initialize(ARGS&&... p_args)
|
||||||
{
|
{
|
||||||
new (ms_instance.data()) TYPE(eastl::forward<ARGS>(p_args)...);
|
ms_instance.emplace(std::forward<ARGS>(p_args)...);
|
||||||
|
|
||||||
ms_initialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,20 +97,13 @@ class Singleton
|
|||||||
*/
|
*/
|
||||||
static void Finalize()
|
static void Finalize()
|
||||||
{
|
{
|
||||||
eastl::bit_cast<TYPE*>(ms_instance.data())->~TYPE();
|
ms_instance.reset();
|
||||||
|
|
||||||
ms_initialized = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The singleton.
|
* The singleton.
|
||||||
*/
|
*/
|
||||||
alignas(alignof(TYPE)) inline static eastl::array<std::byte, sizeof(TYPE)> ms_instance;
|
inline static eastl::optional<TYPE> ms_instance;
|
||||||
|
|
||||||
/**
|
|
||||||
* Is the singleton initialized?
|
|
||||||
*/
|
|
||||||
inline static bool ms_initialized = false;
|
|
||||||
};
|
};
|
||||||
} // namespace Bigfoot
|
} // namespace Bigfoot
|
||||||
#endif
|
#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
|
|
||||||
Reference in New Issue
Block a user