mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-07 01:06:45 +08:00
upd: [imp] rearrange the relationship between result and error_code
This commit is contained in:
parent
424bb73c94
commit
e7262af0db
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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_();
|
||||
|
||||
@ -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 |
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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};
|
||||
}
|
||||
|
||||
@ -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";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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, "]"));
|
||||
}
|
||||
}
|
||||
@ -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");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user