blob.hpp (3600B)
1 #ifndef _C4_BLOB_HPP_ 2 #define _C4_BLOB_HPP_ 3 4 #include "c4/types.hpp" 5 #include "c4/error.hpp" 6 7 /** @file blob.hpp Mutable and immutable binary data blobs. 8 */ 9 10 namespace c4 { 11 12 template<class T> 13 struct blob_; 14 15 namespace detail { 16 template<class T> struct is_blob_type : std::integral_constant<bool, false> {}; 17 template<class T> struct is_blob_type<blob_<T>> : std::integral_constant<bool, true> {}; 18 template<class T> struct is_blob_value_type : std::integral_constant<bool, (std::is_fundamental<T>::value || std::is_trivially_copyable<T>::value)> {}; 19 } // namespace 20 21 template<class T> 22 struct blob_ 23 { 24 static_assert(std::is_same<T, byte>::value || std::is_same<T, cbyte>::value, "must be either byte or cbyte"); 25 static_assert(sizeof(T) == 1u, "must be either byte or cbyte"); 26 27 public: 28 29 T * buf; 30 size_t len; 31 32 public: 33 34 C4_ALWAYS_INLINE blob_() noexcept = default; 35 C4_ALWAYS_INLINE blob_(blob_ const& that) noexcept = default; 36 C4_ALWAYS_INLINE blob_(blob_ && that) noexcept = default; 37 C4_ALWAYS_INLINE blob_& operator=(blob_ && that) noexcept = default; 38 C4_ALWAYS_INLINE blob_& operator=(blob_ const& that) noexcept = default; 39 40 template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_(blob_<U> const& that) noexcept : buf(that.buf), len(that.len) {} 41 template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_(blob_<U> && that) noexcept : buf(that.buf), len(that.len) {} 42 template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_& operator=(blob_<U> && that) noexcept { buf = that.buf; len = that.len; } 43 template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_& operator=(blob_<U> const& that) noexcept { buf = that.buf; len = that.len; } 44 45 C4_ALWAYS_INLINE blob_(void *ptr, size_t n) noexcept : buf(reinterpret_cast<T*>(ptr)), len(n) {} 46 C4_ALWAYS_INLINE blob_(void const *ptr, size_t n) noexcept : buf(reinterpret_cast<T*>(ptr)), len(n) {} 47 48 #define _C4_REQUIRE_BLOBTYPE(ty) class=typename std::enable_if<((!detail::is_blob_type<ty>::value) && (detail::is_blob_value_type<ty>::value)), T>::type 49 template<class U, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_(U &var) noexcept : buf(reinterpret_cast<T*>(&var)), len(sizeof(U)) {} 50 template<class U, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_(U *ptr, size_t n) noexcept : buf(reinterpret_cast<T*>(ptr)), len(sizeof(U) * n) { C4_ASSERT(is_aligned(ptr)); } 51 template<class U, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_& operator= (U &var) noexcept { buf = reinterpret_cast<T*>(&var); len = sizeof(U); return *this; } 52 template<class U, size_t N, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_(U (&arr)[N]) noexcept : buf(reinterpret_cast<T*>(arr)), len(sizeof(U) * N) {} 53 template<class U, size_t N, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_& operator= (U (&arr)[N]) noexcept { buf = reinterpret_cast<T*>(arr); len = sizeof(U) * N; return *this; } 54 #undef _C4_REQUIRE_BLOBTYPE 55 }; 56 57 /** an immutable binary blob */ 58 using cblob = blob_<cbyte>; 59 /** a mutable binary blob */ 60 using blob = blob_< byte>; 61 62 C4_MUST_BE_TRIVIAL_COPY(blob); 63 C4_MUST_BE_TRIVIAL_COPY(cblob); 64 65 } // namespace c4 66 67 #endif // _C4_BLOB_HPP_