simdjson  3.1.5
Ridiculously Fast JSON
string_view.hpp
1 // Copyright 2017-2020 by Martin Moene
2 //
3 // string-view lite, a C++17-like string_view for C++98 and later.
4 // For more information see https://github.com/martinmoene/string-view-lite
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 
9 #pragma once
10 
11 #ifndef NONSTD_SV_LITE_H_INCLUDED
12 #define NONSTD_SV_LITE_H_INCLUDED
13 
14 #define string_view_lite_MAJOR 1
15 #define string_view_lite_MINOR 6
16 #define string_view_lite_PATCH 0
17 
18 #define string_view_lite_VERSION nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH)
19 
20 #define nssv_STRINGIFY( x ) nssv_STRINGIFY_( x )
21 #define nssv_STRINGIFY_( x ) #x
22 
23 // string-view lite configuration:
24 
25 #define nssv_STRING_VIEW_DEFAULT 0
26 #define nssv_STRING_VIEW_NONSTD 1
27 #define nssv_STRING_VIEW_STD 2
28 
29 // tweak header support:
30 
31 #ifdef __has_include
32 # if __has_include(<nonstd/string_view.tweak.hpp>)
33 # include <nonstd/string_view.tweak.hpp>
34 # endif
35 #define nssv_HAVE_TWEAK_HEADER 1
36 #else
37 #define nssv_HAVE_TWEAK_HEADER 0
38 //# pragma message("string_view.hpp: Note: Tweak header not supported.")
39 #endif
40 
41 // string_view selection and configuration:
42 
43 #if !defined( nssv_CONFIG_SELECT_STRING_VIEW )
44 # define nssv_CONFIG_SELECT_STRING_VIEW ( nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD )
45 #endif
46 
47 #ifndef nssv_CONFIG_STD_SV_OPERATOR
48 # define nssv_CONFIG_STD_SV_OPERATOR 0
49 #endif
50 
51 #ifndef nssv_CONFIG_USR_SV_OPERATOR
52 # define nssv_CONFIG_USR_SV_OPERATOR 1
53 #endif
54 
55 #ifdef nssv_CONFIG_CONVERSION_STD_STRING
56 # define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS nssv_CONFIG_CONVERSION_STD_STRING
57 # define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS nssv_CONFIG_CONVERSION_STD_STRING
58 #endif
59 
60 #ifndef nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
61 # define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS 1
62 #endif
63 
64 #ifndef nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
65 # define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1
66 #endif
67 
68 #ifndef nssv_CONFIG_NO_STREAM_INSERTION
69 # define nssv_CONFIG_NO_STREAM_INSERTION 0
70 #endif
71 
72 // Control presence of exception handling (try and auto discover):
73 
74 #ifndef nssv_CONFIG_NO_EXCEPTIONS
75 # if _MSC_VER
76 # include <cstddef> // for _HAS_EXCEPTIONS
77 # endif
78 # if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS)
79 # define nssv_CONFIG_NO_EXCEPTIONS 0
80 # else
81 # define nssv_CONFIG_NO_EXCEPTIONS 1
82 # endif
83 #endif
84 
85 // C++ language version detection (C++20 is speculative):
86 // Note: VC14.0/1900 (VS2015) lacks too much from C++14.
87 
88 #ifndef nssv_CPLUSPLUS
89 # if defined(_MSVC_LANG ) && !defined(__clang__)
90 # define nssv_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
91 # else
92 # define nssv_CPLUSPLUS __cplusplus
93 # endif
94 #endif
95 
96 #define nssv_CPP98_OR_GREATER ( nssv_CPLUSPLUS >= 199711L )
97 #define nssv_CPP11_OR_GREATER ( nssv_CPLUSPLUS >= 201103L )
98 #define nssv_CPP11_OR_GREATER_ ( nssv_CPLUSPLUS >= 201103L )
99 #define nssv_CPP14_OR_GREATER ( nssv_CPLUSPLUS >= 201402L )
100 #define nssv_CPP17_OR_GREATER ( nssv_CPLUSPLUS >= 201703L )
101 #define nssv_CPP20_OR_GREATER ( nssv_CPLUSPLUS >= 202000L )
102 
103 // use C++17 std::string_view if available and requested:
104 
105 #if nssv_CPP17_OR_GREATER && defined(__has_include )
106 # if __has_include( <string_view> )
107 # define nssv_HAVE_STD_STRING_VIEW 1
108 # else
109 # define nssv_HAVE_STD_STRING_VIEW 0
110 # endif
111 #else
112 # define nssv_HAVE_STD_STRING_VIEW 0
113 #endif
114 
115 #define nssv_USES_STD_STRING_VIEW ( (nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && nssv_HAVE_STD_STRING_VIEW) )
116 
117 #define nssv_HAVE_STARTS_WITH ( nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW )
118 #define nssv_HAVE_ENDS_WITH nssv_HAVE_STARTS_WITH
119 
120 //
121 // Use C++17 std::string_view:
122 //
123 
124 #if nssv_USES_STD_STRING_VIEW
125 
126 #include <string_view>
127 
128 // Extensions for std::string:
129 
130 #if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
131 
132 namespace nonstd {
133 
134 template< class CharT, class Traits, class Allocator = std::allocator<CharT> >
135 std::basic_string<CharT, Traits, Allocator>
136 to_string( std::basic_string_view<CharT, Traits> v, Allocator const & a = Allocator() )
137 {
138  return std::basic_string<CharT,Traits, Allocator>( v.begin(), v.end(), a );
139 }
140 
141 template< class CharT, class Traits, class Allocator >
142 std::basic_string_view<CharT, Traits>
143 to_string_view( std::basic_string<CharT, Traits, Allocator> const & s )
144 {
145  return std::basic_string_view<CharT, Traits>( s.data(), s.size() );
146 }
147 
148 // Literal operators sv and _sv:
149 
150 #if nssv_CONFIG_STD_SV_OPERATOR
151 
152 using namespace std::literals::string_view_literals;
153 
154 #endif
155 
156 #if nssv_CONFIG_USR_SV_OPERATOR
157 
158 inline namespace literals {
159 inline namespace string_view_literals {
160 
161 
162 constexpr std::string_view operator "" _sv( const char* str, size_t len ) noexcept // (1)
163 {
164  return std::string_view{ str, len };
165 }
166 
167 constexpr std::u16string_view operator "" _sv( const char16_t* str, size_t len ) noexcept // (2)
168 {
169  return std::u16string_view{ str, len };
170 }
171 
172 constexpr std::u32string_view operator "" _sv( const char32_t* str, size_t len ) noexcept // (3)
173 {
174  return std::u32string_view{ str, len };
175 }
176 
177 constexpr std::wstring_view operator "" _sv( const wchar_t* str, size_t len ) noexcept // (4)
178 {
179  return std::wstring_view{ str, len };
180 }
181 
182 }} // namespace literals::string_view_literals
183 
184 #endif // nssv_CONFIG_USR_SV_OPERATOR
185 
186 } // namespace nonstd
187 
188 #endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
189 
190 namespace nonstd {
191 
192 using std::string_view;
193 using std::wstring_view;
194 using std::u16string_view;
195 using std::u32string_view;
196 using std::basic_string_view;
197 
198 // literal "sv" and "_sv", see above
199 
200 using std::operator==;
201 using std::operator!=;
202 using std::operator<;
203 using std::operator<=;
204 using std::operator>;
205 using std::operator>=;
206 
207 using std::operator<<;
208 
209 } // namespace nonstd
210 
211 #else // nssv_HAVE_STD_STRING_VIEW
212 
213 //
214 // Before C++17: use string_view lite:
215 //
216 
217 // Compiler versions:
218 //
219 // MSVC++ 6.0 _MSC_VER == 1200 nssv_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0)
220 // MSVC++ 7.0 _MSC_VER == 1300 nssv_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002)
221 // MSVC++ 7.1 _MSC_VER == 1310 nssv_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003)
222 // MSVC++ 8.0 _MSC_VER == 1400 nssv_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
223 // MSVC++ 9.0 _MSC_VER == 1500 nssv_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008)
224 // MSVC++ 10.0 _MSC_VER == 1600 nssv_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010)
225 // MSVC++ 11.0 _MSC_VER == 1700 nssv_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012)
226 // MSVC++ 12.0 _MSC_VER == 1800 nssv_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
227 // MSVC++ 14.0 _MSC_VER == 1900 nssv_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015)
228 // MSVC++ 14.1 _MSC_VER >= 1910 nssv_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
229 // MSVC++ 14.2 _MSC_VER >= 1920 nssv_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
230 
231 #if defined(_MSC_VER ) && !defined(__clang__)
232 # define nssv_COMPILER_MSVC_VER (_MSC_VER )
233 # define nssv_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
234 #else
235 # define nssv_COMPILER_MSVC_VER 0
236 # define nssv_COMPILER_MSVC_VERSION 0
237 #endif
238 
239 #define nssv_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
240 
241 #if defined( __apple_build_version__ )
242 # define nssv_COMPILER_APPLECLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
243 # define nssv_COMPILER_CLANG_VERSION 0
244 #elif defined( __clang__ )
245 # define nssv_COMPILER_APPLECLANG_VERSION 0
246 # define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
247 #else
248 # define nssv_COMPILER_APPLECLANG_VERSION 0
249 # define nssv_COMPILER_CLANG_VERSION 0
250 #endif
251 
252 #if defined(__GNUC__) && !defined(__clang__)
253 # define nssv_COMPILER_GNUC_VERSION nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
254 #else
255 # define nssv_COMPILER_GNUC_VERSION 0
256 #endif
257 
258 // half-open range [lo..hi):
259 #define nssv_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
260 
261 // Presence of language and library features:
262 
263 #ifdef _HAS_CPP0X
264 # define nssv_HAS_CPP0X _HAS_CPP0X
265 #else
266 # define nssv_HAS_CPP0X 0
267 #endif
268 
269 // Unless defined otherwise below, consider VC14 as C++11 for variant-lite:
270 
271 #if nssv_COMPILER_MSVC_VER >= 1900
272 # undef nssv_CPP11_OR_GREATER
273 # define nssv_CPP11_OR_GREATER 1
274 #endif
275 
276 #define nssv_CPP11_90 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500)
277 #define nssv_CPP11_100 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600)
278 #define nssv_CPP11_110 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700)
279 #define nssv_CPP11_120 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800)
280 #define nssv_CPP11_140 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900)
281 #define nssv_CPP11_141 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910)
282 
283 #define nssv_CPP14_000 (nssv_CPP14_OR_GREATER)
284 #define nssv_CPP17_000 (nssv_CPP17_OR_GREATER)
285 
286 // Presence of C++11 language features:
287 
288 #define nssv_HAVE_CONSTEXPR_11 nssv_CPP11_140
289 #define nssv_HAVE_EXPLICIT_CONVERSION nssv_CPP11_140
290 #define nssv_HAVE_INLINE_NAMESPACE nssv_CPP11_140
291 #define nssv_HAVE_NOEXCEPT nssv_CPP11_140
292 #define nssv_HAVE_NULLPTR nssv_CPP11_100
293 #define nssv_HAVE_REF_QUALIFIER nssv_CPP11_140
294 #define nssv_HAVE_UNICODE_LITERALS nssv_CPP11_140
295 #define nssv_HAVE_USER_DEFINED_LITERALS nssv_CPP11_140
296 #define nssv_HAVE_WCHAR16_T nssv_CPP11_100
297 #define nssv_HAVE_WCHAR32_T nssv_CPP11_100
298 
299 #if ! ( ( nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION ) || nssv_BETWEEN( nssv_COMPILER_CLANG_VERSION, 300, 400 ) )
300 # define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140
301 #else
302 # define nssv_HAVE_STD_DEFINED_LITERALS 0
303 #endif
304 
305 // Presence of C++14 language features:
306 
307 #define nssv_HAVE_CONSTEXPR_14 nssv_CPP14_000
308 
309 // Presence of C++17 language features:
310 
311 #define nssv_HAVE_NODISCARD nssv_CPP17_000
312 
313 // Presence of C++ library features:
314 
315 #define nssv_HAVE_STD_HASH nssv_CPP11_120
316 
317 // Presence of compiler intrinsics:
318 
319 // Providing char-type specializations for compare() and length() that
320 // use compiler intrinsics can improve compile- and run-time performance.
321 //
322 // The challenge is in using the right combinations of builtin availability
323 // and its constexpr-ness.
324 //
325 // | compiler | __builtin_memcmp (constexpr) | memcmp (constexpr) |
326 // |----------|------------------------------|---------------------|
327 // | clang | 4.0 (>= 4.0 ) | any (? ) |
328 // | clang-a | 9.0 (>= 9.0 ) | any (? ) |
329 // | gcc | any (constexpr) | any (? ) |
330 // | msvc | >= 14.2 C++17 (>= 14.2 ) | any (? ) |
331 
332 #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 )
333 #define nssv_HAVE_BUILTIN_CE ( nssv_HAVE_BUILTIN_VER )
334 
335 #define nssv_HAVE_BUILTIN_MEMCMP ( (nssv_HAVE_CONSTEXPR_14 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_14 )
336 #define nssv_HAVE_BUILTIN_STRLEN ( (nssv_HAVE_CONSTEXPR_11 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_11 )
337 
338 #ifdef __has_builtin
339 # define nssv_HAVE_BUILTIN( x ) __has_builtin( x )
340 #else
341 # define nssv_HAVE_BUILTIN( x ) 0
342 #endif
343 
344 #if nssv_HAVE_BUILTIN(__builtin_memcmp) || nssv_HAVE_BUILTIN_VER
345 # define nssv_BUILTIN_MEMCMP __builtin_memcmp
346 #else
347 # define nssv_BUILTIN_MEMCMP memcmp
348 #endif
349 
350 #if nssv_HAVE_BUILTIN(__builtin_strlen) || nssv_HAVE_BUILTIN_VER
351 # define nssv_BUILTIN_STRLEN __builtin_strlen
352 #else
353 # define nssv_BUILTIN_STRLEN strlen
354 #endif
355 
356 // C++ feature usage:
357 
358 #if nssv_HAVE_CONSTEXPR_11
359 # define nssv_constexpr constexpr
360 #else
361 # define nssv_constexpr /*constexpr*/
362 #endif
363 
364 #if nssv_HAVE_CONSTEXPR_14
365 # define nssv_constexpr14 constexpr
366 #else
367 # define nssv_constexpr14 /*constexpr*/
368 #endif
369 
370 #if nssv_HAVE_EXPLICIT_CONVERSION
371 # define nssv_explicit explicit
372 #else
373 # define nssv_explicit /*explicit*/
374 #endif
375 
376 #if nssv_HAVE_INLINE_NAMESPACE
377 # define nssv_inline_ns inline
378 #else
379 # define nssv_inline_ns /*inline*/
380 #endif
381 
382 #if nssv_HAVE_NOEXCEPT
383 # define nssv_noexcept noexcept
384 #else
385 # define nssv_noexcept /*noexcept*/
386 #endif
387 
388 //#if nssv_HAVE_REF_QUALIFIER
389 //# define nssv_ref_qual &
390 //# define nssv_refref_qual &&
391 //#else
392 //# define nssv_ref_qual /*&*/
393 //# define nssv_refref_qual /*&&*/
394 //#endif
395 
396 #if nssv_HAVE_NULLPTR
397 # define nssv_nullptr nullptr
398 #else
399 # define nssv_nullptr NULL
400 #endif
401 
402 #if nssv_HAVE_NODISCARD
403 # define nssv_nodiscard [[nodiscard]]
404 #else
405 # define nssv_nodiscard /*[[nodiscard]]*/
406 #endif
407 
408 // Additional includes:
409 
410 #include <algorithm>
411 #include <cassert>
412 #include <iterator>
413 #include <limits>
414 #include <string> // std::char_traits<>
415 
416 #if ! nssv_CONFIG_NO_STREAM_INSERTION
417 # include <ostream>
418 #endif
419 
420 #if ! nssv_CONFIG_NO_EXCEPTIONS
421 # include <stdexcept>
422 #endif
423 
424 #if nssv_CPP11_OR_GREATER
425 # include <type_traits>
426 #endif
427 
428 // Clang, GNUC, MSVC warning suppression macros:
429 
430 #if defined(__clang__)
431 # pragma clang diagnostic ignored "-Wreserved-user-defined-literal"
432 # pragma clang diagnostic push
433 # pragma clang diagnostic ignored "-Wuser-defined-literals"
434 #elif defined(__GNUC__)
435 # pragma GCC diagnostic push
436 # pragma GCC diagnostic ignored "-Wliteral-suffix"
437 #endif // __clang__
438 
439 #if nssv_COMPILER_MSVC_VERSION >= 140
440 # define nssv_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]]
441 # define nssv_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress: code) )
442 # define nssv_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes))
443 #else
444 # define nssv_SUPPRESS_MSGSL_WARNING(expr)
445 # define nssv_SUPPRESS_MSVC_WARNING(code, descr)
446 # define nssv_DISABLE_MSVC_WARNINGS(codes)
447 #endif
448 
449 #if defined(__clang__)
450 # define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
451 #elif defined(__GNUC__)
452 # define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
453 #elif nssv_COMPILER_MSVC_VERSION >= 140
454 # define nssv_RESTORE_WARNINGS() __pragma(warning(pop ))
455 #else
456 # define nssv_RESTORE_WARNINGS()
457 #endif
458 
459 // Suppress the following MSVC (GSL) warnings:
460 // - C4455, non-gsl : 'operator ""sv': literal suffix identifiers that do not
461 // start with an underscore are reserved
462 // - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions;
463 // use brace initialization, gsl::narrow_cast or gsl::narow
464 // - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
465 
466 nssv_DISABLE_MSVC_WARNINGS( 4455 26481 26472 )
467 //nssv_DISABLE_CLANG_WARNINGS( "-Wuser-defined-literals" )
468 //nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix )
469 
470 namespace nonstd { namespace sv_lite {
471 
472 namespace detail {
473 
474 // support constexpr comparison in C++14;
475 // for C++17 and later, use provided traits:
476 
477 template< typename CharT >
478 inline nssv_constexpr14 int compare( CharT const * s1, CharT const * s2, std::size_t count )
479 {
480  while ( count-- != 0 )
481  {
482  if ( *s1 < *s2 ) return -1;
483  if ( *s1 > *s2 ) return +1;
484  ++s1; ++s2;
485  }
486  return 0;
487 }
488 
489 #if nssv_HAVE_BUILTIN_MEMCMP
490 
491 // specialization of compare() for char, see also generic compare() above:
492 
493 inline nssv_constexpr14 int compare( char const * s1, char const * s2, std::size_t count )
494 {
495  return nssv_BUILTIN_MEMCMP( s1, s2, count );
496 }
497 
498 #endif
499 
500 #if nssv_HAVE_BUILTIN_STRLEN
501 
502 // specialization of length() for char, see also generic length() further below:
503 
504 inline nssv_constexpr std::size_t length( char const * s )
505 {
506  return nssv_BUILTIN_STRLEN( s );
507 }
508 
509 #endif
510 
511 #if defined(__OPTIMIZE__)
512 
513 // gcc, clang provide __OPTIMIZE__
514 // Expect tail call optimization to make length() non-recursive:
515 
516 template< typename CharT >
517 inline nssv_constexpr std::size_t length( CharT * s, std::size_t result = 0 )
518 {
519  return *s == '\0' ? result : length( s + 1, result + 1 );
520 }
521 
522 #else // OPTIMIZE
523 
524 // non-recursive:
525 
526 template< typename CharT >
527 inline nssv_constexpr14 std::size_t length( CharT * s )
528 {
529  std::size_t result = 0;
530  while ( *s++ != '\0' )
531  {
532  ++result;
533  }
534  return result;
535 }
536 
537 #endif // OPTIMIZE
538 
539 } // namespace detail
540 
541 template
542 <
543  class CharT,
544  class Traits = std::char_traits<CharT>
545 >
546 class basic_string_view;
547 
548 //
549 // basic_string_view:
550 //
551 
552 template
553 <
554  class CharT,
555  class Traits /* = std::char_traits<CharT> */
556 >
557 class basic_string_view
558 {
559 public:
560  // Member types:
561 
562  typedef Traits traits_type;
563  typedef CharT value_type;
564 
565  typedef CharT * pointer;
566  typedef CharT const * const_pointer;
567  typedef CharT & reference;
568  typedef CharT const & const_reference;
569 
570  typedef const_pointer iterator;
571  typedef const_pointer const_iterator;
572  typedef std::reverse_iterator< const_iterator > reverse_iterator;
573  typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
574 
575  typedef std::size_t size_type;
576  typedef std::ptrdiff_t difference_type;
577 
578  // 24.4.2.1 Construction and assignment:
579 
580  nssv_constexpr basic_string_view() nssv_noexcept
581  : data_( nssv_nullptr )
582  , size_( 0 )
583  {}
584 
585 #if nssv_CPP11_OR_GREATER
586  nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept = default;
587 #else
588  nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept
589  : data_( other.data_)
590  , size_( other.size_)
591  {}
592 #endif
593 
594  nssv_constexpr basic_string_view( CharT const * s, size_type count ) nssv_noexcept // non-standard noexcept
595  : data_( s )
596  , size_( count )
597  {}
598 
599  nssv_constexpr basic_string_view( CharT const * s) nssv_noexcept // non-standard noexcept
600  : data_( s )
601 #if nssv_CPP17_OR_GREATER
602  , size_( Traits::length(s) )
603 #elif nssv_CPP11_OR_GREATER
604  , size_( detail::length(s) )
605 #else
606  , size_( Traits::length(s) )
607 #endif
608  {}
609 
610  // Assignment:
611 
612 #if nssv_CPP11_OR_GREATER
613  nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept = default;
614 #else
615  nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept
616  {
617  data_ = other.data_;
618  size_ = other.size_;
619  return *this;
620  }
621 #endif
622 
623  // 24.4.2.2 Iterator support:
624 
625  nssv_constexpr const_iterator begin() const nssv_noexcept { return data_; }
626  nssv_constexpr const_iterator end() const nssv_noexcept { return data_ + size_; }
627 
628  nssv_constexpr const_iterator cbegin() const nssv_noexcept { return begin(); }
629  nssv_constexpr const_iterator cend() const nssv_noexcept { return end(); }
630 
631  nssv_constexpr const_reverse_iterator rbegin() const nssv_noexcept { return const_reverse_iterator( end() ); }
632  nssv_constexpr const_reverse_iterator rend() const nssv_noexcept { return const_reverse_iterator( begin() ); }
633 
634  nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept { return rbegin(); }
635  nssv_constexpr const_reverse_iterator crend() const nssv_noexcept { return rend(); }
636 
637  // 24.4.2.3 Capacity:
638 
639  nssv_constexpr size_type size() const nssv_noexcept { return size_; }
640  nssv_constexpr size_type length() const nssv_noexcept { return size_; }
641  nssv_constexpr size_type max_size() const nssv_noexcept { return (std::numeric_limits< size_type >::max)(); }
642 
643  // since C++20
644  nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept
645  {
646  return 0 == size_;
647  }
648 
649  // 24.4.2.4 Element access:
650 
651  nssv_constexpr const_reference operator[]( size_type pos ) const
652  {
653  return data_at( pos );
654  }
655 
656  nssv_constexpr14 const_reference at( size_type pos ) const
657  {
658 #if nssv_CONFIG_NO_EXCEPTIONS
659  assert( pos < size() );
660 #else
661  if ( pos >= size() )
662  {
663  throw std::out_of_range("nonstd::string_view::at()");
664  }
665 #endif
666  return data_at( pos );
667  }
668 
669  nssv_constexpr const_reference front() const { return data_at( 0 ); }
670  nssv_constexpr const_reference back() const { return data_at( size() - 1 ); }
671 
672  nssv_constexpr const_pointer data() const nssv_noexcept { return data_; }
673 
674  // 24.4.2.5 Modifiers:
675 
676  nssv_constexpr14 void remove_prefix( size_type n )
677  {
678  assert( n <= size() );
679  data_ += n;
680  size_ -= n;
681  }
682 
683  nssv_constexpr14 void remove_suffix( size_type n )
684  {
685  assert( n <= size() );
686  size_ -= n;
687  }
688 
689  nssv_constexpr14 void swap( basic_string_view & other ) nssv_noexcept
690  {
691  const basic_string_view tmp(other);
692  other = *this;
693  *this = tmp;
694  }
695 
696  // 24.4.2.6 String operations:
697 
698  size_type copy( CharT * dest, size_type n, size_type pos = 0 ) const
699  {
700 #if nssv_CONFIG_NO_EXCEPTIONS
701  assert( pos <= size() );
702 #else
703  if ( pos > size() )
704  {
705  throw std::out_of_range("nonstd::string_view::copy()");
706  }
707 #endif
708  const size_type rlen = (std::min)( n, size() - pos );
709 
710  (void) Traits::copy( dest, data() + pos, rlen );
711 
712  return rlen;
713  }
714 
715  nssv_constexpr14 basic_string_view substr( size_type pos = 0, size_type n = npos ) const
716  {
717 #if nssv_CONFIG_NO_EXCEPTIONS
718  assert( pos <= size() );
719 #else
720  if ( pos > size() )
721  {
722  throw std::out_of_range("nonstd::string_view::substr()");
723  }
724 #endif
725  return basic_string_view( data() + pos, (std::min)( n, size() - pos ) );
726  }
727 
728  // compare(), 6x:
729 
730  nssv_constexpr14 int compare( basic_string_view other ) const nssv_noexcept // (1)
731  {
732 #if nssv_CPP17_OR_GREATER
733  if ( const int result = Traits::compare( data(), other.data(), (std::min)( size(), other.size() ) ) )
734 #else
735  if ( const int result = detail::compare( data(), other.data(), (std::min)( size(), other.size() ) ) )
736 #endif
737  {
738  return result;
739  }
740 
741  return size() == other.size() ? 0 : size() < other.size() ? -1 : 1;
742  }
743 
744  nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other ) const // (2)
745  {
746  return substr( pos1, n1 ).compare( other );
747  }
748 
749  nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other, size_type pos2, size_type n2 ) const // (3)
750  {
751  return substr( pos1, n1 ).compare( other.substr( pos2, n2 ) );
752  }
753 
754  nssv_constexpr int compare( CharT const * s ) const // (4)
755  {
756  return compare( basic_string_view( s ) );
757  }
758 
759  nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s ) const // (5)
760  {
761  return substr( pos1, n1 ).compare( basic_string_view( s ) );
762  }
763 
764  nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s, size_type n2 ) const // (6)
765  {
766  return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) );
767  }
768 
769  // 24.4.2.7 Searching:
770 
771  // starts_with(), 3x, since C++20:
772 
773  nssv_constexpr bool starts_with( basic_string_view v ) const nssv_noexcept // (1)
774  {
775  return size() >= v.size() && compare( 0, v.size(), v ) == 0;
776  }
777 
778  nssv_constexpr bool starts_with( CharT c ) const nssv_noexcept // (2)
779  {
780  return starts_with( basic_string_view( &c, 1 ) );
781  }
782 
783  nssv_constexpr bool starts_with( CharT const * s ) const // (3)
784  {
785  return starts_with( basic_string_view( s ) );
786  }
787 
788  // ends_with(), 3x, since C++20:
789 
790  nssv_constexpr bool ends_with( basic_string_view v ) const nssv_noexcept // (1)
791  {
792  return size() >= v.size() && compare( size() - v.size(), npos, v ) == 0;
793  }
794 
795  nssv_constexpr bool ends_with( CharT c ) const nssv_noexcept // (2)
796  {
797  return ends_with( basic_string_view( &c, 1 ) );
798  }
799 
800  nssv_constexpr bool ends_with( CharT const * s ) const // (3)
801  {
802  return ends_with( basic_string_view( s ) );
803  }
804 
805  // find(), 4x:
806 
807  nssv_constexpr14 size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1)
808  {
809  return assert( v.size() == 0 || v.data() != nssv_nullptr )
810  , pos >= size()
811  ? npos
812  : to_pos( std::search( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq ) );
813  }
814 
815  nssv_constexpr14 size_type find( CharT c, size_type pos = 0 ) const nssv_noexcept // (2)
816  {
817  return find( basic_string_view( &c, 1 ), pos );
818  }
819 
820  nssv_constexpr14 size_type find( CharT const * s, size_type pos, size_type n ) const // (3)
821  {
822  return find( basic_string_view( s, n ), pos );
823  }
824 
825  nssv_constexpr14 size_type find( CharT const * s, size_type pos = 0 ) const // (4)
826  {
827  return find( basic_string_view( s ), pos );
828  }
829 
830  // rfind(), 4x:
831 
832  nssv_constexpr14 size_type rfind( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1)
833  {
834  if ( size() < v.size() )
835  {
836  return npos;
837  }
838 
839  if ( v.empty() )
840  {
841  return (std::min)( size(), pos );
842  }
843 
844  const_iterator last = cbegin() + (std::min)( size() - v.size(), pos ) + v.size();
845  const_iterator result = std::find_end( cbegin(), last, v.cbegin(), v.cend(), Traits::eq );
846 
847  return result != last ? size_type( result - cbegin() ) : npos;
848  }
849 
850  nssv_constexpr14 size_type rfind( CharT c, size_type pos = npos ) const nssv_noexcept // (2)
851  {
852  return rfind( basic_string_view( &c, 1 ), pos );
853  }
854 
855  nssv_constexpr14 size_type rfind( CharT const * s, size_type pos, size_type n ) const // (3)
856  {
857  return rfind( basic_string_view( s, n ), pos );
858  }
859 
860  nssv_constexpr14 size_type rfind( CharT const * s, size_type pos = npos ) const // (4)
861  {
862  return rfind( basic_string_view( s ), pos );
863  }
864 
865  // find_first_of(), 4x:
866 
867  nssv_constexpr size_type find_first_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1)
868  {
869  return pos >= size()
870  ? npos
871  : to_pos( std::find_first_of( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq ) );
872  }
873 
874  nssv_constexpr size_type find_first_of( CharT c, size_type pos = 0 ) const nssv_noexcept // (2)
875  {
876  return find_first_of( basic_string_view( &c, 1 ), pos );
877  }
878 
879  nssv_constexpr size_type find_first_of( CharT const * s, size_type pos, size_type n ) const // (3)
880  {
881  return find_first_of( basic_string_view( s, n ), pos );
882  }
883 
884  nssv_constexpr size_type find_first_of( CharT const * s, size_type pos = 0 ) const // (4)
885  {
886  return find_first_of( basic_string_view( s ), pos );
887  }
888 
889  // find_last_of(), 4x:
890 
891  nssv_constexpr size_type find_last_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1)
892  {
893  return empty()
894  ? npos
895  : pos >= size()
896  ? find_last_of( v, size() - 1 )
897  : to_pos( std::find_first_of( const_reverse_iterator( cbegin() + pos + 1 ), crend(), v.cbegin(), v.cend(), Traits::eq ) );
898  }
899 
900  nssv_constexpr size_type find_last_of( CharT c, size_type pos = npos ) const nssv_noexcept // (2)
901  {
902  return find_last_of( basic_string_view( &c, 1 ), pos );
903  }
904 
905  nssv_constexpr size_type find_last_of( CharT const * s, size_type pos, size_type count ) const // (3)
906  {
907  return find_last_of( basic_string_view( s, count ), pos );
908  }
909 
910  nssv_constexpr size_type find_last_of( CharT const * s, size_type pos = npos ) const // (4)
911  {
912  return find_last_of( basic_string_view( s ), pos );
913  }
914 
915  // find_first_not_of(), 4x:
916 
917  nssv_constexpr size_type find_first_not_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1)
918  {
919  return pos >= size()
920  ? npos
921  : to_pos( std::find_if( cbegin() + pos, cend(), not_in_view( v ) ) );
922  }
923 
924  nssv_constexpr size_type find_first_not_of( CharT c, size_type pos = 0 ) const nssv_noexcept // (2)
925  {
926  return find_first_not_of( basic_string_view( &c, 1 ), pos );
927  }
928 
929  nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos, size_type count ) const // (3)
930  {
931  return find_first_not_of( basic_string_view( s, count ), pos );
932  }
933 
934  nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos = 0 ) const // (4)
935  {
936  return find_first_not_of( basic_string_view( s ), pos );
937  }
938 
939  // find_last_not_of(), 4x:
940 
941  nssv_constexpr size_type find_last_not_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1)
942  {
943  return empty()
944  ? npos
945  : pos >= size()
946  ? find_last_not_of( v, size() - 1 )
947  : to_pos( std::find_if( const_reverse_iterator( cbegin() + pos + 1 ), crend(), not_in_view( v ) ) );
948  }
949 
950  nssv_constexpr size_type find_last_not_of( CharT c, size_type pos = npos ) const nssv_noexcept // (2)
951  {
952  return find_last_not_of( basic_string_view( &c, 1 ), pos );
953  }
954 
955  nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos, size_type count ) const // (3)
956  {
957  return find_last_not_of( basic_string_view( s, count ), pos );
958  }
959 
960  nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos = npos ) const // (4)
961  {
962  return find_last_not_of( basic_string_view( s ), pos );
963  }
964 
965  // Constants:
966 
967 #if nssv_CPP17_OR_GREATER
968  static nssv_constexpr size_type npos = size_type(-1);
969 #elif nssv_CPP11_OR_GREATER
970  enum : size_type { npos = size_type(-1) };
971 #else
972  enum { npos = size_type(-1) };
973 #endif
974 
975 private:
976  struct not_in_view
977  {
978  const basic_string_view v;
979 
980  nssv_constexpr explicit not_in_view( basic_string_view v_ ) : v( v_ ) {}
981 
982  nssv_constexpr bool operator()( CharT c ) const
983  {
984  return npos == v.find_first_of( c );
985  }
986  };
987 
988  nssv_constexpr size_type to_pos( const_iterator it ) const
989  {
990  return it == cend() ? npos : size_type( it - cbegin() );
991  }
992 
993  nssv_constexpr size_type to_pos( const_reverse_iterator it ) const
994  {
995  return it == crend() ? npos : size_type( crend() - it - 1 );
996  }
997 
998  nssv_constexpr const_reference data_at( size_type pos ) const
999  {
1000 #if nssv_BETWEEN( nssv_COMPILER_GNUC_VERSION, 1, 500 )
1001  return data_[pos];
1002 #else
1003  return assert( pos < size() ), data_[pos];
1004 #endif
1005  }
1006 
1007 private:
1008  const_pointer data_;
1009  size_type size_;
1010 
1011 public:
1012 #if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
1013 
1014  template< class Allocator >
1015  basic_string_view( std::basic_string<CharT, Traits, Allocator> const & s ) nssv_noexcept
1016  : data_( s.data() )
1017  , size_( s.size() )
1018  {}
1019 
1020 #if nssv_HAVE_EXPLICIT_CONVERSION
1021 
1022  template< class Allocator >
1023  explicit operator std::basic_string<CharT, Traits, Allocator>() const
1024  {
1025  return to_string( Allocator() );
1026  }
1027 
1028 #endif // nssv_HAVE_EXPLICIT_CONVERSION
1029 
1030 #if nssv_CPP11_OR_GREATER
1031 
1032  template< class Allocator = std::allocator<CharT> >
1033  std::basic_string<CharT, Traits, Allocator>
1034  to_string( Allocator const & a = Allocator() ) const
1035  {
1036  return std::basic_string<CharT, Traits, Allocator>( begin(), end(), a );
1037  }
1038 
1039 #else
1040 
1041  std::basic_string<CharT, Traits>
1042  to_string() const
1043  {
1044  return std::basic_string<CharT, Traits>( begin(), end() );
1045  }
1046 
1047  template< class Allocator >
1048  std::basic_string<CharT, Traits, Allocator>
1049  to_string( Allocator const & a ) const
1050  {
1051  return std::basic_string<CharT, Traits, Allocator>( begin(), end(), a );
1052  }
1053 
1054 #endif // nssv_CPP11_OR_GREATER
1055 
1056 #endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
1057 };
1058 
1059 //
1060 // Non-member functions:
1061 //
1062 
1063 // 24.4.3 Non-member comparison functions:
1064 // lexicographically compare two string views (function template):
1065 
1066 template< class CharT, class Traits >
1067 nssv_constexpr bool operator== (
1068  basic_string_view <CharT, Traits> lhs,
1069  basic_string_view <CharT, Traits> rhs ) nssv_noexcept
1070 { return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
1071 
1072 template< class CharT, class Traits >
1073 nssv_constexpr bool operator!= (
1074  basic_string_view <CharT, Traits> lhs,
1075  basic_string_view <CharT, Traits> rhs ) nssv_noexcept
1076 { return !( lhs == rhs ); }
1077 
1078 template< class CharT, class Traits >
1079 nssv_constexpr bool operator< (
1080  basic_string_view <CharT, Traits> lhs,
1081  basic_string_view <CharT, Traits> rhs ) nssv_noexcept
1082 { return lhs.compare( rhs ) < 0; }
1083 
1084 template< class CharT, class Traits >
1085 nssv_constexpr bool operator<= (
1086  basic_string_view <CharT, Traits> lhs,
1087  basic_string_view <CharT, Traits> rhs ) nssv_noexcept
1088 { return lhs.compare( rhs ) <= 0; }
1089 
1090 template< class CharT, class Traits >
1091 nssv_constexpr bool operator> (
1092  basic_string_view <CharT, Traits> lhs,
1093  basic_string_view <CharT, Traits> rhs ) nssv_noexcept
1094 { return lhs.compare( rhs ) > 0; }
1095 
1096 template< class CharT, class Traits >
1097 nssv_constexpr bool operator>= (
1098  basic_string_view <CharT, Traits> lhs,
1099  basic_string_view <CharT, Traits> rhs ) nssv_noexcept
1100 { return lhs.compare( rhs ) >= 0; }
1101 
1102 // Let S be basic_string_view<CharT, Traits>, and sv be an instance of S.
1103 // Implementations shall provide sufficient additional overloads marked
1104 // constexpr and noexcept so that an object t with an implicit conversion
1105 // to S can be compared according to Table 67.
1106 
1107 #if ! nssv_CPP11_OR_GREATER || nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 100, 141 )
1108 
1109 // accommodate for older compilers:
1110 
1111 // ==
1112 
1113 template< class CharT, class Traits>
1114 nssv_constexpr bool operator==(
1115  basic_string_view<CharT, Traits> lhs,
1116  CharT const * rhs ) nssv_noexcept
1117 { return lhs.size() == detail::length( rhs ) && lhs.compare( rhs ) == 0; }
1118 
1119 template< class CharT, class Traits>
1120 nssv_constexpr bool operator==(
1121  CharT const * lhs,
1122  basic_string_view<CharT, Traits> rhs ) nssv_noexcept
1123 { return detail::length( lhs ) == rhs.size() && rhs.compare( lhs ) == 0; }
1124 
1125 template< class CharT, class Traits>
1126 nssv_constexpr bool operator==(
1127  basic_string_view<CharT, Traits> lhs,
1128  std::basic_string<CharT, Traits> rhs ) nssv_noexcept
1129 { return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
1130 
1131 template< class CharT, class Traits>
1132 nssv_constexpr bool operator==(
1133  std::basic_string<CharT, Traits> rhs,
1134  basic_string_view<CharT, Traits> lhs ) nssv_noexcept
1135 { return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
1136 
1137 // !=
1138 
1139 template< class CharT, class Traits>
1140 nssv_constexpr bool operator!=(
1141  basic_string_view<CharT, Traits> lhs,
1142  CharT const * rhs ) nssv_noexcept
1143 { return !( lhs == rhs ); }
1144 
1145 template< class CharT, class Traits>
1146 nssv_constexpr bool operator!=(
1147  CharT const * lhs,
1148  basic_string_view<CharT, Traits> rhs ) nssv_noexcept
1149 { return !( lhs == rhs ); }
1150 
1151 template< class CharT, class Traits>
1152 nssv_constexpr bool operator!=(
1153  basic_string_view<CharT, Traits> lhs,
1154  std::basic_string<CharT, Traits> rhs ) nssv_noexcept
1155 { return !( lhs == rhs ); }
1156 
1157 template< class CharT, class Traits>
1158 nssv_constexpr bool operator!=(
1159  std::basic_string<CharT, Traits> rhs,
1160  basic_string_view<CharT, Traits> lhs ) nssv_noexcept
1161 { return !( lhs == rhs ); }
1162 
1163 // <
1164 
1165 template< class CharT, class Traits>
1166 nssv_constexpr bool operator<(
1167  basic_string_view<CharT, Traits> lhs,
1168  CharT const * rhs ) nssv_noexcept
1169 { return lhs.compare( rhs ) < 0; }
1170 
1171 template< class CharT, class Traits>
1172 nssv_constexpr bool operator<(
1173  CharT const * lhs,
1174  basic_string_view<CharT, Traits> rhs ) nssv_noexcept
1175 { return rhs.compare( lhs ) > 0; }
1176 
1177 template< class CharT, class Traits>
1178 nssv_constexpr bool operator<(
1179  basic_string_view<CharT, Traits> lhs,
1180  std::basic_string<CharT, Traits> rhs ) nssv_noexcept
1181 { return lhs.compare( rhs ) < 0; }
1182 
1183 template< class CharT, class Traits>
1184 nssv_constexpr bool operator<(
1185  std::basic_string<CharT, Traits> rhs,
1186  basic_string_view<CharT, Traits> lhs ) nssv_noexcept
1187 { return rhs.compare( lhs ) > 0; }
1188 
1189 // <=
1190 
1191 template< class CharT, class Traits>
1192 nssv_constexpr bool operator<=(
1193  basic_string_view<CharT, Traits> lhs,
1194  CharT const * rhs ) nssv_noexcept
1195 { return lhs.compare( rhs ) <= 0; }
1196 
1197 template< class CharT, class Traits>
1198 nssv_constexpr bool operator<=(
1199  CharT const * lhs,
1200  basic_string_view<CharT, Traits> rhs ) nssv_noexcept
1201 { return rhs.compare( lhs ) >= 0; }
1202 
1203 template< class CharT, class Traits>
1204 nssv_constexpr bool operator<=(
1205  basic_string_view<CharT, Traits> lhs,
1206  std::basic_string<CharT, Traits> rhs ) nssv_noexcept
1207 { return lhs.compare( rhs ) <= 0; }
1208 
1209 template< class CharT, class Traits>
1210 nssv_constexpr bool operator<=(
1211  std::basic_string<CharT, Traits> rhs,
1212  basic_string_view<CharT, Traits> lhs ) nssv_noexcept
1213 { return rhs.compare( lhs ) >= 0; }
1214 
1215 // >
1216 
1217 template< class CharT, class Traits>
1218 nssv_constexpr bool operator>(
1219  basic_string_view<CharT, Traits> lhs,
1220  CharT const * rhs ) nssv_noexcept
1221 { return lhs.compare( rhs ) > 0; }
1222 
1223 template< class CharT, class Traits>
1224 nssv_constexpr bool operator>(
1225  CharT const * lhs,
1226  basic_string_view<CharT, Traits> rhs ) nssv_noexcept
1227 { return rhs.compare( lhs ) < 0; }
1228 
1229 template< class CharT, class Traits>
1230 nssv_constexpr bool operator>(
1231  basic_string_view<CharT, Traits> lhs,
1232  std::basic_string<CharT, Traits> rhs ) nssv_noexcept
1233 { return lhs.compare( rhs ) > 0; }
1234 
1235 template< class CharT, class Traits>
1236 nssv_constexpr bool operator>(
1237  std::basic_string<CharT, Traits> rhs,
1238  basic_string_view<CharT, Traits> lhs ) nssv_noexcept
1239 { return rhs.compare( lhs ) < 0; }
1240 
1241 // >=
1242 
1243 template< class CharT, class Traits>
1244 nssv_constexpr bool operator>=(
1245  basic_string_view<CharT, Traits> lhs,
1246  CharT const * rhs ) nssv_noexcept
1247 { return lhs.compare( rhs ) >= 0; }
1248 
1249 template< class CharT, class Traits>
1250 nssv_constexpr bool operator>=(
1251  CharT const * lhs,
1252  basic_string_view<CharT, Traits> rhs ) nssv_noexcept
1253 { return rhs.compare( lhs ) <= 0; }
1254 
1255 template< class CharT, class Traits>
1256 nssv_constexpr bool operator>=(
1257  basic_string_view<CharT, Traits> lhs,
1258  std::basic_string<CharT, Traits> rhs ) nssv_noexcept
1259 { return lhs.compare( rhs ) >= 0; }
1260 
1261 template< class CharT, class Traits>
1262 nssv_constexpr bool operator>=(
1263  std::basic_string<CharT, Traits> rhs,
1264  basic_string_view<CharT, Traits> lhs ) nssv_noexcept
1265 { return rhs.compare( lhs ) <= 0; }
1266 
1267 #else // newer compilers:
1268 
1269 #define nssv_BASIC_STRING_VIEW_I(T,U) typename std::decay< basic_string_view<T,U> >::type
1270 
1271 #if defined(_MSC_VER) // issue 40
1272 # define nssv_MSVC_ORDER(x) , int=x
1273 #else
1274 # define nssv_MSVC_ORDER(x) /*, int=x*/
1275 #endif
1276 
1277 // ==
1278 
1279 template< class CharT, class Traits nssv_MSVC_ORDER(1) >
1280 nssv_constexpr bool operator==(
1281  basic_string_view <CharT, Traits> lhs,
1282  nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs ) nssv_noexcept
1283 { return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
1284 
1285 template< class CharT, class Traits nssv_MSVC_ORDER(2) >
1286 nssv_constexpr bool operator==(
1287  nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
1288  basic_string_view <CharT, Traits> rhs ) nssv_noexcept
1289 { return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
1290 
1291 // !=
1292 
1293 template< class CharT, class Traits nssv_MSVC_ORDER(1) >
1294 nssv_constexpr bool operator!= (
1295  basic_string_view < CharT, Traits > lhs,
1296  nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
1297 { return !( lhs == rhs ); }
1298 
1299 template< class CharT, class Traits nssv_MSVC_ORDER(2) >
1300 nssv_constexpr bool operator!= (
1301  nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
1302  basic_string_view < CharT, Traits > rhs ) nssv_noexcept
1303 { return !( lhs == rhs ); }
1304 
1305 // <
1306 
1307 template< class CharT, class Traits nssv_MSVC_ORDER(1) >
1308 nssv_constexpr bool operator< (
1309  basic_string_view < CharT, Traits > lhs,
1310  nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
1311 { return lhs.compare( rhs ) < 0; }
1312 
1313 template< class CharT, class Traits nssv_MSVC_ORDER(2) >
1314 nssv_constexpr bool operator< (
1315  nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
1316  basic_string_view < CharT, Traits > rhs ) nssv_noexcept
1317 { return lhs.compare( rhs ) < 0; }
1318 
1319 // <=
1320 
1321 template< class CharT, class Traits nssv_MSVC_ORDER(1) >
1322 nssv_constexpr bool operator<= (
1323  basic_string_view < CharT, Traits > lhs,
1324  nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
1325 { return lhs.compare( rhs ) <= 0; }
1326 
1327 template< class CharT, class Traits nssv_MSVC_ORDER(2) >
1328 nssv_constexpr bool operator<= (
1329  nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
1330  basic_string_view < CharT, Traits > rhs ) nssv_noexcept
1331 { return lhs.compare( rhs ) <= 0; }
1332 
1333 // >
1334 
1335 template< class CharT, class Traits nssv_MSVC_ORDER(1) >
1336 nssv_constexpr bool operator> (
1337  basic_string_view < CharT, Traits > lhs,
1338  nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
1339 { return lhs.compare( rhs ) > 0; }
1340 
1341 template< class CharT, class Traits nssv_MSVC_ORDER(2) >
1342 nssv_constexpr bool operator> (
1343  nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
1344  basic_string_view < CharT, Traits > rhs ) nssv_noexcept
1345 { return lhs.compare( rhs ) > 0; }
1346 
1347 // >=
1348 
1349 template< class CharT, class Traits nssv_MSVC_ORDER(1) >
1350 nssv_constexpr bool operator>= (
1351  basic_string_view < CharT, Traits > lhs,
1352  nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
1353 { return lhs.compare( rhs ) >= 0; }
1354 
1355 template< class CharT, class Traits nssv_MSVC_ORDER(2) >
1356 nssv_constexpr bool operator>= (
1357  nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
1358  basic_string_view < CharT, Traits > rhs ) nssv_noexcept
1359 { return lhs.compare( rhs ) >= 0; }
1360 
1361 #undef nssv_MSVC_ORDER
1362 #undef nssv_BASIC_STRING_VIEW_I
1363 
1364 #endif // compiler-dependent approach to comparisons
1365 
1366 // 24.4.4 Inserters and extractors:
1367 
1368 #if ! nssv_CONFIG_NO_STREAM_INSERTION
1369 
1370 namespace detail {
1371 
1372 template< class Stream >
1373 void write_padding( Stream & os, std::streamsize n )
1374 {
1375  for ( std::streamsize i = 0; i < n; ++i )
1376  os.rdbuf()->sputc( os.fill() );
1377 }
1378 
1379 template< class Stream, class View >
1380 Stream & write_to_stream( Stream & os, View const & sv )
1381 {
1382  typename Stream::sentry sentry( os );
1383 
1384  if ( !os )
1385  return os;
1386 
1387  const std::streamsize length = static_cast<std::streamsize>( sv.length() );
1388 
1389  // Whether, and how, to pad:
1390  const bool pad = ( length < os.width() );
1391  const bool left_pad = pad && ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::right;
1392 
1393  if ( left_pad )
1394  write_padding( os, os.width() - length );
1395 
1396  // Write span characters:
1397  os.rdbuf()->sputn( sv.begin(), length );
1398 
1399  if ( pad && !left_pad )
1400  write_padding( os, os.width() - length );
1401 
1402  // Reset output stream width:
1403  os.width( 0 );
1404 
1405  return os;
1406 }
1407 
1408 } // namespace detail
1409 
1410 template< class CharT, class Traits >
1411 std::basic_ostream<CharT, Traits> &
1412 operator<<(
1413  std::basic_ostream<CharT, Traits>& os,
1414  basic_string_view <CharT, Traits> sv )
1415 {
1416  return detail::write_to_stream( os, sv );
1417 }
1418 
1419 #endif // nssv_CONFIG_NO_STREAM_INSERTION
1420 
1421 // Several typedefs for common character types are provided:
1422 
1423 typedef basic_string_view<char> string_view;
1424 typedef basic_string_view<wchar_t> wstring_view;
1425 #if nssv_HAVE_WCHAR16_T
1426 typedef basic_string_view<char16_t> u16string_view;
1427 typedef basic_string_view<char32_t> u32string_view;
1428 #endif
1429 
1430 }} // namespace nonstd::sv_lite
1431 
1432 //
1433 // 24.4.6 Suffix for basic_string_view literals:
1434 //
1435 
1436 #if nssv_HAVE_USER_DEFINED_LITERALS
1437 
1438 namespace nonstd {
1439 nssv_inline_ns namespace literals {
1440 nssv_inline_ns namespace string_view_literals {
1441 
1442 #if nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
1443 
1444 nssv_constexpr nonstd::sv_lite::string_view operator "" sv( const char* str, size_t len ) nssv_noexcept // (1)
1445 {
1446  return nonstd::sv_lite::string_view{ str, len };
1447 }
1448 
1449 nssv_constexpr nonstd::sv_lite::u16string_view operator "" sv( const char16_t* str, size_t len ) nssv_noexcept // (2)
1450 {
1451  return nonstd::sv_lite::u16string_view{ str, len };
1452 }
1453 
1454 nssv_constexpr nonstd::sv_lite::u32string_view operator "" sv( const char32_t* str, size_t len ) nssv_noexcept // (3)
1455 {
1456  return nonstd::sv_lite::u32string_view{ str, len };
1457 }
1458 
1459 nssv_constexpr nonstd::sv_lite::wstring_view operator "" sv( const wchar_t* str, size_t len ) nssv_noexcept // (4)
1460 {
1461  return nonstd::sv_lite::wstring_view{ str, len };
1462 }
1463 
1464 #endif // nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
1465 
1466 #if nssv_CONFIG_USR_SV_OPERATOR
1467 
1468 nssv_constexpr nonstd::sv_lite::string_view operator "" _sv( const char* str, size_t len ) nssv_noexcept // (1)
1469 {
1470  return nonstd::sv_lite::string_view{ str, len };
1471 }
1472 
1473 nssv_constexpr nonstd::sv_lite::u16string_view operator "" _sv( const char16_t* str, size_t len ) nssv_noexcept // (2)
1474 {
1475  return nonstd::sv_lite::u16string_view{ str, len };
1476 }
1477 
1478 nssv_constexpr nonstd::sv_lite::u32string_view operator "" _sv( const char32_t* str, size_t len ) nssv_noexcept // (3)
1479 {
1480  return nonstd::sv_lite::u32string_view{ str, len };
1481 }
1482 
1483 nssv_constexpr nonstd::sv_lite::wstring_view operator "" _sv( const wchar_t* str, size_t len ) nssv_noexcept // (4)
1484 {
1485  return nonstd::sv_lite::wstring_view{ str, len };
1486 }
1487 
1488 #endif // nssv_CONFIG_USR_SV_OPERATOR
1489 
1490 }}} // namespace nonstd::literals::string_view_literals
1491 
1492 #endif
1493 
1494 //
1495 // Extensions for std::string:
1496 //
1497 
1498 #if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
1499 
1500 namespace nonstd {
1501 namespace sv_lite {
1502 
1503 // Exclude MSVC 14 (19.00): it yields ambiguous to_string():
1504 
1505 #if nssv_CPP11_OR_GREATER && nssv_COMPILER_MSVC_VERSION != 140
1506 
1507 template< class CharT, class Traits, class Allocator = std::allocator<CharT> >
1508 std::basic_string<CharT, Traits, Allocator>
1509 to_string( basic_string_view<CharT, Traits> v, Allocator const & a = Allocator() )
1510 {
1511  return std::basic_string<CharT,Traits, Allocator>( v.begin(), v.end(), a );
1512 }
1513 
1514 #else
1515 
1516 template< class CharT, class Traits >
1517 std::basic_string<CharT, Traits>
1518 to_string( basic_string_view<CharT, Traits> v )
1519 {
1520  return std::basic_string<CharT, Traits>( v.begin(), v.end() );
1521 }
1522 
1523 template< class CharT, class Traits, class Allocator >
1524 std::basic_string<CharT, Traits, Allocator>
1525 to_string( basic_string_view<CharT, Traits> v, Allocator const & a )
1526 {
1527  return std::basic_string<CharT, Traits, Allocator>( v.begin(), v.end(), a );
1528 }
1529 
1530 #endif // nssv_CPP11_OR_GREATER
1531 
1532 template< class CharT, class Traits, class Allocator >
1533 basic_string_view<CharT, Traits>
1534 to_string_view( std::basic_string<CharT, Traits, Allocator> const & s )
1535 {
1536  return basic_string_view<CharT, Traits>( s.data(), s.size() );
1537 }
1538 
1539 }} // namespace nonstd::sv_lite
1540 
1541 #endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
1542 
1543 //
1544 // make types and algorithms available in namespace nonstd:
1545 //
1546 
1547 namespace nonstd {
1548 
1549 using sv_lite::basic_string_view;
1550 using sv_lite::string_view;
1551 using sv_lite::wstring_view;
1552 
1553 #if nssv_HAVE_WCHAR16_T
1554 using sv_lite::u16string_view;
1555 #endif
1556 #if nssv_HAVE_WCHAR32_T
1557 using sv_lite::u32string_view;
1558 #endif
1559 
1560 // literal "sv"
1561 
1562 using sv_lite::operator==;
1563 using sv_lite::operator!=;
1564 using sv_lite::operator<;
1565 using sv_lite::operator<=;
1566 using sv_lite::operator>;
1567 using sv_lite::operator>=;
1568 
1569 #if ! nssv_CONFIG_NO_STREAM_INSERTION
1570 using sv_lite::operator<<;
1571 #endif
1572 
1573 #if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
1574 using sv_lite::to_string;
1575 using sv_lite::to_string_view;
1576 #endif
1577 
1578 } // namespace nonstd
1579 
1580 // 24.4.5 Hash support (C++11):
1581 
1582 // Note: The hash value of a string view object is equal to the hash value of
1583 // the corresponding string object.
1584 
1585 #if nssv_HAVE_STD_HASH
1586 
1587 #include <functional>
1588 
1589 namespace std {
1590 
1591 template<>
1592 struct hash< nonstd::string_view >
1593 {
1594 public:
1595  std::size_t operator()( nonstd::string_view v ) const nssv_noexcept
1596  {
1597  return std::hash<std::string>()( std::string( v.data(), v.size() ) );
1598  }
1599 };
1600 
1601 template<>
1602 struct hash< nonstd::wstring_view >
1603 {
1604 public:
1605  std::size_t operator()( nonstd::wstring_view v ) const nssv_noexcept
1606  {
1607  return std::hash<std::wstring>()( std::wstring( v.data(), v.size() ) );
1608  }
1609 };
1610 
1611 template<>
1612 struct hash< nonstd::u16string_view >
1613 {
1614 public:
1615  std::size_t operator()( nonstd::u16string_view v ) const nssv_noexcept
1616  {
1617  return std::hash<std::u16string>()( std::u16string( v.data(), v.size() ) );
1618  }
1619 };
1620 
1621 template<>
1622 struct hash< nonstd::u32string_view >
1623 {
1624 public:
1625  std::size_t operator()( nonstd::u32string_view v ) const nssv_noexcept
1626  {
1627  return std::hash<std::u32string>()( std::u32string( v.data(), v.size() ) );
1628  }
1629 };
1630 
1631 } // namespace std
1632 
1633 #endif // nssv_HAVE_STD_HASH
1634 
1635 nssv_RESTORE_WARNINGS()
1636 
1637 #endif // nssv_HAVE_STD_STRING_VIEW
1638 #endif // NONSTD_SV_LITE_H_INCLUDED
simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept
Comparisons between raw_json_string and std::string_view instances are potentially unsafe: the user i...
std::string to_string(T x)
Converts JSON to a string.