From 39f64a03ee761f13b7deb4269130a7250a35e9c8 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 19 Aug 2023 23:40:36 +1000 Subject: [PATCH] Common: Error/FileSystem backports --- src/common/error.cpp | 324 ++++++++--------------------------- src/common/error.h | 89 ++++------ src/common/file_system.cpp | 44 +++-- src/common/file_system.h | 29 +++- src/core/pcdrv.cpp | 2 +- src/core/system.cpp | 26 +-- src/util/cd_image.cpp | 9 +- src/util/cd_image.h | 22 ++- src/util/cd_image_bin.cpp | 6 +- src/util/cd_image_chd.cpp | 63 +++---- src/util/cd_image_cue.cpp | 39 ++--- src/util/cd_image_device.cpp | 15 +- src/util/cd_image_ecm.cpp | 36 ++-- src/util/cd_image_m3u.cpp | 13 +- src/util/cd_image_mds.cpp | 52 ++---- src/util/cd_image_pbp.cpp | 53 +++--- src/util/cue_parser.cpp | 24 ++- src/util/cue_parser.h | 20 +-- 18 files changed, 311 insertions(+), 555 deletions(-) diff --git a/src/common/error.cpp b/src/common/error.cpp index a789ea3c9..32b71d2f7 100644 --- a/src/common/error.cpp +++ b/src/common/error.cpp @@ -1,182 +1,140 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "error.h" +#include "string_util.h" + #include #include #include -// Platform-specific includes +#include "fmt/format.h" + #if defined(_WIN32) #include "windows_headers.h" -static_assert(std::is_same::value, "DWORD is unsigned long"); -static_assert(std::is_same::value, "HRESULT is long"); #endif -namespace Common { +Error::Error() = default; -Error::Error() : m_type(Type::None) -{ - m_error.none = 0; -} +Error::Error(const Error& c) = default; -Error::Error(const Error& c) -{ - m_type = c.m_type; - std::memcpy(&m_error, &c.m_error, sizeof(m_error)); - m_code_string.AppendString(c.m_code_string); - m_message.AppendString(c.m_message); -} +Error::Error(Error&& e) = default; Error::~Error() = default; void Error::Clear() { - m_type = Type::None; - m_error.none = 0; - m_code_string.Clear(); - m_message.Clear(); + m_description = {}; } void Error::SetErrno(int err) { m_type = Type::Errno; - m_error.errno_f = err; - - m_code_string.Format("%i", err); #ifdef _MSC_VER - strerror_s(m_message.GetWriteableCharArray(), m_message.GetBufferSize(), err); - m_message.UpdateSize(); -#else - const char* message = std::strerror(err); - if (message) - m_message = message; + char buf[128]; + if (strerror_s(buf, sizeof(buf), err) != 0) + m_description = fmt::format("errno {}: {}", err, buf); else - m_message = StaticString(""); -#endif -} - -void Error::SetSocket(int err) -{ -// Socket errors are win32 errors on windows -#ifdef _WIN32 - SetWin32(err); + m_description = fmt::format("errno {}: ", err); #else - SetErrno(err); + const char* buf = std::strerror(err); + if (buf) + m_description = fmt::format("errno {}: {}", err, buf); + else + m_description = fmt::format("errno {}: ", err); #endif } -void Error::SetMessage(const char* msg) +void Error::SetErrno(Error* errptr, int err) { - m_type = Type::User; - m_error.user = 0; - m_code_string.Clear(); - m_message = msg; + if (errptr) + errptr->SetErrno(err); } -void Error::SetUser(int err, const char* msg) +void Error::SetString(std::string description) { m_type = Type::User; - m_error.user = err; - m_code_string.Format("%d", err); - m_message = msg; + m_description = std::move(description); } -void Error::SetUser(const char* code, const char* message) +void Error::SetString(Error* errptr, std::string description) { - m_type = Type::User; - m_error.user = 0; - m_code_string = code; - m_message = message; -} - -void Error::SetUserFormatted(int err, const char* format, ...) -{ - std::va_list ap; - va_start(ap, format); - - m_type = Type::User; - m_error.user = err; - m_code_string.Format("%d", err); - m_message.FormatVA(format, ap); - va_end(ap); -} - -void Error::SetUserFormatted(const char* code, const char* format, ...) -{ - std::va_list ap; - va_start(ap, format); - - m_type = Type::User; - m_error.user = 0; - m_code_string = code; - m_message.FormatVA(format, ap); - va_end(ap); -} - -void Error::SetFormattedMessage(const char* format, ...) -{ - std::va_list ap; - va_start(ap, format); - - m_type = Type::User; - m_error.user = 0; - m_code_string.Clear(); - m_message.FormatVA(format, ap); - va_end(ap); + if (errptr) + errptr->SetString(std::move(description)); } #ifdef _WIN32 - void Error::SetWin32(unsigned long err) { m_type = Type::Win32; - m_error.win32 = err; - m_code_string.Format("%u", static_cast(err)); - m_message.Clear(); - const DWORD r = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, m_error.win32, 0, m_message.GetWriteableCharArray(), - m_message.GetWritableBufferSize(), NULL); + 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_message.Resize(r); - m_message.RStrip(); + m_description = + fmt::format("Win32 Error {}: {}", err, StringUtil::WideStringToUTF8String(std::wstring_view(buf, r))); } else { - m_message = ""; + m_description = fmt::format("Win32 Error {}: ", err); } } +void Error::SetWin32(Error* errptr, unsigned long err) +{ + if (errptr) + errptr->SetWin32(err); +} + void Error::SetHResult(long err) { m_type = Type::HResult; - m_error.win32 = err; - m_code_string.Format("%08X", static_cast(err)); - m_message.Clear(); - const DWORD r = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, m_error.win32, 0, m_message.GetWriteableCharArray(), - m_message.GetWritableBufferSize(), NULL); + 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_message.Resize(r); - m_message.RStrip(); + m_description = + fmt::format("HRESULT {:08X}: {}", err, StringUtil::WideStringToUTF8String(std::wstring_view(buf, r))); } else { - m_message = ""; + m_description = fmt::format("HRESULT {:08X}: ", err); } } +void Error::SetHResult(Error* errptr, long err) +{ + if (errptr) + errptr->SetHResult(err); +} + #endif -// constructors +void Error::SetSocket(int err) +{ + // Socket errors are win32 errors on windows +#ifdef _WIN32 + SetWin32(err); +#else + SetErrno(err); +#endif + m_type = Type::Socket; +} + +void Error::SetSocket(Error* errptr, int err) +{ + if (errptr) + errptr->SetSocket(err); +} + Error Error::CreateNone() { - Error ret; - ret.Clear(); - return ret; + return Error(); } Error Error::CreateErrno(int err) @@ -193,70 +151,10 @@ Error Error::CreateSocket(int err) return ret; } -Error Error::CreateMessage(const char* msg) +Error Error::CreateString(std::string description) { Error ret; - ret.SetMessage(msg); - return ret; -} - -Error Error::CreateUser(int err, const char* msg) -{ - Error ret; - ret.SetUser(err, msg); - return ret; -} - -Error Error::CreateUser(const char* code, const char* message) -{ - Error ret; - ret.SetUser(code, message); - return ret; -} - -Error Error::CreateMessageFormatted(const char* format, ...) -{ - std::va_list ap; - va_start(ap, format); - - Error ret; - ret.m_type = Type::User; - ret.m_message.FormatVA(format, ap); - - va_end(ap); - - return ret; -} - -Error Error::CreateUserFormatted(int err, const char* format, ...) -{ - std::va_list ap; - va_start(ap, format); - - Error ret; - ret.m_type = Type::User; - ret.m_error.user = err; - ret.m_code_string.Format("%d", err); - ret.m_message.FormatVA(format, ap); - - va_end(ap); - - return ret; -} - -Error Error::CreateUserFormatted(const char* code, const char* format, ...) -{ - std::va_list ap; - va_start(ap, format); - - Error ret; - ret.m_type = Type::User; - ret.m_error.user = 0; - ret.m_code_string = code; - ret.m_message.FormatVA(format, ap); - - va_end(ap); - + ret.SetString(std::move(description)); return ret; } @@ -277,86 +175,16 @@ Error Error::CreateHResult(long err) #endif -Error& Error::operator=(const Error& e) -{ - m_type = e.m_type; - std::memcpy(&m_error, &e.m_error, sizeof(m_error)); - m_code_string.Clear(); - m_code_string.AppendString(e.m_code_string); - m_message.Clear(); - m_message.AppendString(e.m_message); - return *this; -} +Error& Error::operator=(const Error& e) = default; + +Error& Error::operator=(Error&& e) = default; bool Error::operator==(const Error& e) const { - switch (m_type) - { - case Type::None: - return true; - - case Type::Errno: - return m_error.errno_f == e.m_error.errno_f; - - case Type::Socket: - return m_error.socketerr == e.m_error.socketerr; - - case Type::User: - return m_error.user == e.m_error.user; - -#ifdef _WIN32 - case Type::Win32: - return m_error.win32 == e.m_error.win32; - - case Type::HResult: - return m_error.hresult == e.m_error.hresult; -#endif - } - - return false; + return (m_type == e.m_type && m_description == e.m_description); } bool Error::operator!=(const Error& e) const { - switch (m_type) - { - case Type::None: - return false; - - case Type::Errno: - return m_error.errno_f != e.m_error.errno_f; - - case Type::Socket: - return m_error.socketerr != e.m_error.socketerr; - - case Type::User: - return m_error.user != e.m_error.user; - -#ifdef _WIN32 - case Type::Win32: - return m_error.win32 != e.m_error.win32; - - case Type::HResult: - return m_error.hresult != e.m_error.hresult; -#endif - } - - return true; -} - -SmallString Error::GetCodeAndMessage() const -{ - SmallString ret; - GetCodeAndMessage(ret); - return ret; -} - -void Error::GetCodeAndMessage(String& dest) const -{ - if (m_code_string.IsEmpty()) - dest.Assign(m_message); - else - dest.Format("[%s]: %s", m_code_string.GetCharArray(), m_message.GetCharArray()); -} - -} // namespace Common \ No newline at end of file + return (m_type != e.m_type || m_description != e.m_description); +} \ No newline at end of file diff --git a/src/common/error.h b/src/common/error.h index d41a8a0cb..754cc65a9 100644 --- a/src/common/error.h +++ b/src/common/error.h @@ -1,100 +1,75 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #pragma once -#include "string.h" + #include "types.h" -namespace Common { +#include -// this class provides enough storage room for all of these types class Error { public: Error(); Error(const Error& e); + Error(Error&& e); ~Error(); enum class Type { - None = 0, // Set by default constructor, returns 'No Error'. - Errno = 1, // Error that is set by system functions, such as open(). - Socket = 2, // Error that is set by socket functions, such as socket(). On Unix this is the same as errno. - User = 3, // When translated, will return 'User Error %u' if no message is specified. - Win32 = 4, // Error that is returned by some Win32 functions, such as RegOpenKeyEx. Also used by other APIs through - // GetLastError(). - HResult = 5, // Error that is returned by Win32 COM methods, e.g. S_OK. + None = 0, + Errno = 1, + Socket = 2, + User = 3, + Win32 = 4, + HResult = 5, }; ALWAYS_INLINE Type GetType() const { return m_type; } - ALWAYS_INLINE int GetErrnoCode() const { return m_error.errno_f; } - ALWAYS_INLINE int GetSocketCode() const { return m_error.socketerr; } - ALWAYS_INLINE int GetUserCode() const { return m_error.user; } -#ifdef _WIN32 - ALWAYS_INLINE unsigned long GetWin32Code() const { return m_error.win32; } - ALWAYS_INLINE long GetHResultCode() const { return m_error.hresult; } -#endif + ALWAYS_INLINE const std::string& GetDescription() const { return m_description; } - // get code, e.g. "0x00000002" - ALWAYS_INLINE const String& GetCodeString() const { return m_code_string; } - - // get description, e.g. "File not Found" - ALWAYS_INLINE const String& GetMessage() const { return m_message; } - - // setter functions void Clear(); + + /// Error that is set by system functions, such as open(). void SetErrno(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 SetMessage(const char* msg); - void SetFormattedMessage(const char* format, ...) printflike(2, 3); - void SetUser(int err, const char* msg); - void SetUser(const char* code, const char* message); - void SetUserFormatted(int err, const char* format, ...) printflike(3, 4); - void SetUserFormatted(const char* code, const char* format, ...) printflike(3, 4); + + /// Set both description and message. + void SetString(std::string description); + #ifdef _WIN32 + /// Error that is returned by some Win32 functions, such as RegOpenKeyEx. Also used by other APIs through + /// GetLastError(). void SetWin32(unsigned long err); + + /// Error that is returned by Win32 COM methods, e.g. S_OK. void SetHResult(long err); #endif - // constructors static Error CreateNone(); static Error CreateErrno(int err); static Error CreateSocket(int err); - static Error CreateMessage(const char* msg); - static Error CreateMessageFormatted(const char* format, ...) printflike(1, 2); - static Error CreateUser(int err, const char* msg); - static Error CreateUser(const char* code, const char* message); - static Error CreateUserFormatted(int err, const char* format, ...) printflike(2, 3); - static Error CreateUserFormatted(const char* code, const char* format, ...) printflike(2, 3); + static Error CreateString(std::string description); #ifdef _WIN32 static Error CreateWin32(unsigned long err); static Error CreateHResult(long err); #endif - // get code and description, e.g. "[0x00000002]: File not Found" - SmallString GetCodeAndMessage() const; - void GetCodeAndMessage(String& dest) const; + // helpers for setting + static void SetErrno(Error* errptr, int err); + static void SetSocket(Error* errptr, int err); + static void SetString(Error* errptr, std::string description); + static void SetWin32(Error* errptr, unsigned long err); + static void SetHResult(Error* errptr, long err); - // operators Error& operator=(const Error& e); + Error& operator=(Error&& e); bool operator==(const Error& e) const; bool operator!=(const Error& e) const; private: Type m_type = Type::None; - union - { - int none; - int errno_f; // renamed from errno to avoid conflicts with #define'd errnos. - int socketerr; - int user; -#ifdef _WIN32 - unsigned long win32; - long hresult; -#endif - } m_error{}; - StackString<16> m_code_string; - TinyString m_message; + std::string m_description; }; - -} // namespace Common diff --git a/src/common/file_system.cpp b/src/common/file_system.cpp index 87cbbed60..c83c31e07 100644 --- a/src/common/file_system.cpp +++ b/src/common/file_system.cpp @@ -3,9 +3,11 @@ #include "file_system.h" #include "assert.h" +#include "error.h" #include "log.h" #include "path.h" #include "string_util.h" + #include #include #include @@ -587,7 +589,7 @@ std::string Path::Combine(const std::string_view& base, const std::string_view& return ret; } -std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode) +std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode, Error* error) { #ifdef _WIN32 const std::wstring wfilename(StringUtil::UTF8StringToWideString(filename)); @@ -595,23 +597,34 @@ std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode) if (!wfilename.empty() && !wmode.empty()) { std::FILE* fp; - if (_wfopen_s(&fp, wfilename.c_str(), wmode.c_str()) != 0) + const errno_t err = _wfopen_s(&fp, wfilename.c_str(), wmode.c_str()); + if (err != 0) + { + Error::SetErrno(error, err); return nullptr; + } return fp; } std::FILE* fp; - if (fopen_s(&fp, filename, mode) != 0) + const errno_t err = fopen_s(&fp, filename, mode); + if (err != 0) + { + Error::SetErrno(error, err); return nullptr; + } return fp; #else - return std::fopen(filename, mode); + std::FILE* fp = std::fopen(filename, mode); + if (!fp) + Error::SetErrno(error, errno); + return fp; #endif } -int FileSystem::OpenFDFile(const char* filename, int flags, int mode) +int FileSystem::OpenFDFile(const char* filename, int flags, int mode, Error* error) { #ifdef _WIN32 const std::wstring wfilename(StringUtil::UTF8StringToWideString(filename)); @@ -620,18 +633,21 @@ int FileSystem::OpenFDFile(const char* filename, int flags, int mode) return -1; #else - return open(filename, flags, mode); + const int fd = open(filename, flags, mode); + if (fd < 0) + Error::SetErrno(error, errno); + return fd; #endif } #endif -FileSystem::ManagedCFilePtr FileSystem::OpenManagedCFile(const char* filename, const char* mode) +FileSystem::ManagedCFilePtr FileSystem::OpenManagedCFile(const char* filename, const char* mode, Error* error) { - return ManagedCFilePtr(OpenCFile(filename, mode), [](std::FILE* fp) { std::fclose(fp); }); + return ManagedCFilePtr(OpenCFile(filename, mode, error)); } -std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode) +std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, Error* error) { #ifdef _WIN32 const std::wstring wfilename(StringUtil::UTF8StringToWideString(filename)); @@ -661,16 +677,20 @@ std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, F if (fp) return fp; + Error::SetErrno(error, errno); return nullptr; #else - return std::fopen(filename, mode); + std::FILE* fp = std::fopen(filename, mode); + if (!fp) + Error::SetErrno(error, errno); + return fp; #endif } FileSystem::ManagedCFilePtr FileSystem::OpenManagedSharedCFile(const char* filename, const char* mode, - FileShareMode share_mode) + FileShareMode share_mode, Error* error) { - return ManagedCFilePtr(OpenSharedCFile(filename, mode, share_mode), [](std::FILE* fp) { std::fclose(fp); }); + return ManagedCFilePtr(OpenSharedCFile(filename, mode, share_mode, error)); } int FileSystem::FSeek64(std::FILE* fp, s64 offset, int whence) diff --git a/src/common/file_system.h b/src/common/file_system.h index d68dd2597..1bad77af0 100644 --- a/src/common/file_system.h +++ b/src/common/file_system.h @@ -1,8 +1,10 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #pragma once + #include "types.h" + #include #include #include @@ -11,6 +13,8 @@ #include #include +class Error; + #ifdef _WIN32 #define FS_OSPATH_SEPARATOR_CHARACTER '\\' #define FS_OSPATH_SEPARATOR_STR "\\" @@ -87,15 +91,25 @@ bool DeleteFile(const char* path); /// Rename file bool RenamePath(const char* OldPath, const char* NewPath); +/// Deleter functor for managed file pointers +struct FileDeleter +{ + ALWAYS_INLINE void operator()(std::FILE* fp) + { + if (fp) + std::fclose(fp); + } +}; + /// open files -using ManagedCFilePtr = std::unique_ptr; -ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode); -std::FILE* OpenCFile(const char* filename, const char* mode); +using ManagedCFilePtr = std::unique_ptr; +ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode, Error* error = nullptr); +std::FILE* OpenCFile(const char* filename, const char* mode, Error* error = nullptr); int FSeek64(std::FILE* fp, s64 offset, int whence); s64 FTell64(std::FILE* fp); s64 FSize64(std::FILE* fp); -int OpenFDFile(const char* filename, int flags, int mode); +int OpenFDFile(const char* filename, int flags, int mode, Error* error = nullptr); /// Sharing modes for OpenSharedCFile(). enum class FileShareMode @@ -108,8 +122,9 @@ enum class FileShareMode /// Opens a file in shareable mode (where other processes can access it concurrently). /// Only has an effect on Windows systems. -ManagedCFilePtr OpenManagedSharedCFile(const char* filename, const char* mode, FileShareMode share_mode); -std::FILE* OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode); +ManagedCFilePtr OpenManagedSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, + Error* error = nullptr); +std::FILE* OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, Error* error = nullptr); /// Abstracts a POSIX file lock. #ifndef _WIN32 diff --git a/src/core/pcdrv.cpp b/src/core/pcdrv.cpp index 4a055e9f5..f43ff660b 100644 --- a/src/core/pcdrv.cpp +++ b/src/core/pcdrv.cpp @@ -38,7 +38,7 @@ static s32 GetFreeFileHandle() } const s32 index = static_cast(s_files.size()); - s_files.emplace_back(nullptr, [](std::FILE*) {}); + s_files.emplace_back(nullptr, FileSystem::FileDeleter()); return index; } diff --git a/src/core/system.cpp b/src/core/system.cpp index 1ecd409eb..4936200ee 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -1142,7 +1142,7 @@ bool System::BootSystem(SystemBootParameters parameters) Host::OnSystemStarting(); // Load CD image up and detect region. - Common::Error error; + Error error; std::unique_ptr disc; DiscRegion disc_region = DiscRegion::NonPS1; std::string exe_boot; @@ -1172,7 +1172,7 @@ bool System::BootSystem(SystemBootParameters parameters) if (!disc) { Host::ReportErrorAsync("Error", fmt::format("Failed to load CD image '{}': {}", - Path::GetFileName(parameters.filename), error.GetCodeAndMessage())); + Path::GetFileName(parameters.filename), error.GetDescription())); s_state = State::Shutdown; Host::OnSystemDestroyed(); return false; @@ -1209,9 +1209,9 @@ bool System::BootSystem(SystemBootParameters parameters) // Switch subimage. if (disc && parameters.media_playlist_index != 0 && !disc->SwitchSubImage(parameters.media_playlist_index, &error)) { - Host::ReportFormattedErrorAsync("Error", "Failed to switch to subimage %u in '%s': %s", - parameters.media_playlist_index, parameters.filename.c_str(), - error.GetCodeAndMessage().GetCharArray()); + Host::ReportErrorAsync("Error", + fmt::format("Failed to switch to subimage {] in '{}': {}", parameters.media_playlist_index, + parameters.filename, error.GetDescription())); s_state = State::Shutdown; Host::OnSystemDestroyed(); return false; @@ -2137,7 +2137,7 @@ bool System::DoLoadState(ByteStream* state, bool force_software_renderer, bool u return false; } - Common::Error error; + Error error; std::string media_filename; std::unique_ptr media; if (header.media_filename_length > 0) @@ -2166,7 +2166,7 @@ bool System::DoLoadState(ByteStream* state, bool force_software_renderer, bool u 30.0f, Host::TranslateString("OSDMessage", "Failed to open CD image from save state '%s': %s. Using " "existing image '%s', this may result in instability."), - media_filename.c_str(), error.GetCodeAndMessage().GetCharArray(), old_media->GetFileName().c_str()); + media_filename.c_str(), error.GetDescription().c_str(), old_media->GetFileName().c_str()); media = std::move(old_media); header.media_subimage_index = media->GetCurrentSubImage(); } @@ -2174,7 +2174,7 @@ bool System::DoLoadState(ByteStream* state, bool force_software_renderer, bool u { Host::ReportFormattedErrorAsync( "Error", Host::TranslateString("System", "Failed to open CD image '%s' used by save state: %s."), - media_filename.c_str(), error.GetCodeAndMessage().GetCharArray()); + media_filename.c_str(), error.GetDescription().c_str()); return false; } } @@ -2193,7 +2193,7 @@ bool System::DoLoadState(ByteStream* state, bool force_software_renderer, bool u Host::ReportFormattedErrorAsync( "Error", Host::TranslateString("System", "Failed to switch to subimage %u in CD image '%s' used by save state: %s."), - header.media_subimage_index + 1u, media_filename.c_str(), error.GetCodeAndMessage().GetCharArray()); + header.media_subimage_index + 1u, media_filename.c_str(), error.GetDescription().c_str()); return false; } else @@ -3081,12 +3081,12 @@ std::string System::GetMediaFileName() bool System::InsertMedia(const char* path) { - Common::Error error; + Error error; std::unique_ptr image = CDImage::Open(path, g_settings.cdrom_load_image_patches, &error); if (!image) { Host::AddFormattedOSDMessage(10.0f, Host::TranslateString("OSDMessage", "Failed to open disc image '%s': %s."), - path, error.GetCodeAndMessage().GetCharArray()); + path, error.GetDescription().c_str()); return false; } @@ -3272,12 +3272,12 @@ bool System::SwitchMediaSubImage(u32 index) std::unique_ptr image = CDROM::RemoveMedia(true); Assert(image); - Common::Error error; + Error error; if (!image->SwitchSubImage(index, &error)) { Host::AddFormattedOSDMessage(10.0f, Host::TranslateString("OSDMessage", "Failed to switch to subimage %u in '%s': %s."), - index + 1u, image->GetFileName().c_str(), error.GetCodeAndMessage().GetCharArray()); + index + 1u, image->GetFileName().c_str(), error.GetDescription().c_str()); const DiscRegion region = GetRegionForImage(image.get()); CDROM::InsertMedia(std::move(image), region); diff --git a/src/util/cd_image.cpp b/src/util/cd_image.cpp index b448077bf..81d1821c3 100644 --- a/src/util/cd_image.cpp +++ b/src/util/cd_image.cpp @@ -21,7 +21,7 @@ u32 CDImage::GetBytesPerSector(TrackMode mode) return sizes[static_cast(mode)]; } -std::unique_ptr CDImage::Open(const char* filename, bool allow_patches, Common::Error* error) +std::unique_ptr CDImage::Open(const char* filename, bool allow_patches, Error* error) { const char* extension; @@ -94,10 +94,7 @@ std::unique_ptr CDImage::Open(const char* filename, bool allow_patches, { image = CDImage::OverlayPPFPatch(ppf_filename.c_str(), std::move(image)); if (!image) - { - if (error) - error->SetFormattedMessage("Failed to apply ppf patch from '%s'.", ppf_filename.c_str()); - } + Error::SetString(error, fmt::format("Failed to apply ppf patch from '{}'.", ppf_filename)); } } @@ -343,7 +340,7 @@ u32 CDImage::GetCurrentSubImage() const return 0; } -bool CDImage::SwitchSubImage(u32 index, Common::Error* error) +bool CDImage::SwitchSubImage(u32 index, Error* error) { return false; } diff --git a/src/util/cd_image.h b/src/util/cd_image.h index 05d715ca6..4b7a10beb 100644 --- a/src/util/cd_image.h +++ b/src/util/cd_image.h @@ -11,9 +11,7 @@ #include #include -namespace Common { class Error; -} class CDImage { @@ -220,15 +218,15 @@ public: static bool IsDeviceName(const char* filename); // Opening disc image. - static std::unique_ptr Open(const char* filename, bool allow_patches, Common::Error* error); - static std::unique_ptr OpenBinImage(const char* filename, Common::Error* error); - static std::unique_ptr OpenCueSheetImage(const char* filename, Common::Error* error); - static std::unique_ptr OpenCHDImage(const char* filename, Common::Error* error); - static std::unique_ptr OpenEcmImage(const char* filename, Common::Error* error); - static std::unique_ptr OpenMdsImage(const char* filename, Common::Error* error); - static std::unique_ptr OpenPBPImage(const char* filename, Common::Error* error); - static std::unique_ptr OpenM3uImage(const char* filename, bool apply_patches, Common::Error* error); - static std::unique_ptr OpenDeviceImage(const char* filename, Common::Error* error); + static std::unique_ptr Open(const char* filename, bool allow_patches, Error* error); + static std::unique_ptr OpenBinImage(const char* filename, Error* error); + static std::unique_ptr OpenCueSheetImage(const char* filename, Error* error); + static std::unique_ptr OpenCHDImage(const char* filename, Error* error); + static std::unique_ptr OpenEcmImage(const char* filename, Error* error); + static std::unique_ptr OpenMdsImage(const char* filename, Error* error); + static std::unique_ptr OpenPBPImage(const char* filename, Error* error); + static std::unique_ptr OpenM3uImage(const char* filename, bool apply_patches, Error* error); + static std::unique_ptr OpenDeviceImage(const char* filename, Error* error); static std::unique_ptr CreateMemoryImage(CDImage* image, ProgressCallback* progress = ProgressCallback::NullProgressCallback); static std::unique_ptr OverlayPPFPatch(const char* filename, std::unique_ptr parent_image, @@ -341,7 +339,7 @@ public: virtual u32 GetCurrentSubImage() const; // Changes the current sub-image. If this fails, the image state is unchanged. - virtual bool SwitchSubImage(u32 index, Common::Error* error); + virtual bool SwitchSubImage(u32 index, Error* error); // Retrieve sub-image metadata. virtual std::string GetSubImageMetadata(u32 index, const std::string_view& type) const; diff --git a/src/util/cd_image_bin.cpp b/src/util/cd_image_bin.cpp index 0aab50a78..885f010d3 100644 --- a/src/util/cd_image_bin.cpp +++ b/src/util/cd_image_bin.cpp @@ -15,7 +15,7 @@ public: CDImageBin(); ~CDImageBin() override; - bool Open(const char* filename, Common::Error* error); + bool Open(const char* filename, Error* error); bool ReadSubChannelQ(SubChannelQ* subq, const Index& index, LBA lba_in_index) override; bool HasNonStandardSubchannel() const override; @@ -38,7 +38,7 @@ CDImageBin::~CDImageBin() std::fclose(m_fp); } -bool CDImageBin::Open(const char* filename, Common::Error* error) +bool CDImageBin::Open(const char* filename, Error* error) { m_filename = filename; m_fp = FileSystem::OpenCFile(filename, "rb"); @@ -136,7 +136,7 @@ bool CDImageBin::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_i return true; } -std::unique_ptr CDImage::OpenBinImage(const char* filename, Common::Error* error) +std::unique_ptr CDImage::OpenBinImage(const char* filename, Error* error) { std::unique_ptr image = std::make_unique(); if (!image->Open(filename, error)) diff --git a/src/util/cd_image_chd.cpp b/src/util/cd_image_chd.cpp index 076f59bc2..d4a81b2d3 100644 --- a/src/util/cd_image_chd.cpp +++ b/src/util/cd_image_chd.cpp @@ -59,7 +59,7 @@ public: CDImageCHD(); ~CDImageCHD() override; - bool Open(const char* filename, Common::Error* error); + bool Open(const char* filename, Error* error); bool ReadSubChannelQ(SubChannelQ* subq, const Index& index, LBA lba_in_index) override; bool HasNonStandardSubchannel() const override; @@ -77,7 +77,7 @@ private: MAX_PARENTS = 32 // Surely someone wouldn't be insane enough to go beyond this... }; - chd_file* OpenCHD(const char* filename, FileSystem::ManagedCFilePtr fp, Common::Error* error, u32 recursion_level); + chd_file* OpenCHD(const char* filename, FileSystem::ManagedCFilePtr fp, Error* error, u32 recursion_level); bool ReadHunk(u32 hunk_index); chd_file* m_chd = nullptr; @@ -100,8 +100,7 @@ CDImageCHD::~CDImageCHD() chd_close(m_chd); } -chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr fp, Common::Error* error, - u32 recursion_level) +chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr fp, Error* error, u32 recursion_level) { chd_file* chd; chd_error err = chd_open_file(fp.get(), CHD_OPEN_READ | CHD_OPEN_TRANSFER_FILE, nullptr, &chd); @@ -114,16 +113,14 @@ chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr else if (err != CHDERR_REQUIRES_PARENT) { Log_ErrorPrintf("Failed to open CHD '%s': %s", filename, chd_error_string(err)); - if (error) - error->SetMessage(chd_error_string(err)); + Error::SetString(error, chd_error_string(err)); return nullptr; } if (recursion_level >= MAX_PARENTS) { Log_ErrorPrintf("Failed to open CHD '%s': Too many parent files", filename); - if (error) - error->SetMessage("Too many parent files"); + Error::SetString(error, "Too many parent files"); return nullptr; } @@ -133,8 +130,7 @@ chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr if (err != CHDERR_NONE) { Log_ErrorPrintf("Failed to read CHD header '%s': %s", filename, chd_error_string(err)); - if (error) - error->SetMessage(chd_error_string(err)); + Error::SetString(error, chd_error_string(err)); return nullptr; } @@ -163,15 +159,16 @@ chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr // Match! Open this one. if ((parent_chd = OpenCHD(fd.FileName.c_str(), std::move(parent_fp), error, recursion_level + 1)) != nullptr) { - Log_DevPrintf(fmt::format("Found parent CHD '{}' for '{}'.", Path::GetFileName(fd.FileName), Path::GetFileName(filename)).c_str()); + Log_DevPrintf( + fmt::format("Found parent CHD '{}' for '{}'.", Path::GetFileName(fd.FileName), Path::GetFileName(filename)) + .c_str()); break; } } if (!parent_chd) { Log_ErrorPrintf("Failed to open CHD '%s': Failed to find parent CHD, it must be in the same directory.", filename); - if (error) - error->SetMessage("Failed to find parent CHD, it must be in the same directory."); + Error::SetString(error, "Failed to find parent CHD, it must be in the same directory."); return nullptr; } @@ -180,8 +177,7 @@ chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr if (err != CHDERR_NONE) { Log_ErrorPrintf("Failed to open CHD '%s': %s", filename, chd_error_string(err)); - if (error) - error->SetMessage(chd_error_string(err)); + Error::SetString(error, chd_error_string(err)); return nullptr; } @@ -190,7 +186,7 @@ chd_file* CDImageCHD::OpenCHD(const char* filename, FileSystem::ManagedCFilePtr return chd; } -bool CDImageCHD::Open(const char* filename, Common::Error* error) +bool CDImageCHD::Open(const char* filename, Error* error) { auto fp = FileSystem::OpenManagedSharedCFile(filename, "rb", FileSystem::FileShareMode::DenyWrite); if (!fp) @@ -211,9 +207,8 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error) if ((m_hunk_size % CHD_CD_SECTOR_DATA_SIZE) != 0) { Log_ErrorPrintf("Hunk size (%u) is not a multiple of %u", m_hunk_size, CHD_CD_SECTOR_DATA_SIZE); - if (error) - error->SetFormattedMessage("Hunk size (%u) is not a multiple of %u", m_hunk_size, CHD_CD_SECTOR_DATA_SIZE); - + Error::SetString(error, fmt::format("Hunk size ({}) is not a multiple of {}", m_hunk_size, + static_cast(CHD_CD_SECTOR_DATA_SIZE))); return false; } @@ -244,9 +239,7 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error) &pregap_frames, pgtype_str, pgsub_str, &postgap_frames) != 8) { Log_ErrorPrintf("Invalid track v2 metadata: '%s'", metadata_str); - if (error) - error->SetFormattedMessage("Invalid track v2 metadata: '%s'", metadata_str); - + Error::SetString(error, fmt::format("Invalid track v2 metadata: '{}'", metadata_str)); return false; } } @@ -264,9 +257,7 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error) if (std::sscanf(metadata_str, CDROM_TRACK_METADATA_FORMAT, &track_num, type_str, subtype_str, &frames) != 4) { Log_ErrorPrintf("Invalid track metadata: '%s'", metadata_str); - if (error) - error->SetFormattedMessage("Invalid track v2 metadata: '%s'", metadata_str); - + Error::SetString(error, fmt::format("Invalid track v2 metadata: '{}'", metadata_str)); return false; } } @@ -275,12 +266,8 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error) { Log_ErrorPrintf("Incorrect track number at index %d, expected %d got %d", num_tracks, (num_tracks + 1), track_num); - if (error) - { - error->SetFormattedMessage("Incorrect track number at index %d, expected %d got %d", num_tracks, - (num_tracks + 1), track_num); - } - + Error::SetString(error, fmt::format("Incorrect track number at index {}, expected {} got {}", num_tracks, + (num_tracks + 1), track_num)); return false; } @@ -288,9 +275,7 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error) if (!mode.has_value()) { Log_ErrorPrintf("Invalid track mode: '%s'", type_str); - if (error) - error->SetFormattedMessage("Invalid track mode: '%s'", type_str); - + Error::SetString(error, fmt::format("Invalid track mode: '{}'", type_str)); return false; } @@ -321,9 +306,7 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error) if (pregap_frames > frames) { Log_ErrorPrintf("Pregap length %u exceeds track length %u", pregap_frames, frames); - if (error) - error->SetFormattedMessage("Pregap length %u exceeds track length %u", pregap_frames, frames); - + Error::SetString(error, fmt::format("Pregap length {} exceeds track length {}", pregap_frames, frames)); return false; } @@ -368,9 +351,7 @@ bool CDImageCHD::Open(const char* filename, Common::Error* error) if (m_tracks.empty()) { Log_ErrorPrintf("File '%s' contains no tracks", filename); - if (error) - error->SetFormattedMessage("File '%s' contains no tracks", filename); - + Error::SetString(error, fmt::format("File '{}' contains no tracks", filename)); return false; } @@ -497,7 +478,7 @@ bool CDImageCHD::ReadHunk(u32 hunk_index) return true; } -std::unique_ptr CDImage::OpenCHDImage(const char* filename, Common::Error* error) +std::unique_ptr CDImage::OpenCHDImage(const char* filename, Error* error) { std::unique_ptr image = std::make_unique(); if (!image->Open(filename, error)) diff --git a/src/util/cd_image_cue.cpp b/src/util/cd_image_cue.cpp index 88101da75..a93d8eabc 100644 --- a/src/util/cd_image_cue.cpp +++ b/src/util/cd_image_cue.cpp @@ -3,16 +3,21 @@ #include "cd_image.h" #include "cd_subchannel_replacement.h" +#include "cue_parser.h" + #include "common/assert.h" #include "common/error.h" #include "common/file_system.h" #include "common/log.h" #include "common/path.h" -#include "cue_parser.h" + +#include "fmt/format.h" + #include #include #include #include + Log_SetChannel(CDImageCueSheet); class CDImageCueSheet : public CDImage @@ -21,7 +26,7 @@ public: CDImageCueSheet(); ~CDImageCueSheet() override; - bool OpenAndParse(const char* filename, Common::Error* error); + bool OpenAndParse(const char* filename, Error* error); bool ReadSubChannelQ(SubChannelQ* subq, const Index& index, LBA lba_in_index) override; bool HasNonStandardSubchannel() const override; @@ -48,7 +53,7 @@ CDImageCueSheet::~CDImageCueSheet() std::for_each(m_files.begin(), m_files.end(), [](TrackFile& t) { std::fclose(t.file); }); } -bool CDImageCueSheet::OpenAndParse(const char* filename, Common::Error* error) +bool CDImageCueSheet::OpenAndParse(const char* filename, Error* error) { std::FILE* fp = FileSystem::OpenCFile(filename, "rb"); if (!fp) @@ -94,7 +99,8 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Common::Error* error) { const std::string track_full_filename( !Path::IsAbsolute(track_filename) ? Path::BuildRelativePath(m_filename, track_filename) : track_filename); - std::FILE* track_fp = FileSystem::OpenCFile(track_full_filename.c_str(), "rb"); + Error track_error; + std::FILE* track_fp = FileSystem::OpenCFile(track_full_filename.c_str(), "rb", &track_error); if (!track_fp && track_file_index == 0) { // many users have bad cuesheets, or they're renamed the files without updating the cuesheet. @@ -110,14 +116,11 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Common::Error* error) if (!track_fp) { - Log_ErrorPrintf("Failed to open track filename '%s' (from '%s' and '%s'): errno %d", - track_full_filename.c_str(), track_filename.c_str(), filename, errno); - if (error) - { - error->SetFormattedMessage("Failed to open track filename '%s' (from '%s' and '%s'): errno %d", - track_full_filename.c_str(), track_filename.c_str(), filename, errno); - } - + Log_ErrorPrintf("Failed to open track filename '%s' (from '%s' and '%s'): %s", track_full_filename.c_str(), + track_filename.c_str(), filename, track_error.GetDescription().c_str()); + Error::SetString(error, + fmt::format("Failed to open track filename '{}' (from '{}' and '{}'): {}", track_full_filename, + track_filename, filename, track_error.GetDescription())); return false; } @@ -148,11 +151,8 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Common::Error* error) { Log_ErrorPrintf("Failed to open track %u in '%s': track start is out of range (%u vs %" PRIu64 ")", track_num, filename, track_start, file_size); - if (error) - { - error->SetFormattedMessage("Failed to open track %u in '%s': track start is out of range (%u vs %" PRIu64 ")", - track_num, filename, track_start, file_size); - } + Error::SetString(error, fmt::format("Failed to open track {} in '{}': track start is out of range ({} vs {}))", + track_num, filename, track_start, file_size)); return false; } @@ -283,8 +283,7 @@ bool CDImageCueSheet::OpenAndParse(const char* filename, Common::Error* error) if (m_tracks.empty()) { Log_ErrorPrintf("File '%s' contains no tracks", filename); - if (error) - error->SetFormattedMessage("File '%s' contains no tracks", filename); + Error::SetString(error, fmt::format("File '{}' contains no tracks", filename)); return false; } @@ -333,7 +332,7 @@ bool CDImageCueSheet::ReadSectorFromIndex(void* buffer, const Index& index, LBA return true; } -std::unique_ptr CDImage::OpenCueSheetImage(const char* filename, Common::Error* error) +std::unique_ptr CDImage::OpenCueSheetImage(const char* filename, Error* error) { std::unique_ptr image = std::make_unique(); if (!image->OpenAndParse(filename, error)) diff --git a/src/util/cd_image_device.cpp b/src/util/cd_image_device.cpp index 0044f382f..2b4363d72 100644 --- a/src/util/cd_image_device.cpp +++ b/src/util/cd_image_device.cpp @@ -72,7 +72,7 @@ public: CDImageDeviceWin32(); ~CDImageDeviceWin32() override; - bool Open(const char* filename, Common::Error* error); + bool Open(const char* filename, Error* error); bool ReadSubChannelQ(SubChannelQ* subq, const Index& index, LBA lba_in_index) override; bool HasNonStandardSubchannel() const override; @@ -112,7 +112,7 @@ CDImageDeviceWin32::~CDImageDeviceWin32() CloseHandle(m_hDevice); } -bool CDImageDeviceWin32::Open(const char* filename, Common::Error* error) +bool CDImageDeviceWin32::Open(const char* filename, Error* error) { m_filename = filename; m_hDevice = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, @@ -244,8 +244,7 @@ bool CDImageDeviceWin32::Open(const char* filename, Common::Error* error) if (m_tracks.empty()) { Log_ErrorPrintf("File '%s' contains no tracks", filename); - if (error) - error->SetFormattedMessage("File '%s' contains no tracks", filename); + Error::SetString(error, fmt::format("File '{}' contains no tracks", filename)); return false; } @@ -270,9 +269,7 @@ bool CDImageDeviceWin32::Open(const char* filename, Common::Error* error) if (!DetermineReadMode()) { Log_ErrorPrintf("Could not determine read mode"); - if (error) - error->SetMessage("Could not determine read mode"); - + Error::SetString(error, "Could not determine read mode"); return false; } @@ -476,7 +473,7 @@ bool CDImageDeviceWin32::DetermineReadMode() return false; } -std::unique_ptr CDImage::OpenDeviceImage(const char* filename, Common::Error* error) +std::unique_ptr CDImage::OpenDeviceImage(const char* filename, Error* error) { std::unique_ptr image = std::make_unique(); if (!image->Open(filename, error)) @@ -528,7 +525,7 @@ bool CDImage::IsDeviceName(const char* filename) #else -std::unique_ptr CDImage::OpenDeviceImage(const char* filename, Common::Error* error) +std::unique_ptr CDImage::OpenDeviceImage(const char* filename, Error* error) { return {}; } diff --git a/src/util/cd_image_ecm.cpp b/src/util/cd_image_ecm.cpp index 18eb41f09..0cddd5343 100644 --- a/src/util/cd_image_ecm.cpp +++ b/src/util/cd_image_ecm.cpp @@ -164,7 +164,7 @@ public: CDImageEcm(); ~CDImageEcm() override; - bool Open(const char* filename, Common::Error* error); + bool Open(const char* filename, Error* error); bool ReadSubChannelQ(SubChannelQ* subq, const Index& index, LBA lba_in_index) override; bool HasNonStandardSubchannel() const override; @@ -224,7 +224,7 @@ CDImageEcm::~CDImageEcm() std::fclose(m_fp); } -bool CDImageEcm::Open(const char* filename, Common::Error* error) +bool CDImageEcm::Open(const char* filename, Error* error) { m_filename = filename; m_fp = FileSystem::OpenCFile(filename, "rb"); @@ -253,9 +253,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error) header[3] != 0) { Log_ErrorPrintf("Failed to read/invalid header"); - if (error) - error->SetMessage("Failed to read/invalid header"); - + Error::SetString(error, "Failed to read/invalid header"); return false; } @@ -269,9 +267,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error) if (bits == EOF) { Log_ErrorPrintf("Unexpected EOF after %zu chunks", m_data_map.size()); - if (error) - error->SetFormattedMessage("Unexpected EOF after %zu chunks", m_data_map.size()); - + Error::SetString(error, fmt::format("Unexpected EOF after {} chunks", m_data_map.size())); return false; } @@ -285,9 +281,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error) if (bits == EOF) { Log_ErrorPrintf("Unexpected EOF after %zu chunks", m_data_map.size()); - if (error) - error->SetFormattedMessage("Unexpected EOF after %zu chunks", m_data_map.size()); - + Error::SetString(error, fmt::format("Unexpected EOF after {} chunks", m_data_map.size())); return false; } @@ -305,9 +299,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error) if (count >= 0x80000000u) { Log_ErrorPrintf("Corrupted header after %zu chunks", m_data_map.size()); - if (error) - error->SetFormattedMessage("Corrupted header after %zu chunks", m_data_map.size()); - + Error::SetString(error, fmt::format("Corrupted header after {} chunks", m_data_map.size())); return false; } @@ -324,8 +316,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error) if (static_cast(file_offset) > file_size) { Log_ErrorPrintf("Out of file bounds after %zu chunks", m_data_map.size()); - if (error) - error->SetFormattedMessage("Out of file bounds after %zu chunks", m_data_map.size()); + Error::SetString(error, fmt::format("Out of file bounds after {} chunks", m_data_map.size())); } } } @@ -342,8 +333,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error) if (static_cast(file_offset) > file_size) { Log_ErrorPrintf("Out of file bounds after %zu chunks", m_data_map.size()); - if (error) - error->SetFormattedMessage("Out of file bounds after %zu chunks", m_data_map.size()); + Error::SetString(error, fmt::format("Out of file bounds after {} chunks", m_data_map.size())); } } } @@ -351,9 +341,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error) if (std::fseek(m_fp, file_offset, SEEK_SET) != 0) { Log_ErrorPrintf("Failed to seek to offset %u after %zu chunks", file_offset, m_data_map.size()); - if (error) - error->SetFormattedMessage("Failed to seek to offset %u after %zu chunks", file_offset, m_data_map.size()); - + Error::SetString(error, fmt::format("Failed to seek to offset {} after {} chunks", file_offset, m_data_map.size())); return false; } } @@ -361,9 +349,7 @@ bool CDImageEcm::Open(const char* filename, Common::Error* error) if (m_data_map.empty()) { Log_ErrorPrintf("No data in image '%s'", filename); - if (error) - error->SetFormattedMessage("No data in image '%s'", filename); - + Error::SetString(error, fmt::format("No data in image '{}'", filename)); return false; } @@ -549,7 +535,7 @@ bool CDImageEcm::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_i return true; } -std::unique_ptr CDImage::OpenEcmImage(const char* filename, Common::Error* error) +std::unique_ptr CDImage::OpenEcmImage(const char* filename, Error* error) { std::unique_ptr image = std::make_unique(); if (!image->Open(filename, error)) diff --git a/src/util/cd_image_m3u.cpp b/src/util/cd_image_m3u.cpp index 839f59b59..c843e4786 100644 --- a/src/util/cd_image_m3u.cpp +++ b/src/util/cd_image_m3u.cpp @@ -20,7 +20,7 @@ public: CDImageM3u(); ~CDImageM3u() override; - bool Open(const char* path, bool apply_patches, Common::Error* Error); + bool Open(const char* path, bool apply_patches, Error* Error); bool ReadSubChannelQ(SubChannelQ* subq, const Index& index, LBA lba_in_index) override; bool HasNonStandardSubchannel() const override; @@ -29,7 +29,7 @@ public: u32 GetSubImageCount() const override; u32 GetCurrentSubImage() const override; std::string GetSubImageMetadata(u32 index, const std::string_view& type) const override; - bool SwitchSubImage(u32 index, Common::Error* error) override; + bool SwitchSubImage(u32 index, Error* error) override; protected: bool ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_in_index) override; @@ -52,7 +52,7 @@ CDImageM3u::CDImageM3u() = default; CDImageM3u::~CDImageM3u() = default; -bool CDImageM3u::Open(const char* path, bool apply_patches, Common::Error* error) +bool CDImageM3u::Open(const char* path, bool apply_patches, Error* error) { std::FILE* fp = FileSystem::OpenCFile(path, "rb"); if (!fp) @@ -62,8 +62,7 @@ bool CDImageM3u::Open(const char* path, bool apply_patches, Common::Error* error std::fclose(fp); if (!m3u_file.has_value() || m3u_file->empty()) { - if (error) - error->SetMessage("Failed to read M3u file"); + Error::SetString(error, "Failed to read M3u file"); return false; } @@ -128,7 +127,7 @@ u32 CDImageM3u::GetCurrentSubImage() const return m_current_image_index; } -bool CDImageM3u::SwitchSubImage(u32 index, Common::Error* error) +bool CDImageM3u::SwitchSubImage(u32 index, Error* error) { if (index >= m_entries.size()) return false; @@ -175,7 +174,7 @@ bool CDImageM3u::ReadSubChannelQ(SubChannelQ* subq, const Index& index, LBA lba_ return m_current_image->ReadSubChannelQ(subq, index, lba_in_index); } -std::unique_ptr CDImage::OpenM3uImage(const char* filename, bool apply_patches, Common::Error* error) +std::unique_ptr CDImage::OpenM3uImage(const char* filename, bool apply_patches, Error* error) { std::unique_ptr image = std::make_unique(); if (!image->Open(filename, apply_patches, error)) diff --git a/src/util/cd_image_mds.cpp b/src/util/cd_image_mds.cpp index 539439dda..3cff1b9b1 100644 --- a/src/util/cd_image_mds.cpp +++ b/src/util/cd_image_mds.cpp @@ -39,7 +39,7 @@ public: CDImageMds(); ~CDImageMds() override; - bool OpenAndParse(const char* filename, Common::Error* error); + bool OpenAndParse(const char* filename, Error* error); bool ReadSubChannelQ(SubChannelQ* subq, const Index& index, LBA lba_in_index) override; bool HasNonStandardSubchannel() const override; @@ -61,15 +61,12 @@ CDImageMds::~CDImageMds() std::fclose(m_mdf_file); } -bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error) +bool CDImageMds::OpenAndParse(const char* filename, Error* error) { - std::FILE* mds_fp = FileSystem::OpenCFile(filename, "rb"); + std::FILE* mds_fp = FileSystem::OpenCFile(filename, "rb", error); if (!mds_fp) { Log_ErrorPrintf("Failed to open mds '%s': errno %d", filename, errno); - if (error) - error->SetErrno(errno); - return false; } @@ -78,20 +75,15 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error) if (!mds_data_opt.has_value() || mds_data_opt->size() < 0x54) { Log_ErrorPrintf("Failed to read mds file '%s'", filename); - if (error) - error->SetFormattedMessage("Failed to read mds file '%s'", filename); - + Error::SetString(error, fmt::format("Failed to read mds file '{}'", filename)); return false; } std::string mdf_filename(Path::ReplaceExtension(filename, "mdf")); - m_mdf_file = FileSystem::OpenCFile(mdf_filename.c_str(), "rb"); + m_mdf_file = FileSystem::OpenCFile(mdf_filename.c_str(), "rb", error); if (!m_mdf_file) { Log_ErrorPrintf("Failed to open mdf file '%s': errno %d", mdf_filename.c_str(), errno); - if (error) - error->SetFormattedMessage("Failed to open mdf file '%s': errno %d", mdf_filename.c_str(), errno); - return false; } @@ -100,9 +92,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error) if (std::memcmp(&mds[0], expected_signature, sizeof(expected_signature) - 1) != 0) { Log_ErrorPrintf("Incorrect signature in '%s'", filename); - if (error) - error->SetFormattedMessage("Incorrect signature in '%s'", filename); - + Error::SetString(error, fmt::format("Incorrect signature in '{}'", filename)); return false; } @@ -111,9 +101,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error) if ((session_offset + 24) > mds.size()) { Log_ErrorPrintf("Invalid session offset in '%s'", filename); - if (error) - error->SetFormattedMessage("Invalid session offset in '%s'", filename); - + Error::SetString(error, fmt::format("Invalid session offset in '{}'", filename)); return false; } @@ -124,9 +112,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error) if (track_count > 99 || track_offset >= mds.size()) { Log_ErrorPrintf("Invalid track count/block offset %u/%u in '%s'", track_count, track_offset, filename); - if (error) - error->SetFormattedMessage("Invalid track count/block offset %u/%u in '%s'", track_count, track_offset, filename); - + Error::SetString(error, fmt::format("Invalid track count/block offset {}/{} in '{}'", track_count, track_offset, filename)); return false; } @@ -145,9 +131,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error) if ((track_offset + sizeof(TrackEntry)) > mds.size()) { Log_ErrorPrintf("End of file in '%s' at track %u", filename, track_number); - if (error) - error->SetFormattedMessage("End of file in '%s' at track %u", filename, track_number); - + Error::SetString(error, fmt::format("End of file in '{}' at track {}", filename, track_number)); return false; } @@ -158,9 +142,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error) if (PackedBCDToBinary(track.track_number) != track_number) { Log_ErrorPrintf("Unexpected track number 0x%02X in track %u", track.track_number, track_number); - if (error) - error->SetFormattedMessage("Unexpected track number 0x%02X in track %u", track.track_number, track_number); - + Error::SetString(error, fmt::format("Unexpected track number 0x{:02X} in track {}", track.track_number, track_number)); return false; } @@ -171,9 +153,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error) if ((track.extra_offset + sizeof(u32) + sizeof(u32)) > mds.size()) { Log_ErrorPrintf("Invalid extra offset %u in track %u", track.extra_offset, track_number); - if (error) - error->SetFormattedMessage("Invalid extra offset %u in track %u", track.extra_offset, track_number); - + Error::SetString(error, fmt::format("Invalid extra offset {} in track {}", track.extra_offset, track_number)); return false; } @@ -196,9 +176,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error) if (track_pregap > track_start_lba) { Log_ErrorPrintf("Track pregap %u is too large for start lba %u", track_pregap, track_start_lba); - if (error) - error->SetFormattedMessage("Track pregap %u is too large for start lba %u", track_pregap, track_start_lba); - + Error::SetString(error, fmt::format("Track pregap {} is too large for start lba {}", track_pregap, track_start_lba)); return false; } @@ -247,9 +225,7 @@ bool CDImageMds::OpenAndParse(const char* filename, Common::Error* error) if (m_tracks.empty()) { Log_ErrorPrintf("File '%s' contains no tracks", filename); - if (error) - error->SetFormattedMessage("File '%s' contains no tracks", filename); - + Error::SetString(error, fmt::format("File '{}' contains no tracks", filename)); return false; } @@ -297,7 +273,7 @@ bool CDImageMds::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_i return true; } -std::unique_ptr CDImage::OpenMdsImage(const char* filename, Common::Error* error) +std::unique_ptr CDImage::OpenMdsImage(const char* filename, Error* error) { std::unique_ptr image = std::make_unique(); if (!image->OpenAndParse(filename, error)) diff --git a/src/util/cd_image_pbp.cpp b/src/util/cd_image_pbp.cpp index 5630f9a82..7aa4c7837 100644 --- a/src/util/cd_image_pbp.cpp +++ b/src/util/cd_image_pbp.cpp @@ -27,7 +27,7 @@ public: CDImagePBP() = default; ~CDImagePBP() override; - bool Open(const char* filename, Common::Error* error); + bool Open(const char* filename, Error* error); bool ReadSubChannelQ(SubChannelQ* subq, const Index& index, LBA lba_in_index) override; bool HasNonStandardSubchannel() const override; @@ -35,7 +35,7 @@ public: bool HasSubImages() const override; u32 GetSubImageCount() const override; u32 GetCurrentSubImage() const override; - bool SwitchSubImage(u32 index, Common::Error* error) override; + bool SwitchSubImage(u32 index, Error* error) override; std::string GetMetadata(const std::string_view& type) const override; std::string GetSubImageMetadata(u32 index, const std::string_view& type) const override; @@ -61,12 +61,12 @@ private: bool LoadSFOIndexTable(); bool LoadSFOTable(); - bool IsValidEboot(Common::Error* error); + bool IsValidEboot(Error* error); bool InitDecompressionStream(); bool DecompressBlock(const BlockInfo& block_info); - bool OpenDisc(u32 index, Common::Error* error); + bool OpenDisc(u32 index, Error* error); static const std::string* LookupStringSFOTableEntry(const char* key, const SFOTable& table); @@ -277,7 +277,7 @@ bool CDImagePBP::LoadSFOTable() return true; } -bool CDImagePBP::IsValidEboot(Common::Error* error) +bool CDImagePBP::IsValidEboot(Error* error) { // Check some fields to make sure this is a valid PS1 EBOOT.PBP @@ -288,16 +288,14 @@ bool CDImagePBP::IsValidEboot(Common::Error* error) if (!std::holds_alternative(data_value) || std::get(data_value) != 1) { Log_ErrorPrint("Invalid BOOTABLE value"); - if (error) - error->SetMessage("Invalid BOOTABLE value"); + Error::SetString(error, "Invalid BOOTABLE value"); return false; } } else { Log_ErrorPrint("No BOOTABLE value found"); - if (error) - error->SetMessage("No BOOTABLE value found"); + Error::SetString(error, "No BOOTABLE value found"); return false; } @@ -308,23 +306,21 @@ bool CDImagePBP::IsValidEboot(Common::Error* error) if (!std::holds_alternative(data_value) || std::get(data_value) != "ME") { Log_ErrorPrint("Invalid CATEGORY value"); - if (error) - error->SetMessage("Invalid CATEGORY value"); + Error::SetString(error, "Invalid CATEGORY value"); return false; } } else { Log_ErrorPrint("No CATEGORY value found"); - if (error) - error->SetMessage("No CATEGORY value found"); + Error::SetString(error, "No CATEGORY value found"); return false; } return true; } -bool CDImagePBP::Open(const char* filename, Common::Error* error) +bool CDImagePBP::Open(const char* filename, Error* error) { if (!EndianHelper::HostIsLittleEndian()) { @@ -347,8 +343,7 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error) if (!LoadPBPHeader()) { Log_ErrorPrint("Failed to load PBP header"); - if (error) - error->SetMessage("Failed to load PBP header"); + Error::SetString(error, "Failed to load PBP header"); return false; } @@ -356,8 +351,7 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error) if (!LoadSFOHeader()) { Log_ErrorPrint("Failed to load SFO header"); - if (error) - error->SetMessage("Failed to load SFO header"); + Error::SetString(error, "Failed to load SFO header"); return false; } @@ -365,8 +359,7 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error) if (!LoadSFOIndexTable()) { Log_ErrorPrint("Failed to load SFO index table"); - if (error) - error->SetMessage("Failed to load SFO index table"); + Error::SetString(error, "Failed to load SFO index table"); return false; } @@ -374,8 +367,7 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error) if (!LoadSFOTable()) { Log_ErrorPrint("Failed to load SFO table"); - if (error) - error->SetMessage("Failed to load SFO table"); + Error::SetString(error, "Failed to load SFO table"); return false; } @@ -412,9 +404,7 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error) if (disc_table[0] == 0x44475000) // "\0PGD" { Log_ErrorPrintf("Encrypted PBP images are not supported, skipping %s", m_filename.c_str()); - if (error) - error->SetMessage("Encrypted PBP images are not supported"); - + Error::SetString(error, "Encrypted PBP images are not supported"); return false; } @@ -442,13 +432,12 @@ bool CDImagePBP::Open(const char* filename, Common::Error* error) return OpenDisc(0, error); } -bool CDImagePBP::OpenDisc(u32 index, Common::Error* error) +bool CDImagePBP::OpenDisc(u32 index, Error* error) { if (index >= m_disc_offsets.size()) { Log_ErrorPrintf("File does not contain disc %u", index + 1); - if (error) - error->SetMessage(TinyString::FromFormat("File does not contain disc %u", index + 1)); + Error::SetString(error, fmt::format("File does not contain disc {}", index + 1)); return false; } @@ -484,9 +473,7 @@ bool CDImagePBP::OpenDisc(u32 index, Common::Error* error) if (pgd_magic == 0x44475000) // "\0PGD" { Log_ErrorPrintf("Encrypted PBP images are not supported, skipping %s", m_filename.c_str()); - if (error) - error->SetMessage("Encrypted PBP images are not supported"); - + Error::SetString(error, "Encrypted PBP images are not supported"); return false; } @@ -867,7 +854,7 @@ u32 CDImagePBP::GetCurrentSubImage() const return m_current_disc; } -bool CDImagePBP::SwitchSubImage(u32 index, Common::Error* error) +bool CDImagePBP::SwitchSubImage(u32 index, Error* error) { if (index >= m_disc_offsets.size()) return false; @@ -895,7 +882,7 @@ std::string CDImagePBP::GetSubImageMetadata(u32 index, const std::string_view& t return CDImage::GetSubImageMetadata(index, type); } -std::unique_ptr CDImage::OpenPBPImage(const char* filename, Common::Error* error) +std::unique_ptr CDImage::OpenPBPImage(const char* filename, Error* error) { std::unique_ptr image = std::make_unique(); if (!image->Open(filename, error)) diff --git a/src/util/cue_parser.cpp b/src/util/cue_parser.cpp index 4caf2674c..39a0be6b6 100644 --- a/src/util/cue_parser.cpp +++ b/src/util/cue_parser.cpp @@ -45,7 +45,7 @@ Track* File::GetMutableTrack(u32 n) return nullptr; } -bool File::Parse(std::FILE* fp, Common::Error* error) +bool File::Parse(std::FILE* fp, Error* error) { char line[1024]; u32 line_number = 1; @@ -66,7 +66,7 @@ bool File::Parse(std::FILE* fp, Common::Error* error) return true; } -void File::SetError(u32 line_number, Common::Error* error, const char* format, ...) +void File::SetError(u32 line_number, Error* error, const char* format, ...) { std::va_list ap; SmallString str; @@ -75,9 +75,7 @@ void File::SetError(u32 line_number, Common::Error* error, const char* format, . va_end(ap); Log_ErrorPrintf("Cue parse error at line %u: %s", line_number, str.GetCharArray()); - - if (error) - error->SetFormattedMessage("Cue parse error at line %u: %s", line_number, str.GetCharArray()); + Error::SetString(error, fmt::format("Cue parse error at line {}: {}", line_number, str)); } std::string_view File::GetToken(const char*& line) @@ -166,7 +164,7 @@ std::optional File::GetMSF(const std::string_view& token) return ret; } -bool File::ParseLine(const char* line, u32 line_number, Common::Error* error) +bool File::ParseLine(const char* line, u32 line_number, Error* error) { const std::string_view command(GetToken(line)); if (command.empty()) @@ -210,7 +208,7 @@ bool File::ParseLine(const char* line, u32 line_number, Common::Error* error) return false; } -bool File::HandleFileCommand(const char* line, u32 line_number, Common::Error* error) +bool File::HandleFileCommand(const char* line, u32 line_number, Error* error) { const std::string_view filename(GetToken(line)); const std::string_view mode(GetToken(line)); @@ -232,7 +230,7 @@ bool File::HandleFileCommand(const char* line, u32 line_number, Common::Error* e return true; } -bool File::HandleTrackCommand(const char* line, u32 line_number, Common::Error* error) +bool File::HandleTrackCommand(const char* line, u32 line_number, Error* error) { if (!CompleteLastTrack(line_number, error)) return false; @@ -288,7 +286,7 @@ bool File::HandleTrackCommand(const char* line, u32 line_number, Common::Error* return true; } -bool File::HandleIndexCommand(const char* line, u32 line_number, Common::Error* error) +bool File::HandleIndexCommand(const char* line, u32 line_number, Error* error) { if (!m_current_track.has_value()) { @@ -334,7 +332,7 @@ bool File::HandleIndexCommand(const char* line, u32 line_number, Common::Error* return true; } -bool File::HandlePregapCommand(const char* line, u32 line_number, Common::Error* error) +bool File::HandlePregapCommand(const char* line, u32 line_number, Error* error) { if (!m_current_track.has_value()) { @@ -366,7 +364,7 @@ bool File::HandlePregapCommand(const char* line, u32 line_number, Common::Error* return true; } -bool File::HandleFlagCommand(const char* line, u32 line_number, Common::Error* error) +bool File::HandleFlagCommand(const char* line, u32 line_number, Error* error) { if (!m_current_track.has_value()) { @@ -395,7 +393,7 @@ bool File::HandleFlagCommand(const char* line, u32 line_number, Common::Error* e return true; } -bool File::CompleteLastTrack(u32 line_number, Common::Error* error) +bool File::CompleteLastTrack(u32 line_number, Error* error) { if (!m_current_track.has_value()) return true; @@ -436,7 +434,7 @@ bool File::CompleteLastTrack(u32 line_number, Common::Error* error) return true; } -bool File::SetTrackLengths(u32 line_number, Common::Error* error) +bool File::SetTrackLengths(u32 line_number, Error* error) { for (const Track& track : m_tracks) { diff --git a/src/util/cue_parser.h b/src/util/cue_parser.h index 911ed4be1..050c65ee1 100644 --- a/src/util/cue_parser.h +++ b/src/util/cue_parser.h @@ -60,26 +60,26 @@ public: const Track* GetTrack(u32 n) const; - bool Parse(std::FILE* fp, Common::Error* error); + bool Parse(std::FILE* fp, Error* error); private: Track* GetMutableTrack(u32 n); - void SetError(u32 line_number, Common::Error* error, const char* format, ...); + void SetError(u32 line_number, Error* error, const char* format, ...); static std::string_view GetToken(const char*& line); static std::optional GetMSF(const std::string_view& token); - bool ParseLine(const char* line, u32 line_number, Common::Error* error); + bool ParseLine(const char* line, u32 line_number, Error* error); - bool HandleFileCommand(const char* line, u32 line_number, Common::Error* error); - bool HandleTrackCommand(const char* line, u32 line_number, Common::Error* error); - bool HandleIndexCommand(const char* line, u32 line_number, Common::Error* error); - bool HandlePregapCommand(const char* line, u32 line_number, Common::Error* error); - bool HandleFlagCommand(const char* line, u32 line_number, Common::Error* error); + bool HandleFileCommand(const char* line, u32 line_number, Error* error); + bool HandleTrackCommand(const char* line, u32 line_number, Error* error); + bool HandleIndexCommand(const char* line, u32 line_number, Error* error); + bool HandlePregapCommand(const char* line, u32 line_number, Error* error); + bool HandleFlagCommand(const char* line, u32 line_number, Error* error); - bool CompleteLastTrack(u32 line_number, Common::Error* error); - bool SetTrackLengths(u32 line_number, Common::Error* error); + bool CompleteLastTrack(u32 line_number, Error* error); + bool SetTrackLengths(u32 line_number, Error* error); std::vector m_tracks; std::optional m_current_file;