From 33faa8e355dc47a126790f1ea3e52d1813aedc69 Mon Sep 17 00:00:00 2001 From: Determinant Date: Thu, 12 Jul 2018 17:39:48 -0400 Subject: support array type in smart pointers --- include/salticidae/ref.h | 341 +++++++++++++++++++++++++++++++++----------- include/salticidae/stream.h | 79 ++++++++++ include/salticidae/type.h | 7 +- 3 files changed, 341 insertions(+), 86 deletions(-) diff --git a/include/salticidae/ref.h b/include/salticidae/ref.h index c2dcdd3..a1c5dc7 100644 --- a/include/salticidae/ref.h +++ b/include/salticidae/ref.h @@ -31,45 +31,102 @@ namespace salticidae { template -class BoxObj { - T *obj; +struct default_delete { + constexpr default_delete() = default; + void operator()(T *ptr) const { + static_assert(!std::is_void::value, + "can't delete pointer to incomplete type"); + static_assert(sizeof(T) > 0, + "can't delete pointer to incomplete type"); + delete ptr; + } +}; - void release() { - if (obj) delete obj; +template +struct default_delete { + constexpr default_delete() = default; + void operator()(T *ptr) const { + static_assert(sizeof(T) > 0, + "can't delete pointer to incomplete type"); + delete [] ptr; } +}; + +template +class BoxObj; + +template +class _BoxObj { + protected: + using ptr_type = T *; + ptr_type obj; + constexpr _BoxObj(ptr_type obj): obj(obj) {} public: - template - friend BoxObj static_pointer_cast(const BoxObj &other); - operator T*() const { return obj; } - T *operator->() const { return obj; } - BoxObj(): obj(nullptr) {} - BoxObj(T *obj): obj(obj) {} - BoxObj &operator=(const BoxObj &other) = delete; - BoxObj &operator=(BoxObj &&other) { - release(); - obj = other.obj; + + constexpr _BoxObj(): obj(nullptr) {} + _BoxObj(const _BoxObj &other) = delete; + _BoxObj(_BoxObj &&other): obj(other.obj) { other.obj = nullptr; - return *this; } - BoxObj(const BoxObj &other) = delete; - BoxObj(BoxObj &&other): obj(other.obj) { - other.obj = nullptr; + + ~_BoxObj() { + if (obj) D()(obj); } - template - BoxObj(BoxObj &&other): obj(other.obj) { - other.obj = nullptr; + void swap(_BoxObj &other) { + std::swap(obj, other.obj); } - ~BoxObj() { release(); } + _BoxObj &operator=(const _BoxObj &other) = delete; + _BoxObj &operator=(_BoxObj &&other) { + if (this != &other) + { + _BoxObj tmp(std::move(other)); + tmp.swap(*this); + } + return *this; + } + + operator T*() const { return obj; } +}; + +template> +class BoxObj: public _BoxObj { + using base_t = _BoxObj; + template + friend BoxObj static_pointer_cast(BoxObj &&other); + + public: + BoxObj() = default; + BoxObj(T *obj): base_t(obj) {} + template::value>::value> + BoxObj(BoxObj &&other): base_t(other) {} + + T *operator->() const { return base_t::obj; } +}; + +template +class BoxObj: public _BoxObj { + using base_t = _BoxObj; + template + friend BoxObj static_pointer_cast(BoxObj &&other); + + public: + BoxObj() = default; + BoxObj(T obj[]): base_t(obj) {} + template + BoxObj(BoxObj &&other): base_t(std::move(other)) {} + + T &operator[](size_t idx) { return base_t::obj[idx]; } }; -template -BoxObj static_pointer_cast(BoxObj &&other) { - BoxObj box{}; - box.obj = static_cast(other.obj); +template, typename T_, typename D_> +BoxObj static_pointer_cast(BoxObj &&other) { + BoxObj box{}; + box.obj = static_cast::ptr_type>(other.obj); return std::move(box); } @@ -118,96 +175,147 @@ struct _ARCCtl { ~_ARCCtl() {} }; -template class RcObjBase; +template class RcObjBase; template -class WeakObjBase { +class _WeakObjBase { T *obj; R *ctl; - void release() { if (ctl) ctl->release_weak(); } + + template using ROB = RcObjBase; + friend class ROB; + friend std::hash<_WeakObjBase>; + public: - friend RcObjBase; - friend std::hash>; - WeakObjBase(): ctl(nullptr) {} - WeakObjBase &operator=(const WeakObjBase &other) { - release(); - obj = other.obj; - if ((ctl = other.ctl)) - ctl->add_weak(); + _WeakObjBase(): ctl(nullptr) {} + + void swap(_WeakObjBase &other) { + std::swap(obj, other.obj); + std::swap(ctl, other.ctl); + } + + _WeakObjBase &operator=(const _WeakObjBase &other) { + if (this != &other) + { + _WeakObjBase tmp(other); + tmp.swap(*this); + } return *this; } - WeakObjBase(const WeakObjBase &other): + _WeakObjBase &operator=(_WeakObjBase &&other) { + if (this != &other) + { + _WeakObjBase tmp(std::move(other)); + tmp.swap(*this); + } + return *this; + } + + _WeakObjBase(const _WeakObjBase &other): obj(other.obj), ctl(other.ctl) { if (ctl) ctl->add_weak(); } - WeakObjBase(WeakObjBase &&other): + _WeakObjBase(_WeakObjBase &&other): obj(other.obj), ctl(other.ctl) { other.ctl = nullptr; } - WeakObjBase(const RcObjBase &other); + template + _WeakObjBase(const RcObjBase &other); - ~WeakObjBase() { release(); } + ~_WeakObjBase() { if (ctl) ctl->release_weak(); } }; + template -class RcObjBase { - T *obj; - R *ctl; - void release() { - if (ctl && ctl->release_ref()) - delete obj; - } +class WeakObjBase: public _WeakObjBase { + public: + WeakObjBase() = default; + WeakObjBase(const WeakObjBase &other) = default; + WeakObjBase(WeakObjBase &&other) = default; + template + WeakObjBase(const RcObjBase &other); +}; + +template +class WeakObjBase: public _WeakObjBase { public: + WeakObjBase() = default; + WeakObjBase(const WeakObjBase &other) = default; + WeakObjBase(WeakObjBase &&other) = default; + template + WeakObjBase(const RcObjBase &other); +}; + + +template +class _RcObjBase { + protected: + using ptr_type = T *; + ptr_type obj; + R *ctl; + friend WeakObjBase; - friend std::hash>; - template - friend RcObjBase static_pointer_cast(const RcObjBase &other); - template - friend RcObjBase static_pointer_cast(RcObjBase &&other); - template friend class RcObjBase; + friend std::hash<_RcObjBase>; + template + friend class _RcObjBase; + public: operator T*() const { return obj; } - T *operator->() const { return obj; } - RcObjBase(): obj(nullptr), ctl(nullptr) {} - RcObjBase(T *obj): obj(obj), ctl(new R()) {} - RcObjBase(BoxObj &&box_ref): obj(box_ref.obj), ctl(new R()) { + _RcObjBase(): obj(nullptr), ctl(nullptr) {} + _RcObjBase(ptr_type obj): obj(obj), ctl(new R()) {} + _RcObjBase(BoxObj &&box_ref): obj(box_ref.obj), ctl(new R()) { box_ref.obj = nullptr; } - RcObjBase &operator=(const RcObjBase &other) { - release(); - obj = other.obj; - if ((ctl = other.ctl)) - ctl->add_ref(); + void swap(_RcObjBase &other) { + std::swap(obj, other.obj); + std::swap(ctl, other.ctl); + } + + _RcObjBase &operator=(const _RcObjBase &other) { + if (this != &other) + { + _RcObjBase tmp(other); + tmp.swap(*this); + } return *this; } - RcObjBase(const RcObjBase &other): + _RcObjBase &operator=(_RcObjBase &&other) { + if (this != &other) + { + _RcObjBase tmp(std::move(other)); + tmp.swap(*this); + } + return *this; + } + + _RcObjBase(const _RcObjBase &other): obj(other.obj), ctl(other.ctl) { if (ctl) ctl->add_ref(); } - template - RcObjBase(const RcObjBase &other): + template + _RcObjBase(const _RcObjBase &other): obj(other.obj), ctl(other.ctl) { if (ctl) ctl->add_ref(); } - RcObjBase(RcObjBase &&other): + _RcObjBase(_RcObjBase &&other): obj(other.obj), ctl(other.ctl) { other.ctl = nullptr; } - template - RcObjBase(RcObjBase &&other): + template + _RcObjBase(_RcObjBase &&other): obj(other.obj), ctl(other.ctl) { other.ctl = nullptr; } - RcObjBase(const WeakObjBase &other) { + _RcObjBase(const WeakObjBase &other) { if (other.ctl && other.ctl->ref_cnt) { obj = other.obj; @@ -221,36 +329,101 @@ class RcObjBase { } } - ~RcObjBase() { release(); } + ~_RcObjBase() { + if (ctl && ctl->release_ref()) + D()(obj); + } size_t get_cnt() const { return ctl ? ctl->get_cnt() : 0; } }; -template -RcObjBase static_pointer_cast(const RcObjBase &other) { - RcObjBase rc{}; - rc.obj = static_cast(other.obj); +template> +class RcObjBase: public _RcObjBase { + using base_t = _RcObjBase; + template + friend RcObjBase static_pointer_cast(const RcObjBase &other); + template + friend RcObjBase static_pointer_cast(RcObjBase &&other); + + public: + T *operator->() const { return base_t::obj; } + RcObjBase() = default; + RcObjBase(T *obj): base_t(obj) {} + RcObjBase(BoxObj &&box_ref): base_t(std::move(box_ref)) {} + + template::value>::value> + RcObjBase(const RcObjBase &other): base_t(other) {} + + template::value>::value> + RcObjBase(RcObjBase &&other): base_t(std::move(other)) {} + + RcObjBase(const WeakObjBase &other): base_t(other) {} + + + RcObjBase(const RcObjBase &other) = default; + RcObjBase(RcObjBase &&other) = default; + RcObjBase &operator=(const RcObjBase &) = default; + RcObjBase &operator=(RcObjBase &&) = default; +}; + +template +class RcObjBase: public _RcObjBase { + using base_t = _RcObjBase; + template + friend RcObjBase static_pointer_cast(const RcObjBase &other); + template + friend RcObjBase static_pointer_cast(RcObjBase &&other); + + public: + T &operator[](size_t idx) { return base_t::obj; } + RcObjBase() = default; + RcObjBase(T obj[]): base_t(obj) {} + RcObjBase(BoxObj &&box_ref): base_t(std::move(box_ref)) {} + + template + RcObjBase(const RcObjBase &other): base_t(other) {} + + template + RcObjBase(RcObjBase &&other): base_t(std::move(other)) {} + + RcObjBase(const WeakObjBase &other): base_t(other) {} + + RcObjBase(const RcObjBase &other) = default; + RcObjBase(RcObjBase &&other) = default; + RcObjBase &operator=(const RcObjBase &) = default; + RcObjBase &operator=(RcObjBase &&) = default; +}; + + +template, + typename T_, typename R_, typename D_> +RcObjBase static_pointer_cast(const RcObjBase &other) { + RcObjBase rc{}; + rc.obj = static_cast::ptr_type>(other.obj); if ((rc.ctl = other.ctl)) rc.ctl->add_ref(); return std::move(rc); } -template -RcObjBase static_pointer_cast(RcObjBase &&other) { - RcObjBase rc{}; - rc.obj = static_cast(other.obj); +template, + typename T_, typename R_, typename D_> +RcObjBase static_pointer_cast(RcObjBase &&other) { + RcObjBase rc{}; + rc.obj = static_cast::ptr_type>(other.obj); rc.ctl = other.ctl; other.ctl = nullptr; return std::move(rc); } template -inline WeakObjBase::WeakObjBase(const RcObjBase &other): +template +inline _WeakObjBase::_WeakObjBase(const RcObjBase &other): obj(other.obj), ctl(other.ctl) { if (ctl) ctl->add_weak(); } - template using RcObj = RcObjBase; template using WeakObj = WeakObjBase; @@ -260,9 +433,9 @@ template using AweakObj = WeakObjBase; } namespace std { - template - struct hash> { - size_t operator()(const salticidae::RcObjBase &k) const { + template + struct hash> { + size_t operator()(const salticidae::RcObjBase &k) const { return (size_t)k.obj; } }; diff --git a/include/salticidae/stream.h b/include/salticidae/stream.h index ffffbe2..9e4791c 100644 --- a/include/salticidae/stream.h +++ b/include/salticidae/stream.h @@ -26,6 +26,7 @@ #define _SALTICIDAE_STREAM_H #include "salticidae/type.h" +#include "salticidae/ref.h" #include "salticidae/crypto.h" namespace salticidae { @@ -258,6 +259,84 @@ class Blob { } }; +template +class Bits { + using _impl_type = T; + static const size_t bit_per_datum = sizeof(_impl_type) * 8; + BoxObj<_impl_type[]> data; + size_t nbits; + size_t ndata; + + public: + + Bits(): data(nullptr) {} + Bits(const bytearray_t &arr) { + load(&*arr.begin(), arr.size()); + } + + Bits(const uint8_t *arr, size_t len) { load(arr, len); } + Bits(size_t nbits): nbits(nbits) { + ndata = (nbits + bit_per_datum - 1) / bit_per_datum; + data = new _impl_type[ndata]; + } + + ~Bits() {} + + void load(const uint8_t *arr, size_t len) { + nbits = len * 8; + ndata = (len + sizeof(_impl_type) - 1) / + sizeof(_impl_type); + data = new _impl_type[ndata]; + + uint8_t *end = arr + len; + for (_impl_type *ptr = data; ptr < data + ndata;) + { + _impl_type x = 0; + for (unsigned j = 0, k = 0; j < sizeof(_impl_type); j++, k += 8) + if (arr < end) x |= *(arr++) << k; + *(ptr++) = x; + } + } + + bool is_null() const { return data == nullptr; } + + size_t cheap_hash() const { return *data; } + + void serialize(DataStream &s) const { + s << htole(nbits); + if (data) + { + for (const _impl_type *ptr = data; ptr < data + ndata; ptr++) + s << htole(*ptr); + } + else + { + for (const _impl_type *ptr = data; ptr < data + ndata; ptr++) + s << htole((_impl_type)0); + } + } + + void unserialize(DataStream &s) { + _impl_type x; + s >> x; + nbits = letoh(x); + ndata = (nbits + bit_per_datum - 1) / bit_per_datum; + data = new _impl_type[ndata]; + for (_impl_type *ptr = data; ptr < data + ndata; ptr++) + { + s >> x; + *ptr = letoh(x); + } + } + + operator bytearray_t () const & { + DataStream s; + s << *this; + return std::move(s); + } +}; + + const size_t ENT_HASH_LENGTH = 256 / 8; uint256_t DataStream::get_hash() const { diff --git a/include/salticidae/type.h b/include/salticidae/type.h index edf38a6..d5834a5 100644 --- a/include/salticidae/type.h +++ b/include/salticidae/type.h @@ -54,13 +54,16 @@ template<> inline uint16_t letoh(uint16_t x) { return le16toh(x); } template<> inline uint32_t letoh(uint32_t x) { return le32toh(x); } template<> inline uint64_t letoh(uint64_t x) { return le64toh(x); } +template +using void_t = void; + template struct is_ranged : std::false_type {}; template struct is_ranged().begin()), - decltype(std::declval().end())>> : std::true_type {}; + void_t().begin()), + decltype(std::declval().end())>> : std::true_type {}; } -- cgit v1.2.3-70-g09d2