1 | // Components for manipulating non-owning sequences of characters -*- C++ -*- |
2 | |
3 | // Copyright (C) 2013-2023 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /** @file include/string_view |
26 | * This is a Standard C++ Library header. |
27 | */ |
28 | |
29 | // |
30 | // N3762 basic_string_view library |
31 | // |
32 | |
33 | #ifndef _GLIBCXX_STRING_VIEW |
34 | #define _GLIBCXX_STRING_VIEW 1 |
35 | |
36 | #pragma GCC system_header |
37 | |
38 | #if __cplusplus >= 201703L |
39 | |
40 | #include <bits/char_traits.h> |
41 | #include <bits/functexcept.h> |
42 | #include <bits/functional_hash.h> |
43 | #include <bits/range_access.h> |
44 | #include <bits/stl_algobase.h> |
45 | #include <ext/numeric_traits.h> |
46 | |
47 | #if __cplusplus >= 202002L |
48 | # include <bits/ranges_base.h> |
49 | #endif |
50 | |
51 | #if _GLIBCXX_HOSTED |
52 | # include <iosfwd> |
53 | # include <bits/ostream_insert.h> |
54 | #endif |
55 | |
56 | namespace std _GLIBCXX_VISIBILITY(default) |
57 | { |
58 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
59 | |
60 | #if _GLIBCXX_HOSTED |
61 | # define __cpp_lib_string_view 201803L |
62 | #endif |
63 | |
64 | #if __cplusplus > 201703L |
65 | # define __cpp_lib_constexpr_string_view 201811L |
66 | #endif |
67 | |
68 | // Helper for basic_string and basic_string_view members. |
69 | constexpr size_t |
70 | __sv_check(size_t __size, size_t __pos, const char* __s) |
71 | { |
72 | if (__pos > __size) |
73 | __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > __size " |
74 | "(which is %zu)" ), __s, __pos, __size); |
75 | return __pos; |
76 | } |
77 | |
78 | // Helper for basic_string members. |
79 | // NB: __sv_limit doesn't check for a bad __pos value. |
80 | constexpr size_t |
81 | __sv_limit(size_t __size, size_t __pos, size_t __off) noexcept |
82 | { |
83 | const bool __testoff = __off < __size - __pos; |
84 | return __testoff ? __off : __size - __pos; |
85 | } |
86 | |
87 | /** |
88 | * @class basic_string_view <string_view> |
89 | * @brief A non-owning reference to a string. |
90 | * |
91 | * @ingroup strings |
92 | * @ingroup sequences |
93 | * |
94 | * @tparam _CharT Type of character |
95 | * @tparam _Traits Traits for character type, defaults to |
96 | * char_traits<_CharT>. |
97 | * |
98 | * A basic_string_view looks like this: |
99 | * |
100 | * @code |
101 | * _CharT* _M_str |
102 | * size_t _M_len |
103 | * @endcode |
104 | */ |
105 | template<typename _CharT, typename _Traits = std::char_traits<_CharT>> |
106 | class basic_string_view |
107 | { |
108 | static_assert(!is_array_v<_CharT>); |
109 | static_assert(is_trivial_v<_CharT> && is_standard_layout_v<_CharT>); |
110 | static_assert(is_same_v<_CharT, typename _Traits::char_type>); |
111 | |
112 | public: |
113 | |
114 | // types |
115 | using traits_type = _Traits; |
116 | using value_type = _CharT; |
117 | using pointer = value_type*; |
118 | using const_pointer = const value_type*; |
119 | using reference = value_type&; |
120 | using const_reference = const value_type&; |
121 | using const_iterator = const value_type*; |
122 | using iterator = const_iterator; |
123 | using const_reverse_iterator = std::reverse_iterator<const_iterator>; |
124 | using reverse_iterator = const_reverse_iterator; |
125 | using size_type = size_t; |
126 | using difference_type = ptrdiff_t; |
127 | static constexpr size_type npos = size_type(-1); |
128 | |
129 | // [string.view.cons], construction and assignment |
130 | |
131 | constexpr |
132 | basic_string_view() noexcept |
133 | : _M_len{0}, _M_str{nullptr} |
134 | { } |
135 | |
136 | constexpr basic_string_view(const basic_string_view&) noexcept = default; |
137 | |
138 | [[__gnu__::__nonnull__]] |
139 | constexpr |
140 | basic_string_view(const _CharT* __str) noexcept |
141 | : _M_len{traits_type::length(__str)}, |
142 | _M_str{__str} |
143 | { } |
144 | |
145 | constexpr |
146 | basic_string_view(const _CharT* __str, size_type __len) noexcept |
147 | : _M_len{__len}, _M_str{__str} |
148 | { } |
149 | |
150 | #if __cplusplus >= 202002L && __cpp_lib_concepts |
151 | template<contiguous_iterator _It, sized_sentinel_for<_It> _End> |
152 | requires same_as<iter_value_t<_It>, _CharT> |
153 | && (!convertible_to<_End, size_type>) |
154 | constexpr |
155 | basic_string_view(_It __first, _End __last) |
156 | noexcept(noexcept(__last - __first)) |
157 | : _M_len(__last - __first), _M_str(std::to_address(__first)) |
158 | { } |
159 | |
160 | #if __cplusplus > 202002L |
161 | template<typename _Range, typename _DRange = remove_cvref_t<_Range>> |
162 | requires (!is_same_v<_DRange, basic_string_view>) |
163 | && ranges::contiguous_range<_Range> |
164 | && ranges::sized_range<_Range> |
165 | && is_same_v<ranges::range_value_t<_Range>, _CharT> |
166 | && (!is_convertible_v<_Range, const _CharT*>) |
167 | && (!requires (_DRange& __d) { |
168 | __d.operator ::std::basic_string_view<_CharT, _Traits>(); |
169 | }) |
170 | constexpr explicit |
171 | basic_string_view(_Range&& __r) |
172 | noexcept(noexcept(ranges::size(__r)) && noexcept(ranges::data(__r))) |
173 | : _M_len(ranges::size(__r)), _M_str(ranges::data(__r)) |
174 | { } |
175 | |
176 | basic_string_view(nullptr_t) = delete; |
177 | #endif // C++23 |
178 | #endif // C++20 |
179 | |
180 | constexpr basic_string_view& |
181 | operator=(const basic_string_view&) noexcept = default; |
182 | |
183 | // [string.view.iterators], iterator support |
184 | |
185 | [[nodiscard]] |
186 | constexpr const_iterator |
187 | begin() const noexcept |
188 | { return this->_M_str; } |
189 | |
190 | [[nodiscard]] |
191 | constexpr const_iterator |
192 | end() const noexcept |
193 | { return this->_M_str + this->_M_len; } |
194 | |
195 | [[nodiscard]] |
196 | constexpr const_iterator |
197 | cbegin() const noexcept |
198 | { return this->_M_str; } |
199 | |
200 | [[nodiscard]] |
201 | constexpr const_iterator |
202 | cend() const noexcept |
203 | { return this->_M_str + this->_M_len; } |
204 | |
205 | [[nodiscard]] |
206 | constexpr const_reverse_iterator |
207 | rbegin() const noexcept |
208 | { return const_reverse_iterator(this->end()); } |
209 | |
210 | [[nodiscard]] |
211 | constexpr const_reverse_iterator |
212 | rend() const noexcept |
213 | { return const_reverse_iterator(this->begin()); } |
214 | |
215 | [[nodiscard]] |
216 | constexpr const_reverse_iterator |
217 | crbegin() const noexcept |
218 | { return const_reverse_iterator(this->end()); } |
219 | |
220 | [[nodiscard]] |
221 | constexpr const_reverse_iterator |
222 | crend() const noexcept |
223 | { return const_reverse_iterator(this->begin()); } |
224 | |
225 | // [string.view.capacity], capacity |
226 | |
227 | [[nodiscard]] |
228 | constexpr size_type |
229 | size() const noexcept |
230 | { return this->_M_len; } |
231 | |
232 | [[nodiscard]] |
233 | constexpr size_type |
234 | length() const noexcept |
235 | { return _M_len; } |
236 | |
237 | [[nodiscard]] |
238 | constexpr size_type |
239 | max_size() const noexcept |
240 | { |
241 | return (npos - sizeof(size_type) - sizeof(void*)) |
242 | / sizeof(value_type) / 4; |
243 | } |
244 | |
245 | [[nodiscard]] |
246 | constexpr bool |
247 | empty() const noexcept |
248 | { return this->_M_len == 0; } |
249 | |
250 | // [string.view.access], element access |
251 | |
252 | [[nodiscard]] |
253 | constexpr const_reference |
254 | operator[](size_type __pos) const noexcept |
255 | { |
256 | __glibcxx_assert(__pos < this->_M_len); |
257 | return *(this->_M_str + __pos); |
258 | } |
259 | |
260 | [[nodiscard]] |
261 | constexpr const_reference |
262 | at(size_type __pos) const |
263 | { |
264 | if (__pos >= _M_len) |
265 | __throw_out_of_range_fmt(__N("basic_string_view::at: __pos " |
266 | "(which is %zu) >= this->size() " |
267 | "(which is %zu)" ), __pos, this->size()); |
268 | return *(this->_M_str + __pos); |
269 | } |
270 | |
271 | [[nodiscard]] |
272 | constexpr const_reference |
273 | front() const noexcept |
274 | { |
275 | __glibcxx_assert(this->_M_len > 0); |
276 | return *this->_M_str; |
277 | } |
278 | |
279 | [[nodiscard]] |
280 | constexpr const_reference |
281 | back() const noexcept |
282 | { |
283 | __glibcxx_assert(this->_M_len > 0); |
284 | return *(this->_M_str + this->_M_len - 1); |
285 | } |
286 | |
287 | [[nodiscard]] |
288 | constexpr const_pointer |
289 | data() const noexcept |
290 | { return this->_M_str; } |
291 | |
292 | // [string.view.modifiers], modifiers: |
293 | |
294 | constexpr void |
295 | remove_prefix(size_type __n) noexcept |
296 | { |
297 | __glibcxx_assert(this->_M_len >= __n); |
298 | this->_M_str += __n; |
299 | this->_M_len -= __n; |
300 | } |
301 | |
302 | constexpr void |
303 | remove_suffix(size_type __n) noexcept |
304 | { |
305 | __glibcxx_assert(this->_M_len >= __n); |
306 | this->_M_len -= __n; |
307 | } |
308 | |
309 | constexpr void |
310 | swap(basic_string_view& __sv) noexcept |
311 | { |
312 | auto __tmp = *this; |
313 | *this = __sv; |
314 | __sv = __tmp; |
315 | } |
316 | |
317 | // [string.view.ops], string operations: |
318 | |
319 | _GLIBCXX20_CONSTEXPR |
320 | size_type |
321 | copy(_CharT* __str, size_type __n, size_type __pos = 0) const |
322 | { |
323 | __glibcxx_requires_string_len(__str, __n); |
324 | __pos = std::__sv_check(size: size(), __pos, s: "basic_string_view::copy" ); |
325 | const size_type __rlen = std::min<size_t>(a: __n, b: _M_len - __pos); |
326 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
327 | // 2777. basic_string_view::copy should use char_traits::copy |
328 | traits_type::copy(__str, data() + __pos, __rlen); |
329 | return __rlen; |
330 | } |
331 | |
332 | [[nodiscard]] |
333 | constexpr basic_string_view |
334 | substr(size_type __pos = 0, size_type __n = npos) const noexcept(false) |
335 | { |
336 | __pos = std::__sv_check(size: size(), __pos, s: "basic_string_view::substr" ); |
337 | const size_type __rlen = std::min<size_t>(a: __n, b: _M_len - __pos); |
338 | return basic_string_view{_M_str + __pos, __rlen}; |
339 | } |
340 | |
341 | [[nodiscard]] |
342 | constexpr int |
343 | compare(basic_string_view __str) const noexcept |
344 | { |
345 | const size_type __rlen = std::min(this->_M_len, __str._M_len); |
346 | int __ret = traits_type::compare(this->_M_str, __str._M_str, __rlen); |
347 | if (__ret == 0) |
348 | __ret = _S_compare(n1: this->_M_len, n2: __str._M_len); |
349 | return __ret; |
350 | } |
351 | |
352 | [[nodiscard]] |
353 | constexpr int |
354 | compare(size_type __pos1, size_type __n1, basic_string_view __str) const |
355 | { return this->substr(__pos1, __n1).compare(__str); } |
356 | |
357 | [[nodiscard]] |
358 | constexpr int |
359 | compare(size_type __pos1, size_type __n1, |
360 | basic_string_view __str, size_type __pos2, size_type __n2) const |
361 | { |
362 | return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); |
363 | } |
364 | |
365 | [[nodiscard, __gnu__::__nonnull__]] |
366 | constexpr int |
367 | compare(const _CharT* __str) const noexcept |
368 | { return this->compare(basic_string_view{__str}); } |
369 | |
370 | [[nodiscard, __gnu__::__nonnull__]] |
371 | constexpr int |
372 | compare(size_type __pos1, size_type __n1, const _CharT* __str) const |
373 | { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); } |
374 | |
375 | [[nodiscard]] |
376 | constexpr int |
377 | compare(size_type __pos1, size_type __n1, |
378 | const _CharT* __str, size_type __n2) const noexcept(false) |
379 | { |
380 | return this->substr(__pos1, __n1) |
381 | .compare(basic_string_view(__str, __n2)); |
382 | } |
383 | |
384 | #if __cplusplus > 201703L |
385 | #define __cpp_lib_starts_ends_with 201711L |
386 | [[nodiscard]] |
387 | constexpr bool |
388 | starts_with(basic_string_view __x) const noexcept |
389 | { return this->substr(0, __x.size()) == __x; } |
390 | |
391 | [[nodiscard]] |
392 | constexpr bool |
393 | starts_with(_CharT __x) const noexcept |
394 | { return !this->empty() && traits_type::eq(this->front(), __x); } |
395 | |
396 | [[nodiscard, __gnu__::__nonnull__]] |
397 | constexpr bool |
398 | starts_with(const _CharT* __x) const noexcept |
399 | { return this->starts_with(basic_string_view(__x)); } |
400 | |
401 | [[nodiscard]] |
402 | constexpr bool |
403 | ends_with(basic_string_view __x) const noexcept |
404 | { |
405 | const auto __len = this->size(); |
406 | const auto __xlen = __x.size(); |
407 | return __len >= __xlen |
408 | && traits_type::compare(end() - __xlen, __x.data(), __xlen) == 0; |
409 | } |
410 | |
411 | [[nodiscard]] |
412 | constexpr bool |
413 | ends_with(_CharT __x) const noexcept |
414 | { return !this->empty() && traits_type::eq(this->back(), __x); } |
415 | |
416 | [[nodiscard, __gnu__::__nonnull__]] |
417 | constexpr bool |
418 | ends_with(const _CharT* __x) const noexcept |
419 | { return this->ends_with(basic_string_view(__x)); } |
420 | #endif // C++20 |
421 | |
422 | #if __cplusplus > 202002L |
423 | #if _GLIBCXX_HOSTED |
424 | // This FTM is not freestanding as it also implies matching <string> |
425 | // support, and <string> is omitted from the freestanding subset. |
426 | # define __cpp_lib_string_contains 202011L |
427 | #endif // HOSTED |
428 | [[nodiscard]] |
429 | constexpr bool |
430 | contains(basic_string_view __x) const noexcept |
431 | { return this->find(__x) != npos; } |
432 | |
433 | [[nodiscard]] |
434 | constexpr bool |
435 | contains(_CharT __x) const noexcept |
436 | { return this->find(__x) != npos; } |
437 | |
438 | [[nodiscard, __gnu__::__nonnull__]] |
439 | constexpr bool |
440 | contains(const _CharT* __x) const noexcept |
441 | { return this->find(__x) != npos; } |
442 | #endif // C++23 |
443 | |
444 | // [string.view.find], searching |
445 | |
446 | [[nodiscard]] |
447 | constexpr size_type |
448 | find(basic_string_view __str, size_type __pos = 0) const noexcept |
449 | { return this->find(__str._M_str, __pos, __str._M_len); } |
450 | |
451 | [[nodiscard]] |
452 | constexpr size_type |
453 | find(_CharT __c, size_type __pos = 0) const noexcept; |
454 | |
455 | [[nodiscard]] |
456 | constexpr size_type |
457 | find(const _CharT* __str, size_type __pos, size_type __n) const noexcept; |
458 | |
459 | [[nodiscard, __gnu__::__nonnull__]] |
460 | constexpr size_type |
461 | find(const _CharT* __str, size_type __pos = 0) const noexcept |
462 | { return this->find(__str, __pos, traits_type::length(__str)); } |
463 | |
464 | [[nodiscard]] |
465 | constexpr size_type |
466 | rfind(basic_string_view __str, size_type __pos = npos) const noexcept |
467 | { return this->rfind(__str._M_str, __pos, __str._M_len); } |
468 | |
469 | [[nodiscard]] |
470 | constexpr size_type |
471 | rfind(_CharT __c, size_type __pos = npos) const noexcept; |
472 | |
473 | [[nodiscard]] |
474 | constexpr size_type |
475 | rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept; |
476 | |
477 | [[nodiscard, __gnu__::__nonnull__]] |
478 | constexpr size_type |
479 | rfind(const _CharT* __str, size_type __pos = npos) const noexcept |
480 | { return this->rfind(__str, __pos, traits_type::length(__str)); } |
481 | |
482 | [[nodiscard]] |
483 | constexpr size_type |
484 | find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept |
485 | { return this->find_first_of(__str._M_str, __pos, __str._M_len); } |
486 | |
487 | [[nodiscard]] |
488 | constexpr size_type |
489 | find_first_of(_CharT __c, size_type __pos = 0) const noexcept |
490 | { return this->find(__c, __pos); } |
491 | |
492 | [[nodiscard]] |
493 | constexpr size_type |
494 | find_first_of(const _CharT* __str, size_type __pos, |
495 | size_type __n) const noexcept; |
496 | |
497 | [[nodiscard, __gnu__::__nonnull__]] |
498 | constexpr size_type |
499 | find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept |
500 | { return this->find_first_of(__str, __pos, traits_type::length(__str)); } |
501 | |
502 | [[nodiscard]] |
503 | constexpr size_type |
504 | find_last_of(basic_string_view __str, |
505 | size_type __pos = npos) const noexcept |
506 | { return this->find_last_of(__str._M_str, __pos, __str._M_len); } |
507 | |
508 | [[nodiscard]] |
509 | constexpr size_type |
510 | find_last_of(_CharT __c, size_type __pos=npos) const noexcept |
511 | { return this->rfind(__c, __pos); } |
512 | |
513 | [[nodiscard]] |
514 | constexpr size_type |
515 | find_last_of(const _CharT* __str, size_type __pos, |
516 | size_type __n) const noexcept; |
517 | |
518 | [[nodiscard, __gnu__::__nonnull__]] |
519 | constexpr size_type |
520 | find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept |
521 | { return this->find_last_of(__str, __pos, traits_type::length(__str)); } |
522 | |
523 | [[nodiscard]] |
524 | constexpr size_type |
525 | find_first_not_of(basic_string_view __str, |
526 | size_type __pos = 0) const noexcept |
527 | { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); } |
528 | |
529 | [[nodiscard]] |
530 | constexpr size_type |
531 | find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept; |
532 | |
533 | [[nodiscard]] |
534 | constexpr size_type |
535 | find_first_not_of(const _CharT* __str, |
536 | size_type __pos, size_type __n) const noexcept; |
537 | |
538 | [[nodiscard, __gnu__::__nonnull__]] |
539 | constexpr size_type |
540 | find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept |
541 | { |
542 | return this->find_first_not_of(__str, __pos, |
543 | traits_type::length(__str)); |
544 | } |
545 | |
546 | [[nodiscard]] |
547 | constexpr size_type |
548 | find_last_not_of(basic_string_view __str, |
549 | size_type __pos = npos) const noexcept |
550 | { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); } |
551 | |
552 | [[nodiscard]] |
553 | constexpr size_type |
554 | find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept; |
555 | |
556 | [[nodiscard]] |
557 | constexpr size_type |
558 | find_last_not_of(const _CharT* __str, |
559 | size_type __pos, size_type __n) const noexcept; |
560 | |
561 | [[nodiscard, __gnu__::__nonnull__]] |
562 | constexpr size_type |
563 | find_last_not_of(const _CharT* __str, |
564 | size_type __pos = npos) const noexcept |
565 | { |
566 | return this->find_last_not_of(__str, __pos, |
567 | traits_type::length(__str)); |
568 | } |
569 | |
570 | private: |
571 | |
572 | static constexpr int |
573 | _S_compare(size_type __n1, size_type __n2) noexcept |
574 | { |
575 | using __limits = __gnu_cxx::__int_traits<int>; |
576 | const difference_type __diff = __n1 - __n2; |
577 | if (__diff > __limits::__max) |
578 | return __limits::__max; |
579 | if (__diff < __limits::__min) |
580 | return __limits::__min; |
581 | return static_cast<int>(__diff); |
582 | } |
583 | |
584 | size_t _M_len; |
585 | const _CharT* _M_str; |
586 | }; |
587 | |
588 | #if __cplusplus > 201703L && __cpp_lib_concepts && __cpp_deduction_guides |
589 | template<contiguous_iterator _It, sized_sentinel_for<_It> _End> |
590 | basic_string_view(_It, _End) -> basic_string_view<iter_value_t<_It>>; |
591 | |
592 | #if __cplusplus > 202002L |
593 | template<ranges::contiguous_range _Range> |
594 | basic_string_view(_Range&&) |
595 | -> basic_string_view<ranges::range_value_t<_Range>>; |
596 | #endif |
597 | #endif |
598 | |
599 | // [string.view.comparison], non-member basic_string_view comparison function |
600 | |
601 | // Several of these functions use type_identity_t to create a non-deduced |
602 | // context, so that only one argument participates in template argument |
603 | // deduction and the other argument gets implicitly converted to the deduced |
604 | // type (see N3766). |
605 | |
606 | template<typename _CharT, typename _Traits> |
607 | [[nodiscard]] |
608 | constexpr bool |
609 | operator==(basic_string_view<_CharT, _Traits> __x, |
610 | basic_string_view<_CharT, _Traits> __y) noexcept |
611 | { return __x.size() == __y.size() && __x.compare(__y) == 0; } |
612 | |
613 | template<typename _CharT, typename _Traits> |
614 | [[nodiscard]] |
615 | constexpr bool |
616 | operator==(basic_string_view<_CharT, _Traits> __x, |
617 | __type_identity_t<basic_string_view<_CharT, _Traits>> __y) |
618 | noexcept |
619 | { return __x.size() == __y.size() && __x.compare(__y) == 0; } |
620 | |
621 | #if __cpp_lib_three_way_comparison |
622 | template<typename _CharT, typename _Traits> |
623 | [[nodiscard]] |
624 | constexpr auto |
625 | operator<=>(basic_string_view<_CharT, _Traits> __x, |
626 | basic_string_view<_CharT, _Traits> __y) noexcept |
627 | -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0)) |
628 | { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); } |
629 | |
630 | template<typename _CharT, typename _Traits> |
631 | [[nodiscard]] |
632 | constexpr auto |
633 | operator<=>(basic_string_view<_CharT, _Traits> __x, |
634 | __type_identity_t<basic_string_view<_CharT, _Traits>> __y) |
635 | noexcept |
636 | -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0)) |
637 | { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); } |
638 | #else |
639 | template<typename _CharT, typename _Traits> |
640 | [[nodiscard]] |
641 | constexpr bool |
642 | operator==(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, |
643 | basic_string_view<_CharT, _Traits> __y) noexcept |
644 | { return __x.size() == __y.size() && __x.compare(__y) == 0; } |
645 | |
646 | template<typename _CharT, typename _Traits> |
647 | [[nodiscard]] |
648 | constexpr bool |
649 | operator!=(basic_string_view<_CharT, _Traits> __x, |
650 | basic_string_view<_CharT, _Traits> __y) noexcept |
651 | { return !(__x == __y); } |
652 | |
653 | template<typename _CharT, typename _Traits> |
654 | [[nodiscard]] |
655 | constexpr bool |
656 | operator!=(basic_string_view<_CharT, _Traits> __x, |
657 | __type_identity_t<basic_string_view<_CharT, _Traits>> __y) |
658 | noexcept |
659 | { return !(__x == __y); } |
660 | |
661 | template<typename _CharT, typename _Traits> |
662 | [[nodiscard]] |
663 | constexpr bool |
664 | operator!=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, |
665 | basic_string_view<_CharT, _Traits> __y) noexcept |
666 | { return !(__x == __y); } |
667 | |
668 | template<typename _CharT, typename _Traits> |
669 | [[nodiscard]] |
670 | constexpr bool |
671 | operator< (basic_string_view<_CharT, _Traits> __x, |
672 | basic_string_view<_CharT, _Traits> __y) noexcept |
673 | { return __x.compare(__y) < 0; } |
674 | |
675 | template<typename _CharT, typename _Traits> |
676 | [[nodiscard]] |
677 | constexpr bool |
678 | operator< (basic_string_view<_CharT, _Traits> __x, |
679 | __type_identity_t<basic_string_view<_CharT, _Traits>> __y) |
680 | noexcept |
681 | { return __x.compare(__y) < 0; } |
682 | |
683 | template<typename _CharT, typename _Traits> |
684 | [[nodiscard]] |
685 | constexpr bool |
686 | operator< (__type_identity_t<basic_string_view<_CharT, _Traits>> __x, |
687 | basic_string_view<_CharT, _Traits> __y) noexcept |
688 | { return __x.compare(__y) < 0; } |
689 | |
690 | template<typename _CharT, typename _Traits> |
691 | [[nodiscard]] |
692 | constexpr bool |
693 | operator> (basic_string_view<_CharT, _Traits> __x, |
694 | basic_string_view<_CharT, _Traits> __y) noexcept |
695 | { return __x.compare(__y) > 0; } |
696 | |
697 | template<typename _CharT, typename _Traits> |
698 | [[nodiscard]] |
699 | constexpr bool |
700 | operator> (basic_string_view<_CharT, _Traits> __x, |
701 | __type_identity_t<basic_string_view<_CharT, _Traits>> __y) |
702 | noexcept |
703 | { return __x.compare(__y) > 0; } |
704 | |
705 | template<typename _CharT, typename _Traits> |
706 | [[nodiscard]] |
707 | constexpr bool |
708 | operator> (__type_identity_t<basic_string_view<_CharT, _Traits>> __x, |
709 | basic_string_view<_CharT, _Traits> __y) noexcept |
710 | { return __x.compare(__y) > 0; } |
711 | |
712 | template<typename _CharT, typename _Traits> |
713 | [[nodiscard]] |
714 | constexpr bool |
715 | operator<=(basic_string_view<_CharT, _Traits> __x, |
716 | basic_string_view<_CharT, _Traits> __y) noexcept |
717 | { return __x.compare(__y) <= 0; } |
718 | |
719 | template<typename _CharT, typename _Traits> |
720 | [[nodiscard]] |
721 | constexpr bool |
722 | operator<=(basic_string_view<_CharT, _Traits> __x, |
723 | __type_identity_t<basic_string_view<_CharT, _Traits>> __y) |
724 | noexcept |
725 | { return __x.compare(__y) <= 0; } |
726 | |
727 | template<typename _CharT, typename _Traits> |
728 | [[nodiscard]] |
729 | constexpr bool |
730 | operator<=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, |
731 | basic_string_view<_CharT, _Traits> __y) noexcept |
732 | { return __x.compare(__y) <= 0; } |
733 | |
734 | template<typename _CharT, typename _Traits> |
735 | [[nodiscard]] |
736 | constexpr bool |
737 | operator>=(basic_string_view<_CharT, _Traits> __x, |
738 | basic_string_view<_CharT, _Traits> __y) noexcept |
739 | { return __x.compare(__y) >= 0; } |
740 | |
741 | template<typename _CharT, typename _Traits> |
742 | [[nodiscard]] |
743 | constexpr bool |
744 | operator>=(basic_string_view<_CharT, _Traits> __x, |
745 | __type_identity_t<basic_string_view<_CharT, _Traits>> __y) |
746 | noexcept |
747 | { return __x.compare(__y) >= 0; } |
748 | |
749 | template<typename _CharT, typename _Traits> |
750 | [[nodiscard]] |
751 | constexpr bool |
752 | operator>=(__type_identity_t<basic_string_view<_CharT, _Traits>> __x, |
753 | basic_string_view<_CharT, _Traits> __y) noexcept |
754 | { return __x.compare(__y) >= 0; } |
755 | #endif // three-way comparison |
756 | |
757 | #if _GLIBCXX_HOSTED |
758 | // [string.view.io], Inserters and extractors |
759 | template<typename _CharT, typename _Traits> |
760 | inline basic_ostream<_CharT, _Traits>& |
761 | operator<<(basic_ostream<_CharT, _Traits>& __os, |
762 | basic_string_view<_CharT,_Traits> __str) |
763 | { return __ostream_insert(__os, __str.data(), __str.size()); } |
764 | #endif // HOSTED |
765 | |
766 | // basic_string_view typedef names |
767 | |
768 | using string_view = basic_string_view<char>; |
769 | using wstring_view = basic_string_view<wchar_t>; |
770 | #ifdef _GLIBCXX_USE_CHAR8_T |
771 | using u8string_view = basic_string_view<char8_t>; |
772 | #endif |
773 | using u16string_view = basic_string_view<char16_t>; |
774 | using u32string_view = basic_string_view<char32_t>; |
775 | |
776 | // [string.view.hash], hash support: |
777 | |
778 | template<typename _Tp> |
779 | struct hash; |
780 | |
781 | template<> |
782 | struct hash<string_view> |
783 | : public __hash_base<size_t, string_view> |
784 | { |
785 | [[nodiscard]] |
786 | size_t |
787 | operator()(const string_view& __str) const noexcept |
788 | { return std::_Hash_impl::hash(ptr: __str.data(), clength: __str.length()); } |
789 | }; |
790 | |
791 | template<> |
792 | struct __is_fast_hash<hash<string_view>> : std::false_type |
793 | { }; |
794 | |
795 | template<> |
796 | struct hash<wstring_view> |
797 | : public __hash_base<size_t, wstring_view> |
798 | { |
799 | [[nodiscard]] |
800 | size_t |
801 | operator()(const wstring_view& __s) const noexcept |
802 | { return std::_Hash_impl::hash(ptr: __s.data(), |
803 | clength: __s.length() * sizeof(wchar_t)); } |
804 | }; |
805 | |
806 | template<> |
807 | struct __is_fast_hash<hash<wstring_view>> : std::false_type |
808 | { }; |
809 | |
810 | #ifdef _GLIBCXX_USE_CHAR8_T |
811 | template<> |
812 | struct hash<u8string_view> |
813 | : public __hash_base<size_t, u8string_view> |
814 | { |
815 | [[nodiscard]] |
816 | size_t |
817 | operator()(const u8string_view& __str) const noexcept |
818 | { return std::_Hash_impl::hash(__str.data(), __str.length()); } |
819 | }; |
820 | |
821 | template<> |
822 | struct __is_fast_hash<hash<u8string_view>> : std::false_type |
823 | { }; |
824 | #endif |
825 | |
826 | template<> |
827 | struct hash<u16string_view> |
828 | : public __hash_base<size_t, u16string_view> |
829 | { |
830 | [[nodiscard]] |
831 | size_t |
832 | operator()(const u16string_view& __s) const noexcept |
833 | { return std::_Hash_impl::hash(ptr: __s.data(), |
834 | clength: __s.length() * sizeof(char16_t)); } |
835 | }; |
836 | |
837 | template<> |
838 | struct __is_fast_hash<hash<u16string_view>> : std::false_type |
839 | { }; |
840 | |
841 | template<> |
842 | struct hash<u32string_view> |
843 | : public __hash_base<size_t, u32string_view> |
844 | { |
845 | [[nodiscard]] |
846 | size_t |
847 | operator()(const u32string_view& __s) const noexcept |
848 | { return std::_Hash_impl::hash(ptr: __s.data(), |
849 | clength: __s.length() * sizeof(char32_t)); } |
850 | }; |
851 | |
852 | template<> |
853 | struct __is_fast_hash<hash<u32string_view>> : std::false_type |
854 | { }; |
855 | |
856 | inline namespace literals |
857 | { |
858 | inline namespace string_view_literals |
859 | { |
860 | #pragma GCC diagnostic push |
861 | #pragma GCC diagnostic ignored "-Wliteral-suffix" |
862 | inline constexpr basic_string_view<char> |
863 | operator""sv (const char* __str, size_t __len) noexcept |
864 | { return basic_string_view<char>{__str, __len}; } |
865 | |
866 | inline constexpr basic_string_view<wchar_t> |
867 | operator""sv (const wchar_t* __str, size_t __len) noexcept |
868 | { return basic_string_view<wchar_t>{__str, __len}; } |
869 | |
870 | #ifdef _GLIBCXX_USE_CHAR8_T |
871 | inline constexpr basic_string_view<char8_t> |
872 | operator""sv (const char8_t* __str, size_t __len) noexcept |
873 | { return basic_string_view<char8_t>{__str, __len}; } |
874 | #endif |
875 | |
876 | inline constexpr basic_string_view<char16_t> |
877 | operator""sv (const char16_t* __str, size_t __len) noexcept |
878 | { return basic_string_view<char16_t>{__str, __len}; } |
879 | |
880 | inline constexpr basic_string_view<char32_t> |
881 | operator""sv (const char32_t* __str, size_t __len) noexcept |
882 | { return basic_string_view<char32_t>{__str, __len}; } |
883 | |
884 | #pragma GCC diagnostic pop |
885 | } // namespace string_literals |
886 | } // namespace literals |
887 | |
888 | #if __cpp_lib_concepts |
889 | namespace ranges |
890 | { |
891 | // Opt-in to borrowed_range concept |
892 | template<typename _CharT, typename _Traits> |
893 | inline constexpr bool |
894 | enable_borrowed_range<basic_string_view<_CharT, _Traits>> = true; |
895 | |
896 | // Opt-in to view concept |
897 | template<typename _CharT, typename _Traits> |
898 | inline constexpr bool |
899 | enable_view<basic_string_view<_CharT, _Traits>> = true; |
900 | } |
901 | #endif |
902 | _GLIBCXX_END_NAMESPACE_VERSION |
903 | } // namespace std |
904 | |
905 | #include <bits/string_view.tcc> |
906 | |
907 | #endif // __cplusplus <= 201402L |
908 | |
909 | #endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW |
910 | |