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