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