rodecomp/Recovered/jsoncons/include/jsoncons/byte_string.hpp
ragnarok-clanker 9b9c369f0c Move exe-only code to Recovered/ and rebuild virtualised PakAuxiliary::Extract
Recovered/ holds the code linked only into the standalone exe (scripts/exe/build_exe.py), outside the Clank source dirs:
- jsoncons/ and nProtect/ moved from scripts/exe/; GameGuard stand-in follows main's renamed entry points.
- GPak/PakAuxiliary.cpp: Extract (virtualised in every build; 02-19 jumps out at 0x0065861E) rebuilt from the open GRF Editor decoder, after the visible 02-19 prologue; inline key and kRO keys 1-4. Apply traps (unreachable in 02-19).
- GGHash/GGHash.cpp: CGGHash::Load/Check/VerifyHash trap (RagHash.dat check unreachable in 02-19).
The whole client links: 984 units, 0 unresolved.
2026-11-06 19:33:10 +01:00

820 lines
27 KiB
C++

// Copyright 2013-2023 Daniel Parker
// Distributed under the Boost license, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See https://github.com/danielaparker/jsoncons for latest version
#ifndef JSONCONS_BYTE_STRING_HPP
#define JSONCONS_BYTE_STRING_HPP
#include <sstream>
#include <vector>
#include <ostream>
#include <cmath>
#include <cstring> // std::memcmp
#include <memory> // std::allocator
#include <iterator>
#include <exception>
#include <iomanip> // std::setw
#include <initializer_list>
#include <utility> // std::move
#include <jsoncons/config/jsoncons_config.hpp>
#include <jsoncons/json_exception.hpp>
#include <jsoncons/conv_error.hpp>
#include <jsoncons/extension_traits.hpp>
namespace jsoncons {
// Algorithms
namespace detail {
template <class InputIt, class Container>
typename std::enable_if<std::is_same<typename std::iterator_traits<InputIt>::value_type,uint8_t>::value,size_t>::type
encode_base64_generic(InputIt first, InputIt last, const char alphabet[65], Container& result)
{
std::size_t count = 0;
unsigned char a3[3];
unsigned char a4[4];
unsigned char fill = alphabet[64];
int i = 0;
int j = 0;
while (first != last)
{
a3[i++] = *first++;
if (i == 3)
{
a4[0] = (a3[0] & 0xfc) >> 2;
a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);
a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);
a4[3] = a3[2] & 0x3f;
for (i = 0; i < 4; i++)
{
result.push_back(alphabet[a4[i]]);
++count;
}
i = 0;
}
}
if (i > 0)
{
for (j = i; j < 3; ++j)
{
a3[j] = 0;
}
a4[0] = (a3[0] & 0xfc) >> 2;
a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);
a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);
for (j = 0; j < i + 1; ++j)
{
result.push_back(alphabet[a4[j]]);
++count;
}
if (fill != 0)
{
while (i++ < 3)
{
result.push_back(fill);
++count;
}
}
}
return count;
}
template <class InputIt, class F, class Container>
typename std::enable_if<extension_traits::is_back_insertable_byte_container<Container>::value,decode_result<InputIt>>::type
decode_base64_generic(InputIt first, InputIt last,
const uint8_t reverse_alphabet[256],
F f,
Container& result)
{
uint8_t a4[4], a3[3];
uint8_t i = 0;
uint8_t j = 0;
while (first != last && *first != '=')
{
if (!f(*first))
{
return decode_result<InputIt>{first, conv_errc::conversion_failed};
}
a4[i++] = static_cast<uint8_t>(*first++);
if (i == 4)
{
for (i = 0; i < 4; ++i)
{
a4[i] = reverse_alphabet[a4[i]];
}
a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4);
a3[1] = ((a4[1] & 0xf) << 4) + ((a4[2] & 0x3c) >> 2);
a3[2] = ((a4[2] & 0x3) << 6) + a4[3];
for (i = 0; i < 3; i++)
{
result.push_back(a3[i]);
}
i = 0;
}
}
if (i > 0)
{
for (j = 0; j < i; ++j)
{
a4[j] = reverse_alphabet[a4[j]];
}
a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4);
a3[1] = ((a4[1] & 0xf) << 4) + ((a4[2] & 0x3c) >> 2);
for (j = 0; j < i - 1; ++j)
{
result.push_back(a3[j]);
}
}
return decode_result<InputIt>{last, conv_errc::success};
}
} // namespace detail
template <class InputIt, class Container>
typename std::enable_if<std::is_same<typename std::iterator_traits<InputIt>::value_type,uint8_t>::value,size_t>::type
encode_base16(InputIt first, InputIt last, Container& result)
{
static constexpr char characters[] = "0123456789ABCDEF";
for (auto it = first; it != last; ++it)
{
uint8_t c = *it;
result.push_back(characters[c >> 4]);
result.push_back(characters[c & 0xf]);
}
return (last-first)*2;
}
template <class InputIt, class Container>
typename std::enable_if<std::is_same<typename std::iterator_traits<InputIt>::value_type,uint8_t>::value,size_t>::type
encode_base64url(InputIt first, InputIt last, Container& result)
{
static constexpr char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789-_"
"\0";
return detail::encode_base64_generic(first, last, alphabet, result);
}
template <class InputIt, class Container>
typename std::enable_if<std::is_same<typename std::iterator_traits<InputIt>::value_type,uint8_t>::value,size_t>::type
encode_base64(InputIt first, InputIt last, Container& result)
{
static constexpr char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/"
"=";
return detail::encode_base64_generic(first, last, alphabet, result);
}
template <class Char>
bool is_base64(Char c)
{
return (c >= 0 && c < 128) && (isalnum((int)c) || c == '+' || c == '/');
}
template <class Char>
bool is_base64url(Char c)
{
return (c >= 0 && c < 128) && (isalnum((int)c) || c == '-' || c == '_');
}
inline
static bool is_base64url(int c)
{
return isalnum(c) || c == '-' || c == '_';
}
// decode
template <class InputIt, class Container>
typename std::enable_if<extension_traits::is_back_insertable_byte_container<Container>::value,decode_result<InputIt>>::type
decode_base64url(InputIt first, InputIt last, Container& result)
{
static constexpr uint8_t reverse_alphabet[256] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 62, 0xff, 0xff,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 63,
0xff, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
auto retval = jsoncons::detail::decode_base64_generic(first, last, reverse_alphabet,
is_base64url<typename std::iterator_traits<InputIt>::value_type>,
result);
return retval.ec == conv_errc::success ? retval : decode_result<InputIt>{retval.it, conv_errc::not_base64url};
}
template <class InputIt, class Container>
typename std::enable_if<extension_traits::is_back_insertable_byte_container<Container>::value,decode_result<InputIt>>::type
decode_base64(InputIt first, InputIt last, Container& result)
{
static constexpr uint8_t reverse_alphabet[256] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 62, 0xff, 0xff, 0xff, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
auto retval = jsoncons::detail::decode_base64_generic(first, last, reverse_alphabet,
is_base64<typename std::iterator_traits<InputIt>::value_type>,
result);
return retval.ec == conv_errc::success ? retval : decode_result<InputIt>{retval.it, conv_errc::not_base64};
}
template <class InputIt,class Container>
typename std::enable_if<extension_traits::is_back_insertable_byte_container<Container>::value,decode_result<InputIt>>::type
decode_base16(InputIt first, InputIt last, Container& result)
{
std::size_t len = std::distance(first,last);
if (len & 1)
{
return decode_result<InputIt>{first, conv_errc::not_base16};
}
InputIt it = first;
while (it != last)
{
uint8_t val;
auto a = *it++;
if (a >= '0' && a <= '9')
{
val = static_cast<uint8_t>(a - '0') << 4;
}
else if ((a | 0x20) >= 'a' && (a | 0x20) <= 'f')
{
val = (static_cast<uint8_t>((a | 0x20) - 'a') + 10) << 4;
}
else
{
return decode_result<InputIt>{first, conv_errc::not_base16};
}
auto b = *it++;
if (b >= '0' && b <= '9')
{
val |= (b - '0');
}
else if ((b | 0x20) >= 'a' && (b | 0x20) <= 'f')
{
val |= ((b | 0x20) - 'a' + 10);
}
else
{
return decode_result<InputIt>{first, conv_errc::not_base16};
}
result.push_back(val);
}
return decode_result<InputIt>{last, conv_errc::success};
}
struct byte_traits
{
using char_type = uint8_t;
static constexpr int eof()
{
return std::char_traits<char>::eof();
}
static int compare(const char_type* s1, const char_type* s2, std::size_t count) noexcept
{
return std::memcmp(s1,s2,count);
}
};
// basic_byte_string
template <class Allocator>
class basic_byte_string;
// byte_string_view
class byte_string_view
{
const uint8_t* data_;
std::size_t size_;
public:
using traits_type = byte_traits;
using const_iterator = const uint8_t*;
using iterator = const_iterator;
using size_type = std::size_t;
using value_type = uint8_t;
using reference = uint8_t&;
using const_reference = const uint8_t&;
using difference_type = std::ptrdiff_t;
using pointer = uint8_t*;
using const_pointer = const uint8_t*;
constexpr byte_string_view() noexcept
: data_(nullptr), size_(0)
{
}
constexpr byte_string_view(const uint8_t* data, std::size_t length) noexcept
: data_(data), size_(length)
{
}
template <class Container>
constexpr explicit byte_string_view(const Container& cont,
typename std::enable_if<extension_traits::is_byte_sequence<Container>::value,int>::type = 0)
: data_(reinterpret_cast<const uint8_t*>(cont.data())), size_(cont.size())
{
}
template <class Allocator>
constexpr byte_string_view(const basic_byte_string<Allocator>& bytes);
constexpr byte_string_view(const byte_string_view&) noexcept = default;
JSONCONS_CPP14_CONSTEXPR byte_string_view(byte_string_view&& other) noexcept
: data_(nullptr), size_(0)
{
const_pointer temp_data = data_;
data_ = other.data_;
other.data_ = temp_data;
size_type temp_size = size_;
size_ = other.size_;
other.size_ = temp_size;
}
byte_string_view& operator=(const byte_string_view&) = default;
byte_string_view& operator=(byte_string_view&& other) noexcept
{
std::swap(data_, other.data_);
std::swap(size_, other.size_);
return *this;
}
constexpr const uint8_t* data() const noexcept
{
return data_;
}
#if !defined(JSONCONS_NO_DEPRECATED)
JSONCONS_DEPRECATED_MSG("Instead, use size()")
std::size_t length() const
{
return size_;
}
#endif
constexpr size_t size() const noexcept
{
return size_;
}
// iterator support
constexpr const_iterator begin() const noexcept
{
return data_;
}
constexpr const_iterator end() const noexcept
{
return data_ + size_;
}
constexpr const_iterator cbegin() const noexcept
{
return data_;
}
constexpr const_iterator cend() const noexcept
{
return data_ + size_;
}
constexpr uint8_t operator[](size_type pos) const
{
return data_[pos];
}
JSONCONS_CPP14_CONSTEXPR byte_string_view substr(size_type pos) const
{
if (pos > size_)
{
JSONCONS_THROW(std::out_of_range("pos exceeds size"));
}
std::size_t n = size_ - pos;
return byte_string_view(data_ + pos, n);
}
byte_string_view substr(size_type pos, size_type n) const
{
if (pos > size_)
{
JSONCONS_THROW(std::out_of_range("pos exceeds size"));
}
if (pos + n > size_)
{
n = size_ - pos;
}
return byte_string_view(data_ + pos, n);
}
int compare(const byte_string_view& s) const noexcept
{
const int rc = traits_type::compare(data_, s.data(), (std::min)(size_, s.size()));
return rc != 0 ? rc : (size_ == s.size() ? 0 : size_ < s.size() ? -1 : 1);
}
template <class Allocator>
int compare(const basic_byte_string<Allocator>& s) const noexcept
{
const int rc = traits_type::compare(data_, s.data(), (std::min)(size_, s.size()));
return rc != 0 ? rc : (size_ == s.size() ? 0 : size_ < s.size() ? -1 : 1);
}
template <class CharT>
friend std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, const byte_string_view& bstr)
{
std::basic_ostringstream<CharT> ss;
ss.flags(std::ios::hex);
ss.fill('0');
bool first = true;
for (auto b : bstr)
{
if (first)
{
first = false;
}
else
{
ss << ',';
}
ss << std::setw(2) << static_cast<int>(b);
}
os << ss.str();
return os;
}
};
// basic_byte_string
template <class Allocator = std::allocator<uint8_t>>
class basic_byte_string
{
using byte_allocator_type = typename std::allocator_traits<Allocator>:: template rebind_alloc<uint8_t>;
std::vector<uint8_t,byte_allocator_type> data_;
public:
using traits_type = byte_traits;
using allocator_type = byte_allocator_type;
using value_type = typename std::vector<uint8_t,byte_allocator_type>::value_type;
using size_type = typename std::vector<uint8_t,byte_allocator_type>::size_type;
using difference_type = typename std::vector<uint8_t,byte_allocator_type>::difference_type;
using reference = typename std::vector<uint8_t,byte_allocator_type>::reference;
using const_reference = typename std::vector<uint8_t,byte_allocator_type>::const_reference;
using pointer = typename std::vector<uint8_t,byte_allocator_type>::pointer;
using const_pointer = typename std::vector<uint8_t,byte_allocator_type>::const_pointer;
using iterator = typename std::vector<uint8_t,byte_allocator_type>::iterator;
using const_iterator = typename std::vector<uint8_t,byte_allocator_type>::const_iterator;
basic_byte_string() = default;
explicit basic_byte_string(const Allocator& alloc)
: data_(alloc)
{
}
basic_byte_string(std::initializer_list<uint8_t> init)
: data_(std::move(init))
{
}
basic_byte_string(std::initializer_list<uint8_t> init, const Allocator& alloc)
: data_(std::move(init), alloc)
{
}
explicit basic_byte_string(const byte_string_view& v)
: data_(v.begin(),v.end())
{
}
basic_byte_string(const basic_byte_string<Allocator>& v)
: data_(v.data_)
{
}
basic_byte_string(basic_byte_string<Allocator>&& v) noexcept
: data_(std::move(v.data_))
{
}
basic_byte_string(const byte_string_view& v, const Allocator& alloc)
: data_(v.begin(),v.end(),alloc)
{
}
basic_byte_string(const uint8_t* data, std::size_t length, const Allocator& alloc = Allocator())
: data_(data, data+length,alloc)
{
}
Allocator get_allocator() const
{
return data_.get_allocator();
}
basic_byte_string& operator=(const basic_byte_string& s) = default;
basic_byte_string& operator=(basic_byte_string&& other) noexcept
{
data_.swap(other.data_);
return *this;
}
void reserve(std::size_t new_cap)
{
data_.reserve(new_cap);
}
void push_back(uint8_t b)
{
data_.push_back(b);
}
void assign(const uint8_t* s, std::size_t count)
{
data_.clear();
data_.insert(data_.end(), s, s+count);
}
void append(const uint8_t* s, std::size_t count)
{
data_.insert(data_.end(), s, s+count);
}
void clear()
{
data_.clear();
}
uint8_t operator[](size_type pos) const
{
return data_[pos];
}
// iterator support
iterator begin() noexcept
{
return data_.begin();
}
iterator end() noexcept
{
return data_.end();
}
const_iterator begin() const noexcept
{
return data_.begin();
}
const_iterator end() const noexcept
{
return data_.end();
}
uint8_t* data()
{
return data_.data();
}
const uint8_t* data() const
{
return data_.data();
}
std::size_t size() const
{
return data_.size();
}
#if !defined(JSONCONS_NO_DEPRECATED)
JSONCONS_DEPRECATED_MSG("Instead, use size()")
std::size_t length() const
{
return data_.size();
}
#endif
int compare(const byte_string_view& s) const noexcept
{
const int rc = traits_type::compare(data(), s.data(), (std::min)(size(), s.size()));
return rc != 0 ? rc : (size() == s.size() ? 0 : size() < s.size() ? -1 : 1);
}
int compare(const basic_byte_string& s) const noexcept
{
const int rc = traits_type::compare(data(), s.data(), (std::min)(size(), s.size()));
return rc != 0 ? rc : (size() == s.size() ? 0 : size() < s.size() ? -1 : 1);
}
template <class CharT>
friend std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, const basic_byte_string& o)
{
os << byte_string_view(o);
return os;
}
};
template <class Allocator>
constexpr byte_string_view::byte_string_view(const basic_byte_string<Allocator>& bytes)
: data_(bytes.data()), size_(bytes.size())
{
}
// ==
inline
bool operator==(const byte_string_view& lhs, const byte_string_view& rhs) noexcept
{
return lhs.compare(rhs) == 0;
}
template<class Allocator>
bool operator==(const byte_string_view& lhs, const basic_byte_string<Allocator>& rhs) noexcept
{
return lhs.compare(rhs) == 0;
}
template<class Allocator>
bool operator==(const basic_byte_string<Allocator>& lhs, const byte_string_view& rhs) noexcept
{
return rhs.compare(lhs) == 0;
}
template<class Allocator>
bool operator==(const basic_byte_string<Allocator>& lhs, const basic_byte_string<Allocator>& rhs) noexcept
{
return rhs.compare(lhs) == 0;
}
// !=
inline
bool operator!=(const byte_string_view& lhs, const byte_string_view& rhs) noexcept
{
return lhs.compare(rhs) != 0;
}
template<class Allocator>
bool operator!=(const byte_string_view& lhs, const basic_byte_string<Allocator>& rhs) noexcept
{
return lhs.compare(rhs) != 0;
}
template<class Allocator>
bool operator!=(const basic_byte_string<Allocator>& lhs, const byte_string_view& rhs) noexcept
{
return rhs.compare(lhs) != 0;
}
template<class Allocator>
bool operator!=(const basic_byte_string<Allocator>& lhs, const basic_byte_string<Allocator>& rhs) noexcept
{
return rhs.compare(lhs) != 0;
}
// <=
inline
bool operator<=(const byte_string_view& lhs, const byte_string_view& rhs) noexcept
{
return lhs.compare(rhs) <= 0;
}
template<class Allocator>
bool operator<=(const byte_string_view& lhs, const basic_byte_string<Allocator>& rhs) noexcept
{
return lhs.compare(rhs) <= 0;
}
template<class Allocator>
bool operator<=(const basic_byte_string<Allocator>& lhs, const byte_string_view& rhs) noexcept
{
return rhs.compare(lhs) >= 0;
}
template<class Allocator>
bool operator<=(const basic_byte_string<Allocator>& lhs, const basic_byte_string<Allocator>& rhs) noexcept
{
return rhs.compare(lhs) >= 0;
}
// <
inline
bool operator<(const byte_string_view& lhs, const byte_string_view& rhs) noexcept
{
return lhs.compare(rhs) < 0;
}
template<class Allocator>
bool operator<(const byte_string_view& lhs, const basic_byte_string<Allocator>& rhs) noexcept
{
return lhs.compare(rhs) < 0;
}
template<class Allocator>
bool operator<(const basic_byte_string<Allocator>& lhs, const byte_string_view& rhs) noexcept
{
return rhs.compare(lhs) > 0;
}
template<class Allocator>
bool operator<(const basic_byte_string<Allocator>& lhs, const basic_byte_string<Allocator>& rhs) noexcept
{
return rhs.compare(lhs) > 0;
}
// >=
inline
bool operator>=(const byte_string_view& lhs, const byte_string_view& rhs) noexcept
{
return lhs.compare(rhs) >= 0;
}
template<class Allocator>
bool operator>=(const byte_string_view& lhs, const basic_byte_string<Allocator>& rhs) noexcept
{
return lhs.compare(rhs) >= 0;
}
template<class Allocator>
bool operator>=(const basic_byte_string<Allocator>& lhs, const byte_string_view& rhs) noexcept
{
return rhs.compare(lhs) <= 0;
}
template<class Allocator>
bool operator>=(const basic_byte_string<Allocator>& lhs, const basic_byte_string<Allocator>& rhs) noexcept
{
return rhs.compare(lhs) <= 0;
}
// >
inline
bool operator>(const byte_string_view& lhs, const byte_string_view& rhs) noexcept
{
return lhs.compare(rhs) > 0;
}
template<class Allocator>
bool operator>(const byte_string_view& lhs, const basic_byte_string<Allocator>& rhs) noexcept
{
return lhs.compare(rhs) > 0;
}
template<class Allocator>
bool operator>(const basic_byte_string<Allocator>& lhs, const byte_string_view& rhs) noexcept
{
return rhs.compare(lhs) < 0;
}
template<class Allocator>
bool operator>(const basic_byte_string<Allocator>& lhs, const basic_byte_string<Allocator>& rhs) noexcept
{
return rhs.compare(lhs) < 0;
}
using byte_string = basic_byte_string<std::allocator<uint8_t>>;
namespace extension_traits {
template <typename T>
struct is_basic_byte_string
: std::false_type
{};
template <typename Allocator>
struct is_basic_byte_string<basic_byte_string<Allocator>>
: std::true_type
{};
} // namespace extension_traits
} // namespace jsoncons
#endif