Allow error message to be formatted

This commit is contained in:
SirLynix
2023-08-14 23:16:37 +02:00
committed by Jérôme Leclercq
parent 25957c4b7f
commit a741672a51
119 changed files with 707 additions and 490 deletions

View File

@@ -105,7 +105,7 @@ namespace Nz
using Param = std::decay_t<decltype(arg)>;
if constexpr (std::is_base_of_v<VirtualDirectory::DirectoryEntry, Param>)
{
NazaraError(std::string(assetPath) + " is a directory");
NazaraError("{} is a directory", assetPath);
return false;
}
else if constexpr (std::is_same_v<Param, VirtualDirectory::FileEntry>)
@@ -136,7 +136,7 @@ namespace Nz
using Param = std::decay_t<decltype(arg)>;
if constexpr (std::is_base_of_v<VirtualDirectory::DirectoryEntry, Param>)
{
NazaraError(std::string(assetPath) + " is a directory");
NazaraError("{} is a directory", assetPath);
return false;
}
else if constexpr (std::is_same_v<Param, VirtualDirectory::FileEntry>)

View File

@@ -30,14 +30,10 @@ namespace Nz
enum class ErrorMode
{
None,
Silent,
SilentDisabled,
ThrowException,
ThrowExceptionDisabled,
Max = ThrowExceptionDisabled
Max = ThrowException
};
template<>
@@ -48,6 +44,8 @@ namespace Nz
using ErrorModeFlags = Flags<ErrorMode>;
constexpr ErrorModeFlags ErrorMode_Default = {};
enum class ErrorType
{
AssertFailed,

View File

@@ -10,17 +10,18 @@
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Enums.hpp>
#include <Nazara/Core/ToString.hpp>
#include <string>
#if NAZARA_CORE_ENABLE_ASSERTS || defined(NAZARA_DEBUG)
#define NazaraAssert(a, err) if (!(a)) Nz::Error::Trigger(Nz::ErrorType::AssertFailed, err, __LINE__, __FILE__, NAZARA_PRETTY_FUNCTION)
#define NazaraAssert(a, ...) if NAZARA_UNLIKELY(!(a)) Nz::Error::Trigger(Nz::ErrorType::AssertFailed, __LINE__, __FILE__, NAZARA_PRETTY_FUNCTION, __VA_ARGS__)
#else
#define NazaraAssert(a, err) for (;;) break
#define NazaraAssert(a, ...) for (;;) break
#endif
#define NazaraError(err) Nz::Error::Trigger(Nz::ErrorType::Normal, err, __LINE__, __FILE__, NAZARA_PRETTY_FUNCTION)
#define NazaraInternalError(err) Nz::Error::Trigger(Nz::ErrorType::Internal, err, __LINE__, __FILE__, NAZARA_PRETTY_FUNCTION)
#define NazaraWarning(err) Nz::Error::Trigger(Nz::ErrorType::Warning, err, __LINE__, __FILE__, NAZARA_PRETTY_FUNCTION)
#define NazaraError(...) Nz::Error::Trigger(Nz::ErrorType::Normal, __LINE__, __FILE__, NAZARA_PRETTY_FUNCTION, __VA_ARGS__)
#define NazaraInternalError(...) Nz::Error::Trigger(Nz::ErrorType::Internal, __LINE__, __FILE__, NAZARA_PRETTY_FUNCTION, __VA_ARGS__)
#define NazaraWarning(...) Nz::Error::Trigger(Nz::ErrorType::Warning, __LINE__, __FILE__, NAZARA_PRETTY_FUNCTION, __VA_ARGS__)
namespace Nz
{
@@ -30,25 +31,22 @@ namespace Nz
Error() = delete;
~Error() = delete;
static constexpr std::string_view GetCurrentFileRelativeToEngine(std::string_view file);
static ErrorModeFlags GetFlags();
static std::string GetLastError(const char** file = nullptr, unsigned int* line = nullptr, const char** function = nullptr);
static std::string GetLastError(std::string_view* file = nullptr, unsigned int* line = nullptr, std::string_view* function = nullptr);
static unsigned int GetLastSystemErrorCode();
static std::string GetLastSystemError(unsigned int code = GetLastSystemErrorCode());
static void SetFlags(ErrorModeFlags flags);
static void Trigger(ErrorType type, std::string error);
static void Trigger(ErrorType type, std::string error, unsigned int line, const char* file, const char* function);
template<typename... Args> static void Trigger(ErrorType type, std::string_view error, Args&&... args);
template<typename... Args> static void Trigger(ErrorType type, unsigned int line, std::string_view file, std::string_view function, std::string_view error, Args&&... args);
private:
static const char* GetCurrentFileRelativeToEngine(const char* file);
static ErrorModeFlags s_flags;
static std::string s_lastError;
static const char* s_lastErrorFunction;
static const char* s_lastErrorFile;
static unsigned int s_lastErrorLine;
static void TriggerInternal(ErrorType type, std::string error, unsigned int line, std::string_view file, std::string_view function);
};
}
#include <Nazara/Core/Error.inl>
#endif // NAZARA_CORE_ERROR_HPP

