mirror of https://github.com/axmolengine/axmol.git
1288 lines
48 KiB
C++
1288 lines
48 KiB
C++
//////////////////////////////////////////////////////////////////////////////////////////
|
|
// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
|
|
// client application.
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
/*
|
|
The MIT License (MIT)
|
|
|
|
Copyright (c) 2012-2023 HALX99
|
|
Copyright (c) 2016 Matthew Rodusek(matthew.rodusek@gmail.com) <http://rodusek.me>
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
See: https://github.com/bitwizeshift/string_view-standalone
|
|
*/
|
|
#ifndef YASIO__STRING_VIEW_HPP
|
|
#define YASIO__STRING_VIEW_HPP
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <wchar.h>
|
|
#include <string>
|
|
#include "yasio/impl/char_traits.hpp"
|
|
#include "yasio/compiler/feature_test.hpp"
|
|
|
|
/// wcsncasecmp workaround for android API level < 23, copy from msvc ucrt 10.0.18362.0 'wcsnicmp'
|
|
#if (defined(__ANDROID_API__) && __ANDROID_API__ < 23) || defined(__MINGW32__)
|
|
inline int wcsncasecmp(wchar_t const* const lhs, wchar_t const* const rhs, size_t const count)
|
|
{
|
|
if (count == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
wchar_t const* lhs_ptr = reinterpret_cast<wchar_t const*>(lhs);
|
|
wchar_t const* rhs_ptr = reinterpret_cast<wchar_t const*>(rhs);
|
|
|
|
int result;
|
|
int lhs_value;
|
|
int rhs_value;
|
|
size_t remaining = count;
|
|
do
|
|
{
|
|
lhs_value = ::towlower(*lhs_ptr++);
|
|
rhs_value = ::towlower(*rhs_ptr++);
|
|
result = lhs_value - rhs_value;
|
|
} while (result == 0 && lhs_value != 0 && --remaining != 0);
|
|
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
/// string_view workaround on c++11
|
|
#if YASIO__HAS_CXX17
|
|
# if __has_include(<string_view>)
|
|
# include <string_view>
|
|
# endif
|
|
#else
|
|
# include <algorithm>
|
|
# include <exception>
|
|
# include <stdexcept>
|
|
namespace cxx17
|
|
{
|
|
////////////////////////////////////////////////////////////////////////////
|
|
/// \brief A wrapper around non-owned strings.
|
|
///
|
|
/// This is an implementation of the C++17 string_view proposal
|
|
///
|
|
/// \ingroup core
|
|
////////////////////////////////////////////////////////////////////////////
|
|
template <typename _CharT, typename _Traits = std::char_traits<_CharT>>
|
|
class basic_string_view;
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
class basic_string_view {
|
|
//------------------------------------------------------------------------
|
|
// Public Member Types
|
|
//------------------------------------------------------------------------
|
|
public:
|
|
using char_type = _CharT;
|
|
using traits_type = _Traits;
|
|
using size_type = size_t;
|
|
|
|
using value_type = _CharT;
|
|
using reference = value_type&;
|
|
using const_reference = const value_type&;
|
|
using pointer = value_type*;
|
|
using const_pointer = const value_type*;
|
|
|
|
using iterator = const _CharT*;
|
|
using const_iterator = const _CharT*;
|
|
|
|
//------------------------------------------------------------------------
|
|
// Public Members
|
|
//------------------------------------------------------------------------
|
|
public:
|
|
static const size_type npos = size_type(-1);
|
|
|
|
//------------------------------------------------------------------------
|
|
// Constructors
|
|
//------------------------------------------------------------------------
|
|
public:
|
|
/// \brief Default constructs a basic_string_view without any content
|
|
basic_string_view();
|
|
|
|
/// \brief Constructs a basic_string_view from a std::basic_string
|
|
///
|
|
/// \param str the string to view
|
|
template <typename Allocator>
|
|
basic_string_view(const std::basic_string<_CharT, _Traits, Allocator>& str);
|
|
|
|
/// \brief Constructs a basic_string_view from an ansi-string
|
|
///
|
|
/// \param str the string to view
|
|
basic_string_view(const char_type* str);
|
|
|
|
/// \brief Constructs a basic_string_view from an ansi string of a given size
|
|
///
|
|
/// \param str the string to view
|
|
/// \param count the size of the string
|
|
basic_string_view(const char_type* str, size_type count);
|
|
|
|
//------------------------------------------------------------------------
|
|
// Assignment
|
|
//------------------------------------------------------------------------
|
|
public:
|
|
//------------------------------------------------------------------------
|
|
// Capacity
|
|
//------------------------------------------------------------------------
|
|
public:
|
|
/// \brief Returns the length of the string, in terms of bytes
|
|
///
|
|
/// \return the length of the string, in terms of bytes
|
|
size_type size() const;
|
|
|
|
/// \copydoc basic_string_view::size
|
|
size_type length() const;
|
|
|
|
/// \brief The largest possible number of char-like objects that can be
|
|
/// referred to by a basic_string_view.
|
|
/// \return Maximum number of characters
|
|
size_type max_size() const;
|
|
|
|
/// \brief Returns whether the basic_string_view is empty
|
|
/// (i.e. whether its length is 0).
|
|
///
|
|
/// \return whether the basic_string_view is empty
|
|
bool empty() const;
|
|
|
|
//------------------------------------------------------------------------
|
|
// Element Access
|
|
//------------------------------------------------------------------------
|
|
public:
|
|
/// \brief Gets the ansi-string of the current basic_string_view
|
|
///
|
|
/// \return the ansi-string pointer
|
|
const char_type* c_str() const;
|
|
|
|
/// \brief Gets the data of the current basic_string_view
|
|
///
|
|
/// \note This is an alias of #c_str
|
|
///
|
|
/// \return the data this basic_string_view contains
|
|
const char_type* data() const;
|
|
|
|
/// \brief Accesses the element at index \p pos
|
|
///
|
|
/// \param pos the index to access
|
|
/// \return const reference to the character
|
|
const_reference operator[](size_t pos) const;
|
|
|
|
/// \brief Accesses the element at index \p pos
|
|
///
|
|
/// \param pos the index to access
|
|
/// \return const reference to the character
|
|
const_reference at(size_t pos) const;
|
|
|
|
/// \brief Access the first character of the string
|
|
///
|
|
/// \note Undefined behavior if basic_string_view is empty
|
|
///
|
|
/// \return reference to the first character of the string
|
|
const_reference front() const;
|
|
|
|
/// \brief References the last character of the string
|
|
///
|
|
/// \note Undefined behavior if basic_string_view is empty
|
|
///
|
|
/// \return reference to the last character of the string
|
|
const_reference back() const;
|
|
|
|
//------------------------------------------------------------------------
|
|
// Modifiers
|
|
//------------------------------------------------------------------------
|
|
public:
|
|
/// \brief Moves the start of the view forward by n characters.
|
|
///
|
|
/// The behavior is undefined if n > size().
|
|
///
|
|
/// \param n number of characters to remove from the start of the view
|
|
void remove_prefix(size_type n);
|
|
|
|
/// \brief Moves the end of the view back by n characters.
|
|
///
|
|
/// The behavior is undefined if n > size().
|
|
///
|
|
/// \param n number of characters to remove from the end of the view
|
|
void remove_suffix(size_type n);
|
|
|
|
/// \brief Exchanges the view with that of v.
|
|
///
|
|
/// \param v view to swap with
|
|
void swap(basic_string_view& v);
|
|
|
|
//------------------------------------------------------------------------
|
|
// Conversions
|
|
//------------------------------------------------------------------------
|
|
public:
|
|
/// \brief Creates a basic_string with a copy of the content of the current
|
|
/// view.
|
|
///
|
|
/// \tparam Allocator type used to allocate internal storage
|
|
/// \param a Allocator instance to use for allocating the new string
|
|
///
|
|
/// \return A basic_string containing a copy of the characters of the current
|
|
/// view.
|
|
template <class Allocator = std::allocator<_CharT>>
|
|
std::basic_string<_CharT, _Traits, Allocator> to_string(const Allocator& a = Allocator()) const;
|
|
|
|
/// \copydoc basic_string_view::to_string
|
|
template <class Allocator>
|
|
explicit operator std::basic_string<_CharT, _Traits, Allocator>() const;
|
|
|
|
//------------------------------------------------------------------------
|
|
// Operations
|
|
//------------------------------------------------------------------------
|
|
public:
|
|
/// \brief Copies the substring [pos, pos + rcount) to the character string
|
|
/// pointed
|
|
/// to by dest, where rcount is the smaller of count and size() - pos.
|
|
///
|
|
/// \param dest pointer to the destination character string
|
|
/// \param count requested substring length
|
|
/// \param pos position of the first character
|
|
size_type copy(char_type* dest, size_type count = npos, size_type pos = 0) const;
|
|
|
|
/// \brief Returns a substring of this viewed string
|
|
///
|
|
/// \param pos the position of the first character in the substring
|
|
/// \param len the length of the substring
|
|
/// \return the created substring
|
|
basic_string_view substr(size_t pos = 0, size_t len = npos) const;
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
/// \brief Compares two character sequences
|
|
///
|
|
/// \param v view to compare
|
|
/// \return negative value if this view is less than the other character
|
|
/// sequence, zero if the both character sequences are equal, positive
|
|
/// value if this view is greater than the other character sequence.
|
|
int compare(basic_string_view v) const;
|
|
|
|
/// \brief Compares two character sequences
|
|
///
|
|
/// \param pos position of the first character in this view to compare
|
|
/// \param count number of characters of this view to compare
|
|
/// \param v view to compare
|
|
/// \return negative value if this view is less than the other character
|
|
/// sequence, zero if the both character sequences are equal, positive
|
|
/// value if this view is greater than the other character sequence.
|
|
int compare(size_type pos, size_type count, basic_string_view v) const;
|
|
|
|
/// \brief Compares two character sequences
|
|
///
|
|
/// \param pos1 position of the first character in this view to compare
|
|
/// \param count1 number of characters of this view to compare
|
|
/// \param v view to compare
|
|
/// \param pos2 position of the second character in this view to compare
|
|
/// \param count2 number of characters of the given view to compare
|
|
/// \return negative value if this view is less than the other character
|
|
/// sequence, zero if the both character sequences are equal, positive
|
|
/// value if this view is greater than the other character sequence.
|
|
int compare(size_type pos1, size_type count1, basic_string_view v, size_type pos2, size_type count2) const;
|
|
|
|
/// \brief Compares two character sequences
|
|
///
|
|
/// \param s pointer to the character string to compare to
|
|
/// \return negative value if this view is less than the other character
|
|
/// sequence, zero if the both character sequences are equal, positive
|
|
/// value if this view is greater than the other character sequence.
|
|
int compare(const char_type* s) const;
|
|
|
|
/// \brief Compares two character sequences
|
|
///
|
|
/// \param pos position of the first character in this view to compare
|
|
/// \param count number of characters of this view to compare
|
|
/// \param s pointer to the character string to compare to
|
|
/// \return negative value if this view is less than the other character
|
|
/// sequence, zero if the both character sequences are equal, positive
|
|
/// value if this view is greater than the other character sequence.
|
|
int compare(size_type pos, size_type count, const char_type* s) const;
|
|
|
|
/// \brief Compares two character sequences
|
|
///
|
|
/// \param pos position of the first character in this view to compare
|
|
/// \param count1 number of characters of this view to compare
|
|
/// \param s pointer to the character string to compare to
|
|
/// \param count2 number of characters of the given view to compare
|
|
/// \return negative value if this view is less than the other character
|
|
/// sequence, zero if the both character sequences are equal, positive
|
|
/// value if this view is greater than the other character sequence.
|
|
int compare(size_type pos, size_type count1, const char_type* s, size_type count2) const;
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
size_type find(basic_string_view v, size_type pos = 0) const;
|
|
|
|
size_type find(char_type c, size_type pos = 0) const;
|
|
|
|
size_type find(const char_type* s, size_type pos, size_type count) const;
|
|
|
|
size_type find(const char_type* s, size_type pos = 0) const;
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
size_type rfind(basic_string_view v, size_type pos = npos) const;
|
|
|
|
size_type rfind(char_type c, size_type pos = npos) const;
|
|
|
|
size_type rfind(const char_type* s, size_type pos, size_type count) const;
|
|
|
|
size_type rfind(const char_type* s, size_type pos = npos) const;
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
size_type find_first_of(basic_string_view v, size_type pos = 0) const;
|
|
|
|
size_type find_first_of(char_type c, size_type pos = 0) const;
|
|
|
|
size_type find_first_of(const char_type* s, size_type pos, size_type count) const;
|
|
|
|
size_type find_first_of(const char_type* s, size_type pos = 0) const;
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
size_type find_last_of(basic_string_view v, size_type pos = npos) const;
|
|
|
|
size_type find_last_of(char_type c, size_type pos = npos) const;
|
|
|
|
size_type find_last_of(const char_type* s, size_type pos, size_type count) const;
|
|
|
|
size_type find_last_of(const char_type* s, size_type pos = npos) const;
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
size_type find_first_not_of(basic_string_view v, size_type pos = 0) const;
|
|
|
|
size_type find_first_not_of(char_type c, size_type pos = 0) const;
|
|
|
|
size_type find_first_not_of(const char_type* s, size_type pos, size_type count) const;
|
|
|
|
size_type find_first_not_of(const char_type* s, size_type pos = 0) const;
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
size_type find_last_not_of(basic_string_view v, size_type pos = npos) const;
|
|
|
|
size_type find_last_not_of(char_type c, size_type pos = npos) const;
|
|
|
|
size_type find_last_not_of(const char_type* s, size_type pos, size_type count) const;
|
|
|
|
size_type find_last_not_of(const char_type* s, size_type pos = npos) const;
|
|
|
|
//------------------------------------------------------------------------
|
|
// Iterators
|
|
//------------------------------------------------------------------------
|
|
public:
|
|
/// \brief Retrieves the begin iterator for this basic_string_view
|
|
///
|
|
/// \return the begin iterator
|
|
const_iterator begin() const;
|
|
|
|
/// \brief Retrieves the end iterator for this basic_string_view
|
|
///
|
|
/// \return the end iterator
|
|
const_iterator end() const;
|
|
|
|
/// \copydoc basic_string_view::begin()
|
|
const_iterator cbegin() const;
|
|
|
|
/// \copydoc basic_string_view::end()
|
|
const_iterator cend() const;
|
|
|
|
//------------------------------------------------------------------------
|
|
// Private Member
|
|
//------------------------------------------------------------------------
|
|
private:
|
|
const char_type* m_str; ///< The internal string type
|
|
size_type m_size; ///< The size of this string
|
|
};
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Type Aliases
|
|
//--------------------------------------------------------------------------
|
|
|
|
using string_view = basic_string_view<char>;
|
|
# if defined(__cpp_lib_char8_t)
|
|
using u8string_view = basic_string_view<char8_t>;
|
|
# endif
|
|
using wstring_view = basic_string_view<wchar_t>;
|
|
using u16string_view = basic_string_view<char16_t>;
|
|
using u32string_view = basic_string_view<char32_t>;
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Inline Definitions
|
|
//--------------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline basic_string_view<_CharT, _Traits>::basic_string_view() : m_str(nullptr), m_size(0)
|
|
{}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
template <typename Allocator>
|
|
inline basic_string_view<_CharT, _Traits>::basic_string_view(const std::basic_string<_CharT, _Traits, Allocator>& str) : m_str(str.c_str()), m_size(str.size())
|
|
{}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline basic_string_view<_CharT, _Traits>::basic_string_view(const char_type* str) : m_str(str), m_size(traits_type::length(str))
|
|
{}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline basic_string_view<_CharT, _Traits>::basic_string_view(const char_type* str, size_type count) : m_str(str), m_size(count)
|
|
{}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Capacity
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::size() const
|
|
{
|
|
return m_size;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::length() const
|
|
{
|
|
return size();
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::max_size() const
|
|
{
|
|
return npos - 1;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool basic_string_view<_CharT, _Traits>::empty() const
|
|
{
|
|
return m_size == 0;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Element Access
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline const typename basic_string_view<_CharT, _Traits>::char_type* basic_string_view<_CharT, _Traits>::c_str() const
|
|
{
|
|
return m_str;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline const typename basic_string_view<_CharT, _Traits>::char_type* basic_string_view<_CharT, _Traits>::data() const
|
|
{
|
|
return m_str;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::const_reference basic_string_view<_CharT, _Traits>::operator[](size_t pos) const
|
|
{
|
|
return m_str[pos];
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::const_reference basic_string_view<_CharT, _Traits>::at(size_t pos) const
|
|
{
|
|
if (yasio__unlikely(pos >= m_size))
|
|
YASIO__THROW(std::out_of_range("Input out of range in basic_string_view::at"), 0);
|
|
return m_str[pos];
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::const_reference basic_string_view<_CharT, _Traits>::front() const
|
|
{
|
|
return *m_str;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::const_reference basic_string_view<_CharT, _Traits>::back() const
|
|
{
|
|
return m_str[m_size - 1];
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Modifiers
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline void basic_string_view<_CharT, _Traits>::remove_prefix(size_type n)
|
|
{
|
|
m_str += n, m_size -= n;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline void basic_string_view<_CharT, _Traits>::remove_suffix(size_type n)
|
|
{
|
|
m_size -= n;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline void basic_string_view<_CharT, _Traits>::swap(basic_string_view& v)
|
|
{
|
|
using std::swap;
|
|
swap(m_size, v.m_size);
|
|
swap(m_str, v.m_str);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Conversions
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
template <class Allocator>
|
|
inline std::basic_string<_CharT, _Traits, Allocator> basic_string_view<_CharT, _Traits>::to_string(const Allocator& a) const
|
|
{
|
|
return std::basic_string<_CharT, _Traits, Allocator>(m_str, m_size, a);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
template <class Allocator>
|
|
inline basic_string_view<_CharT, _Traits>::operator std::basic_string<_CharT, _Traits, Allocator>() const
|
|
{
|
|
return std::basic_string<_CharT, _Traits, Allocator>(m_str, m_size);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// String Operations
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::copy(char_type* dest, size_type count, size_type pos) const
|
|
{
|
|
if (yasio__unlikely(pos >= m_size))
|
|
YASIO__THROW(std::out_of_range("Index out of range in basic_string_view::copy"), 0);
|
|
|
|
const size_type rcount = (std::min)(m_size - pos, count + 1);
|
|
std::copy(m_str + pos, m_str + pos + rcount, dest);
|
|
return rcount;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline basic_string_view<_CharT, _Traits> basic_string_view<_CharT, _Traits>::substr(size_t pos, size_t len) const
|
|
{
|
|
const size_type max_length = pos > m_size ? 0 : m_size - pos;
|
|
if (yasio__unlikely(pos >= m_size))
|
|
YASIO__THROW(std::out_of_range("Index out of range in basic_string_view::substr"), (basic_string_view<_CharT, _Traits>{}));
|
|
return basic_string_view<_CharT, _Traits>(m_str + pos, len > max_length ? max_length : len);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline int basic_string_view<_CharT, _Traits>::compare(basic_string_view v) const
|
|
{
|
|
const size_type rlen = (std::min)(m_size, v.m_size);
|
|
const int compare = _Traits::compare(m_str, v.m_str, rlen);
|
|
|
|
return (compare ? compare : (m_size < v.m_size ? -1 : (m_size > v.m_size ? 1 : 0)));
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline int basic_string_view<_CharT, _Traits>::compare(size_type pos, size_type count, basic_string_view v) const
|
|
{
|
|
return substr(pos, count).compare(v);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline int basic_string_view<_CharT, _Traits>::compare(size_type pos1, size_type count1, basic_string_view v, size_type pos2, size_type count2) const
|
|
{
|
|
return substr(pos1, count1).compare(v.substr(pos2, count2));
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline int basic_string_view<_CharT, _Traits>::compare(const char_type* s) const
|
|
{
|
|
return compare(basic_string_view<_CharT, _Traits>(s));
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline int basic_string_view<_CharT, _Traits>::compare(size_type pos, size_type count, const char_type* s) const
|
|
{
|
|
return substr(pos, count).compare(basic_string_view<_CharT, _Traits>(s));
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline int basic_string_view<_CharT, _Traits>::compare(size_type pos, size_type count1, const char_type* s, size_type count2) const
|
|
{
|
|
return substr(pos, count1).compare(basic_string_view<_CharT, _Traits>(s, count2));
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find(basic_string_view v, size_type pos) const
|
|
{
|
|
return __xxtraits_find<_Traits>(m_str, m_size, pos, v.m_str, v.m_size);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find(char_type c, size_type pos) const
|
|
{
|
|
return find(basic_string_view<_CharT, _Traits>(&c, 1), pos);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find(const char_type* s, size_type pos, size_type count) const
|
|
{
|
|
return find(basic_string_view<_CharT, _Traits>(s, count), pos);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find(const char_type* s, size_type pos) const
|
|
{
|
|
return find(basic_string_view<_CharT, _Traits>(s), pos);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::rfind(basic_string_view v, size_type pos) const
|
|
{
|
|
return __xxtraits_rfind<_Traits>(m_str, m_size, pos, v.m_str, v.m_size);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::rfind(char_type c, size_type pos) const
|
|
{
|
|
return rfind(basic_string_view<_CharT, _Traits>(&c, 1), pos);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::rfind(const char_type* s, size_type pos,
|
|
size_type count) const
|
|
{
|
|
return rfind(basic_string_view<_CharT, _Traits>(s, count), pos);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::rfind(const char_type* s, size_type pos) const
|
|
{
|
|
return rfind(basic_string_view<_CharT, _Traits>(s), pos);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_first_of(basic_string_view v, size_type pos) const
|
|
{
|
|
return __xxtraits_find_first_of<_Traits>(m_str, m_size, pos, v.m_str, v.m_size);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_first_of(char_type c, size_type pos) const
|
|
{
|
|
return __xxtraits_find_ch<_Traits>(m_str, m_size, pos, c);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_first_of(const char_type* s, size_type pos,
|
|
size_type count) const
|
|
{
|
|
return find_first_of(basic_string_view<_CharT, _Traits>(s, count), pos);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_first_of(const char_type* s, size_type pos) const
|
|
{
|
|
return find_first_of(basic_string_view<_CharT, _Traits>(s), pos);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_last_of(basic_string_view v, size_type pos) const
|
|
{
|
|
return __xxtraits_find_last_of<_Traits>(m_str, m_size, pos, v.m_str, v.m_size);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_last_of(char_type c, size_type pos) const
|
|
{
|
|
return __xxtraits_rfind_ch<_Traits>(m_str, m_size, pos, c);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_last_of(const char_type* s, size_type pos,
|
|
size_type count) const
|
|
{
|
|
return find_last_of(basic_string_view<_CharT, _Traits>(s, count), pos);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_last_of(const char_type* s, size_type pos) const
|
|
{
|
|
return find_last_of(basic_string_view<_CharT, _Traits>(s), pos);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_first_not_of(basic_string_view v, size_type pos) const
|
|
{
|
|
return __xxtraits_find_first_not_of<_Traits>(m_str, m_size, pos, v.m_str, v.m_size, pos);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_first_not_of(char_type c, size_type pos) const
|
|
{
|
|
return __xxtraits_find_not_ch<_Traits>(m_str, m_size, pos, c);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_first_not_of(const char_type* s, size_type pos,
|
|
size_type count) const
|
|
{
|
|
return find_first_not_of(basic_string_view<_CharT, _Traits>(s, count), pos);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_first_not_of(const char_type* s, size_type pos) const
|
|
{
|
|
return find_first_not_of(basic_string_view<_CharT, _Traits>(s), pos);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_last_not_of(basic_string_view v, size_type pos) const
|
|
{
|
|
return __xxtraits_find_last_not_of<_Traits>(m_str, m_size, pos, v.m_str, v.m_size);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_last_not_of(char_type c, size_type pos) const
|
|
{
|
|
return __xxtraits_rfind_not_ch<_Traits>(m_str, m_size, pos, c);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_last_not_of(const char_type* s, size_type pos,
|
|
size_type count) const
|
|
{
|
|
return find_last_not_of(basic_string_view<_CharT, _Traits>(s, count), pos);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>::find_last_not_of(const char_type* s, size_type pos) const
|
|
{
|
|
return find_last_not_of(basic_string_view<_CharT, _Traits>(s), pos);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Iterator
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::const_iterator basic_string_view<_CharT, _Traits>::begin() const
|
|
{
|
|
return m_str;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::const_iterator basic_string_view<_CharT, _Traits>::end() const
|
|
{
|
|
return m_str + m_size;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::const_iterator basic_string_view<_CharT, _Traits>::cbegin() const
|
|
{
|
|
return m_str;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline typename basic_string_view<_CharT, _Traits>::const_iterator basic_string_view<_CharT, _Traits>::cend() const
|
|
{
|
|
return m_str + m_size;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Public Functions
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& o, const basic_string_view<_CharT, _Traits>& str)
|
|
{
|
|
o.write(str.data(), str.size());
|
|
return o;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline void swap(basic_string_view<_CharT, _Traits>& lhs, basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
lhs.swap(rhs);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Comparison Functions
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator==(const basic_string_view<_CharT, _Traits>& lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return lhs.compare(rhs) == 0;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator==(basic_string_view<_CharT, _Traits> lhs, const _CharT* rhs)
|
|
{
|
|
return lhs == basic_string_view<_CharT, _Traits>(rhs);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator==(const _CharT* lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return basic_string_view<_CharT, _Traits>(lhs) == rhs;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits, typename Allocator>
|
|
inline bool operator==(const std::basic_string<_CharT, _Traits, Allocator>& lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return basic_string_view<_CharT, _Traits>(lhs) == rhs;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits, typename Allocator>
|
|
inline bool operator==(const basic_string_view<_CharT, _Traits>& lhs, const std::basic_string<_CharT, _Traits, Allocator>& rhs)
|
|
{
|
|
return lhs == basic_string_view<_CharT, _Traits>(rhs);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator!=(const basic_string_view<_CharT, _Traits>& lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return lhs.compare(rhs) != 0;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator!=(const basic_string_view<_CharT, _Traits>& lhs, const _CharT* rhs)
|
|
{
|
|
return lhs != basic_string_view<_CharT, _Traits>(rhs);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator!=(const _CharT* lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return basic_string_view<_CharT, _Traits>(lhs) != rhs;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits, typename Allocator>
|
|
inline bool operator!=(const std::basic_string<_CharT, _Traits, Allocator>& lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return basic_string_view<_CharT, _Traits>(lhs) != rhs;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits, typename Allocator>
|
|
inline bool operator!=(const basic_string_view<_CharT, _Traits>& lhs, const std::basic_string<_CharT, _Traits, Allocator>& rhs)
|
|
{
|
|
return lhs != basic_string_view<_CharT, _Traits>(rhs);
|
|
}
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator<(const basic_string_view<_CharT, _Traits>& lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return lhs.compare(rhs) < 0;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator<(const basic_string_view<_CharT, _Traits>& lhs, const _CharT* rhs)
|
|
{
|
|
return lhs < basic_string_view<_CharT, _Traits>(rhs);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator<(const _CharT* lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return basic_string_view<_CharT, _Traits>(lhs) < rhs;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits, typename Allocator>
|
|
inline bool operator<(const std::basic_string<_CharT, _Traits, Allocator>& lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return basic_string_view<_CharT, _Traits>(lhs) < rhs;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits, typename Allocator>
|
|
inline bool operator<(const basic_string_view<_CharT, _Traits>& lhs, const std::basic_string<_CharT, _Traits, Allocator>& rhs)
|
|
{
|
|
return lhs < basic_string_view<_CharT, _Traits>(rhs);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator>(const basic_string_view<_CharT, _Traits>& lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return lhs.compare(rhs) > 0;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator>(const basic_string_view<_CharT, _Traits>& lhs, const _CharT* rhs)
|
|
{
|
|
return lhs > basic_string_view<_CharT, _Traits>(rhs);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator>(const _CharT* lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return basic_string_view<_CharT, _Traits>(lhs) > rhs;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits, typename Allocator>
|
|
inline bool operator>(const std::basic_string<_CharT, _Traits, Allocator>& lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return basic_string_view<_CharT, _Traits>(lhs) > rhs;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits, typename Allocator>
|
|
inline bool operator>(const basic_string_view<_CharT, _Traits>& lhs, const std::basic_string<_CharT, _Traits, Allocator>& rhs)
|
|
{
|
|
return lhs > basic_string_view<_CharT, _Traits>(rhs);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator<=(const basic_string_view<_CharT, _Traits>& lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return lhs.compare(rhs) <= 0;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator<=(const basic_string_view<_CharT, _Traits>& lhs, const _CharT* rhs)
|
|
{
|
|
return lhs <= basic_string_view<_CharT, _Traits>(rhs);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator<=(const _CharT* lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return basic_string_view<_CharT, _Traits>(lhs) <= rhs;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits, typename Allocator>
|
|
inline bool operator<=(const std::basic_string<_CharT, _Traits, Allocator>& lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return basic_string_view<_CharT, _Traits>(lhs) <= rhs;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits, typename Allocator>
|
|
inline bool operator<=(const basic_string_view<_CharT, _Traits>& lhs, const std::basic_string<_CharT, _Traits, Allocator>& rhs)
|
|
{
|
|
return lhs <= basic_string_view<_CharT, _Traits>(rhs);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator>=(const basic_string_view<_CharT, _Traits>& lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return lhs.compare(rhs) >= 0;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator>=(const basic_string_view<_CharT, _Traits>& lhs, const _CharT* rhs)
|
|
{
|
|
return lhs >= basic_string_view<_CharT, _Traits>(rhs);
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits>
|
|
inline bool operator>=(const _CharT* lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return basic_string_view<_CharT, _Traits>(lhs) >= rhs;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits, typename Allocator>
|
|
inline bool operator>=(const std::basic_string<_CharT, _Traits, Allocator>& lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
return basic_string_view<_CharT, _Traits>(lhs) >= rhs;
|
|
}
|
|
|
|
template <typename _CharT, typename _Traits, typename Allocator>
|
|
inline bool operator>=(const basic_string_view<_CharT, _Traits>& lhs, const std::basic_string<_CharT, _Traits, Allocator>& rhs)
|
|
{
|
|
return lhs >= basic_string_view<_CharT, _Traits>(rhs);
|
|
}
|
|
//-----------------------------------------------------------------
|
|
// FNV1a hash from msvc++
|
|
# if YASIO__64BITS
|
|
static const size_t _FNV_offset_basis = 14695981039346656037ULL;
|
|
static const size_t _FNV_prime = 1099511628211ULL;
|
|
# else /* defined(_M_X64), etc. */
|
|
static const size_t _FNV_offset_basis = 2166136261U;
|
|
static const size_t _FNV_prime = 16777619U;
|
|
# endif /* defined(_M_X64), etc. */
|
|
inline size_t _FNV1a_hash(const void* _First, size_t _Count)
|
|
{ // FNV-1a hash function for bytes in [_First, _First+_Count)
|
|
size_t _Val = _FNV_offset_basis;
|
|
for (size_t _Next = 0; _Next < _Count; ++_Next)
|
|
{ // fold in another byte
|
|
_Val ^= (size_t) static_cast<const unsigned char*>(_First)[_Next];
|
|
_Val *= _FNV_prime;
|
|
}
|
|
|
|
return (_Val);
|
|
}
|
|
} // namespace cxx17
|
|
namespace std
|
|
{
|
|
template <class _Elem>
|
|
struct hash<cxx17::basic_string_view<_Elem>> { // hash functor for basic_string_view
|
|
typedef cxx17::basic_string_view<_Elem> _Kty;
|
|
|
|
size_t operator()(const _Kty& _Keyval) const
|
|
{ // hash _Keyval to size_t value by pseudorandomizing transform
|
|
# if defined(_LIBCPP_VERSION)
|
|
return __do_string_hash(_Keyval.data(), _Keyval.data() + _Keyval.size());
|
|
# elif defined(__GLIBCXX__)
|
|
return _Hash_impl::hash(_Keyval.data(), _Keyval.size() * sizeof(_Elem));
|
|
# else // msvc++ or other compiler without stable hash bytes function exists
|
|
return ::cxx17::_FNV1a_hash(_Keyval.data(), _Keyval.size() * sizeof(_Elem));
|
|
# endif
|
|
}
|
|
};
|
|
} // namespace std
|
|
#endif
|
|
|
|
#if YASIO__HAS_CXX14
|
|
namespace cxx17
|
|
{
|
|
// basic_string_view LITERALS
|
|
inline namespace literals
|
|
{
|
|
inline namespace string_view_literals
|
|
{
|
|
inline cxx17::string_view operator"" _sv(const char* _Str, size_t _Len) { return cxx17::string_view(_Str, _Len); }
|
|
inline cxx17::wstring_view operator"" _sv(const wchar_t* _Str, size_t _Len) { return cxx17::wstring_view(_Str, _Len); }
|
|
inline cxx17::u16string_view operator"" _sv(const char16_t* _Str, size_t _Len) { return cxx17::u16string_view(_Str, _Len); }
|
|
inline cxx17::u32string_view operator"" _sv(const char32_t* _Str, size_t _Len) { return cxx17::u32string_view(_Str, _Len); }
|
|
} // namespace string_view_literals
|
|
} // namespace literals
|
|
} // namespace cxx17
|
|
#endif
|
|
|
|
namespace cxx17
|
|
{
|
|
template <typename _CharT, typename _Traits, typename Allocator>
|
|
inline std::basic_string<_CharT, _Traits, Allocator>& assign(std::basic_string<_CharT, _Traits, Allocator>& lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
if (!rhs.empty())
|
|
lhs.assign(rhs.data(), rhs.size());
|
|
else
|
|
lhs.clear();
|
|
return lhs;
|
|
}
|
|
template <typename _CharT, typename _Traits, typename Allocator>
|
|
inline std::basic_string<_CharT, _Traits, Allocator>& append(std::basic_string<_CharT, _Traits, Allocator>& lhs, const basic_string_view<_CharT, _Traits>& rhs)
|
|
{
|
|
if (!rhs.empty())
|
|
lhs.append(rhs.data(), rhs.size());
|
|
else
|
|
lhs.clear();
|
|
return lhs;
|
|
}
|
|
template <typename _CharT, typename _Traits, typename Allocator = std::allocator<_CharT>>
|
|
inline std::basic_string<_CharT, _Traits, Allocator> svtos(const basic_string_view<_CharT, _Traits>& value)
|
|
{
|
|
using string_type = std::basic_string<_CharT, _Traits, Allocator>;
|
|
return !value.empty() ? string_type(value.data(), value.size()) : string_type{};
|
|
}
|
|
} // namespace cxx17
|
|
|
|
namespace cxx20
|
|
{
|
|
template <class T>
|
|
using decay_t = typename std::decay<T>::type;
|
|
template <class T>
|
|
using remove_const_t = typename std::remove_const<T>::type;
|
|
namespace char_ranges
|
|
{ // allow get char type from char*, wchar_t*, std::string, std::wstring
|
|
template <typename _Ty>
|
|
struct value_type {
|
|
using type = typename _Ty::value_type;
|
|
};
|
|
|
|
template <typename _Ty>
|
|
struct value_type<_Ty&> {
|
|
using type = remove_const_t<_Ty>;
|
|
};
|
|
|
|
template <typename _Ty>
|
|
struct value_type<_Ty*> {
|
|
using type = remove_const_t<_Ty>;
|
|
};
|
|
} // namespace char_ranges
|
|
|
|
// starts_with(), since C++20:
|
|
template <typename _CharT>
|
|
inline bool starts_with(cxx17::basic_string_view<_CharT> lhs,
|
|
cxx17::basic_string_view<_CharT> v) // (1)
|
|
{
|
|
return lhs.size() >= v.size() && lhs.compare(0, v.size(), v) == 0;
|
|
}
|
|
|
|
template <typename _T1, typename _T2>
|
|
inline bool starts_with(_T1&& lhs, _T2&& v) // (2)
|
|
{
|
|
using char_type = typename char_ranges::value_type<decay_t<_T1>>::type;
|
|
return starts_with(cxx17::basic_string_view<char_type>{lhs}, cxx17::basic_string_view<char_type>{v});
|
|
}
|
|
|
|
template <typename _CharT>
|
|
inline bool starts_with(cxx17::basic_string_view<_CharT> lhs, int c) // (3)
|
|
{
|
|
return !lhs.empty() && lhs.front() == c;
|
|
}
|
|
|
|
template <typename _Ty>
|
|
inline bool starts_with(_Ty&& lhs, int c) // (4)
|
|
{
|
|
using char_type = typename char_ranges::value_type<decay_t<_Ty>>::type;
|
|
return starts_with(cxx17::basic_string_view<char_type>{lhs}, c);
|
|
}
|
|
|
|
// ends_with(), since C++20:
|
|
template <typename _CharT>
|
|
inline bool ends_with(cxx17::basic_string_view<_CharT> lhs,
|
|
cxx17::basic_string_view<_CharT> v) // (1)
|
|
{
|
|
auto offset = lhs.size() - v.size();
|
|
return lhs.size() >= v.size() && lhs.compare(offset, v.size(), v) == 0;
|
|
}
|
|
|
|
template <typename _T1, typename _T2>
|
|
inline bool ends_with(_T1&& lhs, _T2&& v) // (2)
|
|
{
|
|
using char_type = typename char_ranges::value_type<decay_t<_T1>>::type;
|
|
return ends_with(cxx17::basic_string_view<char_type>{lhs}, cxx17::basic_string_view<char_type>{v});
|
|
}
|
|
|
|
template <typename _CharT>
|
|
inline bool ends_with(cxx17::basic_string_view<_CharT> lhs, int c) // (3)
|
|
{
|
|
return !lhs.empty() && lhs.back() == c;
|
|
}
|
|
|
|
template <typename _Ty>
|
|
inline bool ends_with(_Ty&& lhs, int c) // (4)
|
|
{
|
|
using char_type = typename char_ranges::value_type<decay_t<_Ty>>::type;
|
|
return ends_with(cxx17::basic_string_view<char_type>{lhs}, c);
|
|
}
|
|
|
|
/// The case insensitive implementation of starts_with, ends_with
|
|
namespace ic
|
|
{
|
|
template <typename _CharT>
|
|
inline bool iequals(cxx17::basic_string_view<_CharT> lhs, cxx17::basic_string_view<_CharT> v);
|
|
#if defined(_MSC_VER)
|
|
template <>
|
|
inline bool iequals<char>(cxx17::basic_string_view<char> lhs, cxx17::basic_string_view<char> v)
|
|
{
|
|
return lhs.size() == v.size() && ::_strnicmp(lhs.data(), v.data(), v.size()) == 0;
|
|
}
|
|
template <>
|
|
inline bool iequals<wchar_t>(cxx17::basic_string_view<wchar_t> lhs, cxx17::basic_string_view<wchar_t> v)
|
|
{
|
|
return lhs.size() == v.size() && ::_wcsnicmp(lhs.data(), v.data(), v.size()) == 0;
|
|
}
|
|
#else
|
|
template <>
|
|
inline bool iequals<char>(cxx17::basic_string_view<char> lhs, cxx17::basic_string_view<char> v)
|
|
{
|
|
return lhs.size() == v.size() && ::strncasecmp(lhs.data(), v.data(), v.size()) == 0;
|
|
}
|
|
template <>
|
|
inline bool iequals<wchar_t>(cxx17::basic_string_view<wchar_t> lhs, cxx17::basic_string_view<wchar_t> v)
|
|
{
|
|
return lhs.size() == v.size() && ::wcsncasecmp(lhs.data(), v.data(), v.size()) == 0;
|
|
}
|
|
#endif
|
|
template <typename _T1, typename _T2>
|
|
inline bool iequals(_T1&& lhs, _T2&& v)
|
|
{
|
|
using char_type = typename char_ranges::value_type<decay_t<_T1>>::type;
|
|
return iequals(cxx17::basic_string_view<char_type>{lhs}, cxx17::basic_string_view<char_type>{v});
|
|
}
|
|
// starts_with(), since C++20:
|
|
template <typename _CharT>
|
|
inline bool starts_with(cxx17::basic_string_view<_CharT> lhs,
|
|
cxx17::basic_string_view<_CharT> v) // (1)
|
|
{
|
|
return lhs.size() >= v.size() && iequals(lhs.substr(0, v.size()), v);
|
|
}
|
|
|
|
template <typename _T1, typename _T2>
|
|
inline bool starts_with(_T1&& lhs, _T2&& v) // (2)
|
|
{
|
|
using char_type = typename char_ranges::value_type<decay_t<_T1>>::type;
|
|
return starts_with(cxx17::basic_string_view<char_type>{lhs}, cxx17::basic_string_view<char_type>{v});
|
|
}
|
|
|
|
template <typename _CharT>
|
|
inline bool starts_with(cxx17::basic_string_view<_CharT> lhs, int c) // (3)
|
|
{
|
|
return !lhs.empty() && ::tolower(lhs.front()) == ::tolower(c);
|
|
}
|
|
|
|
template <typename _Ty>
|
|
inline bool starts_with(_Ty&& lhs, int c) // (4)
|
|
{
|
|
using char_type = typename char_ranges::value_type<decay_t<_Ty>>::type;
|
|
return starts_with(cxx17::basic_string_view<char_type>{lhs}, c);
|
|
}
|
|
|
|
// ends_with(), since C++20:
|
|
template <typename _CharT>
|
|
inline bool ends_with(cxx17::basic_string_view<_CharT> lhs,
|
|
cxx17::basic_string_view<_CharT> v) // (1)
|
|
{
|
|
return lhs.size() >= v.size() && iequals(lhs.substr(lhs.size() - v.size(), lhs.npos), v);
|
|
}
|
|
|
|
template <typename _T1, typename _T2>
|
|
inline bool ends_with(_T1&& lhs, _T2&& v) // (2)
|
|
{
|
|
using char_type = typename char_ranges::value_type<decay_t<_T1>>::type;
|
|
return ends_with(cxx17::basic_string_view<char_type>{lhs}, cxx17::basic_string_view<char_type>{v});
|
|
}
|
|
|
|
template <typename _CharT>
|
|
inline bool ends_with(cxx17::basic_string_view<_CharT> lhs, int c) // (3)
|
|
{
|
|
return !lhs.empty() && ::tolower(lhs.back()) == ::tolower(c);
|
|
}
|
|
|
|
template <typename _Ty>
|
|
inline bool ends_with(_Ty&& lhs, int c) // (4)
|
|
{
|
|
using char_type = typename char_ranges::value_type<decay_t<_Ty>>::type;
|
|
return ends_with(cxx17::basic_string_view<char_type>{lhs}, c);
|
|
}
|
|
} // namespace ic
|
|
} // namespace cxx20
|
|
|
|
#endif
|