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