Allow error message to be formatted
This commit is contained in:
committed by
Jérôme Leclercq
parent
25957c4b7f
commit
a741672a51
@@ -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>)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
29
include/Nazara/Core/Error.inl
Normal file
29
include/Nazara/Core/Error.inl
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
17
include/Nazara/Core/Log.inl
Normal file
17
include/Nazara/Core/Log.inl
Normal 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>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
90
include/Nazara/Core/ToString.hpp
Normal file
90
include/Nazara/Core/ToString.hpp
Normal 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
|
||||
88
include/Nazara/Core/ToString.inl
Normal file
88
include/Nazara/Core/ToString.inl
Normal 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>
|
||||
Reference in New Issue
Block a user