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