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