123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615 |
- #pragma once
- #include <system_error>
- #include <memory>
- #include <map>
- #include <string>
- using namespace std::literals;
- #include "TmplBlockBuffer.tlh"
- #include "TmplBlockBuffer.tli"
- #include "Hash.String.hpp"
- // namespace eError = ECOM::Utility::Error;
- //-----------------------------------------------------------------------------
- // ECOM::Utility::Error::...
- //-----------------------------------------------------------------------------
- namespace ECOM::Utility::Error
- {
- using error_code_type = long;
- // using view_type = eSTR::StringView;
- using view_type = std::string_view;
- using string_type = std::string;
- //---------------------------
- // Base
- //---------------------------
- class Base
- {
- public:
- constexpr Base () = default;
- virtual ~Base () = default;
- public:
- [[nodiscard]] virtual size_t Hash () const = 0;
- [[nodiscard]] virtual view_type Name () const = 0;
- };
- //---------------------------
- // Category
- //---------------------------
- class Category : public ECOM::Utility::Error::Base
- {
- public:
- constexpr Category (error_code_type value) : m_Value { value} {}
- [[nodiscard]] virtual view_type Message () const = 0;
- protected:
- error_code_type m_Value;
- };
- //---------------------------
- // Where
- //---------------------------
- class Where : public ECOM::Utility::Error::Base
- {
- public:
- [[nodiscard]] virtual view_type Detail () const = 0;
- };
- //---------------------------
- // When
- //---------------------------
- class When : public ECOM::Utility::Error::Base
- {
- public:
- [[nodiscard]] virtual view_type Detail () const = 0;
- };
- //---------------------------
- // Domain
- //---------------------------
- class Domain : public ECOM::Utility::Error::Base
- {
- public:
- [[nodiscard]] virtual view_type Detail () const = 0;
- };
- //---------------------------
- // HowTo
- //---------------------------
- class HowTo : public ECOM::Utility::Error::Base
- {
- public:
- [[nodiscard]] virtual view_type Detail () const = 0;
- };
- //---------------------------
- // Reserved
- //---------------------------
- class Reserved : public ECOM::Utility::Error::Base
- {
- public:
- [[nodiscard]] virtual view_type Detail () const = 0;
- };
- }
- //-----------------------------------------------------------------------------
- // Default
- //-----------------------------------------------------------------------------
- namespace ECOM::Utility::Error::Default
- {
- //---------------------------
- // Category
- //---------------------------
- class Category : public ECOM::Utility::Error::Category
- {
- using base = ECOM::Utility::Error::Category;
- static constexpr auto _DefName { "Error.Category.Default"sv };
- static constexpr auto _DefHash = ECOM::Utility::Hash (_DefName);
- public:
- using base::base;
- [[nodiscard]] virtual size_t Hash () const override { return _DefHash; }
- [[nodiscard]] virtual view_type Name () const override { return _DefName; }
- [[nodiscard]] virtual view_type Message () const override { return view_type (); }
- public:
- static bool Is (const ECOM::Utility::Error::Category & with)
- {
- return (with.Hash () == _DefHash);
- }
- };
- //---------------------------
- // Where
- //---------------------------
- class Where : public ECOM::Utility::Error::Where
- {
- using base = ECOM::Utility::Error::Where;
- static constexpr auto _DefName { "Error.Where.Default"sv };
- static constexpr auto _DefHash = ECOM::Utility::Hash (_DefName);
- public:
- constexpr Where (const view_type & value) noexcept : m_Value { value } {}
- [[nodiscard]] virtual size_t Hash () const override { return _DefHash; }
- [[nodiscard]] virtual view_type Name () const override { return _DefName; }
- [[nodiscard]] virtual view_type Detail () const override
- {
- return m_Value;
- }
- constexpr Where (const Where & from) noexcept : m_Value { from.m_Value } {}
- constexpr Where (Where && from) noexcept : m_Value { std::move (from.m_Value) } {}
- public:
- static bool Is (const ECOM::Utility::Error::Where & with)
- {
- return (with.Hash () == _DefHash);
- }
- protected:
- const view_type m_Value;
- };
- //---------------------------
- // Domain
- //---------------------------
- class Domain : public ECOM::Utility::Error::Domain
- {
- using base = ECOM::Utility::Error::Domain;
- static constexpr auto _DefName { "Error.Domain.Default"sv };
- static constexpr auto _DefHash = ECOM::Utility::Hash (_DefName);
- public:
- constexpr Domain (const view_type & value) noexcept : m_Value { value } {}
- [[nodiscard]] virtual size_t Hash () const override { return _DefHash; }
- [[nodiscard]] virtual view_type Name () const override { return _DefName; }
- [[nodiscard]] virtual view_type Detail () const override
- {
- return m_Value;
- }
- constexpr Domain (const Domain & from) noexcept : m_Value { from.m_Value } {}
- constexpr Domain (Domain && from) noexcept : m_Value { std::move (from.m_Value) } {}
- public:
- static bool Is (const ECOM::Utility::Error::Domain & with)
- {
- return (with.Hash () == _DefHash);
- }
- protected:
- const view_type m_Value;
- };
- }
- namespace ECOM::Utility::Error
- {
- //-----------------------------------------------------------------------------
- // ErrorCode
- // m_Category 一定非空, 其他的未必
- //-----------------------------------------------------------------------------
- class ErrorCode
- {
- public:
- ErrorCode () noexcept : m_Value (0), m_Category (std::make_unique <Default::Category> (0)) { }
- ErrorCode (error_code_type _Val) noexcept : m_Value (_Val), m_Category (std::make_unique <Default::Category> (_Val)) { }
- ErrorCode (error_code_type _Val, std::unique_ptr <Category> && _cat) noexcept
- : m_Value (_Val), m_Category (std::move (_cat))
- {
- assert (m_Category);
- }
- ErrorCode (error_code_type _Val, std::unique_ptr <Category> && _cat, std::unique_ptr <Where> && _where) noexcept
- : m_Value (_Val), m_Category (std::move (_cat)), m_Where (std::move (_where))
- {
- assert (m_Category);
- }
- ErrorCode (error_code_type _Val, std::unique_ptr <Category> && _cat, std::unique_ptr <Where> && _where, std::unique_ptr <Domain> && _domain) noexcept
- : m_Value (_Val), m_Category (std::move (_cat)), m_Where (std::move (_where)), m_Domain (std::move (_domain))
- {
- assert (m_Category);
- }
- ~ErrorCode () = default;
- ErrorCode (const ErrorCode & from) = delete;
- ErrorCode (ErrorCode && from) noexcept
- {
- MoveAssign (std::move (from));
- }
- public:
- ErrorCode & operator = (const ErrorCode & from) = delete;
- ErrorCode & operator = (ErrorCode && from) noexcept
- {
- MoveAssign (std::move (from));
- return (*this);
- }
- public:
- [[nodiscard]] error_code_type Value () const { return m_Value; }
- [[nodiscard]] view_type What () const { assert (m_Category); return m_Category->Message (); }
- [[nodiscard]] view_type Where () const { return (m_Where ? m_Where ->Detail () : view_type ()); }
- [[nodiscard]] view_type Domain () const { return (m_Domain ? m_Domain ->Detail () : view_type ()); }
- [[nodiscard]] view_type HowTo () const { return (m_HowTo ? m_HowTo ->Detail () : view_type ()); }
- [[nodiscard]] view_type Reserved () const { return (m_Reserved ? m_Reserved ->Detail () : view_type ()); }
- [[nodiscard]] const class Category * GetCategory () const { assert (m_Category); return m_Category.get (); }
- [[nodiscard]] const class Where * GetWhere () const { return m_Where.get (); }
- [[nodiscard]] const class Domain * GetDomain () const { return m_Domain.get (); }
- [[nodiscard]] const class HowTo * GetHowTo () const { return m_HowTo.get (); }
- [[nodiscard]] const class Reserved * GetReserved () const { return m_Reserved.get (); }
- public:
- [[nodiscard]] const class ErrorCode * Cause () const
- {
- if (m_Root)
- return m_Root.get ();
- else
- return this;
- }
- public:
- [[nodiscard]] string_type ToString () const
- {
- string_type rc;
- rc.reserve (1024);
- rc.append ("Code="sv).append (std::to_string (m_Value))
- .append (", Message=["sv).append (What ()).append ("]"sv)
- .append (", Category=["sv).append (m_Category->Name ()).append ("]"sv);
- if (m_Where) rc.append (", Where=["sv).append (m_Where->Name ()).append (", "sv).append (m_Where->Detail ()).append ("]"sv);
- else rc.append (", Where=[?>"sv);
- if (m_Domain) rc.append (", Domain=["sv).append (m_Domain->Name ()).append (", "sv).append (m_Domain->Detail ()).append ("]"sv);
- else rc.append (", Domain=[?>"sv);
- if (m_HowTo) rc.append (", HowTo=["sv).append (m_HowTo->Name ()).append (", "sv).append (m_HowTo->Detail ()).append ("]"sv);
- else rc.append (", HowTo=[?>"sv);
- if (m_Reserved) rc.append (", Reserved=["sv).append (m_Reserved->Name ()).append (", "sv).append (m_Reserved->Detail ()).append ("]"sv);
- else rc.append (", Reserved=[?>"sv);
- return rc;
- }
- public:
- ErrorCode & Set (std::unique_ptr <class Category > && _val) { m_Category = std::move (_val); assert (m_Category); return *this; }
- ErrorCode & Set (std::unique_ptr <class Where > && _val) { m_Where = std::move (_val); return *this; }
- ErrorCode & Set (std::unique_ptr <class Domain > && _val) { m_Domain = std::move (_val); return *this; }
- ErrorCode & Set (std::unique_ptr <class HowTo > && _val) { m_HowTo = std::move (_val); return *this; }
- ErrorCode & Set (std::unique_ptr <class Reserved > && _val) { m_Reserved = std::move (_val); return *this; }
- void Set (class ErrorCode && _val) { m_Root.reset (new ErrorCode (std::move (_val))); }
- private:
- void MoveAssign (ErrorCode && from)
- {
- this->m_Value = from.m_Value;
- this->m_Category = std::move (from.m_Category);
- this->m_Where = std::move (from.m_Where);
- this->m_Domain = std::move (from.m_Domain);
- this->m_HowTo = std::move (from.m_HowTo);
- this->m_Reserved = std::move (from.m_Reserved);
- this->m_Root = std::move (from.m_Root);
- assert (m_Category);
- }
- private:
- error_code_type m_Value;
- std::unique_ptr <class Category> m_Category;
- std::unique_ptr <class Where > m_Where;
- std::unique_ptr <class Domain> m_Domain;
- std::unique_ptr <class HowTo > m_HowTo;
- std::unique_ptr <class Reserved> m_Reserved;
- std::unique_ptr <class ErrorCode> m_Root;
- };
- }
- //-----------------------------------------------------------------------------
- // 通用错误/组件内部错误, 比如参数错误, 检测到 NULL 参数等
- // 枚举量来自 2019\Community\VC\Tools\MSVC\14.29.30133\include\xerrc.h
- //-----------------------------------------------------------------------------
- namespace ECOM::Utility::Error::Generic
- {
- enum class enError
- {
- enOK = 0,
- enNoError = 0,
- enUnknown = 1 , // 未知错误
- create_file_failed,
- read_file_failed,
- write_file_failed,
- device_or_resource_busy, // EBUSY
- device_or_resource_power_off, //
- device_or_resource_offline, //
- invalid_argument, // EINVAL
- invalid_object, // EINVAL
- io_error, // EIO
- no_buffer_space, // ENOBUFS
- permission_denied, // EACCES
- no_message, // ENOMS
- no_such_device_or_address, // ENXIO
- no_such_device, // ENODEV
- no_such_file_or_directory, // ENOENT
- no_enough_memory, // ENOMEM
- operation_not_permitted, // EPERM
- operation_not_supported, // EOPNOTSUPP
- resource_unavailable_try_again, // EAGAIN
- result_out_of_range, // ERANGE
- timed_out, // ETIMEDOUT
- value_too_large, // EOVERFLOW
- value_too_small, //
- lock_failed, //
- bad_protocol, //
- processing_failure, //
- network_error, //
- database_error, //
- exception, //
- };
- //---------------------------
- // Category
- //---------------------------
- class Category : public ECOM::Utility::Error::Category
- {
- using base = ECOM::Utility::Error::Category;
- static constexpr auto _DefName { "Error.Catelog.Generic"sv };
- static constexpr auto _DefHash = ECOM::Utility::Hash (_DefName);
- public:
- using base::base;
- [[nodiscard]] virtual size_t Hash () const override { return _DefHash; }
- [[nodiscard]] virtual view_type Name () const override { return _DefName; }
- [[nodiscard]] virtual view_type Message () const override
- {
- if (m_Message.empty ())
- const_cast <view_type &> (m_Message) = ToMessage ();
- return m_Message;
- }
- public:
- static bool Is (const ECOM::Utility::Error::Category & with)
- {
- return (with.Hash () == _DefHash);
- }
- protected:
- view_type m_Message;
- protected:
- [[nodiscard]] view_type ToMessage () const
- {
- auto ec = static_cast <enError> (m_Value);
- switch (ec)
- {
- case enError::enUnknown : return "Unknown"sv;
- case enError::create_file_failed : return "Create file failed"sv;
- case enError::read_file_failed : return "Read file failed"sv;
- case enError::write_file_failed : return "Write file failed"sv;
- case enError::device_or_resource_busy : return "Device or resource busy"sv;
- case enError::device_or_resource_power_off : return "Device or resource power off"sv;
- case enError::device_or_resource_offline : return "Device or resource offline"sv;
- case enError::invalid_argument : return "Invalid argument"sv;
- case enError::invalid_object : return "Invalid object"sv;
- case enError::io_error : return "IO error"sv;
- case enError::no_buffer_space : return "No buffer space"sv;
- case enError::permission_denied : return "Permission denied"sv;
- case enError::no_message : return "No message"sv;
- case enError::no_such_device_or_address : return "No such device or address"sv;
- case enError::no_such_device : return "No such device"sv;
- case enError::no_such_file_or_directory : return "No such file or directory"sv;
- case enError::no_enough_memory : return "No enough memory"sv;
- case enError::operation_not_permitted : return "Operation not permitted"sv;
- case enError::operation_not_supported : return "Operation not supported"sv;
- case enError::resource_unavailable_try_again : return "Resource unavailable, try again"sv;
- case enError::result_out_of_range : return "Result out of range"sv;
- case enError::timed_out : return "Time out"sv;
- case enError::value_too_large : return "Value too large"sv;
- case enError::value_too_small : return "Value too small"sv;
- case enError::processing_failure : return "Processing failure"sv;
- case enError::lock_failed : return "Lock failed"sv;
- case enError::bad_protocol : return "Bad protocol"sv;
- case enError::network_error : return "Network error"sv;
- case enError::database_error : return "Database error"sv;
- case enError::exception : return "Exception"sv;
-
- default : return "Undefined generic error"sv;
- }
- }
- };
- //---------------------------
- // ErrorCategory_With
- //---------------------------
- class ErrorCategory_With : public Category
- {
- using base = Category;
-
- static constexpr auto _DefName { "Error.Catelog.Generic.With"sv };
- static constexpr auto _DefHash = ECOM::Utility::Hash (_DefName);
- public:
- ErrorCategory_With (error_code_type ec, view_type msg) : base (ec), m_With { msg }
- {
- }
- [[nodiscard]] virtual size_t Hash () const override { return _DefHash; }
- [[nodiscard]] virtual view_type Name () const override { return _DefName; }
- [[nodiscard]] virtual view_type Message () const override
- {
- if (m_Detail.empty ())
- {
- auto & dt = const_cast <string_type &> (m_Detail);
- dt.append (base::Message ()).append (", with=["sv).append (m_With).append ("]"sv);
- }
- return m_Detail;
- }
- private:
- const string_type m_With;
- const string_type m_Detail;
- };
- inline ErrorCode Make (error_code_type ec)
- {
- return { ec, std::make_unique <Category> (ec) };
- }
- inline ErrorCode Make (enError ec)
- {
- return { static_cast <error_code_type> (ec), std::make_unique <Category> (static_cast <error_code_type> (ec)) };
- }
- }
- //-----------------------------------------------------------------------------
- // Windows API 错误
- //-----------------------------------------------------------------------------
- namespace ECOM::Utility::Error::OS::Windows
- {
- //---------------------------
- // Category
- //---------------------------
- class Category : public ECOM::Utility::Error::Category
- {
- using base = ECOM::Utility::Error::Category;
- static constexpr auto _DefName { "Error.Catelog.OS.Windows"sv };
- static constexpr auto _DefHash = ECOM::Utility::Hash (_DefName);
- public:
- Category (error_code_type ec) : base (ec) {}
- [[nodiscard]] virtual size_t Hash () const override { return _DefHash; }
- [[nodiscard]] virtual view_type Name () const override { return _DefName; }
- [[nodiscard]] virtual view_type Message () const override
- {
- if (m_Message.empty ())
- const_cast <string_type&> (m_Message) = ErrorCodeToString (m_Value);
- return m_Message;
- }
- public:
- static bool Is (const ECOM::Utility::Error::Category & with)
- {
- return (with.Hash () == _DefHash);
- }
- private:
- static std::string ErrorCodeToString (DWORD errorCode)
- {
- constexpr int nPreAlloc = 4096;
- OBlockBuffer OMB;
- auto pc = reinterpret_cast <char *> (OMB.GetBufferSetCount (nPreAlloc + 2));
- if (errorCode == 0) errorCode = GetLastError ();
- auto szmsg = ::FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- errorCode, // GetLastError (),
- MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPSTR)pc,
- nPreAlloc,
- NULL);
- std::string rc (pc, szmsg - 2); // -2 是为了去掉尾部的 \r\n
- return rc;
- }
- private:
- string_type m_Message;
- };
- inline ErrorCode Make (error_code_type ec)
- {
- return { ec, std::make_unique <Category> (ec) };
- }
- }
- //-----------------------------------------------------------------------------
- // ErrorCode
- //-----------------------------------------------------------------------------
- //using eiResult = ECOM::Utility::Either <int, ECOM::Utility::Error::ErrorCode>;
- //constexpr auto eiSuccess = ECOM::Utility::left <int> (1);
|