diff --git a/include/simdjson/nonstd/string_view.hpp b/include/simdjson/nonstd/string_view.hpp index 6382d792..5a2cae63 100644 --- a/include/simdjson/nonstd/string_view.hpp +++ b/include/simdjson/nonstd/string_view.hpp @@ -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() +# include +# 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 // 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 #include #include -#include #include // std::char_traits<> +#if ! nssv_CONFIG_NO_STREAM_INSERTION +# include +#endif + #if ! nssv_CONFIG_NO_EXCEPTIONS # include #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 lhs, basic_string_view 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 lhs, basic_string_view rhs ) nssv_noexcept -{ return lhs.compare( rhs ) != 0 ; } +{ return !( lhs == rhs ); } template< class CharT, class Traits > nssv_constexpr bool operator< ( basic_string_view lhs, basic_string_view 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 lhs, basic_string_view 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 lhs, basic_string_view 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 lhs, basic_string_view rhs ) nssv_noexcept -{ return lhs.compare( rhs ) >= 0 ; } +{ return lhs.compare( rhs ) >= 0; } // Let S be basic_string_view, 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 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 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 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 rhs ) nssv_noexcept -{ return rhs.compare( lhs ) != 0; } +{ return !( lhs == rhs ); } template< class CharT, class Traits> nssv_constexpr bool operator!=( basic_string_view lhs, std::basic_string 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 rhs, basic_string_view 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 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 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 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 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 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 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 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 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 >::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 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 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 \ No newline at end of file +#endif // NONSTD_SV_LITE_H_INCLUDED