View File

@@ -0,0 +1,29 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
namespace Nz
{
constexpr std::string_view Error::GetCurrentFileRelativeToEngine(std::string_view file)
{
if (std::size_t offset = file.find("NazaraEngine/"); offset != file.npos)
return file.substr(offset);
if (std::size_t offset = file.find("NazaraEngine\\"); offset != file.npos)
return file.substr(offset);
return file;
}
template<typename... Args>
void Error::Trigger(ErrorType type, std::string_view error, Args&&... args)
{
return TriggerInternal(type, Format(error, std::forward<Args>(args)...), 0, {}, {});
}
template<typename... Args>
void Error::Trigger(ErrorType type, unsigned int line, std::string_view file, std::string_view function, std::string_view error, Args&&... args)
{
return TriggerInternal(type, Format(error, std::forward<Args>(args)...), line, GetCurrentFileRelativeToEngine(file), function);
}
}

View File

@@ -16,14 +16,14 @@ namespace Nz
class NAZARA_CORE_API ErrorFlags
{
public:
ErrorFlags(ErrorModeFlags flags, bool replace = false);
ErrorFlags(ErrorModeFlags orFlags, ErrorModeFlags andFlags = {});
ErrorFlags(const ErrorFlags&) = delete;
ErrorFlags(ErrorFlags&&) = delete;
~ErrorFlags();
ErrorModeFlags GetPreviousFlags() const;
void SetFlags(ErrorModeFlags flags, bool replace = false);
void SetFlags(ErrorModeFlags orFlags, ErrorModeFlags andFlags = {});
ErrorFlags& operator=(const ErrorFlags&) = delete;
ErrorFlags& operator=(ErrorFlags&&) = delete;

View File

@@ -15,12 +15,12 @@
#include <string>
#ifdef NAZARA_DEBUG
#define NazaraDebug(txt) NazaraNotice(txt)
#define NazaraDebug(...) NazaraNotice(__VA_ARGS__)
#else
#define NazaraDebug(txt)
#define NazaraDebug(...)
#endif
#define NazaraNotice(txt) Nz::Log::Write(txt)
#define NazaraNotice(...) Nz::Log::Write(__VA_ARGS__)
namespace Nz
{
@@ -39,7 +39,8 @@ namespace Nz
static void SetLogger(AbstractLogger* logger);
static void Write(std::string_view string);
static void Write(std::string_view str);
template<typename... Args> static void Write(std::string_view str, Args&&... args);
static void WriteError(ErrorType type, std::string_view error, unsigned int line = 0, const char* file = nullptr, const char* function = nullptr);
NazaraStaticSignal(OnLogWrite, const std::string_view& /*string*/);
@@ -54,4 +55,6 @@ namespace Nz
};
}
#include <Nazara/Core/Log.inl>
#endif // NAZARA_CORE_LOG_HPP

View File

