// Copyright Epic Games, Inc. All Rights Reserved. #include #include namespace zen { #if ZEN_PLATFORM_WINDOWS class WindowsException : public std::exception { public: WindowsException(std::string_view Message) { m_hResult = HRESULT_FROM_WIN32(GetLastError()); m_Message = Message; } WindowsException(HRESULT hRes, std::string_view Message) { m_hResult = hRes; m_Message = Message; } WindowsException(HRESULT hRes, const char* Message, const char* Detail) { m_hResult = hRes; ExtendableStringBuilder<128> msg; msg.Append(Message); msg.Append(" (detail: '"); msg.Append(Detail); msg.Append("')"); m_Message = msg.c_str(); } virtual const char* what() const override { return m_Message.c_str(); } private: std::string m_Message; HRESULT m_hResult; }; void ThrowSystemException([[maybe_unused]] HRESULT hRes, [[maybe_unused]] std::string_view Message) { if (HRESULT_FACILITY(hRes) == FACILITY_WIN32) { throw std::system_error(std::error_code(HRESULT_CODE(hRes), std::system_category()), std::string(Message)); } else { throw WindowsException(hRes, Message); } } #endif // ZEN_PLATFORM_WINDOWS void ThrowSystemError(uint32_t ErrorCode, std::string_view Message) { throw std::system_error(std::error_code(ErrorCode, std::system_category()), std::string(Message)); } std::string GetLastErrorAsString() { return GetSystemErrorAsString(zen::GetLastError()); } std::string GetSystemErrorAsString(uint32_t ErrorCode) { return std::error_code(ErrorCode, std::system_category()).message(); } #if defined(__cpp_lib_source_location) void ThrowLastErrorImpl(std::string_view Message, const std::source_location& Location) { throw std::system_error(std::error_code(zen::GetLastError(), std::system_category()), fmt::format("{}({}): {}", Location.file_name(), Location.line(), Message)); } #else void ThrowLastError(std::string_view Message) { throw std::system_error(std::error_code(zen::GetLastError(), std::system_category()), std::string(Message)); } #endif #if ZEN_PLATFORM_WINDOWS static const std::error_code OutOfMemoryErrorCode(ERROR_NOT_ENOUGH_MEMORY, std::system_category()); #else static const std::error_code OutOfMemoryErrorCode(ENOMEM, std::system_category()); #endif #if defined(__cpp_lib_source_location) void ThrowOutOfMemoryImpl(std::string_view Message, const std::source_location& Location) { throw std::system_error(OutOfMemoryErrorCode, fmt::format("{}({}): {}", Location.file_name(), Location.line(), Message)); } #else void ThrowOutOfMemory(std::string_view Message) { throw std::system_error(OutOfMemoryErrorCode, std::string(Message)); } #endif #if ZEN_PLATFORM_WINDOWS bool IsOOM(const std::system_error& SystemError) { switch (SystemError.code().value()) { case ERROR_NOT_ENOUGH_MEMORY: case ERROR_OUTOFMEMORY: case ERROR_PAGEFILE_QUOTA_EXCEEDED: case ERROR_NO_SYSTEM_RESOURCES: case ERROR_NONPAGED_SYSTEM_RESOURCES: case ERROR_PAGED_SYSTEM_RESOURCES: case ERROR_WORKING_SET_QUOTA: case ERROR_PAGEFILE_QUOTA: case ERROR_COMMITMENT_LIMIT: return true; default: return false; } } bool IsOOD(const std::system_error& SystemError) { switch (SystemError.code().value()) { case ERROR_HANDLE_DISK_FULL: case ERROR_DISK_FULL: case ERROR_DISK_RESOURCES_EXHAUSTED: case ERROR_DISK_QUOTA_EXCEEDED: return true; default: return false; } } #else bool IsOOM(const std::system_error& SystemError) { switch (SystemError.code().value()) { case ENOMEM: return true; default: return false; } } bool IsOOD(const std::system_error& SystemError) { switch (SystemError.code().value()) { case ENOSPC: case EDQUOT: return true; default: return false; } } #endif } // namespace zen