24 #ifndef GUL14_STRING_VIEW_H_
25 #define GUL14_STRING_VIEW_H_
48 template <
typename charT,
typename traits>
49 class string_view_traits_eq {
51 string_view_traits_eq ( charT ch ) : ch_(ch) {}
52 bool operator()( charT val )
const {
return traits::eq (ch_, val); }
59 template <
typename charT,
typename BaseT = std::
char_traits<
charT>>
60 struct char_traits :
public BaseT
62 using char_type =
typename BaseT::char_type;
63 using int_type =
typename BaseT::int_type;
64 using pos_type =
typename BaseT::pos_type;
65 using off_type =
typename BaseT::off_type;
66 using state_type =
typename BaseT::state_type;
68 using base_traits = BaseT;
73 static constexpr
void assign(char_type& c1,
const char_type& c2) noexcept
78 static constexpr
int compare(
const char_type* s1,
const char_type* s2,
size_t n) noexcept
80 for (;n > 0; --n, ++s1, ++s2) {
83 else if (lt(*s2, *s1))
89 static constexpr
size_t length(
const char_type* s) noexcept
91 auto len = std::size_t{ };
92 while (!eq(s[len], char_type{ }))
97 static constexpr
const char_type* find(
const char_type* s, std::size_t n,
const char_type& a) noexcept
99 for (;n > 0; --n, ++s) {
113 template<
typename charT,
typename traits = gul14::
char_traits<
charT>>
117 typedef traits traits_type;
118 typedef charT value_type;
119 typedef charT* pointer;
120 typedef const charT* const_pointer;
121 typedef charT& reference;
122 typedef const charT& const_reference;
123 typedef const_pointer const_iterator;
124 typedef const_iterator iterator;
125 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
126 typedef const_reverse_iterator reverse_iterator;
127 typedef std::size_t size_type;
128 typedef std::ptrdiff_t difference_type;
129 static constexpr size_type npos = size_type(-1);
133 : ptr_(NULL), len_(0) {}
141 template<
typename Allocator,
typename Traits>
143 Allocator>& str) noexcept
144 : ptr_(str.data()), len_(str.length()) {}
147 : ptr_(str), len_(traits::length(str)) {}
150 : ptr_(str), len_(len) {}
153 constexpr const_iterator begin()
const noexcept {
return ptr_; }
154 constexpr const_iterator cbegin()
const noexcept {
return ptr_; }
155 constexpr const_iterator end()
const noexcept {
return ptr_ + len_; }
156 constexpr const_iterator cend()
const noexcept {
return ptr_ + len_; }
157 const_reverse_iterator rbegin()
const noexcept {
return const_reverse_iterator(end()); }
158 const_reverse_iterator crbegin()
const noexcept {
return const_reverse_iterator(end()); }
159 const_reverse_iterator rend()
const noexcept {
return const_reverse_iterator(begin()); }
160 const_reverse_iterator crend()
const noexcept {
return const_reverse_iterator(begin()); }
163 constexpr size_type size()
const noexcept {
return len_; }
164 constexpr size_type length()
const noexcept {
return len_; }
165 constexpr size_type max_size()
const noexcept {
return len_; }
166 constexpr
bool empty()
const noexcept {
return len_ == 0; }
169 constexpr const_reference operator[](size_type pos)
const noexcept {
return ptr_[pos]; }
171 constexpr const_reference at(size_type pos)
const {
172 return pos >= len_ ?
throw std::out_of_range(
"gul14::string_view::at") : ptr_[pos];
175 constexpr const_reference front()
const {
return ptr_[0]; }
176 constexpr const_reference back()
const {
return ptr_[len_-1]; }
177 constexpr const_pointer data()
const noexcept {
return ptr_; }
180 constexpr
void remove_prefix(size_type n) {
187 constexpr
void remove_suffix(size_type n) {
199 template<
typename Allocator>
200 explicit operator std::basic_string<charT, typename traits::base_traits, Allocator>()
const {
201 return std::basic_string<charT, typename traits::base_traits, Allocator>(begin(), end());
204 size_type copy(charT* s, size_type n, size_type pos=0)
const {
206 throw std::out_of_range(
"string_view::copy" );
207 size_type rlen = (std::min)(n, len_ - pos);
210 std::copy(begin() + pos, begin() + pos + rlen, s);
216 throw std::out_of_range (
"string_view::substr" );
217 if (n == npos || pos + n > size())
223 const int cmp = traits::compare(ptr_, x.ptr_, (std::min)(len_, x.len_));
224 return cmp != 0 ? cmp : (len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1);
229 return substr(pos1, n1).compare(x);
232 constexpr
int compare(size_type pos1, size_type n1,
234 return substr(pos1, n1).compare(x.substr(pos2, n2));
237 constexpr
int compare(
const charT* x)
const {
241 constexpr
int compare(size_type pos1, size_type n1,
const charT* x)
const {
245 constexpr
int compare(size_type pos1, size_type n1,
246 const charT* x, size_type n2)
const {
251 constexpr size_type find(
basic_string_view s, size_type pos = 0)
const noexcept {
258 auto const end = len_ - s.len_;
259 for (
auto cur = pos; cur <= end; ++cur) {
260 if (traits::compare(ptr_ + cur, s.ptr_, s.len_) == 0)
265 constexpr size_type find(charT c, size_type pos = 0)
const noexcept
267 constexpr size_type find(
const charT* s, size_type pos, size_type n)
const noexcept
269 constexpr size_type find(
const charT* s, size_type pos = 0)
const noexcept
273 constexpr size_type rfind(
basic_string_view s, size_type pos = npos)
const noexcept {
276 if (pos > len_ - s.len_)
280 for (
const charT* cur = ptr_ + pos; ; --cur) {
281 if (traits::compare(cur, s.ptr_, s.len_) == 0)
287 constexpr size_type rfind(charT c, size_type pos = npos)
const noexcept
289 constexpr size_type rfind(
const charT* s, size_type pos, size_type n)
const noexcept
291 constexpr size_type rfind(
const charT* s, size_type pos = npos)
const noexcept
295 constexpr size_type find_first_of(
basic_string_view s, size_type pos = 0)
const noexcept {
296 if (pos >= len_ || s.len_ == 0)
298 const_iterator iter = std::find_first_of
299 (this->cbegin () + pos, this->cend (), s.cbegin (), s.cend (), traits::eq);
300 return iter == this->cend () ? npos :
static_cast< size_type
>(std::distance ( this->cbegin (), iter ));
302 constexpr size_type find_first_of(charT c, size_type pos = 0)
const noexcept
304 constexpr size_type find_first_of(
const charT* s, size_type pos, size_type n)
const noexcept
306 constexpr size_type find_first_of(
const charT* s, size_type pos = 0)
const noexcept
310 constexpr size_type find_last_of(
basic_string_view s, size_type pos = npos)
const noexcept {
316 pos = len_ - (pos+1);
317 const_reverse_iterator iter = std::find_first_of
318 ( this->crbegin () + pos, this->crend (), s.cbegin (), s.cend (), traits::eq );
319 return iter == this->crend () ? npos : ( len_ - 1 -
static_cast< size_type
>(std::distance( this->crbegin (), iter )) );
321 constexpr size_type find_last_of(charT c, size_type pos = npos)
const noexcept
323 constexpr size_type find_last_of(
const charT* s, size_type pos, size_type n)
const noexcept
325 constexpr size_type find_last_of(
const charT* s, size_type pos = npos)
const noexcept
329 constexpr size_type find_first_not_of(
basic_string_view s, size_type pos = 0)
const noexcept {
334 const_iterator iter = find_not_of ( this->cbegin () + pos, this->cend (), s );
335 return iter == this->cend () ? npos :
static_cast< size_type
>(std::distance ( this->cbegin (), iter ));
337 constexpr size_type find_first_not_of(charT c, size_type pos = 0)
const noexcept
339 constexpr size_type find_first_not_of(
const charT* s, size_type pos, size_type n)
const noexcept
341 constexpr size_type find_first_not_of(
const charT* s, size_type pos = 0)
const noexcept
345 constexpr size_type find_last_not_of(
basic_string_view s, size_type pos = npos)
const noexcept {
350 pos = len_ - (pos+1);
351 const_reverse_iterator iter = find_not_of ( this->crbegin () +
static_cast< difference_type
>(pos), this->crend (), s );
352 return iter == this->crend () ? npos : ( len_ - 1 -
static_cast< size_type
>(std::distance( this->crbegin (), iter )) );
354 constexpr size_type find_last_not_of(charT c, size_type pos = npos)
const noexcept
356 constexpr size_type find_last_not_of(
const charT* s, size_type pos, size_type n)
const noexcept
358 constexpr size_type find_last_not_of(
const charT* s, size_type pos = npos)
const noexcept
362 template <
typename Iterator>
363 Iterator find_not_of(Iterator first, Iterator last,
basic_string_view s)
const noexcept {
364 for (; first != last ; ++first)
365 if ( 0 == traits::find(s.ptr_, s.len_, *first))
378 template<
typename charT,
typename traits>
381 if (x.size () != y.size ())
return false;
382 return x.compare(y) == 0;
386 template<
typename charT,
typename traits>
387 inline bool operator!=(basic_string_view<charT, traits> x,
388 basic_string_view<charT, traits> y) noexcept {
389 if ( x.size () != y.size ())
return true;
390 return x.compare(y) != 0;
394 template<
typename charT,
typename traits>
395 inline bool operator<(basic_string_view<charT, traits> x,
396 basic_string_view<charT, traits> y) noexcept {
397 return x.compare(y) < 0;
401 template<
typename charT,
typename traits>
402 inline bool operator>(basic_string_view<charT, traits> x,
403 basic_string_view<charT, traits> y) noexcept {
404 return x.compare(y) > 0;
408 template<
typename charT,
typename traits>
409 inline bool operator<=(basic_string_view<charT, traits> x,
410 basic_string_view<charT, traits> y) noexcept {
411 return x.compare(y) <= 0;
415 template<
typename charT,
typename traits>
416 inline bool operator>=(basic_string_view<charT, traits> x,
417 basic_string_view<charT, traits> y) noexcept {
418 return x.compare(y) >= 0;
422 template<
typename charT,
typename traits,
typename Allocator>
423 inline bool operator==(basic_string_view<charT, traits> x,
424 const std::basic_string<charT,
typename char_traits<charT>::base_traits, Allocator> & y) noexcept {
425 return x == basic_string_view<charT, traits>(y);
428 template<
typename charT,
typename traits,
typename Allocator>
429 inline bool operator==(
const std::basic_string<charT,
typename char_traits<charT>::base_traits, Allocator> & x,
430 basic_string_view<charT, traits> y) noexcept {
431 return basic_string_view<charT, traits>(x) == y;
434 template<
typename charT,
typename traits>
435 inline bool operator==(basic_string_view<charT, traits> x,
436 const charT * y) noexcept {
437 return x == basic_string_view<charT, traits>(y);
440 template<
typename charT,
typename traits>
441 inline bool operator==(
const charT * x,
442 basic_string_view<charT, traits> y) noexcept {
443 return basic_string_view<charT, traits>(x) == y;
446 template<
typename charT,
typename traits,
typename Allocator>
447 inline bool operator!=(basic_string_view<charT, traits> x,
448 const std::basic_string<charT,
typename char_traits<charT>::base_traits, Allocator> & y) noexcept {
449 return x != basic_string_view<charT, traits>(y);
452 template<
typename charT,
typename traits,
typename Allocator>
453 inline bool operator!=(
const std::basic_string<charT,
typename char_traits<charT>::base_traits, Allocator> & x,
454 basic_string_view<charT, traits> y) noexcept {
455 return basic_string_view<charT, traits>(x) != y;
458 template<
typename charT,
typename traits>
459 inline bool operator!=(basic_string_view<charT, traits> x,
460 const charT * y) noexcept {
461 return x != basic_string_view<charT, traits>(y);
464 template<
typename charT,
typename traits>
465 inline bool operator!=(
const charT * x,
466 basic_string_view<charT, traits> y) noexcept {
467 return basic_string_view<charT, traits>(x) != y;
470 template<
typename charT,
typename traits,
typename Allocator>
471 inline bool operator<(basic_string_view<charT, traits> x,
472 const std::basic_string<charT,
typename char_traits<charT>::base_traits, Allocator> & y) noexcept {
473 return x < basic_string_view<charT, traits>(y);
476 template<
typename charT,
typename traits,
typename Allocator>
477 inline bool operator<(
const std::basic_string<charT,
typename char_traits<charT>::base_traits, Allocator> & x,
478 basic_string_view<charT, traits> y) noexcept {
479 return basic_string_view<charT, traits>(x) < y;
482 template<
typename charT,
typename traits>
483 inline bool operator<(basic_string_view<charT, traits> x,
484 const charT * y) noexcept {
485 return x < basic_string_view<charT, traits>(y);
488 template<
typename charT,
typename traits>
489 inline bool operator<(
const charT * x,
490 basic_string_view<charT, traits> y) noexcept {
491 return basic_string_view<charT, traits>(x) < y;
494 template<
typename charT,
typename traits,
typename Allocator>
495 inline bool operator>(basic_string_view<charT, traits> x,
496 const std::basic_string<charT,
typename char_traits<charT>::base_traits, Allocator> & y) noexcept {
497 return x > basic_string_view<charT, traits>(y);
500 template<
typename charT,
typename traits,
typename Allocator>
501 inline bool operator>(
const std::basic_string<charT,
typename char_traits<charT>::base_traits, Allocator> & x,
502 basic_string_view<charT, traits> y) noexcept {
503 return basic_string_view<charT, traits>(x) > y;
506 template<
typename charT,
typename traits>
507 inline bool operator>(basic_string_view<charT, traits> x,
508 const charT * y) noexcept {
509 return x > basic_string_view<charT, traits>(y);
512 template<
typename charT,
typename traits>
513 inline bool operator>(
const charT * x,
514 basic_string_view<charT, traits> y) noexcept {
515 return basic_string_view<charT, traits>(x) > y;
518 template<
typename charT,
typename traits,
typename Allocator>
519 inline bool operator<=(basic_string_view<charT, traits> x,
520 const std::basic_string<charT,
typename char_traits<charT>::base_traits, Allocator> & y) noexcept {
521 return x <= basic_string_view<charT, traits>(y);
524 template<
typename charT,
typename traits,
typename Allocator>
525 inline bool operator<=(
const std::basic_string<charT,
typename char_traits<charT>::base_traits, Allocator> & x,
526 basic_string_view<charT, traits> y) noexcept {
527 return basic_string_view<charT, traits>(x) <= y;
530 template<
typename charT,
typename traits>
531 inline bool operator<=(basic_string_view<charT, traits> x,
532 const charT * y) noexcept {
533 return x <= basic_string_view<charT, traits>(y);
536 template<
typename charT,
typename traits>
537 inline bool operator<=(
const charT * x,
538 basic_string_view<charT, traits> y) noexcept {
539 return basic_string_view<charT, traits>(x) <= y;
542 template<
typename charT,
typename traits,
typename Allocator>
543 inline bool operator>=(basic_string_view<charT, traits> x,
544 const std::basic_string<charT,
typename char_traits<charT>::base_traits, Allocator> & y) noexcept {
545 return x >= basic_string_view<charT, traits>(y);
548 template<
typename charT,
typename traits,
typename Allocator>
549 inline bool operator>=(
const std::basic_string<charT,
typename char_traits<charT>::base_traits, Allocator> & x,
550 basic_string_view<charT, traits> y) noexcept {
551 return basic_string_view<charT, traits>(x) >= y;
554 template<
typename charT,
typename traits>
555 inline bool operator>=(basic_string_view<charT, traits> x,
556 const charT * y) noexcept {
557 return x >= basic_string_view<charT, traits>(y);
560 template<
typename charT,
typename traits>
561 inline bool operator>=(
const charT * x,
562 basic_string_view<charT, traits> y) noexcept {
563 return basic_string_view<charT, traits>(x) >= y;
568 template<
class charT,
class traits>
569 inline void sv_insert_fill_chars(std::basic_ostream<charT, traits>& os, std::size_t n) {
570 enum { chunk_size = 8 };
571 charT fill_chars[chunk_size];
572 std::fill_n(fill_chars,
static_cast< std::size_t
>(chunk_size), os.fill());
573 for (; n >= chunk_size && os.good(); n -= chunk_size)
574 os.write(fill_chars,
static_cast< std::size_t
>(chunk_size));
575 if (n > 0 && os.good())
576 os.write(fill_chars, n);
579 template<
class charT,
class traits>
580 void sv_insert_aligned(std::basic_ostream<charT,
typename char_traits<charT>::base_traits>& os,
const basic_string_view<charT,traits>& str) {
581 const std::size_t size = str.size();
582 const std::size_t alignment_size =
static_cast< std::size_t
>(os.width()) - size;
583 const bool align_left = (os.flags() & std::basic_ostream<charT, typename char_traits<charT>::base_traits>::adjustfield)
584 == std::basic_ostream<charT,
typename char_traits<charT>::base_traits>::left;
586 detail::sv_insert_fill_chars(os, alignment_size);
588 os.write(str.data(), size);
591 os.write(str.data(), size);
593 detail::sv_insert_fill_chars(os, alignment_size);
600 template<
class charT,
class traits>
601 inline std::basic_ostream<charT, typename char_traits<charT>::base_traits>&
602 operator<<(std::basic_ostream<charT,
typename char_traits<charT>::base_traits>& os,
603 const basic_string_view<charT,traits>& str) {
605 const std::size_t size = str.size();
606 const std::size_t w =
static_cast< std::size_t
>(os.width());
608 os.write(str.data(), size);
610 detail::sv_insert_aligned(os, str);
653 inline std::string &operator+=(std::string &a,
string_view b)
655 a.append(b.begin(), b.end());
659 inline std::string operator+(std::string a,
string_view b)
665 inline std::string operator+(
string_view a, std::string b)
667 b.insert(b.begin(), a.begin(), a.end());
A view to a contiguous sequence of chars or char-like objects.
Definition: string_view.h:114
void swap(SmallVector< ElementT, in_capacity > &a, SmallVector< ElementT, in_capacity > &b)
Exchange the contents of one SmallVector with those of another one.
Definition: SmallVector.h:1656
basic_string_view< char > string_view
A view to a contiguous sequence of chars.
Definition: string_view.h:624
Definition of macros used internally by GUL.
Namespace gul14 contains all functions and classes of the General Utility Library.
Definition: doxygen.h:26