bytes.cc | 8 ++---
bytes.hh | 18 ++++++++---
utils/mutable_view.hh | 75 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 92 insertions(+), 9 deletions(-)
diff --git a/bytes.cc b/bytes.cc
index dba49f55b..1ad98b67a 100644
--- a/bytes.cc
+++ b/bytes.cc
@@ -82,10 +82,6 @@ sstring to_hex(const bytes_opt& b) {
return !b ? "null" : to_hex(*b);
}
-std::ostream& operator<<(std::ostream& os, const bytes& b) {
- return os << to_hex(b);
-}
-
std::ostream& operator<<(std::ostream& os, const bytes_opt& b) {
if (b) {
return os << *b;
@@ -95,6 +91,10 @@ std::ostream& operator<<(std::ostream& os, const bytes_opt& b) {
namespace std {
+std::ostream& operator<<(std::ostream& os, const bytes& b) {
+ return os << to_hex(b);
+}
+
std::ostream& operator<<(std::ostream& os, const bytes_view& b) {
return os << to_hex(b);
}
diff --git a/bytes.hh b/bytes.hh
index 35730c194..f1cf109b9 100644
--- a/bytes.hh
+++ b/bytes.hh
@@ -30,9 +30,10 @@
#include "utils/mutable_view.hh"
#include <xxhash.h>
-using bytes = basic_sstring<int8_t, uint32_t, 31, false>;
-using bytes_view = std::basic_string_view<int8_t>;
-using bytes_mutable_view = basic_mutable_view<bytes_view::value_type>;
+using bytes_char_type = int8_t;
+using bytes = basic_sstring<bytes_char_type, uint32_t, 31, false>;
+using bytes_view = basic_view<bytes_char_type>;
+using bytes_mutable_view = basic_mutable_view<bytes_char_type>;
using bytes_opt = std::optional<bytes>;
using sstring_view = std::string_view;
@@ -45,7 +46,7 @@ inline sstring_view to_sstring_view(bytes_view view) {
}
inline bytes_view to_bytes_view(sstring_view view) {
- return {reinterpret_cast<const int8_t*>(view.data()), view.size()};
+ return bytes_view(reinterpret_cast<const bytes_char_type*>(view.data()), view.size());
}
struct fmt_hex {
@@ -60,12 +61,12 @@ sstring to_hex(bytes_view b);
sstring to_hex(const bytes& b);
sstring to_hex(const bytes_opt& b);
-std::ostream& operator<<(std::ostream& os, const bytes& b);
std::ostream& operator<<(std::ostream& os, const bytes_opt& b);
namespace std {
// Must be in std:: namespace, or ADL fails
+std::ostream& operator<<(std::ostream& os, const bytes& b);
std::ostream& operator<<(std::ostream& os, const bytes_view& b);
}
@@ -110,6 +111,13 @@ struct hash<bytes_view> {
return h.finalize();
}
};
+
+template <>
+struct hash<bytes> {
+ size_t operator()(bytes b) const {
+ return std::hash<bytes_view>()(bytes_view(b));
+ }
+};
} // namespace std
inline int32_t compare_unsigned(bytes_view v1, bytes_view v2) {
diff --git a/utils/mutable_view.hh b/utils/mutable_view.hh
index 5283f62c6..894422b36 100644
--- a/utils/mutable_view.hh
+++ b/utils/mutable_view.hh
@@ -41,6 +41,9 @@ class basic_view_base {
using iterator = pointer;
using const_iterator = const_pointer;
using base_iterator = std::conditional_t<is_mutable == mutable_view::yes, iterator, const_iterator>;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using base_reverse_iterator = std::conditional_t<is_mutable == mutable_view::yes, reverse_iterator, const_reverse_iterator>;
private:
base_pointer _begin = nullptr;
base_pointer _end = nullptr;
@@ -48,20 +51,59 @@ class basic_view_base {
basic_view_base() = default;
template <typename U, U N, bool NulTerminate>
+ requires ( is_mutable == mutable_view::no )
+ basic_view_base(const basic_sstring<CharT, U, N, NulTerminate>& str) noexcept
+ : _begin(str.begin())
+ , _end(str.end())
+ { }
+
+ template <typename U, U N, bool NulTerminate>
+ requires ( is_mutable == mutable_view::yes )
basic_view_base(basic_sstring<CharT, U, N, NulTerminate>& str) noexcept
: _begin(str.begin())
, _end(str.end())
{ }
+ basic_view_base(std::basic_string_view<CharT> str) noexcept
+ : _begin(str.begin())
+ , _end(str.end())
+ { }
+
basic_view_base(base_pointer ptr, size_t length) noexcept
: _begin(ptr)
, _end(ptr + length)
{ }
+ template <typename>
+ requires ( is_mutable == mutable_view::no )
+ basic_view_base(const basic_view_base<CharT, mutable_view::yes>& x) noexcept
+ : _begin(x.begin())
+ , _end(x.end())
+ { }
+
+ template <typename>
+ requires ( is_mutable == mutable_view::no )
+ basic_view_base operator=(const basic_view_base<CharT, mutable_view::yes>& x) noexcept {
+ new (this) basic_view_base(x);
+ return *this;
+ }
+
operator std::basic_string_view<CharT>() const noexcept {
return std::basic_string_view<CharT>(begin(), size());
}
+ bool operator==(const basic_view_base& x) const noexcept {
+ return size() == x.size() && std::equal(begin(), end(), x.begin());
+ }
+
+ bool operator!=(const basic_view_base& x) const noexcept {
+ return !operator==(x);
+ }
+
+ constexpr auto operator<=>(const basic_view_base& x) const noexcept {
+ return std::basic_string_view<CharT>(*this) <=> std::basic_string_view<CharT>(x);
+ }
+
base_reference operator[](size_t idx) const noexcept {
assert(idx < size());
return _begin[idx];
@@ -80,8 +122,15 @@ class basic_view_base {
const_iterator cbegin() const noexcept { return _begin; }
const_iterator cend() const noexcept { return _end; }
+ base_reverse_iterator rbegin() const noexcept { return std::make_reverse_iterator<base_iterator>(end()); }
+ base_reverse_iterator rend() const noexcept { return std::make_reverse_iterator<base_iterator>(begin()); }
+
+ const_reverse_iterator crbegin() const noexcept { return std::make_reverse_iterator<const_iterator>(end()); }
+ const_reverse_iterator crend() const noexcept { return std::make_reverse_iterator<const_iterator>(begin()); }
+
base_pointer data() const noexcept { return _begin; }
size_t size() const noexcept { return _end - _begin; }
+ size_t length() const noexcept { return size(); }
bool empty() const noexcept { return _begin == _end; }
template <typename>
@@ -96,6 +145,18 @@ class basic_view_base {
return *_begin;
}
+ template <typename>
+ requires ( is_mutable == mutable_view::yes )
+ reference back() noexcept {
+ assert(!empty());
+ return *(_end - 1);
+ }
+
+ const_reference back() const noexcept {
+ assert(!empty());
+ return *(_end - 1);
+ }
+
void remove_prefix(size_t n) noexcept {
if (__builtin_expect(n <= size(), true)) {
_begin += n;
@@ -119,5 +180,19 @@ class basic_view_base {
}
};
+namespace std {
+
+template <typename CharT, mutable_view is_mutable>
+struct hash<basic_view_base<CharT, is_mutable>> {
+ size_t operator()(const basic_view_base<CharT, is_mutable>& v) const {
+ return std::hash<std::basic_string_view<CharT>>()(v);
+ }
+};
+
+}
+
template <typename CharT>
using basic_mutable_view = basic_view_base<CharT, mutable_view::yes>;
+
+template <typename CharT>
+using basic_view = basic_view_base<CharT, mutable_view::no>;
--
2.31.1