Remove the custom error_code.

This commit is contained in:
mutouyun 2023-09-09 12:13:56 +08:00
parent 6020739552
commit 3d4e92a9c5
16 changed files with 86 additions and 370 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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{};
} }
/** /**

View File

@ -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{};
} }
/** /**

View File

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

View File

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

View File

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

View File

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