aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2018-07-12 17:39:48 -0400
committerDeterminant <ted.sybil@gmail.com>2018-07-12 17:39:48 -0400
commit33faa8e355dc47a126790f1ea3e52d1813aedc69 (patch)
tree151c047fd4b8b8a10be2ca45931c482ceb79b451
parenta0ea3b5fb7eaedb9b6789657bed998585bb98b77 (diff)
support array type in smart pointers
-rw-r--r--include/salticidae/ref.h341
-rw-r--r--include/salticidae/stream.h79
-rw-r--r--include/salticidae/type.h7
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<typename T>
-class BoxObj {
- T *obj;
+struct default_delete {
+ constexpr default_delete() = default;
+ void operator()(T *ptr) const {
+ static_assert(!std::is_void<T>::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<typename T>
+struct default_delete<T[]> {
+ constexpr default_delete() = default;
+ void operator()(T *ptr) const {
+ static_assert(sizeof(T) > 0,
+ "can't delete pointer to incomplete type");
+ delete [] ptr;
}
+};
+
+template<typename T, typename D>
+class BoxObj;
+
+template<typename T, typename D>
+class _BoxObj {
+ protected:
+ using ptr_type = T *;
+ ptr_type obj;
+ constexpr _BoxObj(ptr_type obj): obj(obj) {}
public:
- template<typename T__, typename T_>
- friend BoxObj<T__> static_pointer_cast(const BoxObj<T_> &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<typename T_>
- BoxObj(BoxObj<T_> &&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<typename T, typename D = default_delete<T>>
+class BoxObj: public _BoxObj<T, D> {
+ using base_t = _BoxObj<T, D>;
+ template<typename T__, typename D__, typename T_, typename D_>
+ friend BoxObj<T__, D__> static_pointer_cast(BoxObj<T_, D_> &&other);
+
+ public:
+ BoxObj() = default;
+ BoxObj(T *obj): base_t(obj) {}
+ template<typename T_, typename =
+ typename std::enable_if<!std::is_array<T_>::value>::value>
+ BoxObj(BoxObj<T_> &&other): base_t(other) {}
+
+ T *operator->() const { return base_t::obj; }
+};
+
+template<typename T, typename D>
+class BoxObj<T[], D>: public _BoxObj<T, D> {
+ using base_t = _BoxObj<T, D>;
+ template<typename T__, typename D__, typename T_, typename D_>
+ friend BoxObj<T__, D__> static_pointer_cast(BoxObj<T_, D_> &&other);
+
+ public:
+ BoxObj() = default;
+ BoxObj(T obj[]): base_t(obj) {}
+ template<typename T_>
+ BoxObj(BoxObj<T_[]> &&other): base_t(std::move(other)) {}
+
+ T &operator[](size_t idx) { return base_t::obj[idx]; }
};
-template<typename T, typename T_>
-BoxObj<T> static_pointer_cast(BoxObj<T_> &&other) {
- BoxObj<T> box{};
- box.obj = static_cast<T *>(other.obj);
+template<typename T, typename D = default_delete<T>, typename T_, typename D_>
+BoxObj<T, D> static_pointer_cast(BoxObj<T_, D_> &&other) {
+ BoxObj<T, D> box{};
+ box.obj = static_cast<typename BoxObj<T, D>::ptr_type>(other.obj);
return std::move(box);
}
@@ -118,96 +175,147 @@ struct _ARCCtl {
~_ARCCtl() {}
};
-template<typename T, typename R> class RcObjBase;
+template<typename T, typename R, typename D> class RcObjBase;
template<typename T, typename R>
-class WeakObjBase {
+class _WeakObjBase {
T *obj;
R *ctl;
- void release() { if (ctl) ctl->release_weak(); }
+
+ template<typename D> using ROB = RcObjBase<T, R, D>;
+ friend class ROB;
+ friend std::hash<_WeakObjBase<T, R>>;
+
public:
- friend RcObjBase<T, R>;
- friend std::hash<WeakObjBase<T, R>>;
- 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<T, R> &other);
+ template<typename D>
+ _WeakObjBase(const RcObjBase<T, R, D> &other);
- ~WeakObjBase() { release(); }
+ ~_WeakObjBase() { if (ctl) ctl->release_weak(); }
};
+
template<typename T, typename R>
-class RcObjBase {
- T *obj;
- R *ctl;
- void release() {
- if (ctl && ctl->release_ref())
- delete obj;
- }
+class WeakObjBase: public _WeakObjBase<T, R> {
+ public:
+ WeakObjBase() = default;
+ WeakObjBase(const WeakObjBase &other) = default;
+ WeakObjBase(WeakObjBase &&other) = default;
+ template<typename D>
+ WeakObjBase(const RcObjBase<T, R, D> &other);
+};
+
+template<typename T, typename R>
+class WeakObjBase<T[], R>: public _WeakObjBase<T, R> {
public:
+ WeakObjBase() = default;
+ WeakObjBase(const WeakObjBase &other) = default;
+ WeakObjBase(WeakObjBase &&other) = default;
+ template<typename D>
+ WeakObjBase(const RcObjBase<T[], R, D> &other);
+};
+
+
+template<typename T, typename R, typename D>
+class _RcObjBase {
+ protected:
+ using ptr_type = T *;
+ ptr_type obj;
+ R *ctl;
+
friend WeakObjBase<T, R>;
- friend std::hash<RcObjBase<T, R>>;
- template<typename T__, typename T_, typename R_>
- friend RcObjBase<T__, R_> static_pointer_cast(const RcObjBase<T_, R_> &other);
- template<typename T__, typename T_, typename R_>
- friend RcObjBase<T__, R_> static_pointer_cast(RcObjBase<T_, R_> &&other);
- template<typename T_, typename R_> friend class RcObjBase;
+ friend std::hash<_RcObjBase<T, R, D>>;
+ template<typename T_, typename R_, typename D_>
+ 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<T> &&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<T> &&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<typename T_>
- RcObjBase(const RcObjBase<T_, R> &other):
+ template<typename T_, typename D_>
+ _RcObjBase(const _RcObjBase<T_, R, D_> &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<typename T_>
- RcObjBase(RcObjBase<T_, R> &&other):
+ template<typename T_, typename D_>
+ _RcObjBase(_RcObjBase<T_, R, D_> &&other):
obj(other.obj), ctl(other.ctl) {
other.ctl = nullptr;
}
- RcObjBase(const WeakObjBase<T, R> &other) {
+ _RcObjBase(const WeakObjBase<T, R> &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<typename T, typename T_, typename R>
-RcObjBase<T, R> static_pointer_cast(const RcObjBase<T_, R> &other) {
- RcObjBase<T, R> rc{};
- rc.obj = static_cast<T *>(other.obj);
+template<typename T, typename R, typename D = default_delete<T>>
+class RcObjBase: public _RcObjBase<T, R, D> {
+ using base_t = _RcObjBase<T, R, D>;
+ template<typename T__, typename D__, typename T_, typename R_, typename D_>
+ friend RcObjBase<T__, R_, D__> static_pointer_cast(const RcObjBase<T_, R_, D_> &other);
+ template<typename T__, typename D__, typename T_, typename R_, typename D_>
+ friend RcObjBase<T__, R_, D__> static_pointer_cast(RcObjBase<T_, R_, D_> &&other);
+
+ public:
+ T *operator->() const { return base_t::obj; }
+ RcObjBase() = default;
+ RcObjBase(T *obj): base_t(obj) {}
+ RcObjBase(BoxObj<T> &&box_ref): base_t(std::move(box_ref)) {}
+
+ template<typename T_, typename D_,
+ typename = typename std::enable_if<!std::is_array<T_>::value>::value>
+ RcObjBase(const RcObjBase<T_, R, D_> &other): base_t(other) {}
+
+ template<typename T_, typename D_,
+ typename = typename std::enable_if<!std::is_array<T_>::value>::value>
+ RcObjBase(RcObjBase<T_, R, D_> &&other): base_t(std::move(other)) {}
+
+ RcObjBase(const WeakObjBase<T, R> &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>
+class RcObjBase<T[], R, D>: public _RcObjBase<T, R, D> {
+ using base_t = _RcObjBase<T, R, D>;
+ template<typename T__, typename D__, typename T_, typename R_, typename D_>
+ friend RcObjBase<T__, R_, D__> static_pointer_cast(const RcObjBase<T_, R_, D_> &other);
+ template<typename T__, typename D__, typename T_, typename R_, typename D_>
+ friend RcObjBase<T__, R_, D__> static_pointer_cast(RcObjBase<T_, R_, D_> &&other);
+
+ public:
+ T &operator[](size_t idx) { return base_t::obj; }
+ RcObjBase() = default;
+ RcObjBase(T obj[]): base_t(obj) {}
+ RcObjBase(BoxObj<T[]> &&box_ref): base_t(std::move(box_ref)) {}
+
+ template<typename T_, typename D_>
+ RcObjBase(const RcObjBase<T_[], R, D_> &other): base_t(other) {}
+
+ template<typename T_, typename D_>
+ RcObjBase(RcObjBase<T_[], R, D_> &&other): base_t(std::move(other)) {}
+
+ RcObjBase(const WeakObjBase<T[], R> &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 D = default_delete<T>,
+ typename T_, typename R_, typename D_>
+RcObjBase<T, R_, D> static_pointer_cast(const RcObjBase<T_, R_, D_> &other) {
+ RcObjBase<T, R_, D> rc{};
+ rc.obj = static_cast<typename RcObjBase<T, R_, D>::ptr_type>(other.obj);
if ((rc.ctl = other.ctl))
rc.ctl->add_ref();
return std::move(rc);
}
-template<typename T, typename T_, typename R>
-RcObjBase<T, R> static_pointer_cast(RcObjBase<T_, R> &&other) {
- RcObjBase<T, R> rc{};
- rc.obj = static_cast<T *>(other.obj);
+template<typename T, typename D = default_delete<T>,
+ typename T_, typename R_, typename D_>
+RcObjBase<T, R_, D> static_pointer_cast(RcObjBase<T_, R_, D_> &&other) {
+ RcObjBase<T, R_, D> rc{};
+ rc.obj = static_cast<typename RcObjBase<T, R_, D>::ptr_type>(other.obj);
rc.ctl = other.ctl;
other.ctl = nullptr;
return std::move(rc);
}
template<typename T, typename R>
-inline WeakObjBase<T, R>::WeakObjBase(const RcObjBase<T, R> &other):
+template<typename D>
+inline _WeakObjBase<T, R>::_WeakObjBase(const RcObjBase<T, R, D> &other):
obj(other.obj), ctl(other.ctl) {
if (ctl) ctl->add_weak();
}
-
template<typename T> using RcObj = RcObjBase<T, _RCCtl>;
template<typename T> using WeakObj = WeakObjBase<T, _RCCtl>;
@@ -260,9 +433,9 @@ template<typename T> using AweakObj = WeakObjBase<T, _ARCCtl>;
}
namespace std {
- template<typename T, typename R>
- struct hash<salticidae::RcObjBase<T, R>> {
- size_t operator()(const salticidae::RcObjBase<T, R> &k) const {
+ template<typename T, typename R, typename D>
+ struct hash<salticidae::RcObjBase<T, R, D>> {
+ size_t operator()(const salticidae::RcObjBase<T, R, D> &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<typename T = uint64_t>
+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>(uint16_t x) { return le16toh(x); }
template<> inline uint32_t letoh<uint32_t>(uint32_t x) { return le32toh(x); }
template<> inline uint64_t letoh<uint64_t>(uint64_t x) { return le64toh(x); }
+template<typename... >
+using void_t = void;
+
template <typename T, typename = void>
struct is_ranged : std::false_type {};
template <typename T>
struct is_ranged<T,
- std::void_t<decltype(std::declval<T>().begin()),
- decltype(std::declval<T>().end())>> : std::true_type {};
+ void_t<decltype(std::declval<T>().begin()),
+ decltype(std::declval<T>().end())>> : std::true_type {};
}