diff --git a/common/Error.cpp b/common/Error.cpp index 8faecefd65..1d7b54a153 100644 --- a/common/Error.cpp +++ b/common/Error.cpp @@ -1,13 +1,15 @@ -// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team +// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team // SPDX-License-Identifier: LGPL-3.0+ #include "Error.h" +#include "StringUtil.h" + +#include "fmt/format.h" + #include #include #include -#include "fmt/format.h" - // Platform-specific includes #if defined(_WIN32) #include "RedtapeWindows.h" @@ -29,21 +31,26 @@ void Error::Clear() } void Error::SetErrno(int err) +{ + SetErrno(std::string_view(), err); +} + +void Error::SetErrno(std::string_view prefix, int err) { m_type = Type::Errno; #ifdef _MSC_VER char buf[128]; if (strerror_s(buf, sizeof(buf), err) == 0) - m_description = fmt::format("errno {}: {}", err, buf); + m_description = fmt::format("{}errno {}: {}", prefix, err, buf); else - m_description = fmt::format("errno {}: ", err); + m_description = fmt::format("{}errno {}: ", prefix, err); #else const char* buf = std::strerror(err); if (buf) - m_description = fmt::format("errno {}: {}", err, buf); + m_description = fmt::format("{}errno {}: {}", prefix, err, buf); else - m_description = fmt::format("errno {}: ", err); + m_description = fmt::format("{}errno {}: ", prefix, err); #endif } @@ -53,29 +60,59 @@ void Error::SetErrno(Error* errptr, int err) errptr->SetErrno(err); } +void Error::SetErrno(Error* errptr, std::string_view prefix, int err) +{ + if (errptr) + errptr->SetErrno(prefix, err); +} + void Error::SetString(std::string description) { m_type = Type::User; m_description = std::move(description); } +void Error::SetStringView(std::string_view description) +{ + m_type = Type::User; + m_description = std::string(description); +} + void Error::SetString(Error* errptr, std::string description) { if (errptr) errptr->SetString(std::move(description)); } +void Error::SetStringView(Error* errptr, std::string_view description) +{ + if (errptr) + errptr->SetStringView(std::move(description)); +} + #ifdef _WIN32 + void Error::SetWin32(unsigned long err) +{ + SetWin32(std::string_view(), err); +} + +void Error::SetWin32(std::string_view prefix, unsigned long err) { m_type = Type::Win32; - char buf[128]; - const DWORD r = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, 0, buf, sizeof(buf), nullptr); + WCHAR buf[128]; + const DWORD r = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, LANG_USER_DEFAULT, buf, + static_cast(std::size(buf)), nullptr); if (r > 0) - m_description = fmt::format("Win32 Error {}: {}", err, std::string_view(buf, r)); + { + m_description = + fmt::format("{}Win32 Error {}: {}", prefix, err, StringUtil::WideStringToUTF8String(std::wstring_view(buf, r))); + } else - m_description = fmt::format("Win32 Error {}: ", err); + { + m_description = fmt::format("{}Win32 Error {}: ", prefix, err); + } } void Error::SetWin32(Error* errptr, unsigned long err) @@ -84,16 +121,33 @@ void Error::SetWin32(Error* errptr, unsigned long err) errptr->SetWin32(err); } +void Error::SetWin32(Error* errptr, std::string_view prefix, unsigned long err) +{ + if (errptr) + errptr->SetWin32(prefix, err); +} + void Error::SetHResult(long err) +{ + SetHResult(std::string_view(), err); +} + +void Error::SetHResult(std::string_view prefix, long err) { m_type = Type::HResult; - char buf[128]; - const DWORD r = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, 0, buf, sizeof(buf), nullptr); + WCHAR buf[128]; + const DWORD r = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, LANG_USER_DEFAULT, buf, + static_cast(std::size(buf)), nullptr); if (r > 0) - m_description = fmt::format("HRESULT {:08X}: {}", err, std::string_view(buf, r)); + { + m_description = + fmt::format("{}HRESULT {:08X}: {}", prefix, err, StringUtil::WideStringToUTF8String(std::wstring_view(buf, r))); + } else - m_description = fmt::format("HRESULT {:08X}: ", err); + { + m_description = fmt::format("{}HRESULT {:08X}: ", prefix, err); + } } void Error::SetHResult(Error* errptr, long err) @@ -102,15 +156,26 @@ void Error::SetHResult(Error* errptr, long err) errptr->SetHResult(err); } +void Error::SetHResult(Error* errptr, std::string_view prefix, long err) +{ + if (errptr) + errptr->SetHResult(prefix, err); +} + #endif void Error::SetSocket(int err) +{ + SetSocket(std::string_view(), err); +} + +void Error::SetSocket(std::string_view prefix, int err) { // Socket errors are win32 errors on windows #ifdef _WIN32 - SetWin32(err); + SetWin32(prefix, err); #else - SetErrno(err); + SetErrno(prefix, err); #endif m_type = Type::Socket; } @@ -121,6 +186,12 @@ void Error::SetSocket(Error* errptr, int err) errptr->SetSocket(err); } +void Error::SetSocket(Error* errptr, std::string_view prefix, int err) +{ + if (errptr) + errptr->SetSocket(prefix, err); +} + Error Error::CreateNone() { return Error(); @@ -164,6 +235,28 @@ Error Error::CreateHResult(long err) #endif +void Error::AddPrefix(std::string_view prefix) +{ + m_description.insert(0, prefix); +} + +void Error::AddSuffix(std::string_view suffix) +{ + m_description.append(suffix); +} + +void Error::AddPrefix(Error* errptr, std::string_view prefix) +{ + if (errptr) + errptr->AddPrefix(prefix); +} + +void Error::AddSuffix(Error* errptr, std::string_view prefix) +{ + if (errptr) + errptr->AddSuffix(prefix); +} + Error& Error::operator=(const Error& e) = default; Error& Error::operator=(Error&& e) = default; diff --git a/common/Error.h b/common/Error.h index cd52a16102..b4aac61a8c 100644 --- a/common/Error.h +++ b/common/Error.h @@ -1,8 +1,12 @@ -// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team +// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team // SPDX-License-Identifier: LGPL-3.0+ #pragma once + #include "Pcsx2Defs.h" + +#include "fmt/core.h" + #include class Error @@ -24,25 +28,32 @@ public: }; __fi Type GetType() const { return m_type; } + __fi bool IsValid() const { return (m_type != Type::None); } __fi const std::string& GetDescription() const { return m_description; } void Clear(); /// Error that is set by system functions, such as open(). void SetErrno(int err); + void SetErrno(std::string_view prefix, int err); /// Error that is set by socket functions, such as socket(). On Unix this is the same as errno. void SetSocket(int err); + void SetSocket(std::string_view prefix, int err); /// Set both description and message. void SetString(std::string description); + void SetStringView(std::string_view description); #ifdef _WIN32 - /// Error that is returned by some Win32 functions, such as RegOpenKeyEx. Also used by other APIs through GetLastError(). + /// Error that is returned by some Win32 functions, such as RegOpenKeyEx. Also used by other APIs through + /// GetLastError(). void SetWin32(unsigned long err); + void SetWin32(std::string_view prefix, unsigned long err); /// Error that is returned by Win32 COM methods, e.g. S_OK. void SetHResult(long err); + void SetHResult(std::string_view prefix, long err); #endif static Error CreateNone(); @@ -56,10 +67,31 @@ public: // helpers for setting static void SetErrno(Error* errptr, int err); + static void SetErrno(Error* errptr, std::string_view prefix, int err); static void SetSocket(Error* errptr, int err); + static void SetSocket(Error* errptr, std::string_view prefix, int err); static void SetString(Error* errptr, std::string description); + static void SetStringView(Error* errptr, std::string_view description); + +#ifdef _WIN32 static void SetWin32(Error* errptr, unsigned long err); + static void SetWin32(Error* errptr, std::string_view prefix, unsigned long err); static void SetHResult(Error* errptr, long err); + static void SetHResult(Error* errptr, std::string_view prefix, long err); +#endif + + /// Sets a formatted message. + template + static void SetStringFmt(Error* errptr, fmt::format_string fmt, T&&... args) + { + if (errptr) + Error::SetString(errptr, fmt::vformat(fmt, fmt::make_format_args(args...))); + } + + void AddPrefix(std::string_view prefix); + void AddSuffix(std::string_view suffix); + static void AddPrefix(Error* errptr, std::string_view prefix); + static void AddSuffix(Error* errptr, std::string_view prefix); Error& operator=(const Error& e); Error& operator=(Error&& e);