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