@@ -0,0 +1,17 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/ToString.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
template<typename... Args>
void Log::Write(std::string_view str, Args&&... args)
{
return Write(Format(str, std::forward<Args>(args)...));
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -35,7 +35,7 @@ namespace Nz
{
std::shared_ptr<Type> ref = Query(name);
if (!ref)
NazaraError("Object \"" + name + "\" is not present");
NazaraError("Object \"{}\" is not present", name);
return ref;
}

View File

@@ -66,7 +66,7 @@ namespace Nz
std::string ext = ToLower(PathToString(filePath.extension()));
if (ext.empty())
{
NazaraError("Failed to get file extension from \"" + PathToString(filePath) + '"');
NazaraError("failed to get file extension from \"{0}\"", filePath);
return nullptr;
}
@@ -93,7 +93,7 @@ namespace Nz
{
if (!file.Open(OpenMode::ReadOnly))
{
NazaraError("failed to load resource: unable to open \"" + PathToString(filePath) + '"');
NazaraError("failed to load resource: unable to open \"{0}\"", filePath);
return nullptr;
}
}
@@ -121,9 +121,9 @@ namespace Nz
}
if (found)
NazaraError("failed to load resource from file \"" + PathToString(filePath) + "\": all loaders failed");
NazaraError("failed to load resource from file \"{0}}\": all loaders failed", filePath);
else
NazaraError("failed to load resource from file \"" + PathToString(filePath) + "\": no loader found for extension \"" + ext + '"');
NazaraError("failed to load resource from file \"{0}}\": no loader found for extension \"{1}\"", ext);
return nullptr;
}
@@ -139,9 +139,9 @@ namespace Nz
template<typename Type, typename Parameters>
std::shared_ptr<Type> ResourceLoader<Type, Parameters>::LoadFromMemory(const void* data, std::size_t size, const Parameters& parameters) const
{
NazaraAssert(data, "Invalid data pointer");
NazaraAssert(size, "No data to load");
NazaraAssert(parameters.IsValid(), "Invalid parameters");
NazaraAssert(data, "invalid data pointer");
NazaraAssert(size, "no data to load");
NazaraAssert(parameters.IsValid(), "invalid parameters");
MemoryView stream(data, size);

View File

@@ -50,11 +50,11 @@ namespace Nz
std::shared_ptr<Type> resource = m_loader.LoadFromFile(absolutePath, GetDefaultParameters());
if (!resource)
{
NazaraError("Failed to load resource from file: " + PathToString(absolutePath));
NazaraError("failed to load resource from file: {0}", absolutePath);
return std::shared_ptr<Type>();
}
NazaraDebug("Loaded resource from file " + PathToString(absolutePath));
NazaraDebug("loaded resource from file {0}", absolutePath);
it = m_resources.insert(std::make_pair(absolutePath, resource)).first;
}

View File

@@ -69,7 +69,7 @@ namespace Nz
std::string extension = ToLower(PathToString(filePath.extension()));
if (extension.empty())
{
NazaraError("Failed to get file extension from \"" + PathToString(filePath) + '"');
NazaraError("failed to get file extension from \"{0}\"", filePath);
return false;
}
@@ -93,7 +93,7 @@ namespace Nz
if (!file.Open(OpenMode::WriteOnly | OpenMode::Truncate))
{
NazaraError("failed to save to file: unable to open \"" + PathToString(filePath) + "\" in write mode");
NazaraError("failed to save to file: unable to open \"{0}\" in write mode", filePath);
return false;
}
@@ -107,7 +107,7 @@ namespace Nz
if (found)
NazaraError("failed to save resource: all savers failed");
else
NazaraError("failed to save resource: no saver found for extension \"" + extension + '"');
NazaraError("failed to save resource: no saver found for extension \"extension\"", extension);
return false;
}
@@ -152,7 +152,7 @@ namespace Nz
if (found)
NazaraError("failed to save resource: all savers failed");
else
NazaraError("failed to save resource: no saver found for format \"" + format + '"');
NazaraError("failed to save resource: no saver found for format \"{0}\"", format);
return false;
}

View File

@@ -0,0 +1,90 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_CORE_TOSTRING_HPP
#define NAZARA_CORE_TOSTRING_HPP
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Core/Config.hpp>
#include <NazaraUtils/Algorithm.hpp>
#include <filesystem>
#include <string>
namespace Nz
{
template<typename... Args> std::string Format(std::string_view str, Args&&... args);
template<typename T> decltype(auto) ToString(T&& value);
template<typename T>
struct ToStringFormatter
{
static_assert(AlwaysFalse<T>(), "ToStringFormatter is not implemented for this type");
};
template<>
struct NAZARA_CORE_API ToStringFormatter<std::filesystem::path>
{
static std::string Format(const std::filesystem::path& path);
};
template<>
struct ToStringFormatter<std::string>
{
static const std::string& Format(const std::string& value);
static std::string Format(std::string&& value);
};
template<>
struct ToStringFormatter<std::string_view>
{
static std::string Format(std::string_view value);
};
template<>
struct ToStringFormatter<const char*>
{
static std::string_view Format(const char* value);
template<std::size_t N> static std::string_view Format(const char(&str)[N]);
};
// Specializations declared in .inl
#define NAZARA_TO_STRING_INLINE_SPEC(Type) \
template<> \
struct ToStringFormatter<Type> \
{ \
static std::string Format(Type value); \
}
NAZARA_TO_STRING_INLINE_SPEC(short);
NAZARA_TO_STRING_INLINE_SPEC(int);
NAZARA_TO_STRING_INLINE_SPEC(long);
NAZARA_TO_STRING_INLINE_SPEC(long long);
NAZARA_TO_STRING_INLINE_SPEC(unsigned short);
NAZARA_TO_STRING_INLINE_SPEC(unsigned int);
NAZARA_TO_STRING_INLINE_SPEC(unsigned long);
NAZARA_TO_STRING_INLINE_SPEC(unsigned long long);
#undef NAZARA_TO_STRING_INLINE_SPEC
// Specializations declared in .cpp
#define NAZARA_TO_STRING_CPP_SPEC(Type) \
template<> \
struct NAZARA_CORE_API ToStringFormatter<Type> \
{ \
static std::string Format(Type value); \
}
NAZARA_TO_STRING_CPP_SPEC(float);
NAZARA_TO_STRING_CPP_SPEC(double);
NAZARA_TO_STRING_CPP_SPEC(long double);
#undef NAZARA_TO_STRING_CPP_SPEC
}
#include <Nazara/Core/ToString.inl>
#endif // NAZARA_CORE_TOSTRING_HPP

View File

@@ -0,0 +1,88 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#ifdef NAZARA_BUILD
#include <fmt/format.h>
#include <fmt/std.h>
#endif
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
namespace Detail
{
NAZARA_CORE_API std::string FormatFallback(std::string_view str);
NAZARA_CORE_API std::string FormatFallback(std::string_view str, std::string_view param1);
NAZARA_CORE_API std::string FormatFallback(std::string_view str, std::string_view param1, std::string_view param2);
NAZARA_CORE_API std::string FormatFallback(std::string_view str, std::string_view param1, std::string_view param2, std::string_view param3);
NAZARA_CORE_API std::string FormatFallback(std::string_view str, std::string_view param1, std::string_view param2, std::string_view param3, std::string_view param4);
NAZARA_CORE_API std::string FormatFallback(std::string_view str, std::string_view param1, std::string_view param2, std::string_view param3, std::string_view param4, std::string_view param5);
}
template<typename ...Args>
std::string Format(std::string_view str, Args&&... args)
{
#ifdef NAZARA_BUILD
return fmt::format(str, std::forward<Args>(args)...);
#else
return Detail::FormatFallback(str, ToString(args)...);
#endif
}
template<typename T>
decltype(auto) ToString(T&& value)
{
return ToStringFormatter<std::decay_t<T>>::Format(std::forward<T>(value));
}
inline const std::string& ToStringFormatter<std::string>::Format(const std::string& value)
{
return value;
}
inline std::string ToStringFormatter<std::string>::Format(std::string&& value)
{
return value;
}
inline std::string ToStringFormatter<std::string_view>::Format(std::string_view value)
{
return std::string(value);
}
inline std::string_view ToStringFormatter<const char*>::Format(const char* value)
{
return std::string_view(value);
}
template<std::size_t N>
inline std::string_view ToStringFormatter<const char*>::Format(const char(&str)[N])
{
return std::string_view(str, N);
}
#define NAZARA_TO_STRING_STD_SPEC(Type) \
inline std::string ToStringFormatter<Type>::Format(Type value) \
{ \
return std::to_string(value); \
}
NAZARA_TO_STRING_STD_SPEC(short);
NAZARA_TO_STRING_STD_SPEC(int);
NAZARA_TO_STRING_STD_SPEC(long);
NAZARA_TO_STRING_STD_SPEC(long long);
NAZARA_TO_STRING_STD_SPEC(unsigned short);
NAZARA_TO_STRING_STD_SPEC(unsigned int);
NAZARA_TO_STRING_STD_SPEC(unsigned long);
NAZARA_TO_STRING_STD_SPEC(unsigned long long);
#undef NAZARA_TO_STRING_STD_SPEC
}
#include <Nazara/Core/DebugOff.hpp>