diff --git a/include/libimp/error.h b/include/libimp/error.h index 741b36a..ab0c60a 100644 --- a/include/libimp/error.h +++ b/include/libimp/error.h @@ -7,14 +7,16 @@ #pragma once #include +#include #include "libimp/def.h" #include "libimp/export.h" -#include "libimp/result.h" #include "libimp/fmt_cpo.h" LIBIMP_NAMESPACE_BEG_ +using error_code_t = std::uint64_t; + /** * \brief Serves as the base class for specific error category types. * \see https://en.cppreference.com/w/cpp/error/error_category @@ -29,7 +31,7 @@ public: /// \brief observer virtual std::string name() const = 0; - virtual std::string message(result_code r) const = 0; + virtual std::string message(error_code_t const &r) const = 0; /// \brief comparison function bool operator==(error_category const &rhs) const noexcept; @@ -46,17 +48,16 @@ LIBIMP_EXPORT error_category const &generic_category() noexcept; * \see https://en.cppreference.com/w/cpp/error/error_code */ class LIBIMP_EXPORT error_code { - result_code r_code_; + error_code_t e_code_; error_category const *ec_; public: /// \brief constructors error_code() noexcept; - error_code(result_code r, error_category const &ec) noexcept; + error_code(error_code_t const &r, error_category const &ec) noexcept; /// \brief observers - result_code code() const noexcept; - result_type value() const noexcept; + error_code_t code() const noexcept; error_category const &category() const noexcept; std::string message() const; explicit operator bool() const noexcept; diff --git a/include/libimp/result.h b/include/libimp/result.h index 9c5f813..f7b37ca 100644 --- a/include/libimp/result.h +++ b/include/libimp/result.h @@ -19,25 +19,26 @@ LIBIMP_NAMESPACE_BEG_ -using result_type = std::tuple; +using result_code_t = std::uint64_t; +using result_type = std::tuple; /** - * \brief Use the least significant (in Little-Endian) of - * a 64-bit unsigned integer to indicate success or failure, - * so the data significant bit cannot exceed 63 bits. + * \class class LIBIMP_EXPORT result_code + * \brief Uses std::uint64_t as the default underlying type of error code. */ class LIBIMP_EXPORT result_code { result_type status_; public: result_code() noexcept; - result_code(result_type value) noexcept; - result_code(bool ok, result_type value) noexcept; + result_code(result_code_t value) noexcept; + result_code(result_type const &value) noexcept; + result_code(bool ok, result_code_t value) noexcept; - result_type value() const noexcept; + result_code_t value() const noexcept; bool ok() const noexcept; - result_type operator*() const noexcept { + result_code_t operator*() const noexcept { return value(); } explicit operator bool() const noexcept { @@ -68,7 +69,7 @@ struct default_traits::value>> { code = {}; } constexpr static void init_code(result_code &code, bool ok, T value) noexcept { - code = {ok, static_cast(value)}; + code = {ok, static_cast(value)}; } constexpr static void init_code(result_code &code, T value) noexcept { init_code(code, true, value); @@ -94,12 +95,12 @@ template struct default_traits::value>> { /// \brief Custom initialization. constexpr static void init_code(result_code &code, T value = default_value()) noexcept { - code = {default_value() != value, reinterpret_cast(value)}; + code = {default_value() != value, reinterpret_cast(value)}; } constexpr static void init_code(result_code &code, std::nullptr_t) noexcept { code = {false, {}}; } - constexpr static void init_code(result_code &code, std::nullptr_t, result_type r) noexcept { + constexpr static void init_code(result_code &code, std::nullptr_t, result_code_t r) noexcept { code = {false, r}; } @@ -124,6 +125,10 @@ struct default_traits::value>> { } // namespace detail_result +/** + * \class class result + * \brief The generic wrapper for the result_code. + */ template class result : public TypeTraits { @@ -144,7 +149,7 @@ public: bool ok() const noexcept { return code_.ok(); } T value() const noexcept { return type_traits_t::cast_from_code(code_); } - result_type code_value() const noexcept { return code_.value(); } + result_code_t code_value() const noexcept { return code_.value(); } T operator*() const noexcept { return value(); diff --git a/include/libimp/system.h b/include/libimp/system.h index f5967bb..aed8d7c 100644 --- a/include/libimp/system.h +++ b/include/libimp/system.h @@ -13,6 +13,7 @@ #include "libimp/def.h" #include "libimp/export.h" #include "libimp/error.h" +#include "libimp/result.h" LIBIMP_NAMESPACE_BEG_ namespace sys { @@ -20,13 +21,13 @@ namespace sys { /** * \brief Get/Set the system error number */ -LIBIMP_EXPORT result_code error_no() noexcept; -LIBIMP_EXPORT void error_no(result_code) noexcept; +LIBIMP_EXPORT error_code_t error_no() noexcept; +LIBIMP_EXPORT void error_no(error_code_t const &) noexcept; /** * \brief Gets a text description of the system error */ -LIBIMP_EXPORT std::string error_str(result_code) noexcept; +LIBIMP_EXPORT std::string error_str(error_code_t const &) noexcept; /** * \brief Identifies the operating system error category. diff --git a/src/libimp/error.cpp b/src/libimp/error.cpp index 7c4cafd..12de0f4 100644 --- a/src/libimp/error.cpp +++ b/src/libimp/error.cpp @@ -16,8 +16,8 @@ public: std::string name() const { return "generic"; } - std::string message(result_code r) const { - return fmt(r.value(), (!r ? ", \"success\"" : ", \"failure\"")); + std::string message(error_code_t const &r) const { + return fmt(r, ((r == 0) ? ", \"success\"" : ", \"failure\"")); } }; @@ -29,17 +29,13 @@ error_category const &generic_category() noexcept { } error_code::error_code() noexcept - : r_code_{}, ec_{&generic_category()} {} + : error_code{0, generic_category()} {} -error_code::error_code(result_code r, error_category const &ec) noexcept - : r_code_{r}, ec_{&ec} {} +error_code::error_code(error_code_t const &r, error_category const &ec) noexcept + : e_code_{r}, ec_{&ec} {} -result_code error_code::code() const noexcept { - return r_code_; -} - -result_type error_code::value() const noexcept { - return r_code_.value(); +error_code_t error_code::code() const noexcept { + return e_code_; } error_category const &error_code::category() const noexcept { @@ -47,15 +43,15 @@ error_category const &error_code::category() const noexcept { } std::string error_code::message() const { - return fmt("[", ec_->name(), ": ", ec_->message(r_code_), "]"); + return fmt("[", ec_->name(), ": ", ec_->message(e_code_), "]"); } error_code::operator bool() const noexcept { - return !!r_code_; + return e_code_ != 0; } bool operator==(error_code const &lhs, error_code const &rhs) noexcept { - return (lhs.r_code_ == rhs.r_code_) && (*lhs.ec_ == *rhs.ec_); + return (lhs.e_code_ == rhs.e_code_) && (*lhs.ec_ == *rhs.ec_); } bool operator!=(error_code const &lhs, error_code const &rhs) noexcept { diff --git a/src/libimp/platform/posix/system.h b/src/libimp/platform/posix/system.h index c8dc591..483d119 100644 --- a/src/libimp/platform/posix/system.h +++ b/src/libimp/platform/posix/system.h @@ -32,7 +32,7 @@ result_code error_no() noexcept { * \brief Set the system error number * https://man7.org/linux/man-pages/man3/errno.3.html */ -void error_no(result_code code) noexcept { +void error_no(result_code const &code) noexcept { errno = code ? ENOERR : (int)code.value(); } @@ -41,7 +41,7 @@ void error_no(result_code code) noexcept { * https://man7.org/linux/man-pages/man3/strerror_l.3.html * https://manpages.ubuntu.com/manpages/xenial/en/man3/strerror.3.html */ -std::string error_str(result_code code) noexcept { +std::string error_str(result_code const &code) noexcept { char msg_buf[256] {}; #if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) LIBIMP_LOG_(); diff --git a/src/libimp/platform/win/system.h b/src/libimp/platform/win/system.h index 4a831ad..9cfe4ab 100644 --- a/src/libimp/platform/win/system.h +++ b/src/libimp/platform/win/system.h @@ -24,20 +24,20 @@ namespace sys { * \brief Get the system error number * https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror */ -result_code error_no() noexcept { +error_code_t error_no() noexcept { auto err = ::GetLastError(); if (err == ERROR_SUCCESS) { return {ERROR_SUCCESS}; } - return {false, std::uint64_t(err)}; + return error_code_t(err); } /** * \brief Set the system error number * https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-setlasterror */ -void error_no(result_code code) noexcept { - DWORD err = code ? ERROR_SUCCESS : (DWORD)code.value(); +void error_no(error_code_t const &code) noexcept { + DWORD err = (code == 0) ? ERROR_SUCCESS : (DWORD)code; ::SetLastError(err); } @@ -45,10 +45,10 @@ void error_no(result_code code) noexcept { * \brief Gets a text description of the system error * https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-formatmessage */ -std::string error_str(result_code code) noexcept { +std::string error_str(error_code_t const &code) noexcept { LIBIMP_LOG_(); LIBIMP_TRY { - DWORD err = (DWORD)code.value(); + DWORD err = (DWORD)code; LPTSTR lpErrText = NULL; if (::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | diff --git a/src/libimp/result.cpp b/src/libimp/result.cpp index 4036fe8..55a9941 100644 --- a/src/libimp/result.cpp +++ b/src/libimp/result.cpp @@ -3,38 +3,26 @@ #include "libimp/horrible_cast.h" LIBIMP_NAMESPACE_BEG_ -namespace { - -struct result_code_info { - std::uint64_t ok : 1; - std::uint64_t code: 63; -}; - -std::uint64_t make_status(bool ok, std::uint64_t code) noexcept { - return horrible_cast(result_code_info{(ok ? 1ull : 0ull), code}); -} - -result_code_info info_cast(std::uint64_t status) noexcept { - return horrible_cast(status); -} - -} // namespace result_code::result_code() noexcept : result_code(false, {}) {} -result_code::result_code(std::uint64_t value) noexcept +result_code::result_code(result_code_t value) noexcept : result_code(true, value) {} -result_code::result_code(bool ok, std::uint64_t code) noexcept - : status_(make_status(ok, code)) {} +result_code::result_code(result_type const &value) noexcept + : result_code(std::get(value), + std::get(value)) {} -std::uint64_t result_code::value() const noexcept { - return info_cast(status_).code; +result_code::result_code(bool ok, std::uint64_t code) noexcept + : status_(code, ok) {} + +result_code_t result_code::value() const noexcept { + return std::get(status_); } bool result_code::ok() const noexcept { - return info_cast(status_).ok != 0; + return std::get(status_); } bool operator==(result_code const &lhs, result_code const &rhs) noexcept { diff --git a/src/libimp/system.cpp b/src/libimp/system.cpp index d71167b..2ec307a 100644 --- a/src/libimp/system.cpp +++ b/src/libimp/system.cpp @@ -15,8 +15,8 @@ public: std::string name() const { return "system"; } - std::string message(::LIBIMP::result_code r) const { - return ::LIBIMP::fmt(r.value(), ::LIBIMP::sys::error_str(r)); + std::string message(::LIBIMP::error_code_t const &r) const { + return ::LIBIMP::fmt(r, ::LIBIMP::sys::error_str(r)); } }; diff --git a/src/libipc/platform/win/mmap_impl.h b/src/libipc/platform/win/mmap_impl.h index e77e06c..6466b41 100644 --- a/src/libipc/platform/win/mmap_impl.h +++ b/src/libipc/platform/win/mmap_impl.h @@ -78,7 +78,7 @@ result mmap_open(std::string const &file, std::size_t size, mode::type t if (h == NULL) { auto err = sys::error(); log.error("failed: OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, ", file, "). error = ", err); - return {nullptr, err.value()}; + return {nullptr, err.code()}; } return h; }; @@ -91,7 +91,7 @@ result mmap_open(std::string const &file, std::size_t size, mode::type t if (h == NULL) { auto err = sys::error(); log.error("failed: CreateFileMapping(PAGE_READWRITE | SEC_COMMIT, ", size, ", ", file, "). error = ", err); - return {nullptr, err.value()}; + return {nullptr, err.code()}; } return h; }; @@ -133,7 +133,7 @@ result mmap_memof(HANDLE h) { if (mem == NULL) { auto err = sys::error(); log.error("failed: MapViewOfFile(", h, ", FILE_MAP_ALL_ACCESS). error = ", err); - return {nullptr, err.value()}; + return {nullptr, err.code()}; } return mem; } @@ -152,7 +152,7 @@ result mmap_sizeof(LPCVOID mem) { if (::VirtualQuery(mem, &mem_info, sizeof(mem_info)) == 0) { auto err = sys::error(); log.error("failed: VirtualQuery(", mem, "). error = ", err); - return {false, (SIZE_T)err.value()}; + return {false, (SIZE_T)err.code()}; } return mem_info.RegionSize; } diff --git a/src/libipc/platform/win/shm_impl.h b/src/libipc/platform/win/shm_impl.h index 5291fe5..9ff5dea 100644 --- a/src/libipc/platform/win/shm_impl.h +++ b/src/libipc/platform/win/shm_impl.h @@ -34,7 +34,7 @@ result shm_open(std::string name, std::size_t size, mode::type type) noex if (!sz) { log.error("failed: mmap_sizeof(", *mem, ")."); mmap_close(*h); - return {nullptr, static_cast(sz.value())}; + return {nullptr, static_cast(sz.value())}; } return new shm_handle{std::move(name), *sz, *mem, *h}; } diff --git a/test/imp/test_imp_error.cpp b/test/imp/test_imp_error.cpp index d985a3b..9534743 100644 --- a/test/imp/test_imp_error.cpp +++ b/test/imp/test_imp_error.cpp @@ -13,8 +13,8 @@ public: std::string name() const { return "custom"; } - std::string message(imp::result_code r) const { - return !r ? "success" : "failure"; + std::string message(imp::error_code_t const &r) const { + return (r == 0) ? "success" : "failure"; } }; diff --git a/test/imp/test_imp_result.cpp b/test/imp/test_imp_result.cpp index c6b6177..757038e 100644 --- a/test/imp/test_imp_result.cpp +++ b/test/imp/test_imp_result.cpp @@ -90,4 +90,8 @@ TEST(result, fmt) { imp::result r5; EXPECT_EQ(imp::fmt(r5), "[fail, value = null, code = 0]"); } + { + imp::result r1 {-123}; + EXPECT_EQ(imp::fmt(r1), imp::fmt("[succ, value = ", -123, "]")); + } } \ No newline at end of file diff --git a/test/imp/test_imp_system.cpp b/test/imp/test_imp_system.cpp index d543596..e49f1f9 100644 --- a/test/imp/test_imp_system.cpp +++ b/test/imp/test_imp_system.cpp @@ -15,13 +15,13 @@ #endif TEST(system, error_no) { - imp::sys::error_no({false, 111}); + imp::sys::error_no(111); auto err = imp::sys::error_no(); - EXPECT_FALSE(err); - EXPECT_EQ(err.value(), 111); + EXPECT_FALSE(err == 0); + EXPECT_EQ(err, 111); imp::sys::error_no({}); - EXPECT_TRUE(imp::sys::error_no()); + EXPECT_TRUE(imp::sys::error_no() == 0); auto e_msg = imp::sys::error_str(imp::sys::error_no()); std::cout << e_msg << "\n"; @@ -51,7 +51,7 @@ TEST(system, error_str) { { std::string s_txt; imp::cvt_sstr(u16_err, s_txt); - EXPECT_EQ(imp::sys::error_str({false, ERROR_INVALID_HANDLE}), s_txt); + EXPECT_EQ(imp::sys::error_str(ERROR_INVALID_HANDLE), s_txt); } #else EXPECT_EQ(imp::sys::error_str({false, 1234}), "Unknown error 1234");