add: [result] an additional status code can be returned on failure to return a pointer

This commit is contained in:
mutouyun 2022-05-15 19:20:30 +08:00
parent 9e170999a1
commit e21da4fe2d
5 changed files with 79 additions and 31 deletions

View File

@ -9,10 +9,9 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#if !defined(LIBIMP_NAMESPACE) #define LIBIMP_ imp
# define LIBIMP_NAMESPACE imp #define LIBIMP_NAMESPACE_ LIBIMP_
#endif #define LIBIMP_NAMESPACE_BEG_ namespace LIBIMP_NAMESPACE_ {
#define LIBIMP_NAMESPACE_BEG_ namespace LIBIMP_NAMESPACE {
#define LIBIMP_NAMESPACE_END_ } #define LIBIMP_NAMESPACE_END_ }
LIBIMP_NAMESPACE_BEG_ LIBIMP_NAMESPACE_BEG_

View File

@ -12,6 +12,7 @@
#include "fmt/format.h" #include "fmt/format.h"
#include "libimp/def.h" #include "libimp/def.h"
#include "libimp/detect_plat.h"
#include "libimp/export.h" #include "libimp/export.h"
LIBIMP_NAMESPACE_BEG_ LIBIMP_NAMESPACE_BEG_
@ -26,7 +27,7 @@ class LIBIMP_EXPORT result_code {
public: public:
result_code() noexcept; result_code() noexcept;
result_code(bool ok, std::uint64_t value = 0) noexcept; result_code(bool ok, std::uint64_t value = {}) noexcept;
std::uint64_t value() const noexcept; std::uint64_t value() const noexcept;
bool ok() const noexcept; bool ok() const noexcept;
@ -42,6 +43,11 @@ public:
friend bool operator!=(result_code const &lhs, result_code const &rhs) noexcept; friend bool operator!=(result_code const &lhs, result_code const &rhs) noexcept;
}; };
template <typename T,
typename DefTraits = detail_result::default_traits<T>,
typename = void>
class result;
namespace detail_result { namespace detail_result {
template <typename T, typename = void> template <typename T, typename = void>
@ -57,8 +63,9 @@ struct default_traits<T, std::enable_if_t<std::is_integral<T>::value>> {
static T cast_from_code(std::uint64_t code) noexcept { static T cast_from_code(std::uint64_t code) noexcept {
return static_cast<T>(code); return static_cast<T>(code);
} }
static T regularize(T value) noexcept { template <typename Out>
return value; static auto format(result<T> const &r, Out &&out) noexcept {
return format_to(out, "{}", *r);
} }
}; };
@ -72,16 +79,19 @@ struct default_traits<T, std::enable_if_t<std::is_pointer<T>::value>> {
static T cast_from_code(std::uint64_t code) noexcept { static T cast_from_code(std::uint64_t code) noexcept {
return reinterpret_cast<T>(code); return reinterpret_cast<T>(code);
} }
static void *regularize(T value) noexcept { template <typename Out>
return value; static auto format(result<T> const &r, Out &&out) noexcept {
if LIBIMP_LIKELY(r) {
return format_to(out, "{}", static_cast<void *>(*r));
}
return format_to(out, "{}, code = {}", static_cast<void *>(*r), r.code());
} }
}; };
} // namespace detail_result } // namespace detail_result
template <typename T, template <typename T, typename DefTraits>
typename DefTraits = detail_result::default_traits<T>> class result<T, DefTraits, std::enable_if_t<std::is_integral<T>::value>> {
class result {
result_code code_; result_code code_;
@ -89,7 +99,7 @@ public:
using default_traits_t = DefTraits; using default_traits_t = DefTraits;
result() noexcept = default; result() noexcept = default;
result(bool ok, T value = default_traits_t::value()) result(bool ok, T value = default_traits_t::value()) noexcept
: code_(ok, default_traits_t::cast_to_code(value)) {} : code_(ok, default_traits_t::cast_to_code(value)) {}
T value() const noexcept { return default_traits_t::cast_from_code(code_.value()); } T value() const noexcept { return default_traits_t::cast_from_code(code_.value()); }
@ -104,31 +114,58 @@ public:
friend bool operator==(result const &lhs, result const &rhs) noexcept { return lhs.code_ == rhs.code_; } friend bool operator==(result const &lhs, result const &rhs) noexcept { return lhs.code_ == rhs.code_; }
friend bool operator!=(result const &lhs, result const &rhs) noexcept { return lhs.code_ != rhs.code_; } friend bool operator!=(result const &lhs, result const &rhs) noexcept { return lhs.code_ != rhs.code_; }
};
friend std::ostream &operator<<(std::ostream &o, result const &r) noexcept { return o << r.code_; } template <typename T, typename DefTraits>
class result<T, DefTraits, std::enable_if_t<std::is_pointer<T>::value>> {
result_code code_;
public:
using default_traits_t = DefTraits;
result(T value = default_traits_t::value()) noexcept
: code_(default_traits_t::value() != value,
default_traits_t::cast_to_code(value)) {}
result(std::nullptr_t, std::uint64_t code) noexcept
: code_(false, code) {}
T value() const noexcept { return code_.ok() ? default_traits_t::cast_from_code(code_.value()) : nullptr; }
bool ok() const noexcept { return code_.ok(); }
std::uint64_t code() const noexcept { return code_.value(); }
T operator*() const noexcept {
return value();
}
explicit operator bool() const noexcept {
return ok();
}
friend bool operator==(result const &lhs, result const &rhs) noexcept { return lhs.code_ == rhs.code_; }
friend bool operator!=(result const &lhs, result const &rhs) noexcept { return lhs.code_ != rhs.code_; }
}; };
LIBIMP_NAMESPACE_END_ LIBIMP_NAMESPACE_END_
template <typename T> template <typename T, typename D>
struct fmt::formatter<::LIBIMP_NAMESPACE::result<T>> { struct fmt::formatter<::LIBIMP_::result<T, D>> {
constexpr auto parse(format_parse_context& ctx) { constexpr auto parse(format_parse_context& ctx) {
return ctx.end(); return ctx.end();
} }
template <typename FormatContext> template <typename FormatContext>
auto format(::LIBIMP_NAMESPACE::result<T> r, FormatContext &ctx) { auto format(::LIBIMP_::result<T, D> r, FormatContext &ctx) {
return format_to(ctx.out(), "[{}, value = {}]", return format_to(::LIBIMP_::result<T, D>::default_traits_t::format(r,
(r ? "succ" : "fail"), format_to(ctx.out(), "[{}, value = ", r ? "succ" : "fail")), "]");
::LIBIMP_NAMESPACE::result<T>::default_traits_t::regularize(*r));
} }
}; };
template <> template <>
struct fmt::formatter<::LIBIMP_NAMESPACE::result_code> struct fmt::formatter<::LIBIMP_::result_code>
: formatter<::LIBIMP_NAMESPACE::result<std::uint64_t>> { : formatter<::LIBIMP_::result<std::uint64_t>> {
template <typename FormatContext> template <typename FormatContext>
auto format(::LIBIMP_NAMESPACE::result_code r, FormatContext &ctx) { auto format(::LIBIMP_::result_code r, FormatContext &ctx) {
return format_to(ctx.out(), "[{}, value = {}]", (r ? "succ" : "fail"), *r); return format_to(ctx.out(), "[{}, value = {}]", (r ? "succ" : "fail"), *r);
} }
}; };

View File

@ -9,14 +9,21 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#if !defined(LIBIPC_NAMESPACE) #define LIBIPC_ ipc
# define LIBIPC_NAMESPACE ipc #define LIBIPC_NAMESPACE_ LIBIPC_
#endif #define LIBIPC_NAMESPACE_BEG_ namespace LIBIPC_NAMESPACE_ {
#define LIBIPC_NAMESPACE_BEG_ namespace LIBIPC_NAMESPACE {
#define LIBIPC_NAMESPACE_END_ } #define LIBIPC_NAMESPACE_END_ }
LIBIPC_NAMESPACE_BEG_ LIBIPC_NAMESPACE_BEG_
// constants // constants
struct prot {
enum : std::uint32_t {
none = 0x00,
read = 0x01,
write = 0x02,
};
};
LIBIPC_NAMESPACE_END_ LIBIPC_NAMESPACE_END_

View File

@ -8,6 +8,7 @@
#include "libimp/export.h" #include "libimp/export.h"
#include "libimp/result.h" #include "libimp/result.h"
#include "libipc/def.h" #include "libipc/def.h"
LIBIPC_NAMESPACE_BEG_ LIBIPC_NAMESPACE_BEG_
@ -18,6 +19,6 @@ using mmap_t = mmap_handle *;
/** /**
* @brief Creates a new mapping in the virtual address space of the calling process. * @brief Creates a new mapping in the virtual address space of the calling process.
*/ */
LIBIMP_EXPORT mmap_t mmap_open(); LIBIMP_EXPORT ::LIBIMP_::result<mmap_t> mmap_open();
LIBIPC_NAMESPACE_END_ LIBIPC_NAMESPACE_END_

View File

@ -68,10 +68,14 @@ TEST(result, fmt) {
{ {
imp::result<int> r1 {false, -123}; imp::result<int> r1 {false, -123};
EXPECT_EQ(fmt::format("{}", r1), fmt::format("[fail, value = {}]", -123)); EXPECT_EQ(fmt::format("{}", r1), fmt::format("[fail, value = {}]", -123));
imp::result<void *> r2 {true, &r1}; imp::result<void *> r2 {&r1};
EXPECT_EQ(fmt::format("{}", r2), fmt::format("[succ, value = {}]", (void *)&r1)); EXPECT_EQ(fmt::format("{}", r2), fmt::format("[succ, value = {}]", (void *)&r1));
int aaa {}; int aaa {};
imp::result<int *> r3 {false, &aaa}; imp::result<int *> r3 {&aaa};
EXPECT_EQ(fmt::format("{}", r3), fmt::format("[fail, value = {}]", (void *)&aaa)); EXPECT_EQ(fmt::format("{}", r3), fmt::format("[succ, value = {}]", (void *)&aaa));
imp::result<int *> r4 {nullptr};
EXPECT_EQ(fmt::format("{}", r4), fmt::format("[fail, value = {}, code = 0]", nullptr));
r4 = {nullptr, 1234};
EXPECT_EQ(fmt::format("{}", r4), fmt::format("[fail, value = {}, code = 1234]", nullptr));
} }
} }