upd: [imp] rearrange the relationship between result and error_code

This commit is contained in:
mutouyun 2022-12-24 21:20:18 +08:00
parent 424bb73c94
commit e7262af0db
13 changed files with 74 additions and 79 deletions

View File

@ -7,14 +7,16 @@
#pragma once
#include <string>
#include <cstdint>
#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;

View File

@ -19,25 +19,26 @@
LIBIMP_NAMESPACE_BEG_
using result_type = std::tuple<std::uint64_t, bool>;
using result_code_t = std::uint64_t;
using result_type = std::tuple<result_code_t, bool>;
/**
* \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<T, std::enable_if_t<std::is_integral<T>::value>> {
code = {};
}
constexpr static void init_code(result_code &code, bool ok, T value) noexcept {
code = {ok, static_cast<result_type>(value)};
code = {ok, static_cast<result_code_t>(value)};
}
constexpr static void init_code(result_code &code, T value) noexcept {
init_code(code, true, value);
@ -94,12 +95,12 @@ template <typename T>
struct default_traits<T, std::enable_if_t<std::is_pointer<T>::value>> {
/// \brief Custom initialization.
constexpr static void init_code(result_code &code, T value = default_value()) noexcept {
code = {default_value() != value, reinterpret_cast<result_type>(value)};
code = {default_value() != value, reinterpret_cast<result_code_t>(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<T, std::enable_if_t<std::is_pointer<T>::value>> {
} // namespace detail_result
/**
* \class class result
* \brief The generic wrapper for the result_code.
*/
template <typename T, typename TypeTraits>
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();

View File

@ -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.

View File

@ -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 {

View File

@ -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_();

View File

@ -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 |

View File

@ -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<std::uint64_t>(result_code_info{(ok ? 1ull : 0ull), code});
}
result_code_info info_cast(std::uint64_t status) noexcept {
return horrible_cast<result_code_info>(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<bool>(value),
std::get<result_code_t>(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<result_code_t>(status_);
}
bool result_code::ok() const noexcept {
return info_cast(status_).ok != 0;
return std::get<bool>(status_);
}
bool operator==(result_code const &lhs, result_code const &rhs) noexcept {

View File

@ -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));
}
};

View File

@ -78,7 +78,7 @@ result<HANDLE> 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<HANDLE> 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<LPVOID> 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<SIZE_T> 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;
}

View File

@ -34,7 +34,7 @@ result<shm_t> 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<result_type>(sz.value())};
return {nullptr, static_cast<result_code_t>(sz.value())};
}
return new shm_handle{std::move(name), *sz, *mem, *h};
}

View File

@ -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";
}
};

View File

@ -90,4 +90,8 @@ TEST(result, fmt) {
imp::result<int *> r5;
EXPECT_EQ(imp::fmt(r5), "[fail, value = null, code = 0]");
}
{
imp::result<std::int64_t> r1 {-123};
EXPECT_EQ(imp::fmt(r1), imp::fmt("[succ, value = ", -123, "]"));
}
}

View File

@ -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");