pocketpy/3rd/numpy/include/xtl/xbasic_fixed_string.hpp
Anurag Bhat 86b4fc623c
Merge numpy to pocketpy (#303)
* Merge numpy to pocketpy

* Add CI

* Fix CI
2024-09-02 16:22:41 +08:00

2437 lines
98 KiB
C++

/***************************************************************************
* Copyright (c) Sylvain Corlay and Johan Mabille and Wolf Vollprecht *
* Copyright (c) QuantStack *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_BASIC_FIXED_STRING_HPP
#define XTL_BASIC_FIXED_STRING_HPP
#include <cstddef>
#include <exception>
#include <functional>
#include <iterator>
#include <sstream>
#include <stdexcept>
#include <string>
#include <cassert>
#include <algorithm>
#include <type_traits>
#ifdef __CLING__
#include <nlohmann/json.hpp>
#endif
#include "xhash.hpp"
#include "xtl_config.hpp"
namespace xtl
{
namespace string_policy
{
template <std::size_t>
struct silent_error;
template <std::size_t>
struct throwing_error;
}
/***********************
* xbasic_fixed_string *
***********************/
enum storage_options
{
buffer = 1 << 0,
pointer = 1 << 1,
store_size = 1 << 2,
is_const = 1 << 3
};
template <class CT, std::size_t N = 55, int ST = buffer | store_size, template <std::size_t> class EP = string_policy::silent_error, class TR = std::char_traits<CT>>
class xbasic_fixed_string;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
std::basic_ostream<CT, TR>& operator<<(std::basic_ostream<CT, TR>& os,
const xbasic_fixed_string<CT, N, ST, EP, TR>& str);
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
std::basic_istream<CT, TR>& operator>>(std::basic_istream<CT, TR>& is,
xbasic_fixed_string<CT, N, ST, EP, TR>& str);
template <class CT>
using xbasic_string_view = xbasic_fixed_string<const CT, 0, pointer | store_size | is_const>;
namespace detail
{
template <int selector>
struct select_storage;
template <typename T>
struct fixed_small_string_storage_impl;
template <class T, std::size_t N>
struct fixed_small_string_storage_impl<T[N]>
{
static_assert(N <= (1u << (8 * sizeof(T))), "small string");
fixed_small_string_storage_impl()
{
set_size(0);
}
fixed_small_string_storage_impl(T ptr[N], std::size_t size)
: m_buffer(ptr)
{
m_buffer[N - 1] = N - size;
}
T* buffer()
{
return m_buffer;
}
const T* buffer() const
{
return m_buffer;
}
std::size_t size() const
{
// Don't use std::make_unsinged_t here, this should remain C++11 compatible
using unsigned_type = typename std::make_unsigned<T>::type;
return N - reinterpret_cast<unsigned_type const*>(m_buffer)[N - 1];
}
void set_size(std::size_t sz)
{
assert(sz < N && "setting a small size");
// Don't use std::make_unsinged_t here, this should remain C++11 compatible
using unsigned_type = typename std::make_unsigned<T>::type;
reinterpret_cast<unsigned_type*>(m_buffer)[N - 1] = static_cast<unsigned_type>(N - sz);
m_buffer[sz] = '\0';
}
void adjust_size(std::ptrdiff_t val)
{
assert(size() + val >= 0 && "adjusting to positive size");
set_size(static_cast<std::size_t>(static_cast<std::ptrdiff_t>(size()) + val));
}
T m_buffer[N];
};
template <class T>
struct fixed_string_storage_impl
{
fixed_string_storage_impl() = default;
fixed_string_storage_impl(T ptr, std::size_t size)
: m_buffer(ptr), m_size(size)
{
}
T& buffer()
{
return m_buffer;
}
const T& buffer() const
{
return m_buffer;
}
std::size_t size() const
{
return m_size;
}
void set_size(std::size_t sz)
{
m_size = sz;
m_buffer[sz] = '\0';
}
void adjust_size(std::ptrdiff_t val)
{
m_size += std::size_t(val);
m_buffer[m_size] = '\0';
}
T m_buffer;
std::size_t m_size;
};
template <class T>
struct fixed_string_external_storage_impl
{
fixed_string_external_storage_impl() = default;
fixed_string_external_storage_impl(T ptr, std::ptrdiff_t/*size*/)
{
m_buffer = ptr;
}
T& buffer()
{
return m_buffer;
}
const T& buffer() const
{
return m_buffer;
}
void set_size(std::size_t sz)
{
m_buffer[sz] = '\0';
}
void adjust_size(std::ptrdiff_t val)
{
m_buffer[size() + val] = '\0';
}
std::size_t size() const
{
return std::strlen(m_buffer);
}
T m_buffer;
};
template <class T, bool Small>
struct select_fixed_storage {
using type = fixed_string_storage_impl<T>;
};
template <class T>
struct select_fixed_storage<T, true> {
using type = fixed_small_string_storage_impl<T>;
};
template <>
struct select_storage<buffer | store_size>
{
template <class T, std::size_t N>
using type = typename select_fixed_storage<T[N + 1], N < (1u << (8 * sizeof(T)))>::type;
};
template <>
struct select_storage<buffer>
{
template <class T, std::size_t N>
using type = fixed_string_external_storage_impl<T[N + 1]>;
};
}
template <class CT,
std::size_t N,
int ST,
template <std::size_t> class EP,
class TR>
class xbasic_fixed_string
{
public:
using traits_type = TR;
using value_type = CT;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using storage_type = typename detail::select_storage<ST>::template type<CT, N>;
using reference = value_type&;
using const_reference = const value_type&;
using pointer = value_type*;
using const_pointer = const value_type*;
using iterator = pointer;
using const_iterator = const_pointer;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
static const size_type npos;
using self_type = xbasic_fixed_string;
using initializer_type = std::initializer_list<value_type>;
using string_type = std::basic_string<value_type, traits_type>;
using error_policy = EP<N>;
xbasic_fixed_string();
explicit xbasic_fixed_string(size_type count, value_type ch);
explicit xbasic_fixed_string(const self_type& other,
size_type pos,
size_type count = npos);
explicit xbasic_fixed_string(const string_type& other);
explicit xbasic_fixed_string(const string_type& other,
size_type pos,
size_type count = npos);
xbasic_fixed_string(const_pointer s, size_type count);
xbasic_fixed_string(const_pointer s);
xbasic_fixed_string(initializer_type ilist);
template <class InputIt>
xbasic_fixed_string(InputIt first, InputIt last);
operator string_type() const;
~xbasic_fixed_string() = default;
xbasic_fixed_string(const self_type&) = default;
xbasic_fixed_string(self_type&&) = default;
self_type& operator=(const self_type&) = default;
self_type& operator=(self_type&&) = default;
self_type& operator=(const_pointer s);
self_type& operator=(value_type ch);
self_type& operator=(initializer_type ilist);
self_type& operator=(const string_type& str);
self_type& assign(size_type count, value_type ch);
self_type& assign(const self_type& other,
size_type pos,
size_type count = npos);
self_type& assign(const_pointer s, size_type count);
self_type& assign(const_pointer s);
self_type& assign(initializer_type ilist);
template <class InputIt>
self_type& assign(InputIt first, InputIt last);
self_type& assign(const self_type& rhs);
self_type& assign(self_type&& rhs);
self_type& assign(const string_type& str);
self_type& assign(const string_type& other,
size_type pos,
size_type count = npos);
reference at(size_type pos);
const_reference at(size_type pos) const;
reference operator[](size_type pos);
const_reference operator[](size_type pos) const;
reference front();
const_reference front() const;
reference back();
const_reference back() const;
pointer data() noexcept;
const_pointer data() const noexcept;
const_pointer c_str() const noexcept;
iterator begin() noexcept;
iterator end() noexcept;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
reverse_iterator rbegin() noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rbegin() const noexcept;
const_reverse_iterator rend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
bool empty() const noexcept;
size_type size() const noexcept;
size_type length() const noexcept;
size_type max_size() const noexcept;
void clear() noexcept;
void push_back(value_type ch);
void pop_back();
self_type substr(size_type pos = 0, size_type count = npos) const;
size_type copy(pointer dest, size_type count, size_type pos = 0) const;
void resize(size_type count);
void resize(size_type count, value_type ch);
void swap(self_type& rhs) noexcept;
self_type& insert(size_type index, size_type count, value_type ch);
self_type& insert(size_type index, const_pointer s);
self_type& insert(size_type index, const_pointer s, size_type count);
self_type& insert(size_type index, const self_type& str);
self_type& insert(size_type index, const self_type& str,
size_type index_str, size_type count = npos);
self_type& insert(size_type index, const string_type& str);
self_type& insert(size_type index, const string_type& str,
size_type index_str, size_type count = npos);
iterator insert(const_iterator pos, value_type ch);
iterator insert(const_iterator pos, size_type count, value_type ch);
iterator insert(const_iterator pos, initializer_type ilist);
template <class InputIt>
iterator insert(const_iterator pos, InputIt first, InputIt last);
self_type& erase(size_type index = 0, size_type count = npos);
iterator erase(const_iterator position);
iterator erase(const_iterator first, const_iterator last);
self_type& append(size_type count, value_type ch);
self_type& append(const self_type& str);
self_type& append(const self_type& str,
size_type pos, size_type count = npos);
self_type& append(const string_type& str);
self_type& append(const string_type& str,
size_type pos, size_type count = npos);
self_type& append(const_pointer s, size_type count);
self_type& append(const_pointer s);
self_type& append(initializer_type ilist);
template <class InputIt>
self_type& append(InputIt first, InputIt last);
self_type& operator+=(const self_type& str);
self_type& operator+=(const string_type& str);
self_type& operator+=(value_type ch);
self_type& operator+=(const_pointer s);
self_type& operator+=(initializer_type ilist);
int compare(const self_type& str) const noexcept;
int compare(size_type pos1, size_type count1, const self_type& str) const;
int compare(size_type pos1, size_type count1, const self_type& str,
size_type pos2, size_type count2 = npos) const;
int compare(const string_type& str) const noexcept;
int compare(size_type pos1, size_type count1, const string_type& str) const;
int compare(size_type pos1, size_type count1, const string_type& str,
size_type pos2, size_type count2 = npos) const;
int compare(const_pointer s) const noexcept;
int compare(size_type pos1, size_type count1, const_pointer s) const;
int compare(size_type pos1, size_type count1, const_pointer s, size_type count2) const;
self_type& replace(size_type pos, size_type count, const self_type& str);
self_type& replace(const_iterator first, const_iterator last, const self_type& str);
self_type& replace(size_type pos1, size_type count1, const self_type& str,
size_type pos2, size_type count2 = npos);
self_type& replace(size_type pos, size_type count, const string_type& str);
self_type& replace(const_iterator first, const_iterator last, const string_type& str);
self_type& replace(size_type pos1, size_type count1, const string_type& str,
size_type pos2, size_type count2 = npos);
self_type& replace(size_type pos, size_type count, const_pointer cstr, size_type count2);
self_type& replace(const_iterator first, const_iterator last, const_pointer cstr, size_type count2);
self_type& replace(size_type pos, size_type count, const_pointer cstr);
self_type& replace(const_iterator first, const_iterator last, const_pointer cstr);
self_type& replace(size_type pos, size_type count, size_type count2, value_type ch);
self_type& replace(const_iterator first, const_iterator last, size_type count2, value_type ch);
self_type& replace(const_iterator first, const_iterator last, initializer_type ilist);
template <class InputIt>
self_type& replace(const_iterator first, const_iterator last, InputIt first2, InputIt last2);
size_type find(const self_type& str, size_type pos = 0) const noexcept;
size_type find(const string_type& str, size_type pos = 0) const noexcept;
size_type find(const_pointer s, size_type pos, size_type count) const;
size_type find(const_pointer s, size_type pos = 0) const;
size_type find(value_type ch, size_type pos = 0) const;
size_type rfind(const self_type& str, size_type pos = npos) const noexcept;
size_type rfind(const string_type& str, size_type pos = npos) const noexcept;
size_type rfind(const_pointer s, size_type pos, size_type count) const;
size_type rfind(const_pointer s, size_type pos = npos) const;
size_type rfind(value_type ch, size_type pos = npos) const;
size_type find_first_of(const self_type& str, size_type pos = 0) const noexcept;
size_type find_first_of(const string_type& str, size_type pos = 0) const noexcept;
size_type find_first_of(const_pointer s, size_type pos, size_type count) const;
size_type find_first_of(const_pointer s, size_type pos = 0) const;
size_type find_first_of(value_type ch, size_type pos = 0) const;
size_type find_first_not_of(const self_type& str, size_type pos = 0) const noexcept;
size_type find_first_not_of(const string_type& str, size_type pos = 0) const noexcept;
size_type find_first_not_of(const_pointer s, size_type pos, size_type count) const;
size_type find_first_not_of(const_pointer s, size_type pos = 0) const;
size_type find_first_not_of(value_type ch, size_type pos = 0) const;
size_type find_last_of(const self_type& str, size_type pos = 0) const noexcept;
size_type find_last_of(const string_type& str, size_type pos = 0) const noexcept;
size_type find_last_of(const_pointer s, size_type pos, size_type count) const;
size_type find_last_of(const_pointer s, size_type pos = 0) const;
size_type find_last_of(value_type ch, size_type pos = 0) const;
size_type find_last_not_of(const self_type& str, size_type pos = npos) const noexcept;
size_type find_last_not_of(const string_type& str, size_type pos = npos) const noexcept;
size_type find_last_not_of(const_pointer s, size_type pos, size_type count) const;
size_type find_last_not_of(const_pointer s, size_type pos = npos) const;
size_type find_last_not_of(value_type ch, size_type pos = npos) const;
private:
int compare_impl(const_pointer s1, size_type count1, const_pointer s2, size_type count2) const noexcept;
void update_null_termination() noexcept;
void check_index(size_type pos, size_type size, const char* what) const;
void check_index_strict(size_type pos, size_type size, const char* what) const;
storage_type m_storage;
};
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
const typename xbasic_fixed_string<CT, N, ST, EP, TR>::size_type xbasic_fixed_string<CT, N, ST, EP, TR>::npos
= std::basic_string<value_type, traits_type>::npos;
template <std::size_t N>
using xfixed_string = xbasic_fixed_string<char, N>;
template <std::size_t N>
using xwfixed_string = xbasic_fixed_string<wchar_t, N>;
template <std::size_t N>
using xu16fixed_string = xbasic_fixed_string<char16_t, N>;
template <std::size_t N>
using xu32fixed_string = xbasic_fixed_string<char32_t, N>;
/**************************
* Concatenation operator *
**************************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs);
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const CT* rhs);
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
CT rhs);
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs);
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(CT lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs);
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>&& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs);
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>&& rhs);
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>&& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>&& rhs);
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>&& lhs,
const CT* rhs);
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>&& lhs,
CT rhs);
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>&& rhs);
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(CT lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>&& rhs);
/************************
* Comparison operators *
************************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator==(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator==(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const CT* rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator==(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator==(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const std::basic_string<CT, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator==(const std::basic_string<CT, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator!=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator!=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const CT* rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator!=(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator!=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const std::basic_string<CT, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator!=(const std::basic_string<CT, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator<(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator<(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const CT* rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator<(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator<(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const std::basic_string<CT, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator<(const std::basic_string<CT, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator<=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator<=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const CT* rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator<=(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator<=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const std::basic_string<CT, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator<=(const std::basic_string<CT, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator>(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator>(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const CT* rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator>(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator>(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const std::basic_string<CT, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator>(const std::basic_string<CT, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator>=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator>=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const CT* rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator>=(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator>=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const std::basic_string<CT, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
bool operator>=(const std::basic_string<CT, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept;
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
void swap(xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
xbasic_fixed_string<CT, N, ST, EP, TR>& rhs);
/******************************
* Input / output declaration *
******************************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
std::basic_istream<CT, TR>& getline(std::basic_istream<CT, TR>& input,
xbasic_fixed_string<CT, N, ST, EP, TR>& str,
CT delim);
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
std::basic_istream<CT, TR>& getline(std::basic_istream<CT, TR>&& input,
xbasic_fixed_string<CT, N, ST, EP, TR>& str,
CT delim);
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
std::basic_istream<CT, TR>& getline(std::basic_istream<CT, TR>& input,
xbasic_fixed_string<CT, N, ST, EP, TR>& str);
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
std::basic_istream<CT, TR>& getline(std::basic_istream<CT, TR>&& input,
xbasic_fixed_string<CT, N, ST, EP, TR>& str);
} // namespace xtl
namespace std
{
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
struct hash<::xtl::xbasic_fixed_string<CT, N, ST, EP, TR>>
{
using argument_type = ::xtl::xbasic_fixed_string<CT, N, ST, EP, TR>;
using result_type = std::size_t;
inline result_type operator()(const argument_type& arg) const
{
return ::xtl::hash_bytes(arg.data(), arg.size(), static_cast<std::size_t>(0xc70f6907UL));
}
};
} // namespace std
namespace xtl
{
/********************************
* xbasic_fixed_string policies *
********************************/
namespace string_policy
{
template <std::size_t N>
struct silent_error
{
inline static std::size_t check_size(std::size_t size)
{
return size;
}
inline static std::size_t check_add(std::size_t size1, std::size_t size2)
{
return size1 + size2;
}
};
template <std::size_t N>
struct throwing_error
{
inline static std::size_t check_size(std::size_t size)
{
if (size > N)
{
std::ostringstream oss;
oss << "Invalid size (" << size << ") for xbasic_fixed_string - maximal size: " << N;
#if defined(XTL_NO_EXCEPTIONS)
std::fprintf(stderr, "%s\n", oss.str().c_str());
std::terminate();
#else
throw std::length_error(oss.str());
#endif
}
return size;
}
inline static std::size_t check_add(std::size_t size1, std::size_t size2)
{
return check_size(size1 + size2);
}
};
} // string_policy
/**************************************
* xbasic_fixed_string implementation *
**************************************/
/****************
* Constructors *
****************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>::xbasic_fixed_string()
: m_storage()
{
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>::xbasic_fixed_string(size_type count, value_type ch)
: m_storage()
{
assign(count, ch);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>::xbasic_fixed_string(const self_type& other,
size_type pos,
size_type count)
: m_storage()
{
assign(other, pos, count);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>::xbasic_fixed_string(const string_type& other)
: m_storage()
{
assign(other);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>::xbasic_fixed_string(const string_type& other,
size_type pos,
size_type count)
: m_storage()
{
assign(other, pos, count);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>::xbasic_fixed_string(const_pointer s, size_type count)
: m_storage()
{
assign(s, count);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>::xbasic_fixed_string(const_pointer s)
: m_storage()
{
assign(s);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>::xbasic_fixed_string(initializer_type ilist)
: m_storage()
{
assign(ilist);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
template <class InputIt>
inline xbasic_fixed_string<CT, N, ST, EP, TR>::xbasic_fixed_string(InputIt first, InputIt last)
: m_storage()
{
assign(first, last);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>::operator string_type() const
{
return string_type(data());
}
/**************
* Assignment *
**************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::operator=(const_pointer s) -> self_type&
{
return assign(s);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::operator=(value_type ch) -> self_type&
{
return assign(size_type(1), ch);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::operator=(initializer_type ilist) -> self_type&
{
return assign(ilist);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::operator=(const string_type& str) -> self_type&
{
return assign(str);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::assign(size_type count, value_type ch) -> self_type&
{
m_storage.set_size(error_policy::check_size(count));
traits_type::assign(data(), count, ch);
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::assign(const self_type& other,
size_type pos,
size_type count) -> self_type&
{
check_index_strict(pos, other.size(), "xbasic_fixed_string::assign");
size_type copy_count = std::min(other.size() - pos, count);
m_storage.set_size(error_policy::check_size(copy_count));
traits_type::copy(data(), other.data() + pos, copy_count);
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::assign(const_pointer s, size_type count) -> self_type&
{
m_storage.set_size(error_policy::check_size(count));
traits_type::copy(data(), s, count);
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::assign(const_pointer s) -> self_type&
{
std::size_t ssize = traits_type::length(s);
return assign(s, ssize);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::assign(initializer_type ilist) -> self_type&
{
return assign(ilist.begin(), ilist.end());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
template <class InputIt>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::assign(InputIt first, InputIt last) -> self_type&
{
m_storage.set_size(error_policy::check_size(static_cast<size_type>(std::distance(first, last))));
std::copy(first, last, data());
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::assign(const self_type& rhs) -> self_type&
{
if (this != &rhs)
{
m_storage.set_size(rhs.size());
traits_type::copy(data(), rhs.data(), rhs.size());
}
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::assign(self_type&& rhs) -> self_type&
{
if (this != &rhs)
{
m_storage.set_size(rhs.size());
traits_type::copy(data(), rhs.data(), rhs.size());
}
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::assign(const string_type& other) -> self_type&
{
return assign(other.c_str());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::assign(const string_type& other,
size_type pos,
size_type count) -> self_type&
{
return assign(other.c_str() + pos, std::min(count, other.size() - pos));
}
/******************
* Element access *
******************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::at(size_type pos) -> reference
{
check_index(pos, size(), "basic_fixed_string::at");
return this->operator[](pos);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::at(size_type pos) const -> const_reference
{
check_index(pos, size(), "basic_fixed_string::at");
return this->operator[](pos);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::operator[](size_type pos) -> reference
{
return data()[pos];
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::operator[](size_type pos) const -> const_reference
{
return data()[pos];
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::front() -> reference
{
return this->operator[](0);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::front() const -> const_reference
{
return this->operator[](0);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::back() -> reference
{
return this->operator[](size() - 1);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::back() const -> const_reference
{
return this->operator[](size() - 1);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::data() noexcept -> pointer
{
return m_storage.buffer();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::data() const noexcept -> const_pointer
{
return m_storage.buffer();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::c_str() const noexcept -> const_pointer
{
return m_storage.buffer();
}
/*************
* Iterators *
*************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::begin() noexcept -> iterator
{
return data();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::end() noexcept -> iterator
{
return data() + size();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::begin() const noexcept -> const_iterator
{
return cbegin();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::end() const noexcept -> const_iterator
{
return cend();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::cbegin() const noexcept -> const_iterator
{
return data();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::cend() const noexcept -> const_iterator
{
return data() + size();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::rbegin() noexcept -> reverse_iterator
{
return reverse_iterator(end());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::rend() noexcept -> reverse_iterator
{
return reverse_iterator(begin());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::rbegin() const noexcept -> const_reverse_iterator
{
return const_reverse_iterator(end());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::rend() const noexcept -> const_reverse_iterator
{
return const_reverse_iterator(begin());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::crbegin() const noexcept -> const_reverse_iterator
{
return const_reverse_iterator(end());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::crend() const noexcept -> const_reverse_iterator
{
return const_reverse_iterator(begin());
}
/************
* Capacity *
************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool xbasic_fixed_string<CT, N, ST, EP, TR>::empty() const noexcept
{
return size() == 0;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::size() const noexcept -> size_type
{
return m_storage.size();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::length() const noexcept -> size_type
{
return m_storage.size();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::max_size() const noexcept -> size_type
{
return N;
}
/**************
* Operations *
**************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline void xbasic_fixed_string<CT, N, ST, EP, TR>::clear() noexcept
{
m_storage.set_size(0);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline void xbasic_fixed_string<CT, N, ST, EP, TR>::push_back(value_type ch)
{
error_policy::check_add(size(), size_type(1));
data()[size()] = ch;
m_storage.adjust_size(+1);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline void xbasic_fixed_string<CT, N, ST, EP, TR>::pop_back()
{
m_storage.adjust_size(-1);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::substr(size_type pos, size_type count) const -> self_type
{
return self_type(*this, pos, count);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::copy(pointer dest, size_type count, size_type pos) const -> size_type
{
check_index_strict(pos, size(), "xbasic_fixed_string::copy");
size_type nb_copied = std::min(count, size() - pos);
traits_type::copy(dest, data() + pos, nb_copied);
return nb_copied;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline void xbasic_fixed_string<CT, N, ST, EP, TR>::resize(size_type count)
{
resize(count, value_type(' ')); // need to initialize with some value != \0
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline void xbasic_fixed_string<CT, N, ST, EP, TR>::resize(size_type count, value_type ch)
{
size_type old_size = size();
m_storage.set_size(error_policy::check_size(count));
if (old_size < size())
{
traits_type::assign(data() + old_size, size() - old_size, ch);
}
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline void xbasic_fixed_string<CT, N, ST, EP, TR>::swap(self_type& rhs) noexcept
{
self_type tmp(std::move(rhs));
rhs = std::move(*this);
*this = std::move(tmp);
}
/**********
* insert *
**********/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
auto xbasic_fixed_string<CT, N, ST, EP, TR>::insert(size_type index, size_type count, value_type ch) -> self_type&
{
check_index_strict(index, size(), "xbasic_fixed_string::insert");
size_type old_size = size();
m_storage.set_size(error_policy::check_add(size(), count));
std::copy_backward(data() + index, data() + old_size, end());
traits_type::assign(data() + index, count, ch);
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::insert(size_type index, const_pointer s) -> self_type&
{
return insert(index, s, traits_type::length(s));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
auto xbasic_fixed_string<CT, N, ST, EP, TR>::insert(size_type index, const_pointer s, size_type count) -> self_type&
{
check_index_strict(index, size(), "xbasic_fixed_string::insert");
size_type old_size = size();
m_storage.set_size(error_policy::check_add(size(), count));
std::copy_backward(data() + index, data() + old_size, end());
traits_type::copy(data() + index, s, count);
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::insert(size_type index, const self_type& str) -> self_type&
{
return insert(index, str.data(), str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::insert(size_type index, const self_type& str,
size_type index_str, size_type count) -> self_type&
{
check_index_strict(index_str, str.size(), "xbasic_fixed_string::insert");
return insert(index, str.data() + index_str, std::min(count, str.size() - index_str));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::insert(size_type index, const string_type& str) -> self_type&
{
return insert(index, str.c_str(), str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::insert(size_type index, const string_type& str,
size_type index_str, size_type count) -> self_type&
{
check_index_strict(index_str, str.size(), "xbasic_fixed_string::insert");
return insert(index, str.c_str() + index_str, std::min(count, str.size() - index_str));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::insert(const_iterator pos, value_type ch) -> iterator
{
return insert(pos, size_type(1), ch);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::insert(const_iterator pos, size_type count, value_type ch) -> iterator
{
if (cbegin() <= pos && pos < cend())
{
size_type index = static_cast<size_type>(pos - cbegin());
insert(index, count, ch);
return const_cast<iterator>(pos);
}
return end();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::insert(const_iterator pos, initializer_type ilist) -> iterator
{
return insert(pos, ilist.begin(), ilist.end());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
template <class InputIt>
auto xbasic_fixed_string<CT, N, ST, EP, TR>::insert(const_iterator pos, InputIt first, InputIt last) -> iterator
{
if (cbegin() <= pos && pos < cend())
{
size_type index = static_cast<size_type>(pos - cbegin());
size_type count = static_cast<size_type>(std::distance(first, last));
size_type old_size = size();
m_storage.set_size(error_policy::check_add(size(), count));
std::copy_backward(data() + index, data() + old_size, end());
std::copy(first, last, data() + index);
return begin() + index;
}
return end();
}
/*********
* erase *
*********/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
auto xbasic_fixed_string<CT, N, ST, EP, TR>::erase(size_type index, size_type count) -> self_type&
{
check_index_strict(index, size(), "xbasic_fixed_string::erase");
size_type erase_count = std::min(count, size() - index);
// cannot use traits_type::copy because of overlapping
std::copy(data() + index + erase_count, data() + size(), data() + index);
m_storage.adjust_size(-static_cast<std::ptrdiff_t>(erase_count));
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::erase(const_iterator position) -> iterator
{
return erase(position, position + 1);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
auto xbasic_fixed_string<CT, N, ST, EP, TR>::erase(const_iterator first, const_iterator last) -> iterator
{
if (cbegin() <= first && first < cend())
{
const_iterator adapted_last = std::min(last, cend());
size_type erase_count = static_cast<size_type>(adapted_last - first);
// cannot use traits_type::copy because of overlapping
std::copy(adapted_last, cend(), iterator(first));
m_storage.adjust_size(-static_cast<std::ptrdiff_t>(erase_count));
return const_cast<iterator>(first);
}
return end();
}
/**********
* append *
**********/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::append(size_type count, value_type ch) -> self_type&
{
size_type old_size = m_storage.size();
m_storage.set_size(error_policy::check_add(size(), count));
traits_type::assign(data() + old_size, count, ch);
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::append(const self_type& str) -> self_type&
{
return append(str.data(), str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::append(const self_type& str,
size_type pos, size_type count) -> self_type&
{
check_index_strict(pos, str.size(), "xbasic_fixed_string::append");
return append(str.data() + pos, std::min(count, str.size() - pos));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::append(const string_type& str) -> self_type&
{
return append(str.c_str(), str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::append(const string_type& str,
size_type pos, size_type count) -> self_type&
{
check_index_strict(pos, str.size(), "xbasic_fixed_string::append");
return append(str.c_str() + pos, std::min(count, str.size() - pos));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::append(const_pointer s, size_type count) -> self_type&
{
size_type old_size = m_storage.size();
m_storage.set_size(error_policy::check_add(size(), count));
traits_type::copy(data() + old_size, s, count);
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::append(const_pointer s) -> self_type&
{
return append(s, traits_type::length(s));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::append(initializer_type ilist) -> self_type&
{
return append(ilist.begin(), ilist.end());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
template <class InputIt>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::append(InputIt first, InputIt last) -> self_type&
{
size_type count = static_cast<size_type>(std::distance(first, last));
size_type old_size = m_storage.size();
m_storage.set_size(error_policy::check_add(size(), count));
std::copy(first, last, data() + old_size);
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::operator+=(const self_type& str) -> self_type&
{
return append(str);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::operator+=(const string_type& str) -> self_type&
{
return append(str);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::operator+=(value_type ch) -> self_type&
{
return append(size_type(1), ch);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::operator+=(const_pointer s) -> self_type&
{
return append(s);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::operator+=(initializer_type ilist) -> self_type&
{
return append(ilist);
}
/***********
* compare *
***********/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline int xbasic_fixed_string<CT, N, ST, EP, TR>::compare(const self_type& str) const noexcept
{
return compare_impl(data(), size(), str.data(), str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline int xbasic_fixed_string<CT, N, ST, EP, TR>::compare(size_type pos1, size_type count1, const self_type& str) const
{
check_index_strict(pos1, size(), "xbasic_fixed_string::compare");
return compare_impl(data() + pos1, std::min(count1, size() - pos1), str.data(), str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline int xbasic_fixed_string<CT, N, ST, EP, TR>::compare(size_type pos1, size_type count1, const self_type& str,
size_type pos2, size_type count2) const
{
check_index_strict(pos1, size(), "xbasic_fixed_string::compare");
check_index_strict(pos2, str.size(), "xbasic_fixed_string::compare");
return compare_impl(data() + pos1, std::min(count1, size() - pos1),
str.data() + pos2, std::min(count2, str.size() - pos2));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline int xbasic_fixed_string<CT, N, ST, EP, TR>::compare(const string_type& str) const noexcept
{
return compare_impl(data(), size(), str.data(), str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline int xbasic_fixed_string<CT, N, ST, EP, TR>::compare(size_type pos1, size_type count1, const string_type& str) const
{
check_index_strict(pos1, size(), "xbasic_fixed_string::compare");
return compare_impl(data() + pos1, std::min(count1, size() - pos1), str.data(), str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline int xbasic_fixed_string<CT, N, ST, EP, TR>::compare(size_type pos1, size_type count1, const string_type& str,
size_type pos2, size_type count2) const
{
check_index_strict(pos1, size(), "xbasic_fixed_string::compare");
check_index_strict(pos2, str.size(), "xbasic_fixed_string::compare");
return compare_impl(data() + pos1, std::min(count1, size() - pos1),
str.data() + pos2, std::min(count2, str.size() - pos2));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline int xbasic_fixed_string<CT, N, ST, EP, TR>::compare(const_pointer s) const noexcept
{
return compare_impl(data(), size(), s, traits_type::length(s));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
int xbasic_fixed_string<CT, N, ST, EP, TR>::compare(size_type pos1, size_type count1, const_pointer s) const
{
return compare(pos1, count1, s, traits_type::length(s));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
int xbasic_fixed_string<CT, N, ST, EP, TR>::compare(size_type pos1, size_type count1, const_pointer s, size_type count2) const
{
check_index_strict(pos1, size(), "xbasic_fixed_string::compare");
return compare_impl(data() + pos1, std::min(count1, size() - pos1),
s, count2);
}
/***********
* replace *
***********/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::replace(size_type pos, size_type count, const self_type& str) -> self_type&
{
return replace(pos, count, str.data(), str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::replace(const_iterator first, const_iterator last,
const self_type& str) -> self_type&
{
return replace(first, last, str.data(), str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::replace(size_type pos1, size_type count1, const self_type& str,
size_type pos2, size_type count2) -> self_type&
{
check_index_strict(pos2, str.size(), "xbasic_fixed_string::replace");
return replace(pos1, count1, str.data() + pos2, std::min(count2, str.size() - pos2));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::replace(size_type pos, size_type count, const string_type& str) -> self_type&
{
return replace(pos, count, str.data(), str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::replace(const_iterator first, const_iterator last,
const string_type& str) -> self_type&
{
return replace(first, last, str.data(), str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::replace(size_type pos1, size_type count1, const string_type& str,
size_type pos2, size_type count2) -> self_type&
{
check_index_strict(pos2, str.size(), "xbasic_fixed_string::replace");
return replace(pos1, count1, str.data() + pos2, std::min(count2, str.size() - pos2));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
auto xbasic_fixed_string<CT, N, ST, EP, TR>::replace(size_type pos, size_type count,
const_pointer cstr, size_type count2) -> self_type&
{
check_index_strict(pos, size(), "xbasic_fixed_string::replace");
size_type erase_count = std::min(count, size() - pos);
size_type new_size = error_policy::check_add(size() - erase_count, count2);
if (erase_count > count2)
{
traits_type::copy(data() + pos, cstr, count2);
std::copy(cbegin() + pos + erase_count, cend(), data() + pos + count2);
m_storage.set_size(new_size);
}
else if (erase_count < count2)
{
std::copy_backward(cbegin() + pos + erase_count, cend(), data() + new_size);
traits_type::copy(data() + pos, cstr, count2);
m_storage.set_size(new_size);
}
else
{
traits_type::copy(data() + pos, cstr, count2);
}
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::replace(const_iterator first, const_iterator last,
const_pointer cstr, size_type count2) -> self_type&
{
if (cbegin() <= first && first < last && last <= cend())
{
size_type pos = static_cast<size_type>(first - cbegin());
size_type count = static_cast<size_type>(last - first);
return replace(pos, count, cstr, count2);
}
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::replace(size_type pos, size_type count,
const_pointer cstr) -> self_type&
{
return replace(pos, count, cstr, traits_type::length(cstr));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::replace(const_iterator first, const_iterator last,
const_pointer cstr) -> self_type&
{
return replace(first, last, cstr, traits_type::length(cstr));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::replace(size_type pos, size_type count,
size_type count2, value_type ch) -> self_type&
{
check_index_strict(pos, size(), "xbasic_fixed_string::replace");
size_type erase_count = std::min(count, size() - pos);
size_type new_size = error_policy::check_add(size() - erase_count, count2);
if (erase_count > count2)
{
traits_type::assign(data() + pos, count2, ch);
std::copy(cbegin() + pos + erase_count, cend(), data() + pos + count2);
m_storage.set_size(new_size);
}
else if (erase_count < count2)
{
std::copy_backward(cbegin() + pos + erase_count, cend(), data() + new_size);
traits_type::assign(data() + pos, count2, ch);
m_storage.set_size(new_size);
}
else
{
traits_type::assign(data() + pos, count2, ch);
}
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::replace(const_iterator first, const_iterator last,
size_type count2, value_type ch) -> self_type&
{
if (cbegin() <= first && first < last && last <= cend())
{
size_type pos = static_cast<size_type>(first - cbegin());
size_type count = static_cast<size_type>(last - first);
return replace(pos, count, count2, ch);
}
return *this;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::replace(const_iterator first, const_iterator last,
initializer_type ilist) -> self_type&
{
return replace(first, last, ilist.begin(), ilist.end());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
template <class InputIt>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::replace(const_iterator first, const_iterator last,
InputIt first2, InputIt last2) -> self_type&
{
if (cbegin() <= first && first < last && last <= cend())
{
size_type pos = static_cast<size_type>(first - cbegin());
size_type erase_count = static_cast<size_type>(last - first);
size_type count2 = static_cast<size_type>(std::distance(first2, last2));
size_type new_size = error_policy::check_add(size() - erase_count, count2);
if (erase_count > count2)
{
std::copy(first2, last2, data() + pos);
std::copy(cbegin() + pos + erase_count, cend(), data() + pos + count2);
m_storage.set_size(new_size);
}
else if (erase_count < count2)
{
std::copy_backward(cbegin() + pos + erase_count, cend(), data() + new_size);
std::copy(first2, last2, data() + pos);
m_storage.set_size(new_size);
}
else
{
std::copy(first2, last2, data() + pos);
}
}
return *this;
}
/********
* find *
********/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find(const self_type& str, size_type pos) const noexcept -> size_type
{
return find(str.data(), pos, str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find(const string_type& str, size_type pos) const noexcept -> size_type
{
return find(str.data(), pos, str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
auto xbasic_fixed_string<CT, N, ST, EP, TR>::find(const_pointer s, size_type pos, size_type count) const -> size_type
{
if (count == size_type(0) && pos <= size())
{
return pos;
}
size_type nm;
if (pos < size() && count <= (nm = size() - pos))
{
const_pointer uptr, vptr;
for (nm -= count - 1, vptr = data() + pos;
(uptr = traits_type::find(vptr, nm, *s)) != 0;
nm -= size_type(uptr - vptr) + 1ul, vptr = uptr + 1ul)
{
if (traits_type::compare(uptr, s, count) == 0)
{
return size_type(uptr - data());
}
}
}
return npos;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find(const_pointer s, size_type pos) const -> size_type
{
return find(s, pos, traits_type::length(s));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find(value_type ch, size_type pos) const -> size_type
{
return find((const_pointer)(&ch), pos, size_type(1));
}
/*********
* rfind *
*********/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::rfind(const self_type& str, size_type pos) const noexcept -> size_type
{
return rfind(str.data(), pos, str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::rfind(const string_type& str, size_type pos) const noexcept -> size_type
{
return rfind(str.data(), pos, str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
auto xbasic_fixed_string<CT, N, ST, EP, TR>::rfind(const_pointer s, size_type pos, size_type count) const -> size_type
{
if (count == 0)
{
return std::min(pos, size());
}
if (count <= size())
{
const_pointer uptr = data() + std::min(pos, size() - count);
for (;; --uptr)
{
if (traits_type::eq(*uptr, *s) && traits_type::compare(uptr, s, count) == 0)
{
return size_type(uptr - data());
}
else if (uptr == data())
{
break;
}
}
}
return npos;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::rfind(const_pointer s, size_type pos) const -> size_type
{
return rfind(s, pos, traits_type::length(s));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::rfind(value_type ch, size_type pos) const -> size_type
{
return rfind((const_pointer)(&ch), pos, size_type(1));
}
/*****************
* find_first_of *
*****************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_first_of(const self_type& str, size_type pos) const noexcept -> size_type
{
return find_first_of(str.data(), pos, str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_first_of(const string_type& str, size_type pos) const noexcept -> size_type
{
return find_first_of(str.data(), pos, str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_first_of(const_pointer s, size_type pos, size_type count) const -> size_type
{
if (size_type(0) < count && pos < size())
{
const_pointer vptr = data() + size();
for (const_pointer uptr = data() + pos; uptr < vptr; ++uptr)
{
if (traits_type::find(s, count, *uptr) != 0)
{
return size_type(uptr - data());
}
}
}
return npos;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_first_of(const_pointer s, size_type pos) const -> size_type
{
return find_first_of(s, pos, traits_type::length(s));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_first_of(value_type ch, size_type pos) const -> size_type
{
return find_first_of((const_pointer)(&ch), pos, size_type(1));
}
/*********************
* find_first_not_of *
*********************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_first_not_of(const self_type& str, size_type pos) const noexcept -> size_type
{
return find_first_not_of(str.data(), pos, str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_first_not_of(const string_type& str, size_type pos) const noexcept -> size_type
{
return find_first_not_of(str.data(), pos, str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_first_not_of(const_pointer s, size_type pos, size_type count) const -> size_type
{
if (pos < size())
{
const_pointer vptr = data() + size();
for (const_pointer uptr = data() + pos; uptr < vptr; ++uptr)
{
if (traits_type::find(s, count, *uptr) == 0)
{
return size_type(uptr - data());
}
}
}
return npos;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_first_not_of(const_pointer s, size_type pos) const -> size_type
{
return find_first_not_of(s, pos, traits_type::length(s));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_first_not_of(value_type ch, size_type pos) const -> size_type
{
return find_first_not_of((const_pointer)(&ch), pos, size_type(1));
}
/****************
* find_last_of *
****************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_last_of(const self_type& str, size_type pos) const noexcept -> size_type
{
return find_last_of(str.data(), pos, str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_last_of(const string_type& str, size_type pos) const noexcept -> size_type
{
return find_last_of(str.data(), pos, str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_last_of(const_pointer s, size_type pos, size_type count) const -> size_type
{
if (size_type(0) < count && size_type(0) < size())
{
const_pointer uptr = data() + std::min(pos, size() - 1);
for (;; --uptr)
{
if (traits_type::find(s, count, *uptr) != 0)
{
return size_type(uptr - data());
}
else if (uptr == data())
{
break;
}
}
}
return npos;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_last_of(const_pointer s, size_type pos) const -> size_type
{
return find_last_of(s, pos, traits_type::length(s));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_last_of(value_type ch, size_type pos) const -> size_type
{
return find_last_of((const_pointer)(&ch), pos, size_type(1));
}
/********************
* find_last_not_of *
********************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_last_not_of(const self_type& str, size_type pos) const noexcept -> size_type
{
return find_last_not_of(str.data(), pos, str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_last_not_of(const string_type& str, size_type pos) const noexcept -> size_type
{
return find_last_not_of(str.data(), pos, str.size());
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_last_not_of(const_pointer s, size_type pos, size_type count) const -> size_type
{
if (size_type(0) < size())
{
const_pointer uptr = data() + std::min(pos, size() - 1);
for (;; --uptr)
{
if (traits_type::find(s, count, *uptr) == 0)
{
return size_type(uptr - data());
}
else if (uptr == data())
{
break;
}
}
}
return npos;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_last_not_of(const_pointer s, size_type pos) const -> size_type
{
return find_last_not_of(s, pos, traits_type::length(s));
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline auto xbasic_fixed_string<CT, N, ST, EP, TR>::find_last_not_of(value_type ch, size_type pos) const -> size_type
{
return find_last_not_of((const_pointer)(&ch), pos, size_type(1));
}
/*******************
* Private methods *
*******************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
int xbasic_fixed_string<CT, N, ST, EP, TR>::compare_impl(const_pointer s1, size_type count1,
const_pointer s2, size_type count2) const noexcept
{
size_type rlen = std::min(count1, count2);
int res = traits_type::compare(s1, s2, rlen);
if (res == 0)
{
return count1 < count2 ? -1 : (count1 > count2 ? 1 : 0);
}
else
{
return res;
}
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline void xbasic_fixed_string<CT, N, ST, EP, TR>::update_null_termination() noexcept
{
data()[size()] = '\0';
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
void xbasic_fixed_string<CT, N, ST, EP, TR>::check_index(size_type pos, size_type size, const char* what) const
{
if (pos >= size)
{
#if defined(XTL_NO_EXCEPTIONS)
std::fprintf(stderr, "%s\n", what);
std::terminate();
#else
throw std::out_of_range(what);
#endif
}
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
void xbasic_fixed_string<CT, N, ST, EP, TR>::check_index_strict(size_type pos, size_type size, const char* what) const
{
check_index(pos, size + 1, what);
}
/**************************
* Concatenation operator *
**************************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs)
{
xbasic_fixed_string<CT, N, ST, EP, TR> res(lhs);
return res += rhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const CT* rhs)
{
xbasic_fixed_string<CT, N, ST, EP, TR> res(lhs);
return res += rhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
CT rhs)
{
xbasic_fixed_string<CT, N, ST, EP, TR> res(lhs);
return res += rhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs)
{
xbasic_fixed_string<CT, N, ST, EP, TR> res(lhs);
return res += rhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(CT lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs)
{
using size_type = typename xbasic_fixed_string<CT, N, ST, EP, TR>::size_type;
xbasic_fixed_string<CT, N, ST, EP, TR> res(size_type(1), lhs);
return res += rhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>&& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs)
{
xbasic_fixed_string<CT, N, ST, EP, TR> res(std::move(lhs));
return res += rhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>&& rhs)
{
xbasic_fixed_string<CT, N, ST, EP, TR> res(lhs);
return res += std::move(rhs);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>&& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>&& rhs)
{
xbasic_fixed_string<CT, N, ST, EP, TR> res(std::move(lhs));
return res += std::move(rhs);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>&& lhs,
const CT* rhs)
{
xbasic_fixed_string<CT, N, ST, EP, TR> res(std::move(lhs));
return res += rhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const xbasic_fixed_string<CT, N, ST, EP, TR>&& lhs,
CT rhs)
{
xbasic_fixed_string<CT, N, ST, EP, TR> res(std::move(lhs));
return res += rhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>&& rhs)
{
xbasic_fixed_string<CT, N, ST, EP, TR> res(lhs);
return res += std::move(rhs);
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline xbasic_fixed_string<CT, N, ST, EP, TR>
operator+(CT lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>&& rhs)
{
using size_type = typename xbasic_fixed_string<CT, N, ST, EP, TR>::size_type;
xbasic_fixed_string<CT, N, ST, EP, TR> res(size_type(1), lhs);
return res += std::move(rhs);
}
/************************
* Comparison operators *
************************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator==(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return lhs.compare(rhs) == 0;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator==(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const CT* rhs) noexcept
{
return lhs.compare(rhs) == 0;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator==(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return rhs == lhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator==(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const std::basic_string<CT, TR>& rhs) noexcept
{
return lhs == rhs.c_str();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator==(const std::basic_string<CT, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return lhs.c_str() == rhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator!=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return lhs.compare(rhs) != 0;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator!=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const CT* rhs) noexcept
{
return lhs.compare(rhs) != 0;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator!=(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return rhs != lhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator!=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const std::basic_string<CT, TR>& rhs) noexcept
{
return lhs != rhs.c_str();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator!=(const std::basic_string<CT, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return lhs.c_str() != rhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator<(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return lhs.compare(rhs) < 0;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator<(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const CT* rhs) noexcept
{
return lhs.compare(rhs) < 0;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator<(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return rhs > lhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator<(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const std::basic_string<CT, TR>& rhs) noexcept
{
return lhs < rhs.c_str();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator<(const std::basic_string<CT, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return lhs.c_str() < rhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator<=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return lhs.compare(rhs) <= 0;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator<=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const CT* rhs) noexcept
{
return lhs.compare(rhs) <= 0;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator<=(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return rhs >= lhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator<=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const std::basic_string<CT, TR>& rhs) noexcept
{
return lhs <= rhs.c_str();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator<=(const std::basic_string<CT, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return lhs.c_str() <= rhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator>(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return lhs.compare(rhs) > 0;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator>(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const CT* rhs) noexcept
{
return lhs.compare(rhs) > 0;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator>(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return rhs < lhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator>(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const std::basic_string<CT, TR>& rhs) noexcept
{
return lhs > rhs.c_str();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator>(const std::basic_string<CT, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return lhs.c_str() > rhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator>=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return lhs.compare(rhs) >= 0;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator>=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const CT* rhs) noexcept
{
return lhs.compare(rhs) >= 0;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator>=(const CT* lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return rhs <= lhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator>=(const xbasic_fixed_string<CT, N, ST, EP, TR>& lhs,
const std::basic_string<CT, TR>& rhs) noexcept
{
return lhs >= rhs.c_str();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline bool operator>=(const std::basic_string<CT, TR>& lhs,
const xbasic_fixed_string<CT, N, ST, EP, TR>& rhs) noexcept
{
return lhs.c_str() >= rhs;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline void swap(xbasic_fixed_string<CT, N, ST, EP, TR>& lhs, xbasic_fixed_string<CT, N, ST, EP, TR>& rhs)
{
lhs.swap(rhs);
}
/******************
* Input / output *
******************/
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline std::basic_ostream<CT, TR>& operator<<(std::basic_ostream<CT, TR>& os,
const xbasic_fixed_string<CT, N, ST, EP, TR>& str)
{
os << str.c_str();
return os;
}
#ifdef __CLING__
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
nlohmann::json mime_bundle_repr(const xbasic_fixed_string<CT, N, ST, EP, TR>& str)
{
auto bundle = nlohmann::json::object();
bundle["text/plain"] = str.c_str();
return bundle;
}
#endif
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline std::basic_istream<CT, TR>& operator>>(std::basic_istream<CT, TR>& is,
xbasic_fixed_string<CT, N, ST, EP, TR>& str)
{
// Not optimal
std::string tmp;
is >> tmp;
str = tmp.c_str();
return is;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline std::basic_istream<CT, TR>& getline(std::basic_istream<CT, TR>& input,
xbasic_fixed_string<CT, N, ST, EP, TR>& str,
CT delim)
{
std::string tmp;
auto& ret = std::getline(input, tmp, delim);
str = tmp;
return ret;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline std::basic_istream<CT, TR>& getline(std::basic_istream<CT, TR>&& input,
xbasic_fixed_string<CT, N, ST, EP, TR>& str,
CT delim)
{
std::string tmp;
auto& ret = std::getline(std::move(input), tmp, delim);
str = tmp;
return ret;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline std::basic_istream<CT, TR>& getline(std::basic_istream<CT, TR>& input,
xbasic_fixed_string<CT, N, ST, EP, TR>& str)
{
std::string tmp;
auto& ret = std::getline(input, tmp);
str = tmp;
return ret;
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
inline std::basic_istream<CT, TR>& getline(std::basic_istream<CT, TR>&& input,
xbasic_fixed_string<CT, N, ST, EP, TR>& str)
{
std::string tmp;
auto& ret = std::getline(std::move(input), tmp);
str = tmp;
return ret;
}
}
#endif // xtl