update string_view lite to version 1.6.0 (#1677)

This is the header as seen in the current master branch,
commit d27d7b5081406a35b41cb16b321be8833b4cd811, on
<https://github.com/martinmoene/string-view-lite>.
This commit is contained in:
Dirk Stolle 2021-07-31 17:19:51 +02:00 committed by GitHub
parent bd0f5e9322
commit 5f0b35b2c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 178 additions and 69 deletions

View File

@ -1,4 +1,4 @@
// Copyright 2017-2019 by Martin Moene
// Copyright 2017-2020 by Martin Moene
//
// string-view lite, a C++17-like string_view for C++98 and later.
// For more information see https://github.com/martinmoene/string-view-lite
@ -12,7 +12,7 @@
#define NONSTD_SV_LITE_H_INCLUDED
#define string_view_lite_MAJOR 1
#define string_view_lite_MINOR 4
#define string_view_lite_MINOR 6
#define string_view_lite_PATCH 0
#define string_view_lite_VERSION nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH)
@ -26,12 +26,22 @@
#define nssv_STRING_VIEW_NONSTD 1
#define nssv_STRING_VIEW_STD 2
#if !defined( nssv_CONFIG_SELECT_STRING_VIEW )
# define nssv_CONFIG_SELECT_STRING_VIEW ( nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD )
// tweak header support:
#ifdef __has_include
# if __has_include(<nonstd/string_view.tweak.hpp>)
# include <nonstd/string_view.tweak.hpp>
# endif
#define nssv_HAVE_TWEAK_HEADER 1
#else
#define nssv_HAVE_TWEAK_HEADER 0
//# pragma message("string_view.hpp: Note: Tweak header not supported.")
#endif
#if defined( nssv_CONFIG_SELECT_STD_STRING_VIEW ) || defined( nssv_CONFIG_SELECT_NONSTD_STRING_VIEW )
# error nssv_CONFIG_SELECT_STD_STRING_VIEW and nssv_CONFIG_SELECT_NONSTD_STRING_VIEW are deprecated and removed, please use nssv_CONFIG_SELECT_STRING_VIEW=nssv_STRING_VIEW_...
// string_view selection and configuration:
#if !defined( nssv_CONFIG_SELECT_STRING_VIEW )
# define nssv_CONFIG_SELECT_STRING_VIEW ( nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD )
#endif
#ifndef nssv_CONFIG_STD_SV_OPERATOR
@ -55,10 +65,17 @@
# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1
#endif
#ifndef nssv_CONFIG_NO_STREAM_INSERTION
# define nssv_CONFIG_NO_STREAM_INSERTION 0
#endif
// Control presence of exception handling (try and auto discover):
#ifndef nssv_CONFIG_NO_EXCEPTIONS
# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
# if _MSC_VER
# include <cstddef> // for _HAS_EXCEPTIONS
# endif
# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS)
# define nssv_CONFIG_NO_EXCEPTIONS 0
# else
# define nssv_CONFIG_NO_EXCEPTIONS 1
@ -221,16 +238,21 @@ using std::operator<<;
#define nssv_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
#if defined(__clang__)
# define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
#if defined( __apple_build_version__ )
# define nssv_COMPILER_APPLECLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
# define nssv_COMPILER_CLANG_VERSION 0
#elif defined( __clang__ )
# define nssv_COMPILER_APPLECLANG_VERSION 0
# define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
#else
# define nssv_COMPILER_CLANG_VERSION 0
# define nssv_COMPILER_APPLECLANG_VERSION 0
# define nssv_COMPILER_CLANG_VERSION 0
#endif
#if defined(__GNUC__) && !defined(__clang__)
# define nssv_COMPILER_GNUC_VERSION nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
#else
# define nssv_COMPILER_GNUC_VERSION 0
# define nssv_COMPILER_GNUC_VERSION 0
#endif
// half-open range [lo..hi):
@ -292,6 +314,45 @@ using std::operator<<;
#define nssv_HAVE_STD_HASH nssv_CPP11_120
// Presence of compiler intrinsics:
// Providing char-type specializations for compare() and length() that
// use compiler intrinsics can improve compile- and run-time performance.
//
// The challenge is in using the right combinations of builtin availability
// and its constexpr-ness.
//
// | compiler | __builtin_memcmp (constexpr) | memcmp (constexpr) |
// |----------|------------------------------|---------------------|
// | clang | 4.0 (>= 4.0 ) | any (? ) |
// | clang-a | 9.0 (>= 9.0 ) | any (? ) |
// | gcc | any (constexpr) | any (? ) |
// | msvc | >= 14.2 C++17 (>= 14.2 ) | any (? ) |
#define nssv_HAVE_BUILTIN_VER ( (nssv_CPP17_000 && nssv_COMPILER_MSVC_VERSION >= 142) || nssv_COMPILER_GNUC_VERSION > 0 || nssv_COMPILER_CLANG_VERSION >= 400 || nssv_COMPILER_APPLECLANG_VERSION >= 900 )
#define nssv_HAVE_BUILTIN_CE ( nssv_HAVE_BUILTIN_VER )
#define nssv_HAVE_BUILTIN_MEMCMP ( (nssv_HAVE_CONSTEXPR_14 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_14 )
#define nssv_HAVE_BUILTIN_STRLEN ( (nssv_HAVE_CONSTEXPR_11 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_11 )
#ifdef __has_builtin
# define nssv_HAVE_BUILTIN( x ) __has_builtin( x )
#else
# define nssv_HAVE_BUILTIN( x ) 0
#endif
#if nssv_HAVE_BUILTIN(__builtin_memcmp) || nssv_HAVE_BUILTIN_VER
# define nssv_BUILTIN_MEMCMP __builtin_memcmp
#else
# define nssv_BUILTIN_MEMCMP memcmp
#endif
#if nssv_HAVE_BUILTIN(__builtin_strlen) || nssv_HAVE_BUILTIN_VER
# define nssv_BUILTIN_STRLEN __builtin_strlen
#else
# define nssv_BUILTIN_STRLEN strlen
#endif
// C++ feature usage:
#if nssv_HAVE_CONSTEXPR_11
@ -350,9 +411,12 @@ using std::operator<<;
#include <cassert>
#include <iterator>
#include <limits>
#include <ostream>
#include <string> // std::char_traits<>
#if ! nssv_CONFIG_NO_STREAM_INSERTION
# include <ostream>
#endif
#if ! nssv_CONFIG_NO_EXCEPTIONS
# include <stdexcept>
#endif
@ -405,40 +469,75 @@ nssv_DISABLE_MSVC_WARNINGS( 4455 26481 26472 )
namespace nonstd { namespace sv_lite {
#if nssv_CPP11_OR_GREATER
namespace detail {
#if nssv_CPP14_OR_GREATER
// support constexpr comparison in C++14;
// for C++17 and later, use provided traits:
template< typename CharT >
inline constexpr std::size_t length( CharT * s, std::size_t result = 0 )
inline nssv_constexpr14 int compare( CharT const * s1, CharT const * s2, std::size_t count )
{
CharT * v = s;
std::size_t r = result;
while ( *v != '\0' ) {
++v;
++r;
while ( count-- != 0 )
{
if ( *s1 < *s2 ) return -1;
if ( *s1 > *s2 ) return +1;
++s1; ++s2;
}
return r;
return 0;
}
#else // nssv_CPP14_OR_GREATER
#if nssv_HAVE_BUILTIN_MEMCMP
// specialization of compare() for char, see also generic compare() above:
inline nssv_constexpr14 int compare( char const * s1, char const * s2, std::size_t count )
{
return nssv_BUILTIN_MEMCMP( s1, s2, count );
}
#endif
#if nssv_HAVE_BUILTIN_STRLEN
// specialization of length() for char, see also generic length() further below:
inline nssv_constexpr std::size_t length( char const * s )
{
return nssv_BUILTIN_STRLEN( s );
}
#endif
#if defined(__OPTIMIZE__)
// gcc, clang provide __OPTIMIZE__
// Expect tail call optimization to make length() non-recursive:
template< typename CharT >
inline constexpr std::size_t length( CharT * s, std::size_t result = 0 )
inline nssv_constexpr std::size_t length( CharT * s, std::size_t result = 0 )
{
return *s == '\0' ? result : length( s + 1, result + 1 );
}
#endif // nssv_CPP14_OR_GREATER
#else // OPTIMIZE
// non-recursive:
template< typename CharT >
inline nssv_constexpr14 std::size_t length( CharT * s )
{
std::size_t result = 0;
while ( *s++ != '\0' )
{
++result;
}
return result;
}
#endif // OPTIMIZE
} // namespace detail
#endif // nssv_CPP11_OR_GREATER
template
<
class CharT,
@ -589,9 +688,9 @@ public:
nssv_constexpr14 void swap( basic_string_view & other ) nssv_noexcept
{
using std::swap;
swap( data_, other.data_ );
swap( size_, other.size_ );
const basic_string_view tmp(other);
other = *this;
*this = tmp;
}
// 24.4.2.6 String operations:
@ -630,7 +729,11 @@ public:
nssv_constexpr14 int compare( basic_string_view other ) const nssv_noexcept // (1)
{
#if nssv_CPP17_OR_GREATER
if ( const int result = Traits::compare( data(), other.data(), (std::min)( size(), other.size() ) ) )
#else
if ( const int result = detail::compare( data(), other.data(), (std::min)( size(), other.size() ) ) )
#endif
{
return result;
}
@ -874,7 +977,7 @@ private:
{
const basic_string_view v;
nssv_constexpr explicit not_in_view( basic_string_view v ) : v( v ) {}
nssv_constexpr explicit not_in_view( basic_string_view v_ ) : v( v_ ) {}
nssv_constexpr bool operator()( CharT c ) const
{
@ -964,37 +1067,37 @@ template< class CharT, class Traits >
nssv_constexpr bool operator== (
basic_string_view <CharT, Traits> lhs,
basic_string_view <CharT, Traits> rhs ) nssv_noexcept
{ return lhs.compare( rhs ) == 0 ; }
{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
template< class CharT, class Traits >
nssv_constexpr bool operator!= (
basic_string_view <CharT, Traits> lhs,
basic_string_view <CharT, Traits> rhs ) nssv_noexcept
{ return lhs.compare( rhs ) != 0 ; }
{ return !( lhs == rhs ); }
template< class CharT, class Traits >
nssv_constexpr bool operator< (
basic_string_view <CharT, Traits> lhs,
basic_string_view <CharT, Traits> rhs ) nssv_noexcept
{ return lhs.compare( rhs ) < 0 ; }
{ return lhs.compare( rhs ) < 0; }
template< class CharT, class Traits >
nssv_constexpr bool operator<= (
basic_string_view <CharT, Traits> lhs,
basic_string_view <CharT, Traits> rhs ) nssv_noexcept
{ return lhs.compare( rhs ) <= 0 ; }
{ return lhs.compare( rhs ) <= 0; }
template< class CharT, class Traits >
nssv_constexpr bool operator> (
basic_string_view <CharT, Traits> lhs,
basic_string_view <CharT, Traits> rhs ) nssv_noexcept
{ return lhs.compare( rhs ) > 0 ; }
{ return lhs.compare( rhs ) > 0; }
template< class CharT, class Traits >
nssv_constexpr bool operator>= (
basic_string_view <CharT, Traits> lhs,
basic_string_view <CharT, Traits> rhs ) nssv_noexcept
{ return lhs.compare( rhs ) >= 0 ; }
{ return lhs.compare( rhs ) >= 0; }
// Let S be basic_string_view<CharT, Traits>, and sv be an instance of S.
// Implementations shall provide sufficient additional overloads marked
@ -1003,21 +1106,21 @@ nssv_constexpr bool operator>= (
#if ! nssv_CPP11_OR_GREATER || nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 100, 141 )
// accomodate for older compilers:
// accommodate for older compilers:
// ==
template< class CharT, class Traits>
nssv_constexpr bool operator==(
basic_string_view<CharT, Traits> lhs,
char const * rhs ) nssv_noexcept
{ return lhs.compare( rhs ) == 0; }
CharT const * rhs ) nssv_noexcept
{ return lhs.size() == detail::length( rhs ) && lhs.compare( rhs ) == 0; }
template< class CharT, class Traits>
nssv_constexpr bool operator==(
char const * lhs,
CharT const * lhs,
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
{ return rhs.compare( lhs ) == 0; }
{ return detail::length( lhs ) == rhs.size() && rhs.compare( lhs ) == 0; }
template< class CharT, class Traits>
nssv_constexpr bool operator==(
@ -1036,38 +1139,38 @@ nssv_constexpr bool operator==(
template< class CharT, class Traits>
nssv_constexpr bool operator!=(
basic_string_view<CharT, Traits> lhs,
char const * rhs ) nssv_noexcept
{ return lhs.compare( rhs ) != 0; }
CharT const * rhs ) nssv_noexcept
{ return !( lhs == rhs ); }
template< class CharT, class Traits>
nssv_constexpr bool operator!=(
char const * lhs,
CharT const * lhs,
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
{ return rhs.compare( lhs ) != 0; }
{ return !( lhs == rhs ); }
template< class CharT, class Traits>
nssv_constexpr bool operator!=(
basic_string_view<CharT, Traits> lhs,
std::basic_string<CharT, Traits> rhs ) nssv_noexcept
{ return lhs.size() != rhs.size() && lhs.compare( rhs ) != 0; }
{ return !( lhs == rhs ); }
template< class CharT, class Traits>
nssv_constexpr bool operator!=(
std::basic_string<CharT, Traits> rhs,
basic_string_view<CharT, Traits> lhs ) nssv_noexcept
{ return lhs.size() != rhs.size() || rhs.compare( lhs ) != 0; }
{ return !( lhs == rhs ); }
// <
template< class CharT, class Traits>
nssv_constexpr bool operator<(
basic_string_view<CharT, Traits> lhs,
char const * rhs ) nssv_noexcept
CharT const * rhs ) nssv_noexcept
{ return lhs.compare( rhs ) < 0; }
template< class CharT, class Traits>
nssv_constexpr bool operator<(
char const * lhs,
CharT const * lhs,
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
{ return rhs.compare( lhs ) > 0; }
@ -1088,12 +1191,12 @@ nssv_constexpr bool operator<(
template< class CharT, class Traits>
nssv_constexpr bool operator<=(
basic_string_view<CharT, Traits> lhs,
char const * rhs ) nssv_noexcept
CharT const * rhs ) nssv_noexcept
{ return lhs.compare( rhs ) <= 0; }
template< class CharT, class Traits>
nssv_constexpr bool operator<=(
char const * lhs,
CharT const * lhs,
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
{ return rhs.compare( lhs ) >= 0; }
@ -1114,12 +1217,12 @@ nssv_constexpr bool operator<=(
template< class CharT, class Traits>
nssv_constexpr bool operator>(
basic_string_view<CharT, Traits> lhs,
char const * rhs ) nssv_noexcept
CharT const * rhs ) nssv_noexcept
{ return lhs.compare( rhs ) > 0; }
template< class CharT, class Traits>
nssv_constexpr bool operator>(
char const * lhs,
CharT const * lhs,
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
{ return rhs.compare( lhs ) < 0; }
@ -1140,12 +1243,12 @@ nssv_constexpr bool operator>(
template< class CharT, class Traits>
nssv_constexpr bool operator>=(
basic_string_view<CharT, Traits> lhs,
char const * rhs ) nssv_noexcept
CharT const * rhs ) nssv_noexcept
{ return lhs.compare( rhs ) >= 0; }
template< class CharT, class Traits>
nssv_constexpr bool operator>=(
char const * lhs,
CharT const * lhs,
basic_string_view<CharT, Traits> rhs ) nssv_noexcept
{ return rhs.compare( lhs ) <= 0; }
@ -1165,7 +1268,7 @@ nssv_constexpr bool operator>=(
#define nssv_BASIC_STRING_VIEW_I(T,U) typename std::decay< basic_string_view<T,U> >::type
#if nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 140, 150 )
#if defined(_MSC_VER) // issue 40
# define nssv_MSVC_ORDER(x) , int=x
#else
# define nssv_MSVC_ORDER(x) /*, int=x*/
@ -1177,7 +1280,7 @@ template< class CharT, class Traits nssv_MSVC_ORDER(1) >
nssv_constexpr bool operator==(
basic_string_view <CharT, Traits> lhs,
nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs ) nssv_noexcept
{ return lhs.compare( rhs ) == 0; }
{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
template< class CharT, class Traits nssv_MSVC_ORDER(2) >
nssv_constexpr bool operator==(
@ -1191,13 +1294,13 @@ template< class CharT, class Traits nssv_MSVC_ORDER(1) >
nssv_constexpr bool operator!= (
basic_string_view < CharT, Traits > lhs,
nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
{ return lhs.size() != rhs.size() || lhs.compare( rhs ) != 0 ; }
{ return !( lhs == rhs ); }
template< class CharT, class Traits nssv_MSVC_ORDER(2) >
nssv_constexpr bool operator!= (
nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
basic_string_view < CharT, Traits > rhs ) nssv_noexcept
{ return lhs.compare( rhs ) != 0 ; }
{ return !( lhs == rhs ); }
// <
@ -1205,13 +1308,13 @@ template< class CharT, class Traits nssv_MSVC_ORDER(1) >
nssv_constexpr bool operator< (
basic_string_view < CharT, Traits > lhs,
nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
{ return lhs.compare( rhs ) < 0 ; }
{ return lhs.compare( rhs ) < 0; }
template< class CharT, class Traits nssv_MSVC_ORDER(2) >
nssv_constexpr bool operator< (
nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
basic_string_view < CharT, Traits > rhs ) nssv_noexcept
{ return lhs.compare( rhs ) < 0 ; }
{ return lhs.compare( rhs ) < 0; }
// <=
@ -1219,13 +1322,13 @@ template< class CharT, class Traits nssv_MSVC_ORDER(1) >
nssv_constexpr bool operator<= (
basic_string_view < CharT, Traits > lhs,
nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
{ return lhs.compare( rhs ) <= 0 ; }
{ return lhs.compare( rhs ) <= 0; }
template< class CharT, class Traits nssv_MSVC_ORDER(2) >
nssv_constexpr bool operator<= (
nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
basic_string_view < CharT, Traits > rhs ) nssv_noexcept
{ return lhs.compare( rhs ) <= 0 ; }
{ return lhs.compare( rhs ) <= 0; }
// >
@ -1233,13 +1336,13 @@ template< class CharT, class Traits nssv_MSVC_ORDER(1) >
nssv_constexpr bool operator> (
basic_string_view < CharT, Traits > lhs,
nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
{ return lhs.compare( rhs ) > 0 ; }
{ return lhs.compare( rhs ) > 0; }
template< class CharT, class Traits nssv_MSVC_ORDER(2) >
nssv_constexpr bool operator> (
nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
basic_string_view < CharT, Traits > rhs ) nssv_noexcept
{ return lhs.compare( rhs ) > 0 ; }
{ return lhs.compare( rhs ) > 0; }
// >=
@ -1247,13 +1350,13 @@ template< class CharT, class Traits nssv_MSVC_ORDER(1) >
nssv_constexpr bool operator>= (
basic_string_view < CharT, Traits > lhs,
nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
{ return lhs.compare( rhs ) >= 0 ; }
{ return lhs.compare( rhs ) >= 0; }
template< class CharT, class Traits nssv_MSVC_ORDER(2) >
nssv_constexpr bool operator>= (
nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
basic_string_view < CharT, Traits > rhs ) nssv_noexcept
{ return lhs.compare( rhs ) >= 0 ; }
{ return lhs.compare( rhs ) >= 0; }
#undef nssv_MSVC_ORDER
#undef nssv_BASIC_STRING_VIEW_I
@ -1262,6 +1365,8 @@ nssv_constexpr bool operator>= (
// 24.4.4 Inserters and extractors:
#if ! nssv_CONFIG_NO_STREAM_INSERTION
namespace detail {
template< class Stream >
@ -1311,6 +1416,8 @@ operator<<(
return detail::write_to_stream( os, sv );
}
#endif // nssv_CONFIG_NO_STREAM_INSERTION
// Several typedefs for common character types are provided:
typedef basic_string_view<char> string_view;
@ -1459,7 +1566,9 @@ using sv_lite::operator<=;
using sv_lite::operator>;
using sv_lite::operator>=;
#if ! nssv_CONFIG_NO_STREAM_INSERTION
using sv_lite::operator<<;
#endif
#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
using sv_lite::to_string;
@ -1526,4 +1635,4 @@ public:
nssv_RESTORE_WARNINGS()
#endif // nssv_HAVE_STD_STRING_VIEW
#endif // NONSTD_SV_LITE_H_INCLUDED
#endif // NONSTD_SV_LITE_H_INCLUDED