YSTest: string.hpp 源文件

YSTest PreAlpha_b900_20201012 The YSLib Test Project

string.hpp
浏览该文件的文档.
1 /*
2 © 2012-2020 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
28 #ifndef YB_INC_ystdex_string_hpp_
29 #define YB_INC_ystdex_string_hpp_ 1
30
31 #include "allocator.hpp" // for allocator_traits, enable_if_t, remove_cvref_t,
32 // false_, is_object, decay_t, std::declval, true_, nested_allocator, or_,
33 // is_same, is_enum, yconstraint, is_class, yassume, YAssert;
34 #include "string_view.hpp" // for internal "string_view.hpp" (implying
35 // "range.hpp" and "<libdefect/string.h>"), basic_string_view,
36 // std::char_traits, std::initializer_list, std::to_string, string,
37 // basic_string, ntctslen;
38 #include "container.hpp" // for "container.hpp", enable_for_input_iterator_t,
39 // make_index_sequence, index_sequence, begin, end, size, sort_unique,
40 // underlying, std::hash;
41 #include "cstdio.h" // for vfmtlen, ystdex::is_null;
42 #include "array.hpp" // for std::bidirectional_iterator_tag, to_array;
43 #include <istream> // for std::basic_istream;
44 #include "ios.hpp" // for rethrow_badstate;
45 #include <ostream> // for std::basic_ostream;
46 #include <sstream> // for std::ostringstream, std::wostring_stream;
47 #include <cstdarg> // for std::va_list;
48
49 namespace ystdex
50 {
51
53
54 inline namespace cpp2017
55 {
56
57 // XXX: Although adopted features from LWG issues have some concerns on
58 // compatibility, there is already feature testing macro for the major feature,
59 // i.e. WG21 P0254R2 (see WG21 P0941R2).
60 #if __cpp_lib_string_view >= 201606L || __cplusplus >= 201606L
61 # define YB_Impl_String_has_P0254R2 true
62 #endif
63
64 #if YB_Impl_String_has_P0254R2
65 using std::basic_string;
66 #else
67
74 template<typename _tChar, class _tTraits = std::char_traits<_tChar>,
75 class _tAlloc = std::allocator<_tChar>>
76 class basic_string : yimpl(public) std::basic_string<_tChar, _tTraits, _tAlloc>
77 {
78 private:
79 using base = std::basic_string<_tChar, _tTraits, _tAlloc>;
81 using ator_traits = allocator_traits<_tAlloc>;
82 template<typename _tTrait>
83 using equal_alloc_or = or_<_tTrait, typename ator_traits::is_always_equal>;
84 using equal_alloc_or_pocma = equal_alloc_or<typename
85 ator_traits::propagate_on_container_move_assignment>;
86 using sv_type = basic_string_view<_tChar, _tTraits>;
87 template<class _type, class _tRes = void>
88 // XXX: Ready for LWG 2946, which is not adopted here yet as it is not in
89 // ISO C++17.
90 using enable_if_sv_t = enable_if_t<and_<is_convertible<const _type&,
91 sv_type>, not_<is_convertible<const _type*, const base*>>,
92 not_<is_convertible<const _type&, const _tChar*>>>::value, _tRes>;
93
94 public:
95 using size_type = typename base::size_type;
96 using iterator = typename base::iterator;
97 using const_iterator = typename base::const_iterator;
98
99 static yconstexpr const auto npos{static_cast< size_type>(-1)};
100
101 // NOTE: All signatures in ISO C++17 different from ISO C++11 are addressed
102 // here explicitly. Note the parameter has %base type which reflects the
103 // original %basic_string type, and the return type %basic_string is this
104 // class.
105
110 basic_string() ynoexcept_spec(_tAlloc())
111 : base()
112 {}
114 explicit
115 basic_string(const _tAlloc& a) ynothrow
116 : base(a)
117 {}
119 basic_string(const base& str, size_type pos, const _tAlloc& a = _tAlloc())
120 : base(str, pos, base::npos, a)
121 {}
122 basic_string(const base& str, size_type pos, size_type n,
123 const _tAlloc& a = _tAlloc())
124 : base(str, pos, n, a)
125 {}
127 template<class _type, yimpl(typename = enable_if_sv_t<_type>)>
128 basic_string(const _type& t, size_type pos, size_type n,
129 const _tAlloc& a = _tAlloc())
130 : basic_string(sv_type(t).substr(pos, n), a)
131 {}
133 explicit
134 basic_string(sv_type sv, const _tAlloc& a = _tAlloc())
135 : basic_string(sv.data(), sv.size(), a)
136 {}
137 // NOTE: See $2018-07 @ %Documentation::Workflow.
138 // XXX: Names would not be safely hidden.
139 #if __cpp_inheriting_constructors >= 201511L
140 using base::base;
141 #else
142
144 YB_NONNULL(2)
145 basic_string(const _tChar* s, size_type n, const _tAlloc& a = _tAlloc())
146 : base(s, n, a)
147 {}
148 YB_NONNULL(2)
149 basic_string(const _tChar* s, const _tAlloc& a = _tAlloc())
150 : base(s, a)
151 {}
152 basic_string(size_type n, _tChar c, const _tAlloc& a = _tAlloc())
153 : base(n, c, a)
154 {}
160 template<typename _tIn, yimpl(typename = enable_for_input_iterator_t<_tIn>)>
161 basic_string(_tIn begin, _tIn end, const _tAlloc& a = _tAlloc())
162 : base(begin, end, a)
163 {}
164 basic_string(std::initializer_list<_tChar> il, const _tAlloc& a = _tAlloc())
165 : base(il, a)
166 {}
167 basic_string(const base& str, const _tAlloc& a)
168 : base(str, a)
169 {}
170 basic_string(base&& str, const _tAlloc& a)
171 : base(std::move(str), a)
172 {}
174 #endif
175 basic_string(const base& str)
176 : base(str)
177 {}
178 basic_string(base&& str)
179 : base(std::move(str))
180 {}
181 basic_string(const basic_string&) = default;
182 basic_string(basic_string&&) ynothrow = default;
183
185 basic_string&
186 operator=(sv_type sv)
187 {
188 return assign(sv);
189 }
190 YB_NONNULL(2) basic_string&
191 operator=(const _tChar* s)
192 {
193 return *this = basic_string(s);
194 }
195 basic_string&
196 operator=(_tChar c)
197 {
198 return *this = basic_string(1, c);
199 }
200 basic_string&
201 operator=(std::initializer_list<_tChar> il)
202 {
203 return *this = basic_string(il);
204 }
205 basic_string&
206 operator=(const base& str)
207 {
208 static_cast< base&>(*this) = str;
209 return *this;
210 }
211 basic_string&
212 operator=(base&& str) ynoexcept(equal_alloc_or_pocma())
213 {
214 static_cast< base&>(*this) = std::move(str);
215 return *this;
216 }
217 basic_string&
218 operator=(const basic_string&) = default;
219 basic_string&
220 operator=(basic_string&&) ynoexcept(equal_alloc_or_pocma()) = default;
221
222 basic_string&
223 operator+=(const base& str)
224 {
225 static_cast< base&>(*this) += str;
226 return *this;
227 }
228 basic_string&
229 operator+=(const basic_string& str)
230 {
231 return *this += static_cast<const base&>(str);
232 }
234 basic_string&
235 operator+=(sv_type sv)
236 {
237 return append(sv);
238 }
239 YB_NONNULL(2) basic_string&
240 operator+=(const _tChar* s)
241 {
242 static_cast< base&>(*this) += s;
243 return *this;
244 }
245 basic_string&
246 operator+=(_tChar c)
247 {
248 static_cast< base&>(*this) += c;
249 return *this;
250 }
251 basic_string&
252 operator+=(std::initializer_list<_tChar> il)
253 {
254 static_cast< base&>(*this) += il;
255 return *this;
256 }
257
259 YB_ATTR_nodiscard YB_PURE
260 operator sv_type() const ynothrow
261 {
262 return sv_type(base::data(), base::size());
263 }
264
265 basic_string&
266 append(const base& str)
267 {
268 base::append(str);
269 return *this;
270 }
272 basic_string&
273 append(const base& str, size_type pos, size_type n = npos)
274 {
275 base::append(str, pos, n);
276 return *this;
277 }
279
280 basic_string&
281 append(sv_type sv)
282 {
283 return append(sv.data(), sv.size());
284 }
286 template<typename _type>
287 yimpl(enable_if_sv_t)<_type, basic_string&>
288 append(const _type& t, size_type pos, size_type n = npos)
289 {
290 sv_type sv = t;
291
292 if(!(pos > sv.size()))
293 {
294 const size_type r(sv.size() - pos);
295
296 return append(sv.data() + pos, n < r ? n : r);
297 }
298 throw std::out_of_range("basic_string::append");
299 }
301 YB_NONNULL(2) basic_string&
302 append(const _tChar* s)
303 {
304 base::append(s);
305 return *this;
306 }
307 YB_NONNULL(2) basic_string&
308 append(const _tChar* s, size_type n)
309 {
310 base::append(s, n);
311 return *this;
312 }
313 basic_string&
314 append(size_type n, _tChar c)
315 {
316 base::append(n, c);
317 return *this;
318 }
325 template<typename _tIn, yimpl(typename = enable_for_input_iterator_t<_tIn>)>
326 basic_string&
327 append(_tIn first, _tIn last)
328 {
329 base::append(base(first, last, base::get_allocator()));
330 return *this;
331 }
332 basic_string&
333 append(std::initializer_list<_tChar> il)
334 {
335 base::append(il);
336 return *this;
337 }
338
340 basic_string&
341 assign(const base& str)
342 {
343 return *this = str;
344 }
345 basic_string&
346 assign(base&& str) ynoexcept(equal_alloc_or_pocma())
347 {
348 return *this = std::move(str);
349 }
351 basic_string&
352 assign(const base& str, size_type pos, size_type n = npos)
353 {
354 base::assign(str, pos, n);
355 return *this;
356 }
358
359 basic_string&
360 assign(sv_type sv)
361 {
362 return assign(sv.data(), sv.size());
363 }
365 template<typename _type>
366 yimpl(enable_if_sv_t)<_type, basic_string&>
367 assign(const _type& t, size_type pos, size_type n = npos)
368 {
369 sv_type sv = t;
370
371 if(!(pos > sv.size()))
372 {
373 const size_type r(sv.size() - pos);
374
375 return assign(sv.data() + pos, n < r ? n : r);
376 }
377 throw std::out_of_range("basic_string::assign");
378 }
380 YB_NONNULL(2) basic_string&
381 assign(const _tChar* s)
382 {
383 base::assign(s);
384 return *this;
385 }
386 YB_NONNULL(2) basic_string&
387 assign(const _tChar* s, size_type n)
388 {
389 base::assign(s, n);
390 return *this;
391 }
392 basic_string&
393 assign(size_type n, _tChar c)
394 {
395 base::assign(n, c);
396 return *this;
397 }
404 template<typename _tIn, yimpl(typename = enable_for_input_iterator_t<_tIn>)>
405 basic_string&
406 assign(_tIn first, _tIn last)
407 {
408 base::assign(base(first, last, base::get_allocator()));
409 return *this;
410 }
411 basic_string&
412 assign(std::initializer_list<_tChar> il)
413 {
414 base::assign(il);
415 return *this;
416 }
417
418 basic_string&
419 insert(size_type pos, const base& str)
420 {
421 base::insert(pos, str);
422 return *this;
423 }
425 basic_string&
426 insert(size_type pos1, const base& str, size_type pos2, size_type n = npos)
427 {
428 base::insert(pos1, str, pos2, n);
429 return *this;
430 }
432
433 basic_string&
434 insert(size_type pos, sv_type sv)
435 {
436 return insert(pos, sv.data(), sv.size());
437 }
439 template<typename _type>
440 yimpl(enable_if_sv_t)<_type, basic_string&>
441 insert(size_type pos1, const _type& t, size_type pos2, size_type n = npos)
442 {
443 sv_type sv = t;
444
445 if(!(pos1 > sv.size() || pos2 > sv.size()))
446 {
447 const size_type r(sv.size() - pos2);
448
449 return insert(pos1, sv.data() + pos2, n < r ? n : r);
450 }
451 throw std::out_of_range("basic_string::insert");
452 }
454 YB_NONNULL(3) basic_string&
455 insert(size_type pos, const _tChar* s)
456 {
457 base::insert(pos, s);
458 return *this;
459 }
460 YB_NONNULL(3) basic_string&
461 insert(size_type pos, const _tChar* s, size_type n)
462 {
463 base::insert(pos, s, n);
464 return *this;
465 }
466 basic_string&
467 insert(size_type pos, size_type n, _tChar c)
468 {
469 base::insert(pos, n, c);
470 return *this;
471 }
472 iterator
473 insert(const_iterator p, _tChar c)
474 {
475 return base::insert(p, c);
476 }
477 iterator
478 insert(const_iterator p, size_type n, _tChar c)
479 {
480 return base::insert(p, n, c);
481 }
488 template<typename _tIn, yimpl(typename = enable_for_input_iterator_t<_tIn>)>
489 iterator
490 insert(const_iterator p, _tIn first, _tIn last)
491 {
492 return base::insert(p - base::begin(),
493 base(first, last, base::get_allocator()));
494 }
495 iterator
496 insert(const_iterator p, std::initializer_list<_tChar> il)
497 {
498 return base::insert(p, il);
499 }
500
501 basic_string&
502 replace(size_type pos1, size_type n1, const base& str)
503 {
504 base::replace(pos1, n1, str);
505 return *this;
506 }
508 basic_string&
509 replace(size_type pos1, size_type n1, const base& str,
510 size_type pos2, size_type n2 = npos)
511 {
512 base::replace(pos1, n1, str, pos2, n2);
513 return *this;
514 }
516
517 basic_string&
518 replace(size_type pos1, size_type n1, sv_type sv)
519 {
520 return replace(pos1, n1, sv.data(), sv.size());
521 }
523 template<typename _type>
524 yimpl(enable_if_sv_t)<_type, basic_string&>
525 replace(size_type pos1, size_type n1, const _type& t, size_type pos2,
526 size_type n2 = npos)
527 {
528 sv_type sv = t;
529
530 if(!(pos1 > sv.size() || pos2 > sv.size()))
531 {
532 const size_type r(sv.size() - pos2);
533
534 return replace(pos1, n1, sv.data() + pos2, n2 < r ? n2 : r);
535 }
536 throw std::out_of_range("basic_string::replace");
537 }
539 YB_NONNULL(4) basic_string&
540 replace(size_type pos, size_type n, const _tChar* s)
541 {
542 base::replace(pos, n, s);
543 return *this;
544 }
545 YB_NONNULL(4) basic_string&
546 replace(size_type pos1, size_type n1, const _tChar* s, size_type n2 = npos)
547 {
548 base::replace(pos1, n1, s, n2);
549 return *this;
550 }
551 basic_string&
552 replace(size_type pos1, size_type n1, size_type n2, _tChar c)
553 {
554 base::replace(pos1, n1, base(n2, c));
555 return *this;
556 }
557 basic_string&
558 replace(const_iterator i1, const_iterator i2, const base& str)
559 {
560 base::replace(i1, i2, str);
561 return *this;
562 }
564 basic_string&
565 replace(const_iterator i1, const_iterator i2, sv_type sv)
566 {
567 return replace(i1 - base::begin(), i2 - i1, sv);
568 }
569 YB_NONNULL(4) basic_string&
570 replace(const_iterator i1, const_iterator i2, const _tChar* s, size_type n)
571 {
572 base::replace(i1, i2, s, n);
573 return *this;
574 }
575 basic_string&
576 replace(const_iterator i1, const_iterator i2, size_type n, _tChar c)
577 {
578 base::replace(i1, i2, n, c);
579 return *this;
580 }
587 template<typename _tIn, yimpl(typename = enable_for_input_iterator_t<_tIn>)>
588 basic_string&
589 replace(const_iterator i1, const_iterator i2, _tIn j1, _tIn j2)
590 {
591 base::replace(i1 - base::begin(), i2 - i1,
592 base(j1, j2, base::get_allocator()));
593 return *this;
594 }
595 basic_string&
596 replace(const_iterator i1, const_iterator i2,
597 std::initializer_list<_tChar> il)
598 {
599 base::replace(i1, i2, il);
600 return *this;
601 }
602
604 YB_ATTR_nodiscard YB_PURE basic_string
605 substr(size_type pos = 0, size_type n = npos) const
606 {
607 return basic_string(base::substr(pos, n));
608 }
609
610 void
611 swap(basic_string& s) ynoexcept(equal_alloc_or<typename
612 ator_traits::propagate_on_container_swap>())
613 {
614 base::swap(s);
615 }
617 friend void
618 swap(basic_string& lhs, basic_string& rhs) ynoexcept_spec(lhs.swap(rhs))
619 {
620 lhs.swap(rhs);
621 }
622
623 // XXX: For simplicity, 'find*' and 'compare' funtions are not reworded as
624 // the standard by dispatching to %basic_string_view overloads. This
625 // simplifies the implementation and speed-up translation time.
626 // TODO: The overloads with noexcept exception (even changed in ISO C++ 14)
627 // are also not explicitly specified here to simplify the evolution because
628 // they are still open to be resolved, e.g. LWG 2836.
629
631 YB_ATTR_nodiscard YB_PURE size_type
632 find(sv_type sv, size_type pos = 0) const ynothrow
633 {
634 return find(sv.data(), sv.size(), pos);
635 }
636 using base::find;
637
639 YB_ATTR_nodiscard YB_PURE size_type
640 rfind(sv_type sv, size_type pos = npos) const ynothrow
641 {
642 return rfind(sv.data(), sv.size(), pos);
643 }
644 using base::rfind;
645
647 YB_ATTR_nodiscard YB_PURE size_type
648 find_first_of(sv_type sv, size_type pos = 0) const ynothrow
649 {
650 return find_first_of(sv.data(), sv.size(), pos);
651 }
652 using base::find_first_of;
653
655 YB_ATTR_nodiscard YB_PURE size_type
656 find_last_of(sv_type sv, size_type pos = npos) const ynothrow
657 {
658 return find_last_of(sv.data(), sv.size(), pos);
659 }
660 using base::find_last_of;
661
663 YB_ATTR_nodiscard YB_PURE size_type
664 find_first_not_of(sv_type sv, size_type pos = 0) const ynothrow
665 {
666 return find_first_not_of(sv.data(), sv.size(), pos);
667 }
668 using base::find_first_not_of;
669
671 YB_ATTR_nodiscard YB_PURE size_type
672 find_last_not_of(sv_type sv, size_type pos = npos) const ynothrow
673 {
674 return find_last_not_of(sv.data(), sv.size(), pos);
675 }
676 using base::find_last_not_of;
677
679
680 YB_ATTR_nodiscard YB_PURE int
681 compare(sv_type sv) const ynothrow
682 {
683 return sv_type(this->data(), this->size()).compare(sv);
684 }
686
687 YB_ATTR_nodiscard YB_PURE int
688 compare(size_type pos1, size_type n1, sv_type sv) const
689 {
690 return sv_type(this->data(), this->size()).substr(pos1, n1).compare(sv);
691 }
693 template<typename _type>
694 YB_ATTR_nodiscard YB_PURE yimpl(enable_if_sv_t)<_type, int>
695 compare(size_type pos1, size_type n1, const _type& t, size_type pos2,
696 size_type n2 = npos) const
697 {
698 sv_type sv = t;
699
700 return sv_type(this->data(), this->size()).substr(pos1, n1)
701 .compare(sv.substr(pos2, n2));
702 }
704
705 using base::compare;
707
708 YB_ATTR_nodiscard YB_PURE friend basic_string
709 operator+(const basic_string& lhs, const basic_string& rhs)
710 {
711 return basic_string(lhs).append(rhs);
712 }
713 YB_ATTR_nodiscard YB_PURE friend basic_string
714 operator+(basic_string&& lhs, const basic_string& rhs)
715 {
716 return std::move(lhs.append(rhs));
717 }
718 YB_ATTR_nodiscard YB_PURE friend basic_string
719 operator+(const basic_string& lhs, basic_string&& rhs)
720 {
721 return std::move(rhs.insert(0, lhs));
722 }
723 YB_ATTR_nodiscard YB_PURE friend basic_string
724 operator+(basic_string&& lhs, basic_string&& rhs)
725 {
726 return std::move(lhs.append(rhs));
727 }
728 YB_ATTR_nodiscard YB_NONNULL(1) YB_PURE friend basic_string
729 operator+(const _tChar* lhs, const basic_string& rhs)
730 {
731 return basic_string(lhs) + rhs;
732 }
733 YB_ATTR_nodiscard YB_NONNULL(1) YB_PURE friend basic_string
734 operator+(const _tChar* lhs, basic_string&& rhs)
735 {
736 return std::move(rhs.insert(0, lhs));
737 }
738 YB_ATTR_nodiscard YB_PURE friend basic_string
739 operator+(_tChar lhs, const basic_string& rhs)
740 {
741 return basic_string(1, lhs) + rhs;
742 }
743 YB_ATTR_nodiscard YB_PURE friend basic_string
744 operator+(_tChar lhs, basic_string&& rhs)
745 {
746 return std::move(rhs.insert(0, 1, lhs));
747 }
748 YB_ATTR_nodiscard YB_PURE YB_NONNULL(2) friend basic_string
749 operator+(const basic_string& lhs, const _tChar* rhs)
750 {
751 return lhs + basic_string(rhs);
752 }
753 YB_NONNULL(2) friend basic_string
754 operator+(basic_string&& lhs, const _tChar* rhs)
755 {
756 return std::move(lhs.append(rhs));
757 }
758 YB_ATTR_nodiscard YB_PURE friend basic_string
759 operator+(const basic_string& lhs, _tChar rhs)
760 {
761 return lhs + basic_string(1, rhs);
762 }
763 YB_ATTR_nodiscard YB_PURE friend basic_string
764 operator+(basic_string&& lhs, _tChar rhs)
765 {
766 return std::move(lhs.append(1, rhs));
767 }
768 };
769 #endif
770
771
772 using string = basic_string<char>;
773 using u16string = basic_string<char16_t>;
774 using u32string = basic_string<char32_t>;
775 using wstring = basic_string<wchar_t>;
776
777 } // inline namesapce cpp2017;
778
779
786 template<typename _tString>
787 struct string_traits
788 {
789 using string_type = remove_cvref_t<_tString>;
790 using value_type = remove_cvref_t<decltype(std::declval<string_type>()[0])>;
791 using traits_type = typename std::char_traits<value_type>;
793
794 using allocator_type = _t<nested_allocator<string_type>>;
795 using size_type = typename allocator_traits<allocator_type>::size_type;
796 using difference_type
797 = typename allocator_traits<allocator_type>::difference_type;
798 using reference = value_type&;
799 using const_reference = const value_type&;
801 using pointer = value_type*;
802 using const_pointer = const value_type*;
803 using initializer = std::initializer_list<value_type>;
804 };
805
806
811 template<class _tString>
812 inline basic_string_view<typename string_traits<_tString>::value_type,
813 typename string_traits<_tString>::traits_type>
814 make_string_view(const _tString& str) ynothrowv
815 {
816 return {str.data(), str.size()};
817 }
818
819
821 namespace details
822 {
823
825
826 template<typename _type, typename = void>
827 struct is_string_like : false_
828 {};
829
830 template<typename _type>
831 struct is_string_like<_type, enable_if_t<
832 is_object<decay_t<decltype(std::declval<_type>()[0])>>::value>> : true_
833 {};
835
836
838 template<typename _tFwd1, typename _tFwd2, typename _fPred>
839 YB_ATTR_nodiscard YB_PURE bool
840 ends_with_iter_dispatch(_tFwd1 b, _tFwd1 e, _tFwd2 bt, _tFwd2 et,
841 _fPred comp, std::bidirectional_iterator_tag)
842 {
843 auto i(e);
844 auto it(et);
845
846 while(i != b && it != bt)
847 if(!comp(*--i, *--it))
848 return {};
849 return it == bt;
850 }
851
852
854
855 template<size_t>
856 struct str_algos;
857
858 template<>
859 struct str_algos<0>
860 {
862 template<class _tString,
863 typename _tSize = typename string_traits<_tString>::size_type>
864 static yconstfn auto
865 erase_left(_tString& s, _tSize n) ynothrowv
866 -> yimpl(decltype(s.remove_prefix(n), s))
867 {
868 return yconstraint(n <= s.size()), s.remove_prefix(n), s;
869 }
870
872 template<class _tString,
873 typename _tSize = typename string_traits<_tString>::size_type>
874 static yconstfn auto
875 erase_right(_tString& s, _tSize n) ynothrowv
876 -> yimpl(decltype(s.remove_suffix(n), s))
877 {
878 return yconstraint(n < s.size()), trim_right_pos(s, n);
879 }
880
882 template<class _tString,
883 typename _tSize = typename string_traits<_tString>::size_type>
884 static yconstfn auto
885 trim_left_pos(_tString& s, _tSize n) ynothrowv
886 -> yimpl(decltype(s.remove_prefix(n), s))
887 {
888 return yconstraint(n < s.size() || n == _tSize(-1)),
889 erase_left(s, n != _tSize(-1) ? n : _tSize(s.size())), s;
890 }
891
893 template<class _tString,
894 typename _tSize = typename string_traits<_tString>::size_type>
895 static yconstfn auto
896 trim_right_pos(_tString& s, _tSize n) ynothrowv
897 -> yimpl(decltype(s.remove_suffix(n), s))
898 {
899 return yconstraint(n < s.size() || n == _tSize(-1)),
900 s.remove_suffix(s.size() - n - 1), s;
901 }
902 };
903
904 template<>
905 struct str_algos<1>
906 {
908 template<class _tString,
909 typename _tSize = typename string_traits<_tString>::size_type>
910 static yconstfn auto
911 erase_left(_tString& s, _tSize n) ynothrowv
912 -> yimpl(decltype(s.erase(0, n)))
913 {
914 return yconstraint(n <= s.size()), s.erase(0, n);
915 }
916
918 template<class _tString,
919 typename _tSize = typename string_traits<_tString>::size_type>
920 static yconstfn auto
921 erase_right(_tString& s, _tSize n) ynothrowv
922 -> yimpl(decltype(s.erase(n + 1)))
923 {
924 return yconstraint(n < s.size()), s.erase(n + 1);
925 }
926
928 template<class _tString,
929 typename _tSize = typename string_traits<_tString>::size_type>
930 static yconstfn auto
931 trim_left_pos(_tString& s, _tSize n) ynothrowv
932 -> yimpl(decltype(s.erase(0, n)))
933 {
934 return yconstraint(n < s.size() || n == _tSize(-1)), s.erase(0, n);
935 }
936
938 template<class _tString,
939 typename _tSize = typename string_traits<_tString>::size_type>
940 static yconstfn auto
941 trim_right_pos(_tString& s, _tSize n) ynothrowv
942 -> yimpl(decltype(s.erase(n + 1)))
943 {
944 return yconstraint(n < s.size() || n == _tSize(-1)), s.erase(n + 1);
945 }
946 };
947
948
949 template<yimpl(typename = make_index_sequence<2>)>
950 struct str_algo;
951
952 template<>
953 struct str_algo<index_sequence<>>
954 {
955 void
956 erase_left() = delete;
957
958 void
959 erase_right() = delete;
960
962 void
963 trim_left_pos() = delete;
964
966 void
967 trim_right_pos() = delete;
968 };
969
970 template<size_t _vIdx, size_t... _vSeq>
971 struct str_algo<index_sequence<_vIdx, _vSeq...>>
972 : str_algos<_vIdx>, str_algo<index_sequence<_vSeq...>>
973 {
974 using str_algos<_vIdx>::erase_left;
975 using str_algo<index_sequence<_vSeq...>>::erase_left;
976 using str_algos<_vIdx>::erase_right;
977 using str_algo<index_sequence<_vSeq...>>::erase_right;
979
980 using str_algos<_vIdx>::trim_left_pos;
981 using str_algo<index_sequence<_vSeq...>>::trim_left_pos;
982 using str_algos<_vIdx>::trim_right_pos;
983 using str_algo<index_sequence<_vSeq...>>::trim_right_pos;
985 };
987
988 } // unnamed namespace;
989
990
992
993
997 template<typename _type>
998 struct is_string_like : details::is_string_like<_type>
999 {};
1000
1005 template<typename _type>
1006 struct is_string_class : and_<is_class<_type>, is_string_like<_type>>
1007 {};
1009
1010
1017 template<typename _tParam, typename _type = void>
1018 using enable_for_string_class_t
1019 = enable_if_t<is_string_class<decay_t<_tParam>>::value, _type>;
1020
1021
1031 template<class _tRange>
1032 YB_ATTR_nodiscard yconstfn auto
1033 string_begin(_tRange& c) -> decltype(c.begin())
1034 {
1035 return ystdex::begin(c);
1036 }
1037 template<class _tRange>
1038 YB_ATTR_nodiscard yconstfn auto
1039 string_begin(const _tRange& c) -> decltype(c.begin())
1040 {
1041 return ystdex::begin(c);
1042 }
1044
1045 template<typename _tChar>
1046 YB_ATTR_nodiscard YB_NONNULL(1) yconstfn _tChar*
1047 string_begin(_tChar* str) ynothrow
1048 {
1049 return yconstraint(str), str;
1050 }
1051 #if __cplusplus <= 201402L
1052 template<typename _tElem>
1054 YB_ATTR_nodiscard yconstfn auto
1055 string_begin(std::initializer_list<_tElem> il) -> decltype(il.begin())
1056 {
1057 return il.begin();
1058 }
1059 #endif
1060
1061
1062 template<class _tRange>
1063 YB_ATTR_nodiscard yconstfn auto
1064 string_end(_tRange& c) -> decltype(c.end())
1065 {
1066 return ystdex::end(c);
1067 }
1068 template<class _tRange>
1069 YB_ATTR_nodiscard yconstfn auto
1070 string_end(const _tRange& c) -> decltype(c.end())
1071 {
1072 return ystdex::end(c);
1073 }
1075
1076 template<typename _tChar>
1077 YB_ATTR_nodiscard YB_NONNULL(1) yconstfn _tChar*
1078 string_end(_tChar* str) ynothrow
1079 {
1080 return str + ystdex::ntctslen(str);
1081 }
1082 #if __cplusplus <= 201402L
1083 template<typename _tElem>
1085 YB_ATTR_nodiscard yconstfn auto
1086 string_end(std::initializer_list<_tElem> il) -> decltype(il.end())
1087 {
1088 return il.end();
1089 }
1090 #endif
1091
1092
1093
1094
1107 template<typename _tChar>
1109 YB_ATTR_nodiscard YB_PURE yconstfn bool
1110 string_empty(const _tChar* str) ynothrowv
1111 {
1112 return ystdex::is_null(*str);
1113 }
1114 template<typename _type>
1115 YB_ATTR_nodiscard YB_PURE yconstfn auto
1116 string_empty(const _type& str) -> decltype(size(str))
1117 {
1118 return empty(str);
1119 }
1120 #if __cplusplus <= 201402L
1121 template<typename _tElem>
1123 YB_ATTR_nodiscard YB_PURE yconstfn size_t
1124 string_empty(std::initializer_list<_tElem> il)
1125 {
1126 return il.empty();
1127 }
1128 #endif
1129
1130
1140 template<typename _tChar>
1141 YB_ATTR_nodiscard YB_PURE inline size_t
1142 string_length(const _tChar* str) ynothrowv
1143 {
1144 return std::char_traits<_tChar>::length(str);
1145 }
1146 template<typename _type>
1147 YB_ATTR_nodiscard YB_PURE yconstfn auto
1148 string_length(const _type& str) -> decltype(size(str))
1149 {
1150 return size(str);
1151 }
1152 #if __cplusplus <= 201402L
1153 template<typename _tElem>
1155 YB_ATTR_nodiscard YB_PURE yconstfn size_t
1156 string_length(std::initializer_list<_tElem> il)
1157 {
1158 return il.size();
1159 }
1160 #endif
1161
1162
1163
1171
1173 template<typename _tRange1, typename _tRange2, typename _fPred>
1175 YB_ATTR_nodiscard YB_PURE bool
1176 begins_with(const _tRange1& input, const _tRange2& test, _fPred comp)
1177 {
1178 return ystdex::string_length(test) <= ystdex::string_length(input)
1179 && std::equal(string_begin(test), string_end(test),
1180 string_begin(input), comp);
1181 }
1183 template<typename _tRange1, typename _tRange2>
1184 YB_ATTR_nodiscard YB_PURE inline bool
1185 begins_with(const _tRange1& input, const _tRange2& test)
1186 {
1187 return ystdex::begins_with(input, test, is_equal());
1188 }
1190
1192
1193 template<typename _tRange1, typename _tRange2, typename _fPred>
1194 YB_ATTR_nodiscard YB_PURE inline bool
1195 ends_with(const _tRange1& input, const _tRange2& test, _fPred comp)
1196 {
1197 // NOTE: See $2014-07 @ %Documentation::Workflow.
1198 return details::ends_with_iter_dispatch(string_begin(input),
1199 string_end(input), string_begin(test), string_end(test), comp, typename
1200 std::iterator_traits<remove_reference_t<decltype(string_begin(input))>>
1201 ::iterator_category());
1202 }
1203 template<typename _tRange1, typename _tRange2>
1204 YB_ATTR_nodiscard YB_PURE inline bool
1205 ends_with(const _tRange1& input, const _tRange2& test)
1206 {
1207 return ystdex::ends_with(input, test, is_equal());
1208 }
1210
1211
1212
1219 template<class _tString, typename _type>
1220 YB_ATTR_nodiscard YB_PURE inline bool
1221 exists_substr(const _tString& str, const _type& sub)
1222 {
1223 return str.find(sub) != _tString::npos;
1224 }
1225 template<class _tString, typename _type>
1226 YB_ATTR_nodiscard inline bool
1227 exists_substr(const _tString& str, const typename _tString::value_type* p_sub)
1228 {
1229 yconstraint(p_sub);
1230
1231 return str.find(p_sub) != _tString::npos;
1232 }
1234
1235
1237
1238
1243 template<class _tString>
1244 auto
1245 normalize(_tString& str) -> decltype(str.resize(ystdex::ntctslen(str.c_str())))
1246 {
1247 return str.resize(ystdex::ntctslen(str.c_str()));
1248 }
1249
1257 template<class _tString,
1259 yimpl(typename = ystdex::enable_for_string_class_t<_tString>)>
1260 inline _tString&&
1261 ntctsncpy(_tString&& str, const typename string_traits<_tString>::const_pointer
1262 s, const typename string_traits<_tString>::size_type n)
1263 {
1264 yconstraint(s);
1265 return static_cast<_tString&&>(str = decay_t<_tString>(s, n));
1266 }
1267 template<class _tString,
1268 yimpl(typename = ystdex::enable_for_string_class_t<_tString>)>
1269 inline _tString&&
1270 ntctsncpy(_tString&& str, _tString&& s,
1271 const typename string_traits<_tString>::size_type n)
1272 {
1273 auto sub(yforward(s));
1274
1275 sub.resize(n);
1276 return static_cast<_tString&&>(str = std::move(sub));
1277 }
1279
1280
1281
1286 template<class _tString>
1287 inline _tString&&
1288 restrict_length(_tString&& str,
1289 const typename string_traits<_tString>::size_type n)
1290 {
1291 if(n < str.length())
1292 str.resize(n);
1293 return static_cast<_tString&&>(str);
1294 }
1295
1296
1301 template<class _tString>
1302 YB_ATTR_nodiscard _tString
1303 alph(_tString& str)
1304 {
1305 _tString res(str);
1306
1307 ystdex::sort_unique(res);
1308 return res;
1309 }
1310
1319 template<class _tString>
1320 void
1321 concat(_tString& str, size_t n)
1322 {
1323 yconstraint(n != 0);
1324 if(1 < n)
1325 {
1326 const auto len(str.length());
1327
1328 ystdex::concat(str, n / 2);
1329 str.append(str.data(), str.length());
1330 if(n % 2 != 0)
1331 str.append(str.data(), len);
1332 }
1333 }
1334
1336
1337
1339
1341 template<class _tString>
1342 inline yimpl(enable_if_t)<is_class<decay_t<_tString>>::value, _tString&&>
1343 erase_left(typename string_traits<_tString>::size_type pos, _tString&& str)
1344 {
1345 return static_cast<_tString&&>(pos != decay_t<_tString>::npos
1346 ? details::str_algo<>::erase_left(str, pos) : str);
1347 }
1348 template<class _tString>
1349 inline yimpl(enable_if_t)<is_class<decay_t<_tString>>::value, _tString&&>
1350 erase_left(_tString&& str, typename string_traits<_tString>::value_type c)
1351 {
1352 return
1353 static_cast<_tString&&>(ystdex::erase_left(str.find_first_of(c), str));
1354 }
1355 template<class _tString>
1356 inline yimpl(enable_if_t)<is_class<decay_t<_tString>>::value, _tString&&>
1357 erase_left(_tString&& str, const remove_reference_t<_tString>& t)
1358 {
1359 return
1360 static_cast<_tString&&>(ystdex::erase_left(str.find_first_of(t), str));
1361 }
1366 template<class _tString>
1367 inline yimpl(enable_if_t)<is_class<decay_t<_tString>>::value, _tString&&>
1368 erase_left(_tString&& str, typename string_traits<_tString>::const_pointer t
1369 = &to_array<typename string_traits<_tString>::value_type>(" \f\n\r\t\v")[0])
1370 {
1371 yconstraint(t);
1372 return
1373 static_cast<_tString&&>(ystdex::erase_left(str.find_first_of(t), str));
1374 }
1376
1378
1379 template<class _tString>
1380 inline yimpl(enable_if_t)<is_class<decay_t<_tString>>::value, _tString&&>
1381 erase_right(typename string_traits<_tString>::size_type pos, _tString&& str)
1382 {
1383 return static_cast<_tString&&>(pos != decay_t<_tString>::npos
1384 ? details::str_algo<>::erase_right(str, pos) : str);
1385 }
1386 template<class _tString>
1387 inline yimpl(enable_if_t)<is_class<decay_t<_tString>>::value, _tString&&>
1388 erase_right(_tString&& str, typename string_traits<_tString>::value_type c)
1389 {
1390 return static_cast<_tString&&>(ystdex::erase_right(str.find_last_of(c),
1391 str));
1392 }
1394 template<class _tString>
1395 inline yimpl(enable_if_t)<is_class<decay_t<_tString>>::value, _tString&&>
1396 erase_right(_tString&& str, const remove_reference_t<_tString>& t)
1397 {
1398 return static_cast<_tString&&>(ystdex::erase_right(str.find_last_of(t),
1399 str));
1400 }
1405 template<class _tString>
1406 inline yimpl(enable_if_t)<is_class<decay_t<_tString>>::value, _tString&&>
1407 erase_right(_tString&& str, typename string_traits<_tString>::const_pointer t
1408 = &to_array<typename string_traits<_tString>::value_type>(" \f\n\r\t\v")[0])
1409 {
1410 yconstraint(t);
1411 return static_cast<_tString&&>(ystdex::erase_right(str.find_last_of(t),
1412 str));
1413 }
1415
1416
1418
1419
1421 template<class _tString>
1422 yconstfn _tString&&
1423 ltrim(_tString&& str, typename string_traits<_tString>::value_type c)
1424 {
1425 return static_cast<_tString&&>(
1426 details::str_algo<>::trim_left_pos(str, str.find_first_not_of(c)));
1427 }
1429 template<class _tString>
1430 inline _tString&&
1431 ltrim(_tString&& str, const _tString& t)
1432 {
1433 return static_cast<_tString&&>(
1434 details::str_algo<>::trim_left_pos(str, str.find_first_not_of(t)));
1435 }
1440 template<class _tString>
1441 yconstfn _tString&&
1442 ltrim(_tString&& str, typename string_traits<_tString>::const_pointer t
1443 = &to_array<typename string_traits<_tString>::value_type>(" \f\n\r\t\v")[0])
1444 {
1445 return yconstraint(t), static_cast<_tString&&>(
1446 details::str_algo<>::trim_left_pos(str, str.find_first_not_of(t)));
1447 }
1449
1451
1452 template<class _tString>
1453 yconstfn _tString&&
1454 rtrim(_tString&& str, typename string_traits<_tString>::value_type c)
1455 {
1456 return static_cast<_tString&&>(
1457 details::str_algo<>::trim_right_pos(str, str.find_last_not_of(c)));
1458 }
1460 template<class _tString>
1461 yconstfn _tString&&
1462 rtrim(_tString&& str, const remove_reference_t<_tString>& t) ynothrowv
1463 {
1464 return static_cast<_tString&&>(
1465 details::str_algo<>::trim_right_pos(str, str.find_last_not_of(t)));
1466 }
1471 template<class _tString>
1472 yconstfn _tString&&
1473 rtrim(_tString&& str, typename string_traits<_tString>::const_pointer t
1474 = &to_array<typename string_traits<_tString>::value_type>(" \f\n\r\t\v")[0])
1475 {
1476 return yconstraint(t), static_cast<_tString&&>(
1477 details::str_algo<>::trim_right_pos(str, str.find_last_not_of(t)));
1478 }
1480
1482
1483 template<class _tString>
1484 yconstfn _tString&&
1485 trim(_tString&& str, typename string_traits<_tString>::value_type c)
1486 {
1487 return
1488 yforward(ystdex::ltrim(yforward(ystdex::rtrim(yforward(str), c)), c));
1489 }
1491 template<class _tString>
1492 yconstfn _tString&&
1493 trim(_tString&& str, const _tString& t) ynothrowv
1494 {
1495 return
1496 yforward(ystdex::ltrim(yforward(ystdex::rtrim(yforward(str), t)), t));
1497 }
1502 template<class _tString>
1503 yconstfn _tString&&
1504 trim(_tString&& str, typename string_traits<_tString>::const_pointer t
1505 = &to_array<typename string_traits<_tString>::value_type>(" \f\n\r\t\v")[0])
1506 {
1507 return yconstraint(t),
1508 yforward(ystdex::ltrim(yforward(ystdex::rtrim(yforward(str), t)), t));
1509 }
1511
1512
1513
1514
1516
1517
1519 template<typename _tString, typename... _tParams>
1520 YB_ATTR_nodiscard inline _tString
1521 find_prefix(const _tString& str, _tParams&&... args)
1522 {
1523 if(!str.empty())
1524 {
1525 const auto pos(str.find(yforward(args)...));
1526
1527 if(pos != _tString::npos)
1528 return str.substr(0, pos);
1529 }
1530 return {};
1531 }
1533
1535
1536 template<typename _tString, typename... _tParams>
1537 YB_ATTR_nodiscard inline _tString
1538 find_suffix(const _tString& str, _tParams&&... args)
1539 {
1540 if(!str.empty())
1541 {
1542 const auto pos(str.rfind(yforward(args)...));
1543
1544 if(pos != _tString::npos)
1545 return str.substr(pos + 1);
1546 }
1547 return {};
1548 }
1550
1551
1562 template<typename _tString>
1563 YB_ATTR_nodiscard YB_PURE yconstfn typename string_traits<_tString>::value_type
1564 get_quote_mark_nonstrict(const _tString& str)
1565 {
1566 return str.front() == str.back() ? str.front()
1567 : typename string_traits<_tString>::value_type();
1568 }
1570
1577 template<typename _tString>
1578 YB_ATTR_nodiscard inline decay_t<_tString>
1579 quote(_tString&& str, typename string_traits<decay_t<_tString>>::value_type c
1580 = typename string_traits<decay_t<_tString>>::value_type('"'))
1581 {
1582 return c + yforward(str) + c;
1583 }
1584 template<typename _tString, typename _tString2>
1585 YB_ATTR_nodiscard inline yimpl(enable_if_t)<!is_convertible<_tString2, typename
1586 string_traits<decay_t<_tString>>::value_type>::value, decay_t<_tString>>
1587 quote(_tString&& str, const _tString2& s)
1588 {
1589 return s + yforward(str) + s;
1590 }
1591 template<typename _tString, typename _tPrefix, typename _tSuffix>
1592 YB_ATTR_nodiscard inline auto
1593 quote(_tString&& str, _tPrefix&& pfx, _tSuffix&& sfx)
1594 -> decltype(yforward(pfx) + yforward(str) + yforward(sfx))
1595 {
1596 return yforward(pfx) + yforward(str) + yforward(sfx);
1597 }
1599
1606 template<typename _tString>
1607 YB_ATTR_nodiscard inline _tString
1608 get_mid(const _tString& str, typename _tString::size_type l = 1)
1609 {
1610 yassume(!(str.size() < l * 2));
1611 return str.substr(l, str.size() - l * 2);
1612 }
1613 template<typename _tString>
1614 YB_ATTR_nodiscard inline _tString
1615 get_mid(const _tString& str, typename _tString::size_type l,
1616 typename _tString::size_type r)
1617 {
1618 yassume(!(str.size() < l + r));
1619 return str.substr(l, str.size() - l - r);
1620 }
1622
1623
1624
1625
1631 template<typename _tChar, class _tTraits, class _tAlloc, typename _func>
1633 std::basic_istream<_tChar, _tTraits>&
1634 extract(std::basic_istream<_tChar, _tTraits>& is,
1635 std::basic_string<_tChar, _tTraits, _tAlloc>& str, _func f)
1636 {
1637 typename std::basic_string<_tChar, _tTraits, _tAlloc>::size_type n(0);
1638 // NOTE: The type shall be explicit.
1639 std::ios_base::iostate st(std::ios_base::goodbit);
1640
1641 if(const auto k
1642 = typename std::basic_istream<_tChar, _tTraits>::sentry(is, true))
1643 {
1644 const auto msize(str.max_size());
1645 const auto p_buf(is.rdbuf());
1646
1647 yassume(p_buf);
1648 str.erase();
1649 try
1650 {
1651 const auto eof(_tTraits::eof());
1652
1653 for(auto c(p_buf->sgetc()); ; c = p_buf->snextc())
1654 {
1655 if(_tTraits::eq_int_type(c, eof))
1656 {
1657 st |= std::ios_base::eofbit;
1658 break;
1659 }
1660 if(f(c, *p_buf))
1661 {
1662 ++n;
1663 break;
1664 }
1665 if(!(str.length() < msize))
1666 {
1667 st |= std::ios_base::failbit;
1668 break;
1669 }
1670 str.append(1, _tTraits::to_char_type(c));
1671 ++n;
1672 }
1673 }
1674 catch(...)
1675 {
1676 // NOTE: See LWG 91.
1677 rethrow_badstate(is, std::ios_base::badbit);
1678 }
1679 }
1680 if(n == 0)
1681 st |= std::ios_base::failbit;
1682 if(st)
1683 is.setstate(st);
1684 return is;
1685 }
1686
1688
1689 template<typename _tChar, class _tTraits, class _tAlloc>
1690 std::basic_istream<_tChar, _tTraits>&
1691 extract_line(std::basic_istream<_tChar, _tTraits>& is,
1692 std::basic_string<_tChar, _tTraits, _tAlloc>& str, _tChar delim)
1693 {
1694 const auto d(_tTraits::to_int_type(delim));
1695
1696 return ystdex::extract(is, str,
1697 [d, &str](typename std::basic_istream<_tChar, _tTraits>::int_type c,
1698 std::basic_streambuf<_tChar, _tTraits>& sb) -> bool{
1699 if(_tTraits::eq_int_type(c, d))
1700 {
1701 sb.sbumpc();
1702 // NOTE: If not appended here, this function template shall be
1703 // equivalent with %std::getline.
1704 str.append(1, d);
1705 return true;
1706 }
1707 return {};
1708 });
1709 }
1710 template<typename _tChar, class _tTraits, class _tAlloc>
1711 inline std::basic_istream<_tChar, _tTraits>&
1712 extract_line(std::basic_istream<_tChar, _tTraits>& is,
1713 std::basic_string<_tChar, _tTraits, _tAlloc>& str)
1714 {
1715 return ystdex::extract_line(is, str, is.widen('\n'));
1716 }
1717
1723 template<typename _tChar, class _tTraits, class _tAlloc>
1724 std::basic_istream<_tChar, _tTraits>&
1725 extract_line_cr(std::basic_istream<_tChar, _tTraits>& is,
1726 std::basic_string<_tChar, _tTraits, _tAlloc>& str, _tChar delim_cr = '\r',
1727 _tChar delim = '\n')
1728 {
1729 const auto cr(_tTraits::to_int_type(delim_cr));
1730 const auto d(_tTraits::to_int_type(delim));
1731
1732 return ystdex::extract(is, str,
1733 [cr, d, &str](typename std::basic_istream<_tChar, _tTraits>::int_type c,
1734 std::basic_streambuf<_tChar, _tTraits>& sb) -> bool{
1735 if(_tTraits::eq_int_type(c, d))
1736 str.append(1, d);
1737 else if(_tTraits::eq_int_type(c, cr)
1738 && _tTraits::eq_int_type(sb.sgetc(), d))
1739 {
1740 sb.sbumpc();
1741 str.append(1, cr);
1742 str.append(1, d);
1743 }
1744 else
1745 return {};
1746 sb.sbumpc();
1747 return true;
1748 });
1749 }
1751
1752
1753
1759 template<typename _tChar, class _tString>
1760 std::basic_ostream<_tChar, typename _tString::traits_type>&
1761 write(std::basic_ostream<_tChar, typename _tString::traits_type>& os,
1762 const _tString& str, typename _tString::size_type pos = 0,
1763 typename _tString::size_type n = _tString::npos)
1764 {
1765 const auto len(str.length());
1766
1767 if(pos < len)
1768 os.write(&str[pos], std::streamsize(std::min(n, len - pos)));
1769 return os;
1770 }
1772 template<typename _tChar, class _tTraits, size_t _vN>
1773 std::basic_ostream<_tChar, _tTraits>&
1774 write(std::basic_ostream<_tChar, _tTraits>& os, const _tChar(&s)[_vN])
1775 {
1776 return os.write(std::addressof(s[0]), std::streamsize(size(s)));
1777 }
1778
1783 template<typename _tChar, class _tTraits, size_t _vN>
1784 std::basic_ostream<_tChar, _tTraits>&
1785 write_literal(std::basic_ostream<_tChar, _tTraits>& os, const _tChar(&s)[_vN])
1786 {
1787 static_assert(0 < _vN, "Empty string literal found.");
1788
1789 return
1790 os.write(std::addressof(s[0]), std::streamsize(size(s) - 1));
1791 }
1793
1795 template<class _tStream>
1796 using stream_str_t = decltype(std::declval<_tStream&>().str());
1797
1799 namespace details
1800 {
1801
1802 template<class _tStream, class _tString, typename = void>
1803 struct stream_str_det;
1804
1805 template<class _tStream, class _tString>
1806 struct stream_str_det<_tStream, _tString, void_t<stream_str_t<_tStream>>>
1807 {
1808 using result_type = stream_str_t<_tStream>;
1809 using type = cond_t<is_convertible<result_type, _tString>,
1810 result_type, _tString>;
1811 };
1812
1813 template<typename _type>
1814 using excluded_tostr
1815 = or_<is_same<_type, unsigned short>, is_same<_type, unsigned char>>;
1816
1817 template<typename _type>
1818 YB_ATTR_nodiscard inline auto
1819 arithmetic_to_string(_type val, false_) -> decltype(std::to_string(val))
1820 {
1821 return std::to_string(val);
1822 }
1823 YB_ATTR_nodiscard inline string
1824 arithmetic_to_string(unsigned val, true_)
1825 {
1826 return std::to_string(val);
1827 }
1828
1829 template<typename _type>
1830 YB_ATTR_nodiscard inline auto
1831 arithmetic_to_wstring(_type val, false_) -> decltype(std::to_wstring(val))
1832 {
1833 return std::to_wstring(val);
1834 }
1835 YB_ATTR_nodiscard inline wstring
1836 arithmetic_to_wstring(unsigned val, true_)
1837 {
1838 return std::to_wstring(val);
1839 }
1840
1841 } // namespace details;
1842
1849 template<typename _type>
1850 YB_ATTR_nodiscard inline yimpl(enable_if_t)<is_arithmetic<_type>::value, string>
1851 to_string(_type val)
1852 {
1853 return details::arithmetic_to_string(val, details::excluded_tostr<_type>());
1854 }
1855 template<typename _type>
1856 YB_ATTR_nodiscard inline yimpl(enable_if_t)<is_enum<_type>::value, string>
1857 to_string(_type val)
1858 {
1859 using ystdex::to_string;
1860
1861 return to_string(ystdex::underlying(val));
1862 }
1864 template<typename _type, class _tStream = std::ostringstream,
1865 class _tString = basic_string<typename _tStream::char_type,
1866 typename _tStream::traits_type, typename _tStream::allocator_type>>
1867 YB_ATTR_nodiscard yimpl(enable_if_t)<is_class<_type>::value,
1868 _t<details::stream_str_det<_tStream, _tString>>>
1869 to_string(const _type& x)
1870 {
1871 _tStream oss;
1872
1873 oss << x;
1874 return oss.str();
1875 }
1876
1877 template<typename _type>
1878 YB_ATTR_nodiscard inline
1879 yimpl(enable_if_t)<is_arithmetic<_type>::value, wstring>
1880 to_wstring(_type val)
1881 {
1882 return details::arithmetic_to_wstring(val, details::excluded_tostr<_type>());
1883 }
1884 template<typename _type>
1885 YB_ATTR_nodiscard inline yimpl(enable_if_t)<is_enum<_type>::value, wstring>
1886 to_wstring(_type val)
1887 {
1888 using ystdex::to_wstring;
1889
1890 return to_wstring(ystdex::underlying(val));
1891 }
1892 template<typename _type, class _tStream = std::wostringstream,
1893 class _tString = wstring>
1894 YB_ATTR_nodiscard yimpl(enable_if_t)<is_class<_type>::value,
1895 _t<details::stream_str_det<_tStream, _tString>>>
1896 to_wstring(const _type& x)
1897 {
1898 _tStream oss;
1899
1900 oss << x;
1901 return oss.str();
1902 }
1904
1905
1907 namespace details
1908 {
1909
1911
1912 template<typename _tString, typename _type, typename = void>
1913 struct ston_dispatcher;
1914
1915 template<typename _tChar, typename _type, class _tTraits, class _tAlloc>
1916 struct ston_dispatcher<basic_string<_tChar, _tTraits, _tAlloc>, _type,
1917 enable_if_t<not_<is_same<basic_string<_tChar, _tTraits, _tAlloc>,
1918 std::basic_string<_tChar, _tTraits, _tAlloc>>>::value>>
1919 : ston_dispatcher<std::basic_string<_tChar, _tTraits, _tAlloc>, _type>
1920 {};
1921
1922 #define YB_Impl_String_ston_begin(_tString, _type, _n, ...) \
1923 template<> \
1924 struct ston_dispatcher<_tString, _type, void> \
1925 { \
1926 YB_ATTR_nodiscard static _type \
1927 cast(const _tString& str, __VA_ARGS__) \
1928 { \
1929 return _n(str
1930 #define YB_Impl_String_ston_end \
1931 ); \
1932 } \
1933 };
1934
1935
1936 #define YB_Impl_String_ston_i(_tString, _type, _n) \
1937 YB_Impl_String_ston_begin(_tString, _type, _n, size_t* idx = {}, \
1938 int base = 10), idx, base \
1939 YB_Impl_String_ston_end
1940 #define YB_Impl_String_ston_i_std(_type, _n) \
1941 YB_Impl_String_ston_i(std::string, _type, std::_n)
1942 YB_Impl_String_ston_i_std(int, stoi)
1943 YB_Impl_String_ston_i_std(long, stol)
1944 YB_Impl_String_ston_i_std(unsigned long, stoul)
1945 YB_Impl_String_ston_i_std(long long, stoll)
1946 YB_Impl_String_ston_i_std(unsigned long long, stoull)
1947 #undef YB_Impl_String_ston_i_std
1948 #undef YB_Impl_String_ston_i
1949
1950 #define YB_Impl_String_ston_f(_tString, _type, _n) \
1951 YB_Impl_String_ston_begin(_tString, _type, _n, size_t* idx = {}), idx \
1952 YB_Impl_String_ston_end
1953 #define YB_Impl_String_ston_f_std(_type, _n) \
1954 YB_Impl_String_ston_f(std::string, _type, std::_n)
1955 # ifndef __BIONIC__
1956 YB_Impl_String_ston_f_std(float, stof)
1957 YB_Impl_String_ston_f_std(double, stod)
1958 YB_Impl_String_ston_f_std(long double, stold)
1959 # endif
1960 #undef YB_Impl_String_ston_f_std
1961 #undef YB_Impl_String_ston_f
1962
1963 #undef YB_Impl_String_ston_end
1964 #undef YB_Impl_String_ston_begin
1965
1966 } // namespace details;
1967
1974 template<typename _type, typename _tString, typename... _tParams>
1975 YB_ATTR_nodiscard inline _type
1976 ston(const _tString& str, _tParams&&... args)
1977 {
1978 return details::ston_dispatcher<decay_t<_tString>, _type>::cast(str,
1979 yforward(args)...);
1980 }
1981
1982
1984
1985
1996 template<class _tString = string>
1997 YB_ATTR_nodiscard YB_NONNULL(1) _tString
1998 vsfmt(const typename string_traits<_tString>::value_type* fmt,
1999 std::va_list args)
2000 {
2001 std::va_list ap;
2002
2003 va_copy(ap, args);
2004
2005 const auto l(ystdex::vfmtlen(fmt, ap));
2006
2007 va_end(ap);
2008 if(l == size_t(-1))
2009 throw std::runtime_error("Failed to write formatted string.");
2010
2011 _tString str(l, typename _tString::value_type());
2012
2013 if(l != 0)
2014 {
2015 YAssert(str.length() > 0 && str[0] == typename _tString::value_type(),
2016 "Invalid string value constructed.");
2017 std::vsprintf(&str[0], fmt, args);
2018 }
2019 return str;
2020 }
2021
2026 template<class _tString = string>
2027 YB_ATTR_nodiscard YB_NONNULL(1) _tString
2028 sfmt(const typename string_traits<_tString>::value_type* fmt, ...)
2029 {
2030 std::va_list args;
2031
2032 va_start(args, fmt);
2033 try
2034 {
2035 auto str(ystdex::vsfmt<_tString>(fmt, args));
2036
2037 va_end(args);
2038 return str;
2039 }
2040 catch(...)
2041 {
2042 va_end(args);
2043 throw;
2044 }
2045 }
2047
2052 template YB_ATTR_gnu_printf(1, 2) YB_NONNULL(1) string
2053 sfmt<string>(const char*, ...);
2055
2056
2062 template<typename _type, typename _tString, typename _func>
2063 bool
2064 filter_prefix(const _tString& str, const _type& prefix, _func f)
2065 {
2066 if(ystdex::begins_with(str, prefix))
2067 {
2068 auto&& sub(str.substr(string_length(prefix)));
2069
2070 if(!sub.empty())
2071 f(std::move(sub));
2072 return true;
2073 }
2074 return {};
2075 }
2076
2082 template<typename _type, typename _tString>
2083 YB_ATTR_nodiscard _tString
2084 cond_prefix(const _tString& str, const _type& prefix, _tString&& val = {})
2085 {
2086 ystdex::filter_prefix(str, prefix, [&](_tString&& s)
2087 ynoexcept(is_nothrow_move_assignable<decay_t<_tString>>()){
2088 val = std::move(s);
2089 });
2090 return std::move(val);
2091 }
2092
2093 } // namespace ystdex;
2094
2095 #if !YB_Impl_String_has_P0254R2
2096 namespace std
2098 {
2099
2104 template<typename _tChar, class _tTraits, class _tAlloc>
2105 struct hash<ystdex::basic_string<_tChar, _tTraits, _tAlloc>>
2106 : hash<basic_string<_tChar, _tTraits, _tAlloc>>
2107 {};
2108
2109 } // namespace std;
2110 #endif
2111
2112 #undef YB_Impl_String_has_P0254R2
2113
2114 #endif
2115
ystdex::cpp2017::basic_string::basic_string
basic_string(const base &str)
Definition: string.hpp:175
ystdex::cpp2017::basic_string::basic_string
basic_string(const _tAlloc &a)
Definition: string.hpp:115
ystdex::cpp2017::basic_string::append
basic_string & append(std::initializer_list< _tChar > il)
Definition: string.hpp:333
YB_Impl_String_ston_i_std
#define YB_Impl_String_ston_i_std(_type, _n)
Definition: string.hpp:1940
ystdex::cpp2017::basic_string::replace
basic_string & replace(const_iterator i1, const_iterator i2, std::initializer_list< _tChar > il)
Definition: string.hpp:596
ystdex::begins_with
bool begins_with(const _tRange1 &input, const _tRange2 &test, _fPred comp)
判断第一参数指定的串是否以第二参数起始。
Definition: string.hpp:1176
ystdex::cond_prefix
_tString cond_prefix(const _tString &str, const _type &prefix, _tString &&val={})
选择性过滤前缀。
Definition: string.hpp:2084
ystdex::cpp2017::basic_string::basic_string
basic_string(const base &str, const _tAlloc &a)
Definition: string.hpp:167
YB_ATTR_nodiscard
#define YB_ATTR_nodiscard
标记返回值不被忽略的属性。
Definition: ydef.h:715
ystdex::cpp2017::basic_string::sv_type
basic_string_view< _tChar, _tTraits > sv_type
Definition: string.hpp:86
ystdex::details::str_algo< index_sequence<> >::erase_right
void erase_right()=delete
CHRLib::e
const char const char * e
Definition: CharacterProcessing.h:112
ystdex::string_end
auto string_end(_tRange &c) -> decltype(c.end())
Definition: string.hpp:1064
ystdex::rethrow_badstate
void rethrow_badstate(std::basic_ios< _tChar, _tTraits > &ios, std::ios_base::iostate state=std::ios_base::badbit)
设置流状态并重新抛出当前异常。
Definition: ios.hpp:64
YB_ATTR_gnu_printf
#define YB_ATTR_gnu_printf(...)
GNU 风格 printf 属性。
Definition: ydef.h:671
x
const EncapsulationBase & x
Definition: NPLA1Forms.cpp:1536
size
size_t size
Definition: memory_resource.cpp:295
ystdex::cpp2017::swap
void swap(optional< _type > &x, optional< _type > &y)
Definition: optional.h:888
platform::strings::basic_string
ystdex::basic_string< _tChar, _tTraits, _tAlloc > basic_string
满足 ISO C++03 std::basic_string 但不保证满足 ISO C++11 的实现。
Definition: Container.h:175
ystdex::cpp2017::basic_string::insert
basic_string & insert(size_type pos, const base &str)
Definition: string.hpp:419
ystdex::cpp2017::basic_string::basic_string
basic_string(const _type &t, size_type pos, size_type n, const _tAlloc &a=_tAlloc())
Definition: string.hpp:128
ystdex::cpp2017::basic_string::find
size_type find(sv_type sv, size_type pos=0) const
Definition: string.hpp:632
YB_Impl_String_ston_f_std
#define YB_Impl_String_ston_f_std(_type, _n)
Definition: string.hpp:1953
ystdex::cpp2017::basic_string< char >::enable_if_sv_t
enable_if_t< and_< is_convertible< const _type &, sv_type >, not_< is_convertible< const _type *, const base * > >, not_< is_convertible< const _type &, const char * > >>::value, _tRes > enable_if_sv_t
Definition: string.hpp:92
ystdex::cpp2017::basic_string::basic_string
basic_string()
Definition: string.hpp:110
CHRLib::c
c
Definition: CharacterProcessing.h:84
ystdex::cpp2017::basic_string::replace
basic_string & replace(const_iterator i1, const_iterator i2, const base &str)
Definition: string.hpp:558
ystdex::quote
decay_t< _tString > quote(_tString &&str, typename string_traits< decay_t< _tString >>::value_type c=typename string_traits< decay_t< _tString >>::value_type('"'))
取添加前缀和后缀的字符串。
Definition: string.hpp:1579
yconstexpr
#define yconstexpr
指定编译时常量表达式。
Definition: ydef.h:1072
ystdex::cpp2017::basic_string::operator+
friend basic_string operator+(const basic_string &lhs, const basic_string &rhs)
Definition: string.hpp:709
YB_PURE
#define YB_PURE
指示函数或函数模板实例为纯函数。
Definition: ydef.h:919
ystdex::cpp2017::basic_string::insert
iterator insert(const_iterator p, _tChar c)
Definition: string.hpp:473
ystdex::cpp2017::basic_string::find_last_not_of
size_type find_last_not_of(sv_type sv, size_type pos=npos) const
Definition: string.hpp:672
ystdex::cpp2017::basic_string
Definition: string.hpp:77
string_view.hpp
只读字符串视图。
ystdex::is_string_like
判断指定类型是否为类字符串类型。
Definition: string.hpp:999
ystdex::get_mid
_tString get_mid(const _tString &str, typename _tString::size_type l=1)
取删除前缀和后缀的子字符串。
Definition: string.hpp:1608
ystdex::find_prefix
_tString find_prefix(const _tString &str, _tParams &&... args)
取前缀子字符串。
Definition: string.hpp:1521
ios.hpp
ISO C++ 标准库输入/输出流基类扩展。
ystdex::cpp2014::min
const _type & min(const _type &a, const _type &b, _fComp comp=less< _type >())
取较小的元素。
Definition: algorithm.hpp:614
ystdex::details::str_algos< 1 >::trim_right_pos
static auto trim_right_pos(_tString &s, _tSize n) -> decltype(s.erase(n+1))
Definition: string.hpp:941
YSLib::Drawing::r
The boundary is out of the const Graphics const Rect const Point const Point Color c const Rect const Rect & r
Definition: YDraw.h:174
ystdex::cpp2017::basic_string_view
Definition: string_view.hpp:95
ystdex::cpp2017::basic_string::insert
iterator insert(const_iterator p, _tIn first, _tIn last)
Definition: string.hpp:490
ystdex::cpp2017::basic_string< char >::const_iterator
typename base::const_iterator const_iterator
Definition: string.hpp:97
ystdex::cpp2017::basic_string::replace
basic_string & replace(const_iterator i1, const_iterator i2, sv_type sv)
Definition: string.hpp:565
ystdex::details::ends_with_iter_dispatch
bool ends_with_iter_dispatch(_tFwd1 b, _tFwd1 e, _tFwd2 bt, _tFwd2 et, _fPred comp, std::bidirectional_iterator_tag)
Definition: string.hpp:840
ystdex::cpp2017::allocator_traits
Definition: allocator.hpp:384
ystdex::cpp2017::basic_string::operator+
friend basic_string operator+(basic_string &&lhs, basic_string &&rhs)
Definition: string.hpp:724
YSLib::IO::_tTraits
const string &path const String &path class class _tTraits
Definition: YSLib/Service/FileSystem.h:582
ystdex::cpp2014::enable_if_t
typename enable_if< _bCond, _type >::type enable_if_t
Definition: meta.hpp:199
ystdex::extract_line_cr
std::basic_istream< _tChar, _tTraits > & extract_line_cr(std::basic_istream< _tChar, _tTraits > &is, std::basic_string< _tChar, _tTraits, _tAlloc > &str, _tChar delim_cr='\r', _tChar delim='\n')
同 ystdex::extract_line ，但允许分隔符包含附加的前缀字符。
Definition: string.hpp:1725
ystdex::string_begin
auto string_begin(_tRange &c) -> decltype(c.begin())
Definition: string.hpp:1033
ystdex::cpp2017::basic_string::operator+
friend basic_string operator+(_tChar lhs, basic_string &&rhs)
Definition: string.hpp:744
ystdex::cpp2017::basic_string::basic_string
basic_string(const base &str, size_type pos, const _tAlloc &a=_tAlloc())
Definition: string.hpp:119
ystdex::cpp2017::basic_string::assign
basic_string & assign(std::initializer_list< _tChar > il)
Definition: string.hpp:412
ystdex::cpp2017::basic_string::rfind
size_type rfind(sv_type sv, size_type pos=npos) const
Definition: string.hpp:640
ystdex::cpp2017::basic_string::find_first_of
size_type find_first_of(sv_type sv, size_type pos=0) const
Definition: string.hpp:648
ystdex::cpp2017::basic_string::append
basic_string & append(const base &str, size_type pos, size_type n=npos)
Definition: string.hpp:273
ystdex::cpp2017::basic_string::find_last_of
size_type find_last_of(sv_type sv, size_type pos=npos) const
Definition: string.hpp:656
ystdex::string_traits::pointer
value_type * pointer
Definition: string.hpp:801
ystdex::normalize
auto normalize(_tString &str) -> decltype(str.resize(ystdex::ntctslen(str.c_str())))
NTCTS 正规化：保留空字符之前的字符。
Definition: string.hpp:1245
ystdex::cpp2017::basic_string::insert
basic_string & insert(size_type pos1, const base &str, size_type pos2, size_type n=npos)
Definition: string.hpp:426
CHRLib::d
_tDst * d
Definition: CharacterProcessing.h:142
ystdex::cpp2017::basic_string::append
basic_string & append(size_type n, _tChar c)
Definition: string.hpp:314
ynoexcept_spec
#define ynoexcept_spec(...)
表达式 noexcept 异常规范。
Definition: ydef.h:1181
pfx
ValueObject pfx
Definition: NPLA1.cpp:363
ystdex::cpp2017::basic_string::append
basic_string & append(sv_type sv)
Definition: string.hpp:281
ystdex::cpp2017::basic_string::operator+
friend basic_string operator+(basic_string &&lhs, _tChar rhs)
Definition: string.hpp:764
ystdex::erase_left
enable_if_t< is_class< decay_t< _tString > >::value, _tString && > erase_left(typename string_traits< _tString >::size_type pos, _tString &&str)
删除字符串中指定位置或指定字符最先出现的位置的左侧的字符串。
Definition: string.hpp:1343
ystdex::details::str_algo< index_sequence<> >::trim_right_pos
void trim_right_pos()=delete
ystdex::alph
_tString alph(_tString &str)
取字母表：有序的字符串的不重复序列。
Definition: string.hpp:1303
ystdex::details::str_algo< index_sequence<> >::trim_left_pos
void trim_left_pos()=delete
ystdex::erase_right
enable_if_t< is_class< decay_t< _tString > >::value, _tString && > erase_right(_tString &&str, typename string_traits< _tString >::const_pointer t=&to_array< typename string_traits< _tString >::value_type >(" \f\n\r\t\v")[0])
Definition: string.hpp:1407
ystdex::extract
std::basic_istream< _tChar, _tTraits > & extract(std::basic_istream< _tChar, _tTraits > &is, std::basic_string< _tChar, _tTraits, _tAlloc > &str, _func f)
从输入流中取字符串。
Definition: string.hpp:1634
ystdex::details::arithmetic_to_wstring
auto arithmetic_to_wstring(_type val, false_) -> decltype(std::to_wstring(val))
Definition: string.hpp:1831
ystdex::cpp2017::basic_string::substr
basic_string substr(size_type pos=0, size_type n=npos) const
Definition: string.hpp:605
ystdex::enable_for_string_class_t
enable_if_t< is_string_class< decay_t< _tParam > >::value, _type > enable_for_string_class_t
选择字符串类类型的特定重载避免和其它非字符串类型冲突。
Definition: string.hpp:1019
ystdex::cpp2017::basic_string::operator+
friend basic_string operator+(basic_string &&lhs, const basic_string &rhs)
Definition: string.hpp:714
ystdex::details::str_algo< index_sequence<> >::erase_left
void erase_left()=delete
ystdex::cpp2017::basic_string::equal_alloc_or_pocma
equal_alloc_or< typename ator_traits::propagate_on_container_move_assignment > equal_alloc_or_pocma
Definition: string.hpp:85
ystdex::cpp2017::basic_string::operator+=
basic_string & operator+=(_tChar c)
Definition: string.hpp:246
ystdex::is_equal
相等关系仿函数。
Definition: functor.hpp:196
ystdex::cpp2017::basic_string::assign
basic_string & assign(const base &str, size_type pos, size_type n=npos)
Definition: string.hpp:352
CHRLib::f
f(d, s)
ystdex::cpp2017::basic_string::basic_string
basic_string(std::initializer_list< _tChar > il, const _tAlloc &a=_tAlloc())
Definition: string.hpp:164
YAssert
#define YAssert(_expr, _msg)
Definition: cassert.h:154
ystdex::ntctslen
size_t ntctslen(const _tChar *s)
计算简单 NTCTS 长度。
Definition: cstring.h:456
ystdex::cpp2017::basic_string::operator+=
basic_string & operator+=(sv_type sv)
Definition: string.hpp:235
ystdex::details::arithmetic_to_string
auto arithmetic_to_string(_type val, false_) -> decltype(std::to_string(val))
Definition: string.hpp:1819
ystdex::details::stream_str_det< _tStream, _tString, void_t< stream_str_t< _tStream > > >::type
cond_t< is_convertible< result_type, _tString >, result_type, _tString > type
Definition: string.hpp:1810
delim
TokenValue delim
Definition: NPLA1.cpp:358
allocator.hpp
分配器接口。
ystdex::write_literal
std::basic_ostream< _tChar, _tTraits > & write_literal(std::basic_ostream< _tChar, _tTraits > &os, const _tChar(&s)[_vN])
Definition: string.hpp:1785
ystdex::to_string
enable_if_t< is_class< _type >::value, _t< details::stream_str_det< _tStream, _tString > > > to_string(const _type &x)
Definition: string.hpp:1869
ystdex::cpp2017::basic_string::compare
enable_if_sv_t< _type, int > compare(size_type pos1, size_type n1, const _type &t, size_type pos2, size_type n2=npos) const
Definition: string.hpp:695
ystdex::cpp2017::basic_string::basic_string
basic_string(size_type n, _tChar c, const _tAlloc &a=_tAlloc())
Definition: string.hpp:152
ystdex::details::str_algos< 0 >::erase_left
static auto erase_left(_tString &s, _tSize n) -> decltype(s.remove_prefix(n), s)
Definition: string.hpp:865
ystdex::cpp2017::basic_string::assign
enable_if_sv_t< _type, basic_string & > assign(const _type &t, size_type pos, size_type n=npos)
Definition: string.hpp:367
ystdex::cpp2017::basic_string::assign
basic_string & assign(_tIn first, _tIn last)
Definition: string.hpp:406
CHRLib::args
YB_ATTR_nodiscard _tParams && args
Definition: CharacterProcessing.h:649
ystdex::cpp2017::void_t
well_formed_t< void, _types... > void_t
Definition: meta.hpp:292
ystdex::cpp2017::basic_string::operator=
basic_string & operator=(const base &str)
Definition: string.hpp:206
yassume
#define yassume(_expr)
假定：环境语义。
Definition: cassert.h:96
ystdex::cpp2017::basic_string::swap
friend void swap(basic_string &lhs, basic_string &rhs)
Definition: string.hpp:618
ystdex::cpp2014::decay_t
typename decay< _type >::type decay_t
Definition: meta.hpp:196
ystdex::details::str_algos< 0 >::trim_left_pos
static auto trim_left_pos(_tString &s, _tSize n) -> decltype(s.remove_prefix(n), s)
Definition: string.hpp:885
ystdex::cpp2017::basic_string::replace
enable_if_sv_t< _type, basic_string & > replace(size_type pos1, size_type n1, const _type &t, size_type pos2, size_type n2=npos)
Definition: string.hpp:525
ystdex::vsfmt
_tString vsfmt(const typename string_traits< _tString >::value_type *fmt, std::va_list args)
以 C 标准输出格式的输出字符串类型的对象。
Definition: string.hpp:1998
ystdex::concat
void concat(_tCon &con, _tIn first, _tIn last)
插入元素到容器末尾。
Definition: container.hpp:173
ystdex::erase_left
enable_if_t< is_class< decay_t< _tString > >::value, _tString && > erase_left(_tString &&str, typename string_traits< _tString >::const_pointer t=&to_array< typename string_traits< _tString >::value_type >(" \f\n\r\t\v")[0])
Definition: string.hpp:1368
ystdex::is_null
bool is_null(_tChar c)
使用 std::char_traits::eq 判断是否为空字符。
Definition: cstring.h:127
ystdex::cpp2017::basic_string_view::data
const_pointer data() const
Definition: string_view.hpp:234
ystdex::details::is_string_like
Definition: string.hpp:828
ystdex::string_traits::reference
value_type & reference
Definition: string.hpp:798
ystdex::details::str_algos< 1 >::erase_left
static auto erase_left(_tString &s, _tSize n) -> decltype(s.erase(0, n))
Definition: string.hpp:911
ystdex::cpp2017::basic_string::replace
basic_string & replace(size_type pos1, size_type n1, const base &str, size_type pos2, size_type n2=npos)
Definition: string.hpp:509
ystdex::cpp2017::basic_string::insert
iterator insert(const_iterator p, size_type n, _tChar c)
Definition: string.hpp:478
ystdex::details::stream_str_det< _tStream, _tString, void_t< stream_str_t< _tStream > > >::result_type
stream_str_t< _tStream > result_type
Definition: string.hpp:1808
ystdex::details::str_algo
Definition: string.hpp:950
ystdex::details::str_algos< 0 >::erase_right
static auto erase_right(_tString &s, _tSize n) -> decltype(s.remove_suffix(n), s)
Definition: string.hpp:875
ystdex::details::stream_str_det
Definition: string.hpp:1803
ystdex::cpp2017::basic_string::basic_string
basic_string(_tIn begin, _tIn end, const _tAlloc &a=_tAlloc())
Definition: string.hpp:161
YSLib::IO::_tString
const string &path const String &path class class class _tString
Definition: YSLib/Service/FileSystem.h:612
ystdex::or_
逻辑或。
Definition: integral_constant.hpp:172
ystdex::ltrim
_tString && ltrim(_tString &&str, typename string_traits< _tString >::value_type c)
删除字符串中指定的连续前缀字符。
Definition: string.hpp:1423
yforward
#define yforward(_expr)
根据参数类型使用 std::forward 转发对应参数。
Definition: ydef.h:1508
ystdex::string_traits::const_pointer
const value_type * const_pointer
Definition: string.hpp:802
ystdex::cpp2017::size
auto size(const _tRange &c) -> decltype(c.size())
Definition: range.hpp:540
ystdex::cpp2017::data
auto data(_tRange &c) -> decltype(c.data())
Definition: range.hpp:581
ystdex::cpp2017::basic_string::basic_string
basic_string(sv_type sv, const _tAlloc &a=_tAlloc())
Definition: string.hpp:134
ystdex::cpp2017::basic_string_view::substr
basic_string_view substr(size_type pos=0, size_type n=npos) const
Definition: string_view.hpp:273
ystdex::cpp2017::basic_string::operator=
basic_string & operator=(base &&str)
Definition: string.hpp:212
ystdex::cpp2017::basic_string::basic_string
basic_string(base &&str, const _tAlloc &a)
Definition: string.hpp:170
ystdex::string_traits::traits_type
typename std::char_traits< value_type > traits_type
Definition: string.hpp:791
ystdex::cpp2017::basic_string::basic_string
basic_string(const basic_string &)=default
ystdex::cpp2017::basic_string::operator+=
basic_string & operator+=(const basic_string &str)
Definition: string.hpp:229
ystdex::cpp2017::basic_string::swap
void swap(basic_string &s)
Definition: string.hpp:611
ystdex::cpp2017::end
auto end(_tRange &c) -> decltype(c.end())
Definition: range.hpp:345
ystdex::details::str_algos
Definition: string.hpp:856
ystdex::to_wstring
enable_if_t< is_arithmetic< _type >::value, wstring > to_wstring(_type val)
Definition: string.hpp:1880
ystdex::rtrim
_tString && rtrim(_tString &&str, typename string_traits< _tString >::value_type c)
删除字符串中指定的连续后缀字符。
Definition: string.hpp:1454
ystdex::details::ston_dispatcher
Definition: string.hpp:1913
ystdex::cpp2017::basic_string::replace
basic_string & replace(const_iterator i1, const_iterator i2, _tIn j1, _tIn j2)
Definition: string.hpp:589
std
Definition: optional.h:982
ystdex::cpp2017::basic_string::operator=
basic_string & operator=(std::initializer_list< _tChar > il)
Definition: string.hpp:201
ystdex::sfmt
_tString sfmt(const typename string_traits< _tString >::value_type *fmt,...)
以 C 标准输出格式的输出 basic_string 实例的对象。
Definition: string.hpp:2028
ystdex::details::str_algos< 0 >::trim_right_pos
static auto trim_right_pos(_tString &s, _tSize n) -> decltype(s.remove_suffix(n), s)
Definition: string.hpp:896
ystdex::cpp2017::basic_string::insert
enable_if_sv_t< _type, basic_string & > insert(size_type pos1, const _type &t, size_type pos2, size_type n=npos)
Definition: string.hpp:441
ystdex::string_traits::difference_type
typename allocator_traits< allocator_type >::difference_type difference_type
Definition: string.hpp:797
container.hpp
通用容器操作。
ystdex::to_array
std::array< _type, _vN > to_array(const _tSrc &src)
转换指定参数为 std::array 对象。
Definition: array.hpp:92
YSLib::i
return i
Definition: YCoreUtilities.h:177
ystdex::cpp2017::basic_string::compare
int compare(size_type pos1, size_type n1, sv_type sv) const
Definition: string.hpp:688
ystdex::cpp2017::basic_string::append
enable_if_sv_t< _type, basic_string & > append(const _type &t, size_type pos, size_type n=npos)
Definition: string.hpp:288
ystdex::trim
_tString && trim(_tString &&str, typename string_traits< _tString >::value_type c)
删除字符串中指定的连续前缀与后缀字符。
Definition: string.hpp:1485
ystdex::stream_str_t
decltype(std::declval< _tStream & >().str()) stream_str_t
Definition: string.hpp:1796
ystdex::find_suffix
_tString find_suffix(const _tString &str, _tParams &&... args)
取后缀子字符串。
Definition: string.hpp:1538
ystdex::cpp2017::basic_string::assign
basic_string & assign(size_type n, _tChar c)
Definition: string.hpp:393
ystdex::restrict_length
_tString && restrict_length(_tString &&str, const typename string_traits< _tString >::size_type n)
限制长度不超过指定参数。
Definition: string.hpp:1288
ystdex::cpp2017::basic_string::basic_string
basic_string(const base &str, size_type pos, size_type n, const _tAlloc &a=_tAlloc())
Definition: string.hpp:122
ystdex::cpp2017::basic_string::operator+=
basic_string & operator+=(std::initializer_list< _tChar > il)
Definition: string.hpp:252
ystdex::cpp2017::basic_string::find_first_not_of
size_type find_first_not_of(sv_type sv, size_type pos=0) const
Definition: string.hpp:664
ystdex::string_traits::string_type
remove_cvref_t< _tString > string_type
Definition: string.hpp:789
yconstraint
#define yconstraint(_expr)
约束：接口语义。
Definition: cassert.h:125
ystdex::to_string
std::string to_string(const std::thread::id &)
转换 thread::id 为字符串表示。
ystdex::cpp2017::basic_string< char >::iterator
typename base::iterator iterator
Definition: string.hpp:96
ystdex::cpp2017::wstring
basic_string< wchar_t > wstring
Definition: string.hpp:775
ystdex::true_
bool_< true > true_
Definition: integral_constant.hpp:109
ystdex::to_wstring
enable_if_t< is_class< _type >::value, _t< details::stream_str_det< _tStream, _tString > > > to_wstring(const _type &x)
Definition: string.hpp:1896
ystdex::cpp2017::empty
auto empty(const _tRange &c) -> decltype(c.empty())
Definition: range.hpp:562
ystdex::cpp2017::basic_string::compare
int compare(sv_type sv) const
Definition: string.hpp:681
ystdex::filter_prefix
bool filter_prefix(const _tString &str, const _type &prefix, _func f)
过滤前缀：存在前缀时处理移除前缀后的子串。
Definition: string.hpp:2064
CHRLib::s
_tDst const _tSrc * s
Definition: CharacterProcessing.h:143
ystdex::cpp2017::basic_string::assign
basic_string & assign(sv_type sv)
Definition: string.hpp:360
ystdex::ntctsncpy
enable_if_irreplaceable_char_t< _tChar, _tChar * > ntctsncpy(_tChar *s1, const _tChar *s2, size_t n)
复制不超过指定长度的 NTCTS 。
Definition: cstring.h:315
ystdex::cond_t
_t< cond< _tCond, _tThen, _tElse > > cond_t
Definition: meta.hpp:794
ystdex::cpp2017::basic_string::replace
basic_string & replace(size_type pos1, size_type n1, const base &str)
Definition: string.hpp:502
ystdex::string_length
size_t string_length(const _tChar *str)
计算字符串长度。
Definition: string.hpp:1142
ystdex::cpp2017::basic_string::insert
basic_string & insert(size_type pos, sv_type sv)
Definition: string.hpp:434
ystdex::cpp2017::basic_string::append
basic_string & append(const base &str)
Definition: string.hpp:266
ystdex::cpp2017::basic_string::operator=
basic_string & operator=(const basic_string &)=default
ystdex::cpp2017::basic_string::insert
basic_string & insert(size_type pos, size_type n, _tChar c)
Definition: string.hpp:467
ynothrowv
#define ynothrowv
YSLib 无异常抛出保证验证：有条件地使用无异常抛出规范。
Definition: ydef.h:1219
ystdex
<memory> 特性测试宏。
Definition: ydef.h:1262
ystdex::cpp2017::basic_string::append
basic_string & append(_tIn first, _tIn last)
Definition: string.hpp:327
ystdex::cpp2017::basic_string::assign
basic_string & assign(const base &str)
Definition: string.hpp:341
ystdex::cpp2017::basic_string_view::size
size_type size() const
Definition: string_view.hpp:184
ystdex::assign
void assign(_tCon &con, _tParams &&... args)
插入参数指定的元素到容器。
Definition: container.hpp:150
ystdex::vfmtlen
size_t vfmtlen(const char *, std::va_list)
计算指定格式字符串输出的占用的字节数。
Definition: cstdio.cpp:39
cstdio.h
ISO C 标准输入/输出扩展。
ystdex::string_traits::value_type
remove_cvref_t< decltype(std::declval< string_type >()[0])> value_type
Definition: string.hpp:790
YSLib::_tParams
YB_ATTR_nodiscard YB_PURE typename _tParams
Definition: ValueNode.h:1294
ystdex::cpp2017::basic_string::basic_string
basic_string(basic_string &&)=default
ystdex::string_traits::initializer
std::initializer_list< value_type > initializer
Definition: string.hpp:803
ystdex::exists_substr
bool exists_substr(const _tString &str, const _type &sub)
判断是否存在子串。
Definition: string.hpp:1221
ystdex::extract_line
std::basic_istream< _tChar, _tTraits > & extract_line(std::basic_istream< _tChar, _tTraits > &is, std::basic_string< _tChar, _tTraits, _tAlloc > &str, _tChar delim)
Definition: string.hpp:1691
ystdex::cpp2017::basic_string::assign
basic_string & assign(base &&str)
Definition: string.hpp:346
ystdex::addressof
enable_if_t< has_no_overloaded_addressof< _type >::value, _type * > addressof(_type &r)
尝试对非重载 operator& 提供 constexpr 的 std::addressof 替代。
Definition: addressof.hpp:131
ystdex::_t
typename _type::type _t
嵌套类型别名。
Definition: meta.hpp:45
ystdex::erase_right
enable_if_t< is_class< decay_t< _tString > >::value, _tString && > erase_right(typename string_traits< _tString >::size_type pos, _tString &&str)
删除字符串中指定位置或指定字符最后出现的位置的右侧的字符串。
Definition: string.hpp:1381
ystdex::sort_unique
_tRandom sort_unique(_tRandom first, _tRandom last)
排序指定序列范围，保留不重复元素的区间。
Definition: algorithm.hpp:583
ystdex::cpp2014::equal
bool equal(_tIn1 first1, _tIn1 last1, _tIn2 first2, _tIn2 last2, _fBiPred binary_pred)
Definition: algorithm.hpp:205
ystdex::get_quote_mark_nonstrict
string_traits< _tString >::value_type get_quote_mark_nonstrict(const _tString &str)
取相同的前缀和后缀元素。
Definition: string.hpp:1564
ystdex::write
std::basic_ostream< _tChar, typename _tString::traits_type > & write(std::basic_ostream< _tChar, typename _tString::traits_type > &os, const _tString &str, typename _tString::size_type pos=0, typename _tString::size_type n=_tString::npos)
非格式输出。
Definition: string.hpp:1761
ystdex::ends_with
bool ends_with(const _tRange1 &input, const _tRange2 &test, _fPred comp)
判断第一参数指定的串是否以第二参数结束。
Definition: string.hpp:1195
ystdex::underlying
enable_if_t< is_enum_union< _type >::value, wrapped_enum_traits_t< _type > > underlying(_type val)
Definition: enum.hpp:112
platform::ios::ostringstream
ostringstream_for< string > ostringstream
Definition: Container.h:320
ystdex::cpp2014::integer_sequence
Definition: integer_sequence.hpp:53
ystdex::ston
_type ston(const _tString &str, _tParams &&... args)
转换表示数的字符串。
Definition: string.hpp:1976
ystdex::string_traits::allocator_type
_t< nested_allocator< string_type > > allocator_type
Definition: string.hpp:794
ystdex::cpp2014::remove_reference_t
typename remove_reference< _type >::type remove_reference_t
Definition: meta.hpp:155
ystdex::string_traits::const_reference
const value_type & const_reference
Definition: string.hpp:799
ystdex::details::str_algos< 1 >::erase_right
static auto erase_right(_tString &s, _tSize n) -> decltype(s.erase(n+1))
Definition: string.hpp:921
platform::p
return p p
Definition: YCLib/FileSystem.h:209
ystdex::cpp2017::basic_string::basic_string
basic_string(base &&str)
Definition: string.hpp:178
YSLib::Text::str
YB_ATTR_nodiscard YB_PURE const char const char * str
Definition: TextFile.h:83
const
const Decapsulate const Decapsulate &y ynothrow ContextNode &ctx const
Definition: NPLA1Forms.cpp:1629
yimpl
#define yimpl(...)
实现标签。
Definition: ydef.h:413
ystdex::make_string_view
basic_string_view< typename string_traits< _tString >::value_type, typename string_traits< _tString >::traits_type > make_string_view(const _tString &str)
从字符串创建 basic_string_view 对象。
Definition: string.hpp:814
ystdex::not_
逻辑非。
Definition: integral_constant.hpp:193
ystdex::false_
bool_< false > false_
Definition: integral_constant.hpp:110
ynothrow
#define ynothrow
YSLib 无异常抛出保证：若支持 noexcept 关键字， 指定特定的 noexcept 异常规范。
Definition: ydef.h:1199
ystdex::string_traits::size_type
typename allocator_traits< allocator_type >::size_type size_type
Definition: string.hpp:795
ystdex::string_traits
字符串特征。
Definition: string.hpp:788
ystdex::is_string_class
判断指定类型是否为字符串类类型。
Definition: string.hpp:1007
ynoexcept
#define ynoexcept(...)
YSLib 无异常抛出保证：指定特定的异常规范。
Definition: ydef.h:1151
ystdex::cpp2017::basic_string::replace
basic_string & replace(size_type pos1, size_type n1, size_type n2, _tChar c)
Definition: string.hpp:552
ystdex::cpp2017::basic_string::operator+
friend basic_string operator+(const basic_string &lhs, _tChar rhs)
Definition: string.hpp:759
ystdex::cpp2017::basic_string::replace
basic_string & replace(size_type pos1, size_type n1, sv_type sv)
Definition: string.hpp:518
ystdex::cpp2017::basic_string::operator+
friend basic_string operator+(const basic_string &lhs, basic_string &&rhs)
Definition: string.hpp:719
ystdex::cpp2017::basic_string::insert
iterator insert(const_iterator p, std::initializer_list< _tChar > il)
Definition: string.hpp:496
ystdex::cpp2017::basic_string::operator=
basic_string & operator=(_tChar c)
Definition: string.hpp:196
ystdex::remove_cvref_t
_t< remove_cvref< _type > > remove_cvref_t
Definition: meta.hpp:236
ystdex::cpp2017::basic_string::operator=
basic_string & operator=(basic_string &&)=default
ystdex::cpp2017::basic_string::replace
basic_string & replace(const_iterator i1, const_iterator i2, size_type n, _tChar c)
Definition: string.hpp:576
ystdex::details::str_algos< 1 >::trim_left_pos
static auto trim_left_pos(_tString &s, _tSize n) -> decltype(s.erase(0, n))
Definition: string.hpp:931
ystdex::cpp2017::basic_string::operator+
friend basic_string operator+(_tChar lhs, const basic_string &rhs)
Definition: string.hpp:739
array.hpp
数组操作。
yconstfn
#define yconstfn
指定编译时常量函数。
Definition: ydef.h:1073
ystdex::cpp2017::begin
auto begin(_tRange &c) -> decltype(c.begin())
Definition: range.hpp:323
platform::ios::wostringstream
ostringstream_for< wstring > wostringstream
Definition: Container.h:321
ystdex::string_empty
bool string_empty(const _tChar *str)
判断字符串是否为空。
Definition: string.hpp:1110
YSLib::a
YB_PURE const _type * a
Definition: YCoreUtilities.h:168
platform::l
return l
Definition: YCLib/FileSystem.h:402
ystdex::cpp2017::basic_string< char >::size_type
typename base::size_type size_type
Definition: string.hpp:95
ystdex::cpp2017::basic_string< char >::base
std::basic_string< char, std::char_traits< char >, std::allocator< char > > base
Definition: string.hpp:79
ystdex::and_
逻辑操作元函数。
Definition: integral_constant.hpp:151
ystdex::cpp2017::basic_string::npos
static const auto npos
Definition: string.hpp:99