mirror of
https://github.com/oxen-io/oxen-mq.git
synced 2023-12-13 21:00:31 +01:00
Made simple_string_view take a char type
This allows (most usefully) a `ustring_view` for viewing unsigned char strings.
This commit is contained in:
parent
bc49b5e9a0
commit
af42875e97
2 changed files with 134 additions and 56 deletions
15
lokimq/hex.h
15
lokimq/hex.h
|
@ -75,6 +75,13 @@ inline std::string to_hex(string_view s) {
|
||||||
return hex;
|
return hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::string to_hex(ustring_view s) {
|
||||||
|
std::string hex;
|
||||||
|
hex.reserve(s.size() * 2);
|
||||||
|
to_hex(s.begin(), s.end(), std::back_inserter(hex));
|
||||||
|
return hex;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if all elements in the range are hex characters
|
/// Returns true if all elements in the range are hex characters
|
||||||
template <typename It>
|
template <typename It>
|
||||||
constexpr bool is_hex(It begin, It end) {
|
constexpr bool is_hex(It begin, It end) {
|
||||||
|
@ -87,6 +94,7 @@ constexpr bool is_hex(It begin, It end) {
|
||||||
|
|
||||||
/// Returns true if all elements in the string-like value are hex characters
|
/// Returns true if all elements in the string-like value are hex characters
|
||||||
constexpr bool is_hex(string_view s) { return is_hex(s.begin(), s.end()); }
|
constexpr bool is_hex(string_view s) { return is_hex(s.begin(), s.end()); }
|
||||||
|
constexpr bool is_hex(ustring_view s) { return is_hex(s.begin(), s.end()); }
|
||||||
|
|
||||||
/// Convert a hex digit into its numeric (0-15) value
|
/// Convert a hex digit into its numeric (0-15) value
|
||||||
constexpr char from_hex_digit(unsigned char x) noexcept {
|
constexpr char from_hex_digit(unsigned char x) noexcept {
|
||||||
|
@ -119,4 +127,11 @@ inline std::string from_hex(string_view s) {
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::string from_hex(ustring_view s) {
|
||||||
|
std::string bytes;
|
||||||
|
bytes.reserve(s.size() / 2);
|
||||||
|
from_hex(s.begin(), s.end(), std::back_inserter(bytes));
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,10 @@
|
||||||
#ifdef __cpp_lib_string_view
|
#ifdef __cpp_lib_string_view
|
||||||
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
namespace lokimq { using string_view = std::string_view; }
|
namespace lokimq {
|
||||||
|
using string_view = std::string_view;
|
||||||
|
using ustring_view = std::basic_string_view<unsigned char>;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -43,16 +46,17 @@ namespace lokimq { using string_view = std::string_view; }
|
||||||
namespace lokimq {
|
namespace lokimq {
|
||||||
|
|
||||||
/// Basic implementation of std::string_view (except for std::hash support).
|
/// Basic implementation of std::string_view (except for std::hash support).
|
||||||
|
template <typename CharT>
|
||||||
class simple_string_view {
|
class simple_string_view {
|
||||||
const char *data_;
|
const CharT *data_;
|
||||||
size_t size_;
|
size_t size_;
|
||||||
public:
|
public:
|
||||||
using traits_type = std::char_traits<char>;
|
using traits_type = std::char_traits<CharT>;
|
||||||
using value_type = char;
|
using value_type = CharT;
|
||||||
using pointer = char*;
|
using pointer = CharT*;
|
||||||
using const_pointer = const char*;
|
using const_pointer = const CharT*;
|
||||||
using reference = char&;
|
using reference = CharT&;
|
||||||
using const_reference = const char&;
|
using const_reference = const CharT&;
|
||||||
using const_iterator = const_pointer;
|
using const_iterator = const_pointer;
|
||||||
using iterator = const_iterator;
|
using iterator = const_iterator;
|
||||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
@ -64,27 +68,27 @@ public:
|
||||||
|
|
||||||
constexpr simple_string_view() noexcept : data_{nullptr}, size_{0} {}
|
constexpr simple_string_view() noexcept : data_{nullptr}, size_{0} {}
|
||||||
constexpr simple_string_view(const simple_string_view&) noexcept = default;
|
constexpr simple_string_view(const simple_string_view&) noexcept = default;
|
||||||
simple_string_view(const std::string& str) : data_{str.data()}, size_{str.size()} {}
|
simple_string_view(const std::basic_string<CharT>& str) : data_{str.data()}, size_{str.size()} {}
|
||||||
constexpr simple_string_view(const char* data, size_t size) noexcept : data_{data}, size_{size} {}
|
constexpr simple_string_view(const CharT* data, size_t size) noexcept : data_{data}, size_{size} {}
|
||||||
simple_string_view(const char* data) : data_{data}, size_{traits_type::length(data)} {}
|
simple_string_view(const CharT* data) : data_{data}, size_{traits_type::length(data)} {}
|
||||||
simple_string_view& operator=(const simple_string_view&) = default;
|
simple_string_view& operator=(const simple_string_view&) = default;
|
||||||
constexpr const char* data() const noexcept { return data_; }
|
constexpr const CharT* data() const noexcept { return data_; }
|
||||||
constexpr size_t size() const noexcept { return size_; }
|
constexpr size_t size() const noexcept { return size_; }
|
||||||
constexpr size_t length() const noexcept { return size_; }
|
constexpr size_t length() const noexcept { return size_; }
|
||||||
constexpr size_t max_size() const noexcept { return std::numeric_limits<size_t>::max(); }
|
constexpr size_t max_size() const noexcept { return std::numeric_limits<size_t>::max(); }
|
||||||
constexpr bool empty() const noexcept { return size_ == 0; }
|
constexpr bool empty() const noexcept { return size_ == 0; }
|
||||||
explicit operator std::string() const { return {data_, size_}; }
|
explicit operator std::basic_string<CharT>() const { return {data_, size_}; }
|
||||||
constexpr const char* begin() const noexcept { return data_; }
|
constexpr const CharT* begin() const noexcept { return data_; }
|
||||||
constexpr const char* cbegin() const noexcept { return data_; }
|
constexpr const CharT* cbegin() const noexcept { return data_; }
|
||||||
constexpr const char* end() const noexcept { return data_ + size_; }
|
constexpr const CharT* end() const noexcept { return data_ + size_; }
|
||||||
constexpr const char* cend() const noexcept { return data_ + size_; }
|
constexpr const CharT* cend() const noexcept { return data_ + size_; }
|
||||||
reverse_iterator rbegin() const { return reverse_iterator{end()}; }
|
reverse_iterator rbegin() const { return reverse_iterator{end()}; }
|
||||||
reverse_iterator crbegin() const { return reverse_iterator{end()}; }
|
reverse_iterator crbegin() const { return reverse_iterator{end()}; }
|
||||||
reverse_iterator rend() const { return reverse_iterator{begin()}; }
|
reverse_iterator rend() const { return reverse_iterator{begin()}; }
|
||||||
reverse_iterator crend() const { return reverse_iterator{begin()}; }
|
reverse_iterator crend() const { return reverse_iterator{begin()}; }
|
||||||
constexpr const char& operator[](size_t pos) const { return data_[pos]; }
|
constexpr const CharT& operator[](size_t pos) const { return data_[pos]; }
|
||||||
constexpr const char& front() const { return *data_; }
|
constexpr const CharT& front() const { return *data_; }
|
||||||
constexpr const char& back() const { return data_[size_ - 1]; }
|
constexpr const CharT& back() const { return data_[size_ - 1]; }
|
||||||
int compare(simple_string_view s) const;
|
int compare(simple_string_view s) const;
|
||||||
constexpr void remove_prefix(size_t n) { data_ += n; size_ -= n; }
|
constexpr void remove_prefix(size_t n) { data_ += n; size_ -= n; }
|
||||||
constexpr void remove_suffix(size_t n) { size_ -= n; }
|
constexpr void remove_suffix(size_t n) { size_ -= n; }
|
||||||
|
@ -93,13 +97,13 @@ public:
|
||||||
#if defined(__clang__) || !defined(__GNUG__) || __GNUC__ >= 6
|
#if defined(__clang__) || !defined(__GNUG__) || __GNUC__ >= 6
|
||||||
constexpr // GCC 5.x is buggy wrt constexpr throwing
|
constexpr // GCC 5.x is buggy wrt constexpr throwing
|
||||||
#endif
|
#endif
|
||||||
const char& at(size_t pos) const {
|
const CharT& at(size_t pos) const {
|
||||||
if (pos >= size())
|
if (pos >= size())
|
||||||
throw std::out_of_range{"invalid string_view index"};
|
throw std::out_of_range{"invalid string_view index"};
|
||||||
return data_[pos];
|
return data_[pos];
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t copy(char* dest, size_t count, size_t pos = 0) const {
|
size_t copy(CharT* dest, size_t count, size_t pos = 0) const {
|
||||||
if (pos > size()) throw std::out_of_range{"invalid copy pos"};
|
if (pos > size()) throw std::out_of_range{"invalid copy pos"};
|
||||||
size_t rcount = std::min(count, size_ - pos);
|
size_t rcount = std::min(count, size_ - pos);
|
||||||
traits_type::copy(dest, data_ + pos, rcount);
|
traits_type::copy(dest, data_ + pos, rcount);
|
||||||
|
@ -125,9 +129,9 @@ public:
|
||||||
}
|
}
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
size_t find(char c, size_t pos = 0) const { return find({&c, 1}, pos); }
|
size_t find(CharT c, size_t pos = 0) const { return find({&c, 1}, pos); }
|
||||||
size_t find(const char* c, size_t pos, size_t count) const { return find({c, count}, pos); }
|
size_t find(const CharT* c, size_t pos, size_t count) const { return find({c, count}, pos); }
|
||||||
size_t find(const char* c, size_t pos = 0) const { return find(simple_string_view(c), pos); }
|
size_t find(const CharT* c, size_t pos = 0) const { return find(simple_string_view(c), pos); }
|
||||||
|
|
||||||
size_t rfind(simple_string_view v, size_t pos = npos) const {
|
size_t rfind(simple_string_view v, size_t pos = npos) const {
|
||||||
if (v.size_ > size_) return npos;
|
if (v.size_ > size_) return npos;
|
||||||
|
@ -138,38 +142,38 @@ public:
|
||||||
}
|
}
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
size_t rfind(char c, size_t pos = npos) const { return rfind({&c, 1}, pos); }
|
size_t rfind(CharT c, size_t pos = npos) const { return rfind({&c, 1}, pos); }
|
||||||
size_t rfind(const char* c, size_t pos, size_t count) const { return rfind({c, count}, pos); }
|
size_t rfind(const CharT* c, size_t pos, size_t count) const { return rfind({c, count}, pos); }
|
||||||
size_t rfind(const char* c, size_t pos = npos) const { return rfind(simple_string_view(c), pos); }
|
size_t rfind(const CharT* c, size_t pos = npos) const { return rfind(simple_string_view(c), pos); }
|
||||||
|
|
||||||
constexpr size_t find_first_of(simple_string_view v, size_t pos = 0) const noexcept {
|
constexpr size_t find_first_of(simple_string_view v, size_t pos = 0) const noexcept {
|
||||||
for (; pos < size_; ++pos)
|
for (; pos < size_; ++pos)
|
||||||
for (char c : v)
|
for (CharT c : v)
|
||||||
if (data_[pos] == c)
|
if (data_[pos] == c)
|
||||||
return pos;
|
return pos;
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
constexpr size_t find_first_of(char c, size_t pos = 0) const noexcept { return find_first_of({&c, 1}, pos); }
|
constexpr size_t find_first_of(CharT c, size_t pos = 0) const noexcept { return find_first_of({&c, 1}, pos); }
|
||||||
constexpr size_t find_first_of(const char* c, size_t pos, size_t count) const { return find_first_of({c, count}, pos); }
|
constexpr size_t find_first_of(const CharT* c, size_t pos, size_t count) const { return find_first_of({c, count}, pos); }
|
||||||
size_t find_first_of(const char* c, size_t pos = 0) const { return find_first_of(simple_string_view(c), pos); }
|
size_t find_first_of(const CharT* c, size_t pos = 0) const { return find_first_of(simple_string_view(c), pos); }
|
||||||
|
|
||||||
constexpr size_t find_last_of(simple_string_view v, const size_t pos = npos) const noexcept {
|
constexpr size_t find_last_of(simple_string_view v, const size_t pos = npos) const noexcept {
|
||||||
if (size_ == 0) return npos;
|
if (size_ == 0) return npos;
|
||||||
const size_t last_pos = std::min(pos, size_-1);
|
const size_t last_pos = std::min(pos, size_-1);
|
||||||
for (size_t i = last_pos; i <= last_pos; --i)
|
for (size_t i = last_pos; i <= last_pos; --i)
|
||||||
for (char c : v)
|
for (CharT c : v)
|
||||||
if (data_[i] == c)
|
if (data_[i] == c)
|
||||||
return i;
|
return i;
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
constexpr size_t find_last_of(char c, size_t pos = npos) const noexcept { return find_last_of({&c, 1}, pos); }
|
constexpr size_t find_last_of(CharT c, size_t pos = npos) const noexcept { return find_last_of({&c, 1}, pos); }
|
||||||
constexpr size_t find_last_of(const char* c, size_t pos, size_t count) const { return find_last_of({c, count}, pos); }
|
constexpr size_t find_last_of(const CharT* c, size_t pos, size_t count) const { return find_last_of({c, count}, pos); }
|
||||||
size_t find_last_of(const char* c, size_t pos = npos) const { return find_last_of(simple_string_view(c), pos); }
|
size_t find_last_of(const CharT* c, size_t pos = npos) const { return find_last_of(simple_string_view(c), pos); }
|
||||||
|
|
||||||
constexpr size_t find_first_not_of(simple_string_view v, size_t pos = 0) const noexcept {
|
constexpr size_t find_first_not_of(simple_string_view v, size_t pos = 0) const noexcept {
|
||||||
for (; pos < size_; ++pos) {
|
for (; pos < size_; ++pos) {
|
||||||
bool none = true;
|
bool none = true;
|
||||||
for (char c : v) {
|
for (CharT c : v) {
|
||||||
if (data_[pos] == c) {
|
if (data_[pos] == c) {
|
||||||
none = false;
|
none = false;
|
||||||
break;
|
break;
|
||||||
|
@ -179,16 +183,16 @@ public:
|
||||||
}
|
}
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
constexpr size_t find_first_not_of(char c, size_t pos = 0) const noexcept { return find_first_not_of({&c, 1}, pos); }
|
constexpr size_t find_first_not_of(CharT c, size_t pos = 0) const noexcept { return find_first_not_of({&c, 1}, pos); }
|
||||||
constexpr size_t find_first_not_of(const char* c, size_t pos, size_t count) const { return find_first_not_of({c, count}, pos); }
|
constexpr size_t find_first_not_of(const CharT* c, size_t pos, size_t count) const { return find_first_not_of({c, count}, pos); }
|
||||||
size_t find_first_not_of(const char* c, size_t pos = 0) const { return find_first_not_of(simple_string_view(c), pos); }
|
size_t find_first_not_of(const CharT* c, size_t pos = 0) const { return find_first_not_of(simple_string_view(c), pos); }
|
||||||
|
|
||||||
constexpr size_t find_last_not_of(simple_string_view v, const size_t pos = npos) const noexcept {
|
constexpr size_t find_last_not_of(simple_string_view v, const size_t pos = npos) const noexcept {
|
||||||
if (size_ == 0) return npos;
|
if (size_ == 0) return npos;
|
||||||
const size_t last_pos = std::min(pos, size_-1);
|
const size_t last_pos = std::min(pos, size_-1);
|
||||||
for (size_t i = last_pos; i <= last_pos; --i) {
|
for (size_t i = last_pos; i <= last_pos; --i) {
|
||||||
bool none = true;
|
bool none = true;
|
||||||
for (char c : v) {
|
for (CharT c : v) {
|
||||||
if (data_[i] == c) {
|
if (data_[i] == c) {
|
||||||
none = false;
|
none = false;
|
||||||
break;
|
break;
|
||||||
|
@ -198,47 +202,106 @@ public:
|
||||||
}
|
}
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
constexpr size_t find_last_not_of(char c, size_t pos = npos) const noexcept { return find_last_not_of({&c, 1}, pos); }
|
constexpr size_t find_last_not_of(CharT c, size_t pos = npos) const noexcept { return find_last_not_of({&c, 1}, pos); }
|
||||||
constexpr size_t find_last_not_of(const char* c, size_t pos, size_t count) const { return find_last_not_of({c, count}, pos); }
|
constexpr size_t find_last_not_of(const CharT* c, size_t pos, size_t count) const { return find_last_not_of({c, count}, pos); }
|
||||||
size_t find_last_not_of(const char* c, size_t pos = npos) const { return find_last_not_of(simple_string_view(c), pos); }
|
size_t find_last_not_of(const CharT* c, size_t pos = npos) const { return find_last_not_of(simple_string_view(c), pos); }
|
||||||
};
|
};
|
||||||
inline bool operator==(simple_string_view lhs, simple_string_view rhs) {
|
/// We have three of each of these: one with two string views, one with RHS argument deduction, and
|
||||||
return lhs.size() == rhs.size() && 0 == std::char_traits<char>::compare(lhs.data(), rhs.data(), lhs.size());
|
/// one with LHS argument deduction, so that you can do (sv == sv), (sv == "foo"), and ("foo" == sv)
|
||||||
|
template <typename CharT>
|
||||||
|
inline bool operator==(simple_string_view<CharT> lhs, simple_string_view<CharT> rhs) {
|
||||||
|
return lhs.size() == rhs.size() && 0 == std::char_traits<CharT>::compare(lhs.data(), rhs.data(), lhs.size());
|
||||||
};
|
};
|
||||||
inline bool operator!=(simple_string_view lhs, simple_string_view rhs) {
|
template <typename CharT>
|
||||||
|
inline bool operator==(simple_string_view<CharT> lhs, std::common_type_t<simple_string_view<CharT>> rhs) {
|
||||||
|
return lhs.size() == rhs.size() && 0 == std::char_traits<CharT>::compare(lhs.data(), rhs.data(), lhs.size());
|
||||||
|
};
|
||||||
|
template <typename CharT>
|
||||||
|
inline bool operator==(std::common_type_t<simple_string_view<CharT>> lhs, simple_string_view<CharT> rhs) {
|
||||||
|
return lhs.size() == rhs.size() && 0 == std::char_traits<CharT>::compare(lhs.data(), rhs.data(), lhs.size());
|
||||||
|
};
|
||||||
|
template <typename CharT>
|
||||||
|
inline bool operator!=(simple_string_view<CharT> lhs, simple_string_view<CharT> rhs) {
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
inline int simple_string_view::compare(simple_string_view s) const {
|
template <typename CharT>
|
||||||
int cmp = std::char_traits<char>::compare(data_, s.data(), std::min(size_, s.size()));
|
inline bool operator!=(simple_string_view<CharT> lhs, std::common_type_t<simple_string_view<CharT>> rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
template <typename CharT>
|
||||||
|
inline bool operator!=(std::common_type_t<simple_string_view<CharT>> lhs, simple_string_view<CharT> rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
template <typename CharT>
|
||||||
|
inline int simple_string_view<CharT>::compare(simple_string_view s) const {
|
||||||
|
int cmp = std::char_traits<CharT>::compare(data_, s.data(), std::min(size_, s.size()));
|
||||||
if (cmp) return cmp;
|
if (cmp) return cmp;
|
||||||
if (size_ < s.size()) return -1;
|
if (size_ < s.size()) return -1;
|
||||||
else if (size_ > s.size()) return 1;
|
else if (size_ > s.size()) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
inline bool operator<(simple_string_view lhs, simple_string_view rhs) {
|
template <typename CharT>
|
||||||
|
inline bool operator<(simple_string_view<CharT> lhs, simple_string_view<CharT> rhs) {
|
||||||
return lhs.compare(rhs) < 0;
|
return lhs.compare(rhs) < 0;
|
||||||
};
|
};
|
||||||
inline bool operator<=(simple_string_view lhs, simple_string_view rhs) {
|
template <typename CharT>
|
||||||
|
inline bool operator<(simple_string_view<CharT> lhs, std::common_type_t<simple_string_view<CharT>> rhs) {
|
||||||
|
return lhs.compare(rhs) < 0;
|
||||||
|
};
|
||||||
|
template <typename CharT>
|
||||||
|
inline bool operator<(std::common_type_t<simple_string_view<CharT>> lhs, simple_string_view<CharT> rhs) {
|
||||||
|
return lhs.compare(rhs) < 0;
|
||||||
|
};
|
||||||
|
template <typename CharT>
|
||||||
|
inline bool operator<=(simple_string_view<CharT> lhs, simple_string_view<CharT> rhs) {
|
||||||
return lhs.compare(rhs) <= 0;
|
return lhs.compare(rhs) <= 0;
|
||||||
};
|
};
|
||||||
inline bool operator>(simple_string_view lhs, simple_string_view rhs) {
|
template <typename CharT>
|
||||||
|
inline bool operator<=(simple_string_view<CharT> lhs, std::common_type_t<simple_string_view<CharT>> rhs) {
|
||||||
|
return lhs.compare(rhs) <= 0;
|
||||||
|
};
|
||||||
|
template <typename CharT>
|
||||||
|
inline bool operator<=(std::common_type_t<simple_string_view<CharT>> lhs, simple_string_view<CharT> rhs) {
|
||||||
|
return lhs.compare(rhs) <= 0;
|
||||||
|
};
|
||||||
|
template <typename CharT>
|
||||||
|
inline bool operator>(simple_string_view<CharT> lhs, simple_string_view<CharT> rhs) {
|
||||||
return lhs.compare(rhs) > 0;
|
return lhs.compare(rhs) > 0;
|
||||||
};
|
};
|
||||||
inline bool operator>=(simple_string_view lhs, simple_string_view rhs) {
|
template <typename CharT>
|
||||||
|
inline bool operator>(simple_string_view<CharT> lhs, std::common_type_t<simple_string_view<CharT>> rhs) {
|
||||||
|
return lhs.compare(rhs) > 0;
|
||||||
|
};
|
||||||
|
template <typename CharT>
|
||||||
|
inline bool operator>(std::common_type_t<simple_string_view<CharT>> lhs, simple_string_view<CharT> rhs) {
|
||||||
|
return lhs.compare(rhs) > 0;
|
||||||
|
};
|
||||||
|
template <typename CharT>
|
||||||
|
inline bool operator>=(simple_string_view<CharT> lhs, simple_string_view<CharT> rhs) {
|
||||||
return lhs.compare(rhs) >= 0;
|
return lhs.compare(rhs) >= 0;
|
||||||
};
|
};
|
||||||
inline std::ostream& operator<<(std::ostream& os, const simple_string_view& s) {
|
template <typename CharT>
|
||||||
|
inline bool operator>=(simple_string_view<CharT> lhs, std::common_type_t<simple_string_view<CharT>> rhs) {
|
||||||
|
return lhs.compare(rhs) >= 0;
|
||||||
|
};
|
||||||
|
template <typename CharT>
|
||||||
|
inline bool operator>=(std::common_type_t<simple_string_view<CharT>> lhs, simple_string_view<CharT> rhs) {
|
||||||
|
return lhs.compare(rhs) >= 0;
|
||||||
|
};
|
||||||
|
template <typename CharT>
|
||||||
|
inline std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, const simple_string_view<CharT>& s) {
|
||||||
os.write(s.data(), s.size());
|
os.write(s.data(), s.size());
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
using string_view = simple_string_view;
|
using string_view = simple_string_view<char>;
|
||||||
|
using ustring_view = simple_string_view<unsigned char>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Add a "foo"_sv literal that works exactly like the C++17 "foo"sv literal, but works with out
|
// Add a "foo"_sv literal that works exactly like the C++17 "foo"sv literal, but works with our
|
||||||
// implementation in pre-C++17.
|
// implementation in pre-C++17.
|
||||||
namespace lokimq {
|
namespace lokimq {
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
Loading…
Reference in a new issue