libstdc++
string_view
Go to the documentation of this file.
1// Components for manipulating non-owning sequences of characters -*- C++ -*-
2
3// Copyright (C) 2013-2019 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 experimental/string_view
26 * This is a TS C++ Library header.
27 */
28
29//
30// N3762 basic_string_view library
31//
32
33#ifndef _GLIBCXX_EXPERIMENTAL_STRING_VIEW
34#define _GLIBCXX_EXPERIMENTAL_STRING_VIEW 1
35
36#pragma GCC system_header
37
38#if __cplusplus >= 201402L
39
40#include <string>
41#include <limits>
42#include <experimental/bits/lfts_config.h>
43
44namespace std _GLIBCXX_VISIBILITY(default)
45{
46_GLIBCXX_BEGIN_NAMESPACE_VERSION
47
48namespace experimental
49{
50inline namespace fundamentals_v1
51{
52#define __cpp_lib_experimental_string_view 201411
53
54 /**
55 * @class basic_string_view <experimental/string_view>
56 * @brief A non-owning reference to a string.
57 *
58 * @ingroup strings
59 * @ingroup sequences
60 * @ingroup experimental
61 *
62 * @tparam _CharT Type of character
63 * @tparam _Traits Traits for character type, defaults to
64 * char_traits<_CharT>.
65 *
66 * A basic_string_view looks like this:
67 *
68 * @code
69 * _CharT* _M_str
70 * size_t _M_len
71 * @endcode
72 */
73 template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
74 class basic_string_view
75 {
76 public:
77
78 // types
79 using traits_type = _Traits;
80 using value_type = _CharT;
81 using pointer = _CharT*;
82 using const_pointer = const _CharT*;
83 using reference = _CharT&;
84 using const_reference = const _CharT&;
85 using const_iterator = const _CharT*;
86 using iterator = const_iterator;
87 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
88 using reverse_iterator = const_reverse_iterator;
89 using size_type = size_t;
90 using difference_type = ptrdiff_t;
91 static constexpr size_type npos = size_type(-1);
92
93 // [string.view.cons], construct/copy
94
95 constexpr
96 basic_string_view() noexcept
97 : _M_len{0}, _M_str{nullptr}
98 { }
99
100 constexpr basic_string_view(const basic_string_view&) noexcept = default;
101
102 template<typename _Allocator>
103 basic_string_view(const basic_string<_CharT, _Traits,
104 _Allocator>& __str) noexcept
105 : _M_len{__str.length()}, _M_str{__str.data()}
106 { }
107
108 constexpr basic_string_view(const _CharT* __str)
109 : _M_len{__str == nullptr ? 0 : traits_type::length(__str)},
110 _M_str{__str}
111 { }
112
113 constexpr basic_string_view(const _CharT* __str, size_type __len)
114 : _M_len{__len},
115 _M_str{__str}
116 { }
117
118 basic_string_view&
119 operator=(const basic_string_view&) noexcept = default;
120
121 // [string.view.iterators], iterators
122
123 constexpr const_iterator
124 begin() const noexcept
125 { return this->_M_str; }
126
127 constexpr const_iterator
128 end() const noexcept
129 { return this->_M_str + this->_M_len; }
130
131 constexpr const_iterator
132 cbegin() const noexcept
133 { return this->_M_str; }
134
135 constexpr const_iterator
136 cend() const noexcept
137 { return this->_M_str + this->_M_len; }
138
139 const_reverse_iterator
140 rbegin() const noexcept
141 { return const_reverse_iterator(this->end()); }
142
143 const_reverse_iterator
144 rend() const noexcept
145 { return const_reverse_iterator(this->begin()); }
146
147 const_reverse_iterator
148 crbegin() const noexcept
149 { return const_reverse_iterator(this->end()); }
150
151 const_reverse_iterator
152 crend() const noexcept
153 { return const_reverse_iterator(this->begin()); }
154
155 // [string.view.capacity], capacity
156
157 constexpr size_type
158 size() const noexcept
159 { return this->_M_len; }
160
161 constexpr size_type
162 length() const noexcept
163 { return _M_len; }
164
165 constexpr size_type
166 max_size() const noexcept
167 {
168 return (npos - sizeof(size_type) - sizeof(void*))
169 / sizeof(value_type) / 4;
170 }
171
172 _GLIBCXX_NODISCARD constexpr bool
173 empty() const noexcept
174 { return this->_M_len == 0; }
175
176 // [string.view.access], element access
177
178 constexpr const _CharT&
179 operator[](size_type __pos) const
180 {
181 __glibcxx_assert(__pos < this->_M_len);
182 return *(this->_M_str + __pos);
183 }
184
185 constexpr const _CharT&
186 at(size_type __pos) const
187 {
188 return __pos < this->_M_len
189 ? *(this->_M_str + __pos)
190 : (__throw_out_of_range_fmt(__N("basic_string_view::at: __pos "
191 "(which is %zu) >= this->size() "
192 "(which is %zu)"),
193 __pos, this->size()),
194 *this->_M_str);
195 }
196
197 constexpr const _CharT&
198 front() const
199 {
200 __glibcxx_assert(this->_M_len > 0);
201 return *this->_M_str;
202 }
203
204 constexpr const _CharT&
205 back() const
206 {
207 __glibcxx_assert(this->_M_len > 0);
208 return *(this->_M_str + this->_M_len - 1);
209 }
210
211 constexpr const _CharT*
212 data() const noexcept
213 { return this->_M_str; }
214
215 // [string.view.modifiers], modifiers:
216
217 constexpr void
218 remove_prefix(size_type __n)
219 {
220 __glibcxx_assert(this->_M_len >= __n);
221 this->_M_str += __n;
222 this->_M_len -= __n;
223 }
224
225 constexpr void
226 remove_suffix(size_type __n)
227 { this->_M_len -= __n; }
228
229 constexpr void
230 swap(basic_string_view& __sv) noexcept
231 {
232 auto __tmp = *this;
233 *this = __sv;
234 __sv = __tmp;
235 }
236
237
238 // [string.view.ops], string operations:
239
240 template<typename _Allocator>
241 explicit operator basic_string<_CharT, _Traits, _Allocator>() const
242 {
243 return { this->_M_str, this->_M_len };
244 }
245
246 template<typename _Allocator = std::allocator<_CharT>>
247 basic_string<_CharT, _Traits, _Allocator>
248 to_string(const _Allocator& __alloc = _Allocator()) const
249 {
250 return { this->_M_str, this->_M_len, __alloc };
251 }
252
253 size_type
254 copy(_CharT* __str, size_type __n, size_type __pos = 0) const
255 {
256 __glibcxx_requires_string_len(__str, __n);
257 if (__pos > this->_M_len)
258 __throw_out_of_range_fmt(__N("basic_string_view::copy: __pos "
259 "(which is %zu) > this->size() "
260 "(which is %zu)"),
261 __pos, this->size());
262 size_type __rlen{std::min(__n, size_type{this->_M_len - __pos})};
263 for (auto __begin = this->_M_str + __pos,
264 __end = __begin + __rlen; __begin != __end;)
265 *__str++ = *__begin++;
266 return __rlen;
267 }
268
269
270 // [string.view.ops], string operations:
271
272 constexpr basic_string_view
273 substr(size_type __pos = 0, size_type __n = npos) const
274 {
275 return __pos <= this->_M_len
276 ? basic_string_view{this->_M_str + __pos,
277 std::min(__n, size_type{this->_M_len - __pos})}
278 : (__throw_out_of_range_fmt(__N("basic_string_view::substr: __pos "
279 "(which is %zu) > this->size() "
280 "(which is %zu)"),
281 __pos, this->size()), basic_string_view{});
282 }
283
284 constexpr int
285 compare(basic_string_view __str) const noexcept
286 {
287 int __ret = traits_type::compare(this->_M_str, __str._M_str,
288 std::min(this->_M_len, __str._M_len));
289 if (__ret == 0)
290 __ret = _S_compare(this->_M_len, __str._M_len);
291 return __ret;
292 }
293
294 constexpr int
295 compare(size_type __pos1, size_type __n1, basic_string_view __str) const
296 { return this->substr(__pos1, __n1).compare(__str); }
297
298 constexpr int
299 compare(size_type __pos1, size_type __n1,
300 basic_string_view __str, size_type __pos2, size_type __n2) const
301 { return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); }
302
303 constexpr int
304 compare(const _CharT* __str) const noexcept
305 { return this->compare(basic_string_view{__str}); }
306
307 constexpr int
308 compare(size_type __pos1, size_type __n1, const _CharT* __str) const
309 { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); }
310
311 constexpr int
312 compare(size_type __pos1, size_type __n1,
313 const _CharT* __str, size_type __n2) const
314 {
315 return this->substr(__pos1, __n1)
316 .compare(basic_string_view(__str, __n2));
317 }
318
319 constexpr size_type
320 find(basic_string_view __str, size_type __pos = 0) const noexcept
321 { return this->find(__str._M_str, __pos, __str._M_len); }
322
323 constexpr size_type
324 find(_CharT __c, size_type __pos=0) const noexcept;
325
326 constexpr size_type
327 find(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
328
329 constexpr size_type
330 find(const _CharT* __str, size_type __pos=0) const noexcept
331 { return this->find(__str, __pos, traits_type::length(__str)); }
332
333 constexpr size_type
334 rfind(basic_string_view __str, size_type __pos = npos) const noexcept
335 { return this->rfind(__str._M_str, __pos, __str._M_len); }
336
337 constexpr size_type
338 rfind(_CharT __c, size_type __pos = npos) const noexcept;
339
340 constexpr size_type
341 rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
342
343 constexpr size_type
344 rfind(const _CharT* __str, size_type __pos = npos) const noexcept
345 { return this->rfind(__str, __pos, traits_type::length(__str)); }
346
347 constexpr size_type
348 find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept
349 { return this->find_first_of(__str._M_str, __pos, __str._M_len); }
350
351 constexpr size_type
352 find_first_of(_CharT __c, size_type __pos = 0) const noexcept
353 { return this->find(__c, __pos); }
354
355 constexpr size_type
356 find_first_of(const _CharT* __str, size_type __pos, size_type __n) const;
357
358 constexpr size_type
359 find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept
360 { return this->find_first_of(__str, __pos, traits_type::length(__str)); }
361
362 constexpr size_type
363 find_last_of(basic_string_view __str,
364 size_type __pos = npos) const noexcept
365 { return this->find_last_of(__str._M_str, __pos, __str._M_len); }
366
367 constexpr size_type
368 find_last_of(_CharT __c, size_type __pos=npos) const noexcept
369 { return this->rfind(__c, __pos); }
370
371 constexpr size_type
372 find_last_of(const _CharT* __str, size_type __pos, size_type __n) const;
373
374 constexpr size_type
375 find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept
376 { return this->find_last_of(__str, __pos, traits_type::length(__str)); }
377
378 constexpr size_type
379 find_first_not_of(basic_string_view __str,
380 size_type __pos = 0) const noexcept
381 { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); }
382
383 constexpr size_type
384 find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept;
385
386 constexpr size_type
387 find_first_not_of(const _CharT* __str,
388 size_type __pos, size_type __n) const;
389
390 constexpr size_type
391 find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept
392 {
393 return this->find_first_not_of(__str, __pos,
394 traits_type::length(__str));
395 }
396
397 constexpr size_type
398 find_last_not_of(basic_string_view __str,
399 size_type __pos = npos) const noexcept
400 { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); }
401
402 constexpr size_type
403 find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept;
404
405 constexpr size_type
406 find_last_not_of(const _CharT* __str,
407 size_type __pos, size_type __n) const;
408
409 constexpr size_type
410 find_last_not_of(const _CharT* __str,
411 size_type __pos = npos) const noexcept
412 {
413 return this->find_last_not_of(__str, __pos,
414 traits_type::length(__str));
415 }
416
417 private:
418
419 static constexpr int
420 _S_compare(size_type __n1, size_type __n2) noexcept
421 {
422 return difference_type(__n1 - __n2) > std::numeric_limits<int>::max()
423 ? std::numeric_limits<int>::max()
424 : difference_type(__n1 - __n2) < std::numeric_limits<int>::min()
425 ? std::numeric_limits<int>::min()
426 : static_cast<int>(difference_type(__n1 - __n2));
427 }
428
429 size_t _M_len;
430 const _CharT* _M_str;
431 };
432
433 // [string.view.comparison], non-member basic_string_view comparison functions
434
435 namespace __detail
436 {
437 // Identity transform to create a non-deduced context, so that only one
438 // argument participates in template argument deduction and the other
439 // argument gets implicitly converted to the deduced type. See n3766.html.
440 template<typename _Tp>
441 using __idt = common_type_t<_Tp>;
442 }
443
444 template<typename _CharT, typename _Traits>
445 constexpr bool
446 operator==(basic_string_view<_CharT, _Traits> __x,
447 basic_string_view<_CharT, _Traits> __y) noexcept
448 { return __x.size() == __y.size() && __x.compare(__y) == 0; }
449
450 template<typename _CharT, typename _Traits>
451 constexpr bool
452 operator==(basic_string_view<_CharT, _Traits> __x,
453 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
454 { return __x.size() == __y.size() && __x.compare(__y) == 0; }
455
456 template<typename _CharT, typename _Traits>
457 constexpr bool
458 operator==(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
459 basic_string_view<_CharT, _Traits> __y) noexcept
460 { return __x.size() == __y.size() && __x.compare(__y) == 0; }
461
462 template<typename _CharT, typename _Traits>
463 constexpr bool
464 operator!=(basic_string_view<_CharT, _Traits> __x,
465 basic_string_view<_CharT, _Traits> __y) noexcept
466 { return !(__x == __y); }
467
468 template<typename _CharT, typename _Traits>
469 constexpr bool
470 operator!=(basic_string_view<_CharT, _Traits> __x,
471 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
472 { return !(__x == __y); }
473
474 template<typename _CharT, typename _Traits>
475 constexpr bool
476 operator!=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
477 basic_string_view<_CharT, _Traits> __y) noexcept
478 { return !(__x == __y); }
479
480 template<typename _CharT, typename _Traits>
481 constexpr bool
482 operator< (basic_string_view<_CharT, _Traits> __x,
483 basic_string_view<_CharT, _Traits> __y) noexcept
484 { return __x.compare(__y) < 0; }
485
486 template<typename _CharT, typename _Traits>
487 constexpr bool
488 operator< (basic_string_view<_CharT, _Traits> __x,
489 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
490 { return __x.compare(__y) < 0; }
491
492 template<typename _CharT, typename _Traits>
493 constexpr bool
494 operator< (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
495 basic_string_view<_CharT, _Traits> __y) noexcept
496 { return __x.compare(__y) < 0; }
497
498 template<typename _CharT, typename _Traits>
499 constexpr bool
500 operator> (basic_string_view<_CharT, _Traits> __x,
501 basic_string_view<_CharT, _Traits> __y) noexcept
502 { return __x.compare(__y) > 0; }
503
504 template<typename _CharT, typename _Traits>
505 constexpr bool
506 operator> (basic_string_view<_CharT, _Traits> __x,
507 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
508 { return __x.compare(__y) > 0; }
509
510 template<typename _CharT, typename _Traits>
511 constexpr bool
512 operator> (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
513 basic_string_view<_CharT, _Traits> __y) noexcept
514 { return __x.compare(__y) > 0; }
515
516 template<typename _CharT, typename _Traits>
517 constexpr bool
518 operator<=(basic_string_view<_CharT, _Traits> __x,
519 basic_string_view<_CharT, _Traits> __y) noexcept
520 { return __x.compare(__y) <= 0; }
521
522 template<typename _CharT, typename _Traits>
523 constexpr bool
524 operator<=(basic_string_view<_CharT, _Traits> __x,
525 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
526 { return __x.compare(__y) <= 0; }
527
528 template<typename _CharT, typename _Traits>
529 constexpr bool
530 operator<=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
531 basic_string_view<_CharT, _Traits> __y) noexcept
532 { return __x.compare(__y) <= 0; }
533
534 template<typename _CharT, typename _Traits>
535 constexpr bool
536 operator>=(basic_string_view<_CharT, _Traits> __x,
537 basic_string_view<_CharT, _Traits> __y) noexcept
538 { return __x.compare(__y) >= 0; }
539
540 template<typename _CharT, typename _Traits>
541 constexpr bool
542 operator>=(basic_string_view<_CharT, _Traits> __x,
543 __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
544 { return __x.compare(__y) >= 0; }
545
546 template<typename _CharT, typename _Traits>
547 constexpr bool
548 operator>=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
549 basic_string_view<_CharT, _Traits> __y) noexcept
550 { return __x.compare(__y) >= 0; }
551
552 // [string.view.io], Inserters and extractors
553 template<typename _CharT, typename _Traits>
554 inline basic_ostream<_CharT, _Traits>&
555 operator<<(basic_ostream<_CharT, _Traits>& __os,
556 basic_string_view<_CharT,_Traits> __str)
557 { return __ostream_insert(__os, __str.data(), __str.size()); }
558
559
560 // basic_string_view typedef names
561
562 using string_view = basic_string_view<char>;
563#ifdef _GLIBCXX_USE_WCHAR_T
564 using wstring_view = basic_string_view<wchar_t>;
565#endif
566#ifdef _GLIBCXX_USE_CHAR8_T
567 using u8string_view = basic_string_view<char8_t>;
568#endif
569 using u16string_view = basic_string_view<char16_t>;
570 using u32string_view = basic_string_view<char32_t>;
571} // namespace fundamentals_v1
572} // namespace experimental
573
574
575 // [string.view.hash], hash support:
576 template<typename _Tp>
577 struct hash;
578
579 template<>
580 struct hash<experimental::string_view>
581 : public __hash_base<size_t, experimental::string_view>
582 {
583 size_t
584 operator()(const experimental::string_view& __str) const noexcept
585 { return std::_Hash_impl::hash(__str.data(), __str.length()); }
586 };
587
588 template<>
589 struct __is_fast_hash<hash<experimental::string_view>> : std::false_type
590 { };
591
592#ifdef _GLIBCXX_USE_WCHAR_T
593 template<>
594 struct hash<experimental::wstring_view>
595 : public __hash_base<size_t, wstring>
596 {
597 size_t
598 operator()(const experimental::wstring_view& __s) const noexcept
599 { return std::_Hash_impl::hash(__s.data(),
600 __s.length() * sizeof(wchar_t)); }
601 };
602
603 template<>
604 struct __is_fast_hash<hash<experimental::wstring_view>> : std::false_type
605 { };
606#endif
607
608#ifdef _GLIBCXX_USE_CHAR8_T
609 template<>
610 struct hash<experimental::u8string_view>
611 : public __hash_base<size_t, experimental::u8string_view>
612 {
613 size_t
614 operator()(const experimental::u8string_view& __s) const noexcept
615 { return std::_Hash_impl::hash(__s.data(), __s.length()); }
616 };
617
618 template<>
619 struct __is_fast_hash<hash<experimental::u8string_view>> : std::false_type
620 { };
621#endif
622
623 template<>
624 struct hash<experimental::u16string_view>
625 : public __hash_base<size_t, experimental::u16string_view>
626 {
627 size_t
628 operator()(const experimental::u16string_view& __s) const noexcept
629 { return std::_Hash_impl::hash(__s.data(),
630 __s.length() * sizeof(char16_t)); }
631 };
632
633 template<>
634 struct __is_fast_hash<hash<experimental::u16string_view>> : std::false_type
635 { };
636
637 template<>
638 struct hash<experimental::u32string_view>
639 : public __hash_base<size_t, experimental::u32string_view>
640 {
641 size_t
642 operator()(const experimental::u32string_view& __s) const noexcept
643 { return std::_Hash_impl::hash(__s.data(),
644 __s.length() * sizeof(char32_t)); }
645 };
646
647 template<>
648 struct __is_fast_hash<hash<experimental::u32string_view>> : std::false_type
649 { };
650
651namespace experimental
652{
653 // I added these EMSR.
654 inline namespace literals
655 {
656 inline namespace string_view_literals
657 {
658#pragma GCC diagnostic push
659#pragma GCC diagnostic ignored "-Wliteral-suffix"
660 inline constexpr basic_string_view<char>
661 operator""sv(const char* __str, size_t __len) noexcept
662 { return basic_string_view<char>{__str, __len}; }
663
664#ifdef _GLIBCXX_USE_WCHAR_T
665 inline constexpr basic_string_view<wchar_t>
666 operator""sv(const wchar_t* __str, size_t __len) noexcept
667 { return basic_string_view<wchar_t>{__str, __len}; }
668#endif
669
670#ifdef _GLIBCXX_USE_CHAR8_T
671 inline constexpr basic_string_view<char8_t>
672 operator""sv(const char8_t* __str, size_t __len) noexcept
673 { return basic_string_view<char8_t>{__str, __len}; }
674#endif
675
676 inline constexpr basic_string_view<char16_t>
677 operator""sv(const char16_t* __str, size_t __len) noexcept
678 { return basic_string_view<char16_t>{__str, __len}; }
679
680 inline constexpr basic_string_view<char32_t>
681 operator""sv(const char32_t* __str, size_t __len) noexcept
682 { return basic_string_view<char32_t>{__str, __len}; }
683#pragma GCC diagnostic pop
684 } // namespace string_literals
685 } // namespace literals
686} // namespace experimental
687
688_GLIBCXX_END_NAMESPACE_VERSION
689} // namespace std
690
691#include <experimental/bits/string_view.tcc>
692
693#endif // __cplusplus <= 201103L
694
695#endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW