diff --git a/mdbx.h++ b/mdbx.h++ index 54d30088..bfd83175 100644 --- a/mdbx.h++ +++ b/mdbx.h++ @@ -394,6 +394,16 @@ using path = ::std::wstring; using path = ::std::string; #endif /* mdbx::path */ +#if defined(__SIZEOF_INT128__) || \ + (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128) +#ifndef MDBX_U128_TYPE +#define MDBX_U128_TYPE __uint128_t +#endif /* MDBX_U128_TYPE */ +#ifndef MDBX_I128_TYPE +#define MDBX_I128_TYPE __int128_t +#endif /* MDBX_I128_TYPE */ +#endif /* __SIZEOF_INT128__ || _INTEGRAL_MAX_BITS >= 128 */ + #if __cplusplus >= 201103L || defined(DOXYGEN) /// \brief Duration in 1/65536 units of second. using duration = ::std::chrono::duration>; @@ -552,6 +562,7 @@ MDBX_DECLARE_EXCEPTION(transaction_overlapping); [[noreturn]] LIBMDBX_API void throw_max_length_exceeded(); [[noreturn]] LIBMDBX_API void throw_out_range(); [[noreturn]] LIBMDBX_API void throw_allocators_mismatch(); +[[noreturn]] LIBMDBX_API void throw_bad_value_size(); static MDBX_CXX14_CONSTEXPR size_t check_length(size_t bytes); static MDBX_CXX14_CONSTEXPR size_t check_length(size_t headroom, size_t payload); @@ -1029,6 +1040,35 @@ struct LIBMDBX_API_TYPE slice : public ::MDBX_val { return slice(size_t(-1)); } + template MDBX_CXX14_CONSTEXPR POD as_pod() const { + static_assert(::std::is_standard_layout::value && + !::std::is_pointer::value, + "Must be a standard layout type!"); + if (MDBX_LIKELY(size() == sizeof(POD))) + MDBX_CXX20_LIKELY { + POD r; + memcpy(&r, data(), sizeof(r)); + return r; + } + throw_bad_value_size(); + } + +#ifdef MDBX_U128_TYPE + MDBX_U128_TYPE as_uint128() const; +#endif /* MDBX_U128_TYPE */ + uint64_t as_uint64() const; + uint32_t as_uint32() const; + uint16_t as_uint16() const; + uint8_t as_uint8() const; + +#ifdef MDBX_I128_TYPE + MDBX_I128_TYPE as_int128() const; +#endif /* MDBX_I128_TYPE */ + int64_t as_int64() const; + int32_t as_int32() const; + int16_t as_int16() const; + int8_t as_int8() const; + protected: MDBX_CXX11_CONSTEXPR slice(size_t invalid_length) noexcept : ::MDBX_val({nullptr, invalid_length}) {} @@ -2292,6 +2332,10 @@ public: return buffer(::mdbx::slice::wrap(pod), make_reference, allocator); } + template MDBX_CXX14_CONSTEXPR POD as_pod() const { + return slice_.as_pod(); + } + /// \brief Reserves storage space. void reserve(size_t wanna_headroom, size_t wanna_tailroom) { wanna_headroom = ::std::min(::std::max(headroom(), wanna_headroom), diff --git a/src/mdbx.c++ b/src/mdbx.c++ index 590cc07d..9ac0d8d5 100644 --- a/src/mdbx.c++ +++ b/src/mdbx.c++ @@ -233,6 +233,10 @@ namespace mdbx { "into an incompatible memory allocation scheme."); } +[[noreturn]] __cold void throw_bad_value_size() { + throw bad_value_size(MDBX_BAD_VALSIZE); +} + __cold exception::exception(const ::mdbx::error &error) noexcept : base(error.what()), error_(error) {} @@ -483,6 +487,109 @@ bool slice::is_printable(bool disable_utf8) const noexcept { return true; } +#ifdef MDBX_U128_TYPE +MDBX_U128_TYPE slice::as_uint128() const { + static_assert(sizeof(MDBX_U128_TYPE) == 16, "WTF?"); + if (size() == 16) { + MDBX_U128_TYPE r; + memcpy(&r, data(), sizeof(r)); + return r; + } else + return as_uint64(); +} +#endif /* MDBX_U128_TYPE */ + +uint64_t slice::as_uint64() const { + static_assert(sizeof(uint64_t) == 8, "WTF?"); + if (size() == 8) { + uint64_t r; + memcpy(&r, data(), sizeof(r)); + return r; + } else + return as_uint32(); +} + +uint32_t slice::as_uint32() const { + static_assert(sizeof(uint32_t) == 4, "WTF?"); + if (size() == 4) { + uint32_t r; + memcpy(&r, data(), sizeof(r)); + return r; + } else + return as_uint16(); +} + +uint16_t slice::as_uint16() const { + static_assert(sizeof(uint16_t) == 2, "WTF?"); + if (size() == 2) { + uint16_t r; + memcpy(&r, data(), sizeof(r)); + return r; + } else + return as_uint8(); +} + +uint8_t slice::as_uint8() const { + static_assert(sizeof(uint8_t) == 1, "WTF?"); + if (size() == 1) + return *static_cast(data()); + else if (size() == 0) + return 0; + else + MDBX_CXX20_UNLIKELY throw_bad_value_size(); +} + +#ifdef MDBX_I128_TYPE +MDBX_I128_TYPE slice::as_int128() const { + static_assert(sizeof(MDBX_I128_TYPE) == 16, "WTF?"); + if (size() == 16) { + MDBX_I128_TYPE r; + memcpy(&r, data(), sizeof(r)); + return r; + } else + return as_int64(); +} +#endif /* MDBX_I128_TYPE */ + +int64_t slice::as_int64() const { + static_assert(sizeof(int64_t) == 8, "WTF?"); + if (size() == 8) { + uint64_t r; + memcpy(&r, data(), sizeof(r)); + return r; + } else + return as_int32(); +} + +int32_t slice::as_int32() const { + static_assert(sizeof(int32_t) == 4, "WTF?"); + if (size() == 4) { + int32_t r; + memcpy(&r, data(), sizeof(r)); + return r; + } else + return as_int16(); +} + +int16_t slice::as_int16() const { + static_assert(sizeof(int16_t) == 2, "WTF?"); + if (size() == 2) { + int16_t r; + memcpy(&r, data(), sizeof(r)); + return r; + } else + return as_int8(); +} + +int8_t slice::as_int8() const { + if (size() == 1) + return *static_cast(data()); + else if (size() == 0) + return 0; + else + MDBX_CXX20_UNLIKELY throw_bad_value_size(); +} + //------------------------------------------------------------------------------ char *to_hex::write_bytes(char *__restrict const dest, size_t dest_size) const {