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