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