mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
Remove the custom error_code.
This commit is contained in:
parent
6020739552
commit
3d4e92a9c5
@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <system_error>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
@ -15,68 +16,13 @@
|
|||||||
|
|
||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
using error_code_t = std::uint64_t;
|
|
||||||
constexpr error_code_t error_number_limit = error_code_t(-1);
|
|
||||||
constexpr error_code_t no_error = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Serves as the base class for specific error category types.
|
* \brief Custom defined fmt_to method for imp::fmt
|
||||||
* \see https://en.cppreference.com/w/cpp/error/error_category
|
|
||||||
*/
|
|
||||||
class LIBIMP_EXPORT error_category {
|
|
||||||
public:
|
|
||||||
error_category(error_category const &) = delete;
|
|
||||||
error_category &operator=(error_category const &) = delete;
|
|
||||||
|
|
||||||
constexpr error_category() noexcept = default;
|
|
||||||
virtual ~error_category() noexcept = default;
|
|
||||||
|
|
||||||
/// \brief observer
|
|
||||||
virtual std::string name() const = 0;
|
|
||||||
virtual std::string message(error_code_t const &r) const = 0;
|
|
||||||
|
|
||||||
/// \brief comparison function
|
|
||||||
bool operator==(error_category const &rhs) const noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Identifies the generic error category.
|
|
||||||
* \see https://en.cppreference.com/w/cpp/error/generic_category
|
|
||||||
*/
|
|
||||||
LIBIMP_EXPORT error_category const &generic_category() noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief The error code object.
|
|
||||||
* \see https://en.cppreference.com/w/cpp/error/error_code
|
|
||||||
*/
|
|
||||||
class LIBIMP_EXPORT error_code {
|
|
||||||
error_code_t e_code_;
|
|
||||||
error_category const *ec_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// \brief constructors
|
|
||||||
error_code() noexcept;
|
|
||||||
error_code(error_code_t const &r) noexcept;
|
|
||||||
error_code(error_code_t const &r, error_category const &ec) noexcept;
|
|
||||||
|
|
||||||
/// \brief observers
|
|
||||||
error_code_t code() const noexcept;
|
|
||||||
error_category const &category() const noexcept;
|
|
||||||
std::string message() const;
|
|
||||||
explicit operator bool() const noexcept;
|
|
||||||
|
|
||||||
/// \brief comparison functions
|
|
||||||
friend LIBIMP_EXPORT bool operator==(error_code const &lhs, error_code const &rhs) noexcept;
|
|
||||||
friend LIBIMP_EXPORT bool operator!=(error_code const &lhs, error_code const &rhs) noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief @brief Custom defined fmt_to method for imp::fmt
|
|
||||||
*/
|
*/
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
inline bool tag_invoke(decltype(::LIBIMP::fmt_to), fmt_context &ctx, error_code r) noexcept {
|
inline bool tag_invoke(decltype(::LIBIMP::fmt_to), fmt_context &ctx, std::error_code const &ec) noexcept {
|
||||||
return fmt_to(ctx, r.message());
|
return fmt_to(ctx, '[', ec.value(), ": ", ec.message(), ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
@ -38,19 +38,19 @@ namespace detail_result {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct generic_traits {
|
struct generic_traits {
|
||||||
/// \typedef Combine data and valid identifiers with a tuple.
|
/// \typedef Combine data and valid identifiers with a tuple.
|
||||||
using storage_t = std::tuple<T, error_code>;
|
using storage_t = std::tuple<T, std::error_code>;
|
||||||
|
|
||||||
/// \brief Custom initialization.
|
/// \brief Custom initialization.
|
||||||
constexpr static void init_code(storage_t &code) noexcept {
|
constexpr static void init_code(storage_t &code) noexcept {
|
||||||
code = {0, error_number_limit/*make a default error code*/};
|
code = {0, std::make_error_code(std::errc::invalid_argument)};
|
||||||
}
|
}
|
||||||
constexpr static void init_code(storage_t &code, T value, error_code const &ec) noexcept {
|
constexpr static void init_code(storage_t &code, T value, std::error_code const &ec) noexcept {
|
||||||
code = {value, ec};
|
code = {value, ec};
|
||||||
}
|
}
|
||||||
constexpr static void init_code(storage_t &code, T value) noexcept {
|
constexpr static void init_code(storage_t &code, T value) noexcept {
|
||||||
code = {value, {}};
|
code = {value, {}};
|
||||||
}
|
}
|
||||||
constexpr static void init_code(storage_t &code, error_code const &ec) noexcept {
|
constexpr static void init_code(storage_t &code, std::error_code const &ec) noexcept {
|
||||||
code = {{}, ec};
|
code = {{}, ec};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ struct generic_traits {
|
|||||||
constexpr static bool get_ok(storage_t const &code) noexcept {
|
constexpr static bool get_ok(storage_t const &code) noexcept {
|
||||||
return !std::get<1>(code);
|
return !std::get<1>(code);
|
||||||
}
|
}
|
||||||
constexpr static error_code get_error(storage_t const &code) noexcept {
|
constexpr static std::error_code get_error(storage_t const &code) noexcept {
|
||||||
return std::get<1>(code);
|
return std::get<1>(code);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -69,13 +69,13 @@ struct generic_traits {
|
|||||||
template <typename ___>
|
template <typename ___>
|
||||||
struct default_traits<void, ___> {
|
struct default_traits<void, ___> {
|
||||||
/// \typedef Use the `error_code` as the storage type.
|
/// \typedef Use the `error_code` as the storage type.
|
||||||
using storage_t = error_code;
|
using storage_t = std::error_code;
|
||||||
|
|
||||||
/// \brief Custom initialization.
|
/// \brief Custom initialization.
|
||||||
constexpr static void init_code(storage_t &code) noexcept {
|
constexpr static void init_code(storage_t &code) noexcept {
|
||||||
code = error_number_limit/*make a default error code*/;
|
code = std::make_error_code(std::errc::invalid_argument);
|
||||||
}
|
}
|
||||||
constexpr static void init_code(storage_t &code, error_code const &ec) noexcept {
|
constexpr static void init_code(storage_t &code, std::error_code const &ec) noexcept {
|
||||||
code = ec;
|
code = ec;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ struct default_traits<void, ___> {
|
|||||||
constexpr static bool get_ok(storage_t const &code) noexcept {
|
constexpr static bool get_ok(storage_t const &code) noexcept {
|
||||||
return !code;
|
return !code;
|
||||||
}
|
}
|
||||||
constexpr static error_code get_error(storage_t const &code) noexcept {
|
constexpr static std::error_code get_error(storage_t const &code) noexcept {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,8 +96,7 @@ struct default_traits<T, std::enable_if_t<std::is_integral<T>::value>> : generic
|
|||||||
/// \brief Custom initialization.
|
/// \brief Custom initialization.
|
||||||
constexpr static void init_code(typename generic_traits<T>::storage_t &code,
|
constexpr static void init_code(typename generic_traits<T>::storage_t &code,
|
||||||
T value, bool ok) noexcept {
|
T value, bool ok) noexcept {
|
||||||
code = {value, static_cast<error_code_t>(ok ? 0 :
|
code = {value, ok ? std::error_code() : std::make_error_code(std::errc::invalid_argument)};
|
||||||
((value == 0) ? error_number_limit : value))};
|
|
||||||
}
|
}
|
||||||
using generic_traits<T>::init_code;
|
using generic_traits<T>::init_code;
|
||||||
|
|
||||||
@ -109,12 +108,12 @@ template <typename T>
|
|||||||
struct default_traits<T, std::enable_if_t<std::is_pointer<T>::value>> : generic_traits<T> {
|
struct default_traits<T, std::enable_if_t<std::is_pointer<T>::value>> : generic_traits<T> {
|
||||||
/// \brief Custom initialization.
|
/// \brief Custom initialization.
|
||||||
constexpr static void init_code(typename generic_traits<T>::storage_t &code,
|
constexpr static void init_code(typename generic_traits<T>::storage_t &code,
|
||||||
std::nullptr_t, error_code const &ec) noexcept {
|
std::nullptr_t, std::error_code const &ec) noexcept {
|
||||||
code = {nullptr, ec};
|
code = {nullptr, ec};
|
||||||
}
|
}
|
||||||
constexpr static void init_code(typename generic_traits<T>::storage_t &code,
|
constexpr static void init_code(typename generic_traits<T>::storage_t &code,
|
||||||
std::nullptr_t) noexcept {
|
std::nullptr_t) noexcept {
|
||||||
code = {nullptr, -1};
|
code = {nullptr, std::make_error_code(std::errc::invalid_argument)};
|
||||||
}
|
}
|
||||||
using generic_traits<T>::init_code;
|
using generic_traits<T>::init_code;
|
||||||
|
|
||||||
@ -146,9 +145,9 @@ public:
|
|||||||
type_traits_t::init_code(code_, std::forward<A>(args)...);
|
type_traits_t::init_code(code_, std::forward<A>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
T value() const noexcept { return type_traits_t::get_value(code_); }
|
T value() const noexcept { return type_traits_t::get_value(code_); }
|
||||||
bool ok () const noexcept { return type_traits_t::get_ok (code_); }
|
bool ok () const noexcept { return type_traits_t::get_ok (code_); }
|
||||||
error_code error() const noexcept { return type_traits_t::get_error(code_); }
|
std::error_code error() const noexcept { return type_traits_t::get_error(code_); }
|
||||||
|
|
||||||
T operator * () const noexcept { return value(); }
|
T operator * () const noexcept { return value(); }
|
||||||
explicit operator bool() const noexcept { return ok (); }
|
explicit operator bool() const noexcept { return ok (); }
|
||||||
@ -175,8 +174,8 @@ public:
|
|||||||
type_traits_t::init_code(code_, std::forward<A>(args)...);
|
type_traits_t::init_code(code_, std::forward<A>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok () const noexcept { return type_traits_t::get_ok (code_); }
|
bool ok () const noexcept { return type_traits_t::get_ok (code_); }
|
||||||
error_code error() const noexcept { return type_traits_t::get_error(code_); }
|
std::error_code error() const noexcept { return type_traits_t::get_error(code_); }
|
||||||
|
|
||||||
explicit operator bool() const noexcept { return ok(); }
|
explicit operator bool() const noexcept { return ok(); }
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#include "libimp/def.h"
|
#include "libimp/def.h"
|
||||||
|
#include "libimp/detect_plat.h"
|
||||||
|
|
||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
@ -73,6 +74,6 @@ struct scope_exit_helper {
|
|||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
#define LIBIMP_SCOPE_EXIT($val) \
|
#define LIBIMP_SCOPE_EXIT($val) \
|
||||||
auto $val = ::LIBIMP::detail::scope_exit_helper{}
|
LIBIMP_UNUSED auto $val = ::LIBIMP::detail::scope_exit_helper{}
|
||||||
|
|
||||||
LIBIMP_NAMESPACE_END_
|
LIBIMP_NAMESPACE_END_
|
||||||
|
|||||||
@ -18,35 +18,17 @@
|
|||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
namespace sys {
|
namespace sys {
|
||||||
|
|
||||||
/**
|
/// \brief A platform-dependent error code.
|
||||||
* \brief Get/Set the system error number
|
LIBIMP_EXPORT std::error_code error() noexcept;
|
||||||
*/
|
|
||||||
LIBIMP_EXPORT error_code_t error_no() noexcept;
|
|
||||||
LIBIMP_EXPORT void error_no(error_code_t const &) noexcept;
|
|
||||||
|
|
||||||
/**
|
/// \enum The name of the `conf()` argument used to inquire about its value.
|
||||||
* \brief Gets a text description of the system error
|
/// \brief Certain options are supported,
|
||||||
*/
|
/// or what the value is of certain configurable constants or limits.
|
||||||
LIBIMP_EXPORT std::string error_str(error_code_t const &) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Identifies the operating system error category.
|
|
||||||
* \see https://en.cppreference.com/w/cpp/error/system_category
|
|
||||||
*/
|
|
||||||
LIBIMP_EXPORT error_category const &category() noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief A platform-dependent error code.
|
|
||||||
* \see https://en.cppreference.com/w/cpp/error/error_code
|
|
||||||
*/
|
|
||||||
LIBIMP_EXPORT error_code error() noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Get system configuration information at run time
|
|
||||||
*/
|
|
||||||
enum class info : std::int32_t {
|
enum class info : std::int32_t {
|
||||||
page_size,
|
page_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Get system configuration information at run time.
|
||||||
LIBIMP_EXPORT result<std::int64_t> conf(info) noexcept;
|
LIBIMP_EXPORT result<std::int64_t> conf(info) noexcept;
|
||||||
|
|
||||||
} // namespace sys
|
} // namespace sys
|
||||||
|
|||||||
@ -1,70 +0,0 @@
|
|||||||
#include <typeinfo>
|
|
||||||
|
|
||||||
#include "libimp/error.h"
|
|
||||||
#include "libimp/fmt.h"
|
|
||||||
|
|
||||||
LIBIMP_NAMESPACE_BEG_
|
|
||||||
|
|
||||||
bool error_category::operator==(error_category const &rhs) const noexcept {
|
|
||||||
return typeid(*this) == typeid(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class generic_error_category : public error_category {
|
|
||||||
public:
|
|
||||||
std::string name() const {
|
|
||||||
return "generic";
|
|
||||||
}
|
|
||||||
std::string message(error_code_t const &r) const {
|
|
||||||
if (r == error_number_limit) {
|
|
||||||
return "0, \"failure\"";
|
|
||||||
}
|
|
||||||
if (r == error_code_t(0)) {
|
|
||||||
return "0, \"success\"";
|
|
||||||
}
|
|
||||||
return fmt(r, ", \"failure\"");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
error_category const &generic_category() noexcept {
|
|
||||||
static generic_error_category ec;
|
|
||||||
return ec;
|
|
||||||
}
|
|
||||||
|
|
||||||
error_code::error_code() noexcept
|
|
||||||
: error_code{0, generic_category()} {}
|
|
||||||
|
|
||||||
error_code::error_code(error_code_t const &r) noexcept
|
|
||||||
: error_code{r, generic_category()} {}
|
|
||||||
|
|
||||||
error_code::error_code(error_code_t const &r, error_category const &ec) noexcept
|
|
||||||
: e_code_{r}, ec_{&ec} {}
|
|
||||||
|
|
||||||
error_code_t error_code::code() const noexcept {
|
|
||||||
return e_code_;
|
|
||||||
}
|
|
||||||
|
|
||||||
error_category const &error_code::category() const noexcept {
|
|
||||||
return *ec_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string error_code::message() const {
|
|
||||||
return fmt("[", ec_->name(), ": ", ec_->message(e_code_), "]");
|
|
||||||
}
|
|
||||||
|
|
||||||
error_code::operator bool() const noexcept {
|
|
||||||
return e_code_ != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(error_code const &lhs, error_code const &rhs) noexcept {
|
|
||||||
return (lhs.e_code_ == rhs.e_code_) && (*lhs.ec_ == *rhs.ec_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(error_code const &lhs, error_code const &rhs) noexcept {
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
LIBIMP_NAMESPACE_END_
|
|
||||||
@ -14,47 +14,13 @@
|
|||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
namespace sys {
|
namespace sys {
|
||||||
|
|
||||||
#ifndef ENOERR
|
|
||||||
#define ENOERR (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Get the system error number
|
* \brief Get the system error number.
|
||||||
* https://man7.org/linux/man-pages/man3/errno.3.html
|
* \see https://en.cppreference.com/w/cpp/error/generic_category
|
||||||
*/
|
* https://man7.org/linux/man-pages/man3/errno.3.html
|
||||||
error_code_t error_no() noexcept {
|
*/
|
||||||
auto err = errno;
|
std::error_code error() noexcept {
|
||||||
if (err == ENOERR) return {ENOERR};
|
return std::error_code(errno, std::generic_category());
|
||||||
return error_code_t(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Set the system error number
|
|
||||||
* https://man7.org/linux/man-pages/man3/errno.3.html
|
|
||||||
*/
|
|
||||||
void error_no(error_code_t const &code) noexcept {
|
|
||||||
errno = (code == 0) ? ENOERR : (int)code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Gets a text description of the system error
|
|
||||||
* 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(error_code_t const &code) noexcept {
|
|
||||||
char msg_buf[256] {};
|
|
||||||
#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE)
|
|
||||||
LIBIMP_LOG_();
|
|
||||||
if (::strerror_r((int)code, msg_buf, sizeof(msg_buf)) != 0) {
|
|
||||||
log.error("failed: strerror_r(code = ", (int)code,
|
|
||||||
", buf, buf-size = ", sizeof(msg_buf),
|
|
||||||
"). error = ", error_code());
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return msg_buf;
|
|
||||||
#else
|
|
||||||
return ::strerror_r((int)code, msg_buf, sizeof(msg_buf));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,7 +33,7 @@ result<std::int64_t> conf(info r) noexcept {
|
|||||||
switch (r) {
|
switch (r) {
|
||||||
case info::page_size: {
|
case info::page_size: {
|
||||||
auto val = ::sysconf(_SC_PAGESIZE);
|
auto val = ::sysconf(_SC_PAGESIZE);
|
||||||
if (val >= 0) return (std::int64_t)val;
|
if (val >= 0) return static_cast<std::int64_t>(val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -76,7 +42,7 @@ result<std::int64_t> conf(info r) noexcept {
|
|||||||
}
|
}
|
||||||
auto err = sys::error();
|
auto err = sys::error();
|
||||||
log.error("info = ", underlyof(r), ", error = ", err);
|
log.error("info = ", underlyof(r), ", error = ", err);
|
||||||
return {false, (int)err.code()};
|
return {false, err};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sys
|
} // namespace sys
|
||||||
|
|||||||
@ -36,7 +36,7 @@ std::size_t cvt_cstr(char const *src, std::size_t slen, wchar_t *des, std::size_
|
|||||||
int cch_wc = (des == nullptr) ? 0 : (int)dlen;
|
int cch_wc = (des == nullptr) ? 0 : (int)dlen;
|
||||||
int size_needed = ::MultiByteToWideChar(CP_ACP, 0, src, (int)slen, des, cch_wc);
|
int size_needed = ::MultiByteToWideChar(CP_ACP, 0, src, (int)slen, des, cch_wc);
|
||||||
if (size_needed <= 0) {
|
if (size_needed <= 0) {
|
||||||
log.error("failed: MultiByteToWideChar(CP_ACP). error = ", sys::error_no());
|
log.error("failed: MultiByteToWideChar(CP_ACP). error = ", sys::error());
|
||||||
}
|
}
|
||||||
return size_needed;
|
return size_needed;
|
||||||
}
|
}
|
||||||
@ -51,7 +51,7 @@ std::size_t cvt_cstr(wchar_t const *src, std::size_t slen, char *des, std::size_
|
|||||||
int cb_mb = (des == nullptr) ? 0 : (int)dlen;
|
int cb_mb = (des == nullptr) ? 0 : (int)dlen;
|
||||||
int size_needed = ::WideCharToMultiByte(CP_ACP, 0, src, (int)slen, des, cb_mb, NULL, NULL);
|
int size_needed = ::WideCharToMultiByte(CP_ACP, 0, src, (int)slen, des, cb_mb, NULL, NULL);
|
||||||
if (size_needed <= 0) {
|
if (size_needed <= 0) {
|
||||||
log.error("failed: WideCharToMultiByte(CP_ACP). error = ", sys::error_no());
|
log.error("failed: WideCharToMultiByte(CP_ACP). error = ", sys::error());
|
||||||
}
|
}
|
||||||
return size_needed;
|
return size_needed;
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ std::size_t cvt_cstr(char8_t const *src, std::size_t slen, wchar_t *des, std::si
|
|||||||
int cch_wc = (des == nullptr) ? 0 : (int)dlen;
|
int cch_wc = (des == nullptr) ? 0 : (int)dlen;
|
||||||
int size_needed = ::MultiByteToWideChar(CP_UTF8, 0, (char *)src, (int)slen, des, cch_wc);
|
int size_needed = ::MultiByteToWideChar(CP_UTF8, 0, (char *)src, (int)slen, des, cch_wc);
|
||||||
if (size_needed <= 0) {
|
if (size_needed <= 0) {
|
||||||
log.error("failed: MultiByteToWideChar(CP_UTF8). error = ", sys::error_code());
|
log.error("failed: MultiByteToWideChar(CP_UTF8). error = ", sys::error());
|
||||||
}
|
}
|
||||||
return size_needed;
|
return size_needed;
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ std::size_t cvt_cstr(wchar_t const *src, std::size_t slen, char8_t *des, std::si
|
|||||||
int cb_mb = (des == nullptr) ? 0 : (int)dlen;
|
int cb_mb = (des == nullptr) ? 0 : (int)dlen;
|
||||||
int size_needed = ::WideCharToMultiByte(CP_UTF8, 0, src, (int)slen, (char *)des, cb_mb, NULL, NULL);
|
int size_needed = ::WideCharToMultiByte(CP_UTF8, 0, src, (int)slen, (char *)des, cb_mb, NULL, NULL);
|
||||||
if (size_needed <= 0) {
|
if (size_needed <= 0) {
|
||||||
log.error("failed: WideCharToMultiByte(CP_UTF8). error = ", sys::error_code());
|
log.error("failed: WideCharToMultiByte(CP_UTF8). error = ", sys::error());
|
||||||
}
|
}
|
||||||
return size_needed;
|
return size_needed;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <memory>
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
@ -16,56 +15,33 @@
|
|||||||
#include "libimp/codecvt.h"
|
#include "libimp/codecvt.h"
|
||||||
#include "libimp/underlyof.h"
|
#include "libimp/underlyof.h"
|
||||||
#include "libimp/detect_plat.h"
|
#include "libimp/detect_plat.h"
|
||||||
|
#include "libimp/scope_exit.h"
|
||||||
|
|
||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
namespace sys {
|
namespace sys {
|
||||||
|
namespace {
|
||||||
/**
|
|
||||||
* \brief Get the system error number
|
|
||||||
* https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror
|
|
||||||
*/
|
|
||||||
error_code_t error_no() noexcept {
|
|
||||||
auto err = ::GetLastError();
|
|
||||||
if (err == ERROR_SUCCESS) {
|
|
||||||
return {ERROR_SUCCESS};
|
|
||||||
}
|
|
||||||
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(error_code_t const &code) noexcept {
|
|
||||||
DWORD err = (code == 0) ? ERROR_SUCCESS : (DWORD)code;
|
|
||||||
::SetLastError(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Gets a text description of the system error
|
* \brief Gets a text description of the system error
|
||||||
* https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-formatmessage
|
* \see https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-formatmessage
|
||||||
*/
|
*/
|
||||||
std::string error_str(error_code_t const &code) noexcept {
|
std::string error_string(DWORD code) noexcept {
|
||||||
LIBIMP_LOG_();
|
LIBIMP_LOG_();
|
||||||
LIBIMP_TRY {
|
LIBIMP_TRY {
|
||||||
DWORD err = (DWORD)code;
|
|
||||||
LPTSTR lpErrText = NULL;
|
LPTSTR lpErrText = NULL;
|
||||||
if (::FormatMessage(
|
if (::FormatMessage(
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
NULL,
|
NULL,
|
||||||
err,
|
code,
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
(LPTSTR)&lpErrText,
|
(LPTSTR)&lpErrText,
|
||||||
0, NULL) == 0) {
|
0, NULL) == 0) {
|
||||||
log.error("failed: FormatMessage(dwMessageId = ", err, "). error = ", error_code());
|
log.error("failed: FormatMessage(dwMessageId = ", code, "). error = ", ::GetLastError());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
LIBIMP_UNUSED auto buf_guard = std::unique_ptr<std::remove_pointer_t<LPVOID>,
|
LIBIMP_SCOPE_EXIT(finally) = [lpErrText] { ::LocalFree(lpErrText); };
|
||||||
void(*)(LPVOID)> {
|
|
||||||
lpErrText, [](LPVOID lp) { ::LocalFree(lp); }
|
|
||||||
};
|
|
||||||
std::size_t msg_len = ::_tcslen(lpErrText);
|
std::size_t msg_len = ::_tcslen(lpErrText);
|
||||||
std::size_t len = cvt_cstr(lpErrText, msg_len, (char *)nullptr, 0);
|
std::size_t len = cvt_cstr(lpErrText, msg_len, (char *)nullptr, 0);
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
@ -80,10 +56,21 @@ std::string error_str(error_code_t const &code) noexcept {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Retrieves information about the current system
|
* \brief Get the system error number.
|
||||||
* https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsysteminfo
|
* \see https://en.cppreference.com/w/cpp/error/system_category
|
||||||
* https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getnativesysteminfo
|
* https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror
|
||||||
|
*/
|
||||||
|
std::error_code error() noexcept {
|
||||||
|
return std::error_code(::GetLastError(), std::system_category());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieves information about the current system.
|
||||||
|
* \see https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsysteminfo
|
||||||
|
* https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getnativesysteminfo
|
||||||
*/
|
*/
|
||||||
result<std::int64_t> conf(info r) noexcept {
|
result<std::int64_t> conf(info r) noexcept {
|
||||||
LIBIMP_LOG_();
|
LIBIMP_LOG_();
|
||||||
|
|||||||
@ -7,32 +7,3 @@
|
|||||||
#else
|
#else
|
||||||
# include "libimp/platform/posix/system.h"
|
# include "libimp/platform/posix/system.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class system_error_category : public ::LIBIMP::error_category {
|
|
||||||
public:
|
|
||||||
std::string name() const {
|
|
||||||
return "system";
|
|
||||||
}
|
|
||||||
std::string message(::LIBIMP::error_code_t const &r) const {
|
|
||||||
return ::LIBIMP::fmt(r, ::LIBIMP::sys::error_str(r));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
LIBIMP_NAMESPACE_BEG_
|
|
||||||
namespace sys {
|
|
||||||
|
|
||||||
error_category const &category() noexcept {
|
|
||||||
static system_error_category ec;
|
|
||||||
return ec;
|
|
||||||
}
|
|
||||||
|
|
||||||
error_code error() noexcept {
|
|
||||||
return error_code{error_no(), category()};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sys
|
|
||||||
LIBIMP_NAMESPACE_END_
|
|
||||||
|
|||||||
@ -161,7 +161,7 @@ result<void> shm_close(shm_t h) noexcept {
|
|||||||
}
|
}
|
||||||
/// \brief no unlink the file.
|
/// \brief no unlink the file.
|
||||||
delete shm;
|
delete shm;
|
||||||
return no_error;
|
return std::error_code{};
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBIPC_NAMESPACE_END_
|
LIBIPC_NAMESPACE_END_
|
||||||
|
|||||||
@ -70,7 +70,7 @@ result<void> evt_close(evt_t evt) noexcept {
|
|||||||
log.error("failed: CloseHandle(", evt->h_event, "). error = ", err);
|
log.error("failed: CloseHandle(", evt->h_event, "). error = ", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
return no_error;
|
return std::error_code{};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,7 +88,7 @@ result<void> evt_set(evt_t evt) noexcept {
|
|||||||
log.error("failed: SetEvent(", evt->h_event, "). error = ", err);
|
log.error("failed: SetEvent(", evt->h_event, "). error = ", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
return no_error;
|
return std::error_code{};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -44,7 +44,7 @@ result<void> mmap_close(HANDLE h) {
|
|||||||
log.error("failed: CloseHandle(", h, "). error = ", err);
|
log.error("failed: CloseHandle(", h, "). error = ", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
return no_error;
|
return std::error_code{};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -6,29 +6,9 @@
|
|||||||
#include "libimp/result.h"
|
#include "libimp/result.h"
|
||||||
#include "libimp/fmt.h"
|
#include "libimp/fmt.h"
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class custom_error_category : public imp::error_category {
|
|
||||||
public:
|
|
||||||
std::string name() const {
|
|
||||||
return "custom";
|
|
||||||
}
|
|
||||||
std::string message(imp::error_code_t const &r) const {
|
|
||||||
return (r == 0) ? "success" : "failure";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
TEST(error, error_code) {
|
TEST(error, error_code) {
|
||||||
imp::error_code ecode;
|
std::error_code ecode;
|
||||||
EXPECT_FALSE(ecode);
|
EXPECT_FALSE(ecode);
|
||||||
std::cout << ecode.message() << "\n";
|
std::cout << ecode.message() << "\n";
|
||||||
EXPECT_EQ(ecode.message(), "[generic: 0, \"success\"]");
|
EXPECT_EQ(ecode.message(), "[generic: 0, \"success\"]");
|
||||||
|
}
|
||||||
custom_error_category cec;
|
|
||||||
ecode = {123, cec};
|
|
||||||
EXPECT_TRUE(ecode);
|
|
||||||
std::cout << ecode.message() << "\n";
|
|
||||||
EXPECT_EQ(ecode.message(), imp::fmt("[", cec.name(), ": ", cec.message(123), "]"));
|
|
||||||
}
|
|
||||||
|
|||||||
@ -25,19 +25,19 @@ TEST(fmt, to_string) {
|
|||||||
EXPECT_EQ(joined, std::forward<decltype(txt)>(txt));
|
EXPECT_EQ(joined, std::forward<decltype(txt)>(txt));
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief string
|
/// \brief string
|
||||||
check("", "");
|
check("", "");
|
||||||
check("%what%", "%what%");
|
check("%what%", "%what%");
|
||||||
check(" %what%", "%what%", "10");
|
check(" %what%", "%what%", "10");
|
||||||
check("%what% ", "%what%", "-10");
|
check("%what% ", "%what%", "-10");
|
||||||
|
|
||||||
/// @brief character
|
/// \brief character
|
||||||
check("A", 'A');
|
check("A", 'A');
|
||||||
check("A", L'A');
|
check("A", L'A');
|
||||||
check("A", u'A');
|
check("A", u'A');
|
||||||
check("A", U'A');
|
check("A", U'A');
|
||||||
|
|
||||||
/// @brief numeric
|
/// \brief numeric
|
||||||
check("123" , (signed char)123 );
|
check("123" , (signed char)123 );
|
||||||
check("-65" , (signed char)-321 );
|
check("-65" , (signed char)-321 );
|
||||||
check("123" , (unsigned char)123 );
|
check("123" , (unsigned char)123 );
|
||||||
@ -63,7 +63,7 @@ TEST(fmt, to_string) {
|
|||||||
check("1CAAB5C3B3", 123123123123ll, "X" );
|
check("1CAAB5C3B3", 123123123123ll, "X" );
|
||||||
check("1CAAB5C3B3", 123123123123ull, "X" );
|
check("1CAAB5C3B3", 123123123123ull, "X" );
|
||||||
|
|
||||||
/// @brief floating point
|
/// \brief floating point
|
||||||
check("123.123" , 123.123f, ".3");
|
check("123.123" , 123.123f, ".3");
|
||||||
check("0123.12300" , 123.123, "010.5");
|
check("0123.12300" , 123.123, "010.5");
|
||||||
check("123.123000" , 123.123l, "010.6");
|
check("123.123000" , 123.123l, "010.6");
|
||||||
@ -75,13 +75,13 @@ TEST(fmt, to_string) {
|
|||||||
ctx.reset(); EXPECT_TRUE(imp::to_string(ctx, 1.0/r)); ctx.finish();
|
ctx.reset(); EXPECT_TRUE(imp::to_string(ctx, 1.0/r)); ctx.finish();
|
||||||
std::cout << joined << "\n";
|
std::cout << joined << "\n";
|
||||||
|
|
||||||
/// @brief pointer
|
/// \brief pointer
|
||||||
check("null", nullptr);
|
check("null", nullptr);
|
||||||
int *p = (int *)0x0f013a04;
|
int *p = (int *)0x0f013a04;
|
||||||
ctx.reset(); EXPECT_TRUE(imp::to_string(ctx, (void *)p)); ctx.finish();
|
ctx.reset(); EXPECT_TRUE(imp::to_string(ctx, (void *)p)); ctx.finish();
|
||||||
std::cout << joined << "\n";
|
std::cout << joined << "\n";
|
||||||
|
|
||||||
/// @brief date and time
|
/// \brief date and time
|
||||||
auto tp = std::chrono::system_clock::now();
|
auto tp = std::chrono::system_clock::now();
|
||||||
auto tt = std::chrono::system_clock::to_time_t(tp);
|
auto tt = std::chrono::system_clock::to_time_t(tp);
|
||||||
auto tm = *std::localtime(&tt);
|
auto tm = *std::localtime(&tt);
|
||||||
@ -95,14 +95,14 @@ TEST(fmt, to_string) {
|
|||||||
TEST(fmt, fmt) {
|
TEST(fmt, fmt) {
|
||||||
char const txt[] = "hello world.";
|
char const txt[] = "hello world.";
|
||||||
|
|
||||||
/// @brief hello world
|
/// \brief hello world
|
||||||
auto s = imp::fmt("hello", " ", "world", ".");
|
auto s = imp::fmt("hello", " ", "world", ".");
|
||||||
EXPECT_EQ(s, txt);
|
EXPECT_EQ(s, txt);
|
||||||
|
|
||||||
/// @brief chrono
|
/// \brief chrono
|
||||||
std::cout << imp::fmt('[', std::chrono::system_clock::now(), "] ", s) << "\n";
|
std::cout << imp::fmt('[', std::chrono::system_clock::now(), "] ", s) << "\n";
|
||||||
|
|
||||||
/// @brief long string
|
/// \brief long string
|
||||||
s = imp::fmt(imp::spec("4096")(txt));
|
s = imp::fmt(imp::spec("4096")(txt));
|
||||||
std::string test(4096, ' ');
|
std::string test(4096, ' ');
|
||||||
std::memcpy(&test[test.size() - sizeof(txt) + 1], txt, sizeof(txt) - 1);
|
std::memcpy(&test[test.size() - sizeof(txt) + 1], txt, sizeof(txt) - 1);
|
||||||
|
|||||||
@ -50,15 +50,15 @@ TEST(result, ok) {
|
|||||||
|
|
||||||
imp::result<void> r1;
|
imp::result<void> r1;
|
||||||
EXPECT_FALSE(r1);
|
EXPECT_FALSE(r1);
|
||||||
r1 = 0;
|
r1 = std::error_code{};
|
||||||
EXPECT_TRUE(r1);
|
EXPECT_TRUE(r1);
|
||||||
r1 = {};
|
r1 = {};
|
||||||
EXPECT_FALSE(r1);
|
EXPECT_FALSE(r1);
|
||||||
r1 = 9999;
|
r1 = std::error_code{9999, std::generic_category()};
|
||||||
EXPECT_FALSE(r1);
|
EXPECT_FALSE(r1);
|
||||||
EXPECT_EQ(r1.error(), 9999);
|
EXPECT_EQ(r1.error().value(), 9999);
|
||||||
|
|
||||||
imp::result<int *> r2 {nullptr, 4321};
|
imp::result<int *> r2 {nullptr, std::error_code{4321, std::generic_category()}};
|
||||||
EXPECT_NE(r2, nullptr); // imp::result<int *>{nullptr}
|
EXPECT_NE(r2, nullptr); // imp::result<int *>{nullptr}
|
||||||
EXPECT_EQ(*r2, nullptr);
|
EXPECT_EQ(*r2, nullptr);
|
||||||
EXPECT_FALSE(r2);
|
EXPECT_FALSE(r2);
|
||||||
@ -103,7 +103,7 @@ TEST(result, fmt) {
|
|||||||
EXPECT_EQ(imp::fmt(r3), imp::fmt("succ, value = ", (void *)&aaa));
|
EXPECT_EQ(imp::fmt(r3), imp::fmt("succ, value = ", (void *)&aaa));
|
||||||
imp::result<int *> r4 {nullptr};
|
imp::result<int *> r4 {nullptr};
|
||||||
EXPECT_EQ(imp::fmt(r4), imp::fmt("fail, value = ", nullptr, ", error = [generic: 0, \"failure\"]"));
|
EXPECT_EQ(imp::fmt(r4), imp::fmt("fail, value = ", nullptr, ", error = [generic: 0, \"failure\"]"));
|
||||||
r4 = {nullptr, 1234};
|
r4 = {nullptr, std::error_code{1234, std::generic_category()}};
|
||||||
EXPECT_EQ(imp::fmt(r4), imp::fmt("fail, value = ", nullptr, ", error = [generic: 1234, \"failure\"]"));
|
EXPECT_EQ(imp::fmt(r4), imp::fmt("fail, value = ", nullptr, ", error = [generic: 1234, \"failure\"]"));
|
||||||
imp::result<int *> r5;
|
imp::result<int *> r5;
|
||||||
EXPECT_EQ(imp::fmt(r5), "fail, value = null, error = [generic: 0, \"failure\"]");
|
EXPECT_EQ(imp::fmt(r5), "fail, value = null, error = [generic: 0, \"failure\"]");
|
||||||
@ -115,8 +115,8 @@ TEST(result, fmt) {
|
|||||||
{
|
{
|
||||||
imp::result<void> r1;
|
imp::result<void> r1;
|
||||||
EXPECT_EQ(imp::fmt(r1), "fail, error = [generic: 0, \"failure\"]");
|
EXPECT_EQ(imp::fmt(r1), "fail, error = [generic: 0, \"failure\"]");
|
||||||
r1 = 0;
|
r1 = std::error_code{};
|
||||||
EXPECT_TRUE(r1);
|
EXPECT_TRUE(r1);
|
||||||
EXPECT_EQ(imp::fmt(r1), "succ, error = [generic: 0, \"success\"]");
|
EXPECT_EQ(imp::fmt(r1), "succ, error = [generic: 0, \"success\"]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,54 +14,8 @@
|
|||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST(system, error_no) {
|
|
||||||
imp::sys::error_no(111);
|
|
||||||
auto err = imp::sys::error_no();
|
|
||||||
EXPECT_FALSE(err == 0);
|
|
||||||
EXPECT_EQ(err, 111);
|
|
||||||
|
|
||||||
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";
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(system, error_str) {
|
|
||||||
#if defined(LIBIMP_OS_WIN)
|
|
||||||
std::wstring u16_ok, u16_err;
|
|
||||||
LANGID lId = ::GetSystemDefaultLangID();
|
|
||||||
switch (lId) {
|
|
||||||
case 0x0804:
|
|
||||||
u16_ok = L"操作成功完成。\r\n";
|
|
||||||
u16_err = L"句柄无效。\r\n";
|
|
||||||
break;
|
|
||||||
case 0x0409:
|
|
||||||
u16_ok = L"The operation completed successfully.\r\n";
|
|
||||||
u16_err = L"The handle is invalid.\r\n";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
std::string s_txt;
|
|
||||||
imp::cvt_sstr(u16_ok, s_txt);
|
|
||||||
EXPECT_EQ(imp::sys::error_str({}), s_txt);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
std::string s_txt;
|
|
||||||
imp::cvt_sstr(u16_err, s_txt);
|
|
||||||
EXPECT_EQ(imp::sys::error_str(ERROR_INVALID_HANDLE), s_txt);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
EXPECT_EQ(imp::sys::error_str(1234), "Unknown error 1234");
|
|
||||||
EXPECT_EQ(imp::sys::error_str({}), "Success");
|
|
||||||
EXPECT_EQ(imp::sys::error_str(EINVAL), "Invalid argument");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(system, conf) {
|
TEST(system, conf) {
|
||||||
auto ret = imp::sys::conf(imp::sys::info::page_size);
|
auto ret = imp::sys::conf(imp::sys::info::page_size);
|
||||||
EXPECT_TRUE(ret);
|
EXPECT_TRUE(ret);
|
||||||
EXPECT_EQ(ret.value(), 4096);
|
EXPECT_EQ(ret.value(), 4096);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user