From d8e500b2d785b6c8e12ceb25efe68c32aad46a8b Mon Sep 17 00:00:00 2001 From: Determinant Date: Fri, 13 Jul 2018 14:35:03 -0400 Subject: finish Bits impl --- include/salticidae/ref.h | 1 + include/salticidae/stream.h | 66 ++++++++++++++++++++++++++++++++------------- include/salticidae/type.h | 17 ++++++++++++ 3 files changed, 65 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/include/salticidae/ref.h b/include/salticidae/ref.h index c0b77a3..7239402 100644 --- a/include/salticidae/ref.h +++ b/include/salticidae/ref.h @@ -131,6 +131,7 @@ class BoxObj: public _BoxObj { BoxObj(BoxObj &&other): base_t(std::move(other)) {} T &operator[](size_t idx) { return base_t::obj[idx]; } + const T &operator[] (size_t idx) const { return base_t::obj[idx]; } }; template, typename T_, typename D_> diff --git a/include/salticidae/stream.h b/include/salticidae/stream.h index b5e0757..5b7e936 100644 --- a/include/salticidae/stream.h +++ b/include/salticidae/stream.h @@ -271,36 +271,36 @@ class Blob { }; template -class Bits { +class _Bits { using _impl_type = T; - static const size_t bit_per_datum = sizeof(_impl_type) * 8; + static const uint32_t bit_per_datum = sizeof(_impl_type) * 8; + static const uint32_t shift_per_datum = log2::value; BoxObj<_impl_type[]> data; - size_t nbits; - size_t ndata; + uint32_t nbits; + uint32_t ndata; public: - Bits(): data(nullptr) {} - Bits(const bytearray_t &arr) { + _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) { + _Bits(const uint8_t *arr, uint32_t len) { load(arr, len); } + _Bits(uint32_t nbits): nbits(nbits) { ndata = (nbits + bit_per_datum - 1) / bit_per_datum; data = new _impl_type[ndata]; } - ~Bits() {} + ~_Bits() {} - void load(const uint8_t *arr, size_t len) { + void load(const uint8_t *arr, uint32_t len) { nbits = len * 8; - ndata = (len + sizeof(_impl_type) - 1) / - sizeof(_impl_type); + ndata = (nbits + bit_per_datum - 1) / bit_per_datum; data = new _impl_type[ndata]; uint8_t *end = arr + len; - for (_impl_type *ptr = data; ptr < data + ndata;) + for (_impl_type *ptr = data.get(); ptr < data.get() + ndata;) { _impl_type x = 0; for (unsigned j = 0, k = 0; j < sizeof(_impl_type); j++, k += 8) @@ -317,24 +317,24 @@ class Bits { s << htole(nbits); if (data) { - for (const _impl_type *ptr = data; ptr < data + ndata; ptr++) + for (const _impl_type *ptr = data.get(); ptr < data.get() + ndata; ptr++) s << htole(*ptr); } else { - for (const _impl_type *ptr = data; ptr < data + ndata; ptr++) + for (const _impl_type *ptr = data.get(); ptr < data.get() + ndata; ptr++) s << htole((_impl_type)0); } } void unserialize(DataStream &s) { - _impl_type x; - s >> x; - nbits = letoh(x); + s >> nbits; + nbits = letoh(nbits); ndata = (nbits + bit_per_datum - 1) / bit_per_datum; data = new _impl_type[ndata]; - for (_impl_type *ptr = data; ptr < data + ndata; ptr++) + for (_impl_type *ptr = data.get(); ptr < data.get() + ndata; ptr++) { + _impl_type x; s >> x; *ptr = letoh(x); } @@ -345,8 +345,36 @@ class Bits { s << *this; return std::move(s); } + + uint8_t get(uint32_t idx) const { + return (data[idx >> shift_per_datum] >> + (idx & (bit_per_datum - 1))) & 1; + } + + void set(uint32_t idx) { + auto i = idx >> shift_per_datum; + auto pos = idx & (bit_per_datum - 1); + data[i] ^= ((data[i] >> pos) ^ 1) << pos; + } + + void unset(uint32_t idx) { + auto i = idx >> shift_per_datum; + auto pos = idx & (bit_per_datum - 1); + data[i] ^= (data[i] >> pos) << pos; + } + + void flip(uint32_t idx) { + auto i = idx >> shift_per_datum; + auto pos = idx & (bit_per_datum - 1); + data[i] ^= ((_impl_type)1) << pos; + } + + uint8_t operator[](uint32_t idx) const { return get(idx); } + + uint32_t size() const { return nbits; } }; +using Bits = _Bits<>; const size_t ENT_HASH_LENGTH = 256 / 8; diff --git a/include/salticidae/type.h b/include/salticidae/type.h index d5834a5..13975a5 100644 --- a/include/salticidae/type.h +++ b/include/salticidae/type.h @@ -65,6 +65,23 @@ struct is_ranged().begin()), decltype(std::declval().end())>> : std::true_type {}; +template +struct log2 { + enum { + value = 1 + log2::value + }; +}; + +template<> +struct log2<0> { + enum { value = 0 }; +}; + +template<> +struct log2<1> { + enum { value = 0 }; +}; + } #endif -- cgit v1.2.3-70-g09d2