qxLib
string.inl
Go to the documentation of this file.
1 /**
2 
3  @file string.inl
4  @author Khrapov
5  @date 4.09.2019
6  @copyright © Nick Khrapov, 2021. All right reserved.
7 
8 **/
9 
10 namespace qx
11 {
12 
13 template<class char_t, class traits_t>
14 inline basic_string<char_t, traits_t>::basic_string(size_type nSymbols, value_type chSymbol) noexcept
15 {
16  assign(nSymbols, chSymbol);
17 }
18 
19 template<class char_t, class traits_t>
20 inline basic_string<char_t, traits_t>::basic_string(const_pointer pszSource, size_type nSymbols) noexcept
21 {
22  assign(pszSource, nSymbols);
23 }
24 
25 template<class char_t, class traits_t>
26 inline basic_string<char_t, traits_t>::basic_string(const_pointer pszSource) noexcept
27 {
28  assign(pszSource);
29 }
30 
31 template<class char_t, class traits_t>
33 {
34  assign(std::move(sAnother));
35 }
36 
37 template<class char_t, class traits_t>
39 {
40  assign(sAnother);
41 }
42 
43 template<class char_t, class traits_t>
44 template<class fwd_it_t>
45 inline basic_string<char_t, traits_t>::basic_string(fwd_it_t itFirst, fwd_it_t itLast) noexcept
46 {
47  assign(itFirst, itLast);
48 }
49 
50 template<class char_t, class traits_t>
51 template<range_of_t_c<char_t> string_t>
52 inline basic_string<char_t, traits_t>::basic_string(const string_t& sAnother) noexcept
53 {
54  assign(sAnother);
55 }
56 
57 template<class char_t, class traits_t>
59 {
60  free();
61 }
62 
63 template<class char_t, class traits_t>
64 inline void basic_string<char_t, traits_t>::assign(size_type nSymbols, value_type chSymbol) noexcept
65 {
66  if (_resize(nSymbols))
67  std::fill(begin(), end(), chSymbol);
68 }
69 
70 template<class char_t, class traits_t>
71 inline void basic_string<char_t, traits_t>::assign(const_pointer pszSource, size_type nSymbols) noexcept
72 {
73  if (pszSource && _resize(nSymbols))
74  std::memmove(data(), pszSource, nSymbols * sizeof(value_type));
75 }
76 
77 template<class char_t, class traits_t>
78 inline void basic_string<char_t, traits_t>::assign(const_pointer pszSource) noexcept
79 {
80  if (pszSource != data())
81  assign(pszSource, traits_t::length(pszSource));
82 }
83 
84 template<class char_t, class traits_t>
85 inline void basic_string<char_t, traits_t>::assign(basic_string&& sAnother) noexcept
86 {
87  std::swap(m_Data, sAnother.m_Data);
88 }
89 
90 template<class char_t, class traits_t>
91 inline void basic_string<char_t, traits_t>::assign(const basic_string& sAnother) noexcept
92 {
93  if (sAnother.data() != data())
94  assign(sAnother.data());
95 }
96 
97 template<class char_t, class traits_t>
98 template<class fwd_it_t>
99 inline void basic_string<char_t, traits_t>::assign(fwd_it_t itFirst, fwd_it_t itLast) noexcept
100 {
101  if (_resize(std::distance(itFirst, itLast)))
102  {
103  fwd_it_t itOther = itFirst;
104  iterator itThis = begin();
105 
106  while (itOther != itLast)
107  {
108  *itThis = *itOther;
109  ++itThis;
110  ++itOther;
111  }
112  }
113 }
114 
115 template<class char_t, class traits_t>
116 template<range_of_t_c<char_t> string_t>
117 inline void basic_string<char_t, traits_t>::assign(const string_t& sAnother) noexcept
118 {
119  assign(sAnother.cbegin(), sAnother.cend());
120 }
121 
122 template<class char_t, class traits_t>
123 template<class... args_t>
124  requires format_acceptable_args<char_t, args_t...>
126  const format_string_type<std::type_identity_t<args_t>...> sFormat,
127  args_t&&... args)
128 {
129  vformat(sFormat.get(), std::forward<args_t>(args)...);
130 }
131 
132 template<class char_t, class traits_t>
133 template<class... args_t>
134  requires format_acceptable_args<char_t, args_t...>
136  const format_string_type<std::type_identity_t<args_t>...> sFormat,
137  args_t&&... args)
138 {
139  return static_vformat(sFormat.get(), std::forward<args_t>(args)...);
140 }
141 
142 template<class char_t, class traits_t>
143 template<class... args_t>
144  requires format_acceptable_args<char_t, args_t...>
146  const format_string_type<std::type_identity_t<args_t>...> sFormat,
147  args_t&&... args)
148 {
149  append_vformat(sFormat.get(), std::forward<args_t>(args)...);
150 }
151 
152 template<class char_t, class traits_t>
153 template<class... args_t>
154  requires format_acceptable_args<char_t, args_t...>
155 void basic_string<char_t, traits_t>::vformat(string_view svFormat, args_t&&... args)
156 {
157  clear();
158  append_vformat(svFormat, std::forward<args_t>(args)...);
159 }
160 
161 template<class char_t, class traits_t>
162 template<class... args_t>
163  requires format_acceptable_args<char_t, args_t...>
165  string_view svFormat,
166  args_t&&... args)
167 {
168  basic_string sTemp;
169  sTemp.vformat(svFormat, std::forward<args_t>(args)...);
170  return sTemp;
171 }
172 
173 template<class char_t, class traits_t>
174 template<class... args_t>
175  requires format_acceptable_args<char_t, args_t...>
176 inline void basic_string<char_t, traits_t>::append_vformat(string_view svFormat, args_t&&... args)
177 {
178  if (!svFormat.empty())
179  traits_t::format_to(std::back_inserter(*this), svFormat, std::forward<args_t>(args)...);
180 }
181 
182 template<class char_t, class traits_t>
184 {
185  std::swap(m_Data, sOther.m_Data);
186 }
187 
188 template<class char_t, class traits_t>
189 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::reserve(
190  size_type nCapacity) noexcept
191 {
192  if (nCapacity > capacity())
193  _resize(nCapacity, string_resize_type::reserve);
194 
195  return capacity();
196 }
197 
198 template<class char_t, class traits_t>
200 {
201  if (!m_Data.is_small() && capacity() > size())
202  _resize(size(), string_resize_type::shrink_to_fit);
203 }
204 
205 template<class char_t, class traits_t>
207 {
208  m_Data.free();
209 }
210 
211 template<class char_t, class traits_t>
212 inline typename basic_string<char_t, traits_t>::string_view basic_string<char_t, traits_t>::substr(
213  size_type nPos,
214  size_type nSymbols) const noexcept
215 {
216  return string_view(data() + nPos, nSymbols != npos ? nSymbols : size() - nPos);
217 }
218 
219 template<class char_t, class traits_t>
221 {
222  for (value_type& ch : *this)
223  ch = traits_t::to_lower(ch);
224 }
225 
226 template<class char_t, class traits_t>
228 {
229  for (value_type& ch : *this)
230  ch = traits_t::to_upper(ch);
231 }
232 
233 template<class char_t, class traits_t>
234 inline typename basic_string<char_t, traits_t>::value_type basic_string<char_t, traits_t>::front() const noexcept
235 {
236  return at(0);
237 }
238 
239 template<class char_t, class traits_t>
240 inline typename basic_string<char_t, traits_t>::value_type basic_string<char_t, traits_t>::back() const noexcept
241 {
242  return at(size() - 1);
243 }
244 
245 template<class char_t, class traits_t>
246 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::length() const noexcept
247 {
248  return size();
249 }
250 
251 template<class char_t, class traits_t>
252 inline typename basic_string<char_t, traits_t>::const_pointer basic_string<char_t, traits_t>::c_str() const noexcept
253 {
254  return data();
255 }
256 
257 template<class char_t, class traits_t>
258 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::capacity() const noexcept
259 {
260  return m_Data.capacity();
261 }
262 
263 template<class char_t, class traits_t>
264 constexpr typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::max_size() noexcept
265 {
266  return std::numeric_limits<size_type>::max() - 1 // npos reserved
267  - 1; // null terminator
268 }
269 
270 template<class char_t, class traits_t>
271 template<class to_t>
272 inline std::optional<to_t> basic_string<char_t, traits_t>::to(const_pointer pszFormat) const noexcept
273 {
274  std::optional<to_t> optResult = std::nullopt;
275 
276  if constexpr (
277  std::is_trivial_v<to_t> && std::is_standard_layout_v<to_t> || std::is_pointer_v<to_t>
278  || std::is_same_v<to_t, std::nullptr_t>)
279  {
280  if constexpr (std::is_same_v<to_t, std::nullptr_t>)
281  {
282  if (compare(QX_STR_PREFIX(typename traits_t::value_type, "nullptr")) == 0)
283  {
284  optResult = nullptr;
285  }
286  }
287  else if constexpr (std::is_same_v<to_t, bool>)
288  {
289  if (compare(QX_STR_PREFIX(typename traits_t::value_type, "true")) == 0)
290  {
291  optResult = true;
292  }
293  else if (compare(QX_STR_PREFIX(typename traits_t::value_type, "false")) == 0)
294  {
295  optResult = false;
296  }
297  }
298  else if (const auto pszSelectedFormat = pszFormat ? pszFormat : get_format_specifier<value_type, to_t>())
299  {
300  to_t result;
301  const int nConvertedArgs = traits_t::sscanf(data(), pszSelectedFormat, &result);
302 
303  if (nConvertedArgs == 1)
304  optResult = result;
305  }
306  }
307  else
308  {
309  to_t result;
310  sstream_type ss(data());
311  ss >> result;
312  optResult = result;
313  }
314 
315  return optResult;
316 }
317 
318 template<class char_t, class traits_t>
319 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::copy(
320  pointer pDest,
321  size_type nCount,
322  size_type nPos) const noexcept
323 {
324  size_type nCharsToCopy = 0;
325 
326  if (pDest && nCount > 0 && nPos < size())
327  {
328  nCharsToCopy = std::min(nPos + nCount, size()) - nPos;
329  std::memcpy(pDest, data() + nPos, nCharsToCopy * sizeof(value_type));
330  }
331 
332  return nCharsToCopy;
333 }
334 
335 template<class char_t, class traits_t>
336 template<class from_t>
337 inline void basic_string<char_t, traits_t>::from(const from_t& data)
338 {
339  if constexpr (
340  std::is_trivial_v<from_t> && std::is_standard_layout_v<from_t> || std::is_pointer_v<from_t>
341  || std::is_same_v<from_t, std::nullptr_t>)
342  {
343  if constexpr (std::is_same_v<from_t, std::nullptr_t>)
344  {
345  assign(QX_STR_PREFIX(typename traits_t::value_type, "nullptr"));
346  }
347  else if constexpr (std::is_same_v<from_t, bool>)
348  {
349  assign(
350  data ? QX_STR_PREFIX(typename traits_t::value_type, "true")
351  : QX_STR_PREFIX(typename traits_t::value_type, "false"));
352  }
353  else
354  {
355  format(QX_STR_PREFIX(typename traits_t::value_type, "{}"), data);
356  }
357  }
358  else
359  {
360  sstream_type ss;
361  ss << data;
362  assign(ss.str());
363  }
364 }
365 
366 template<class char_t, class traits_t>
367 template<class from_t>
368 inline basic_string<char_t, traits_t> basic_string<char_t, traits_t>::static_from(const from_t& data)
369 {
370  basic_string sTemp;
371  sTemp.from(data);
372  return std::move(sTemp);
373 }
374 
375 template<class char_t, class traits_t>
376 inline void basic_string<char_t, traits_t>::append(value_type chSymbol) noexcept
377 {
378  append(&chSymbol, 1);
379 }
380 
381 template<class char_t, class traits_t>
382 inline void basic_string<char_t, traits_t>::append(const_pointer pszStr, size_type nSymbols) noexcept
383 {
384  if (pszStr)
385  {
386  const size_type nSize = size();
387  const size_type nSizeSource = nSymbols == npos ? traits_t::length(pszStr) : nSymbols;
388 
389  if (_resize(nSize + nSizeSource))
390  std::memcpy(data() + nSize, pszStr, nSizeSource * sizeof(value_type));
391  }
392 }
393 
394 template<class char_t, class traits_t>
395 inline void basic_string<char_t, traits_t>::append(const basic_string& sStr) noexcept
396 {
397  append(sStr.data(), sStr.size());
398 }
399 
400 template<class char_t, class traits_t>
401 template<class fwd_it_t>
402 inline void basic_string<char_t, traits_t>::append(fwd_it_t itBegin, fwd_it_t itEnd) noexcept
403 {
404  for (auto it = itBegin; it != itEnd; ++it)
405  push_back(*it);
406 }
407 
408 template<class char_t, class traits_t>
409 template<range_of_t_c<char_t> string_t>
410 inline void basic_string<char_t, traits_t>::append(const string_t& sStr) noexcept
411 {
412  append(sStr.cbegin(), sStr.cend());
413 }
414 
415 template<class char_t, class traits_t>
416 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::insert(
417  size_type nPos,
418  value_type chSymbol) noexcept
419 {
420  return insert(nPos, &chSymbol, 1);
421 }
422 
423 template<class char_t, class traits_t>
424 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::insert(
425  size_type nPos,
426  const_pointer pszWhat,
427  size_type nSymbols) noexcept
428 {
429  if (pszWhat)
430  {
431  const size_type nSize = size();
432  const size_type nSizeSource = nSymbols == npos ? traits_t::length(pszWhat) : nSymbols;
433 
434  if (nSizeSource > 0 && _resize(nSize + nSizeSource))
435  {
436  std::memmove(data() + nPos + nSizeSource, data() + nPos, (nSize - nPos) * sizeof(value_type));
437  std::memcpy(data() + nPos, pszWhat, nSizeSource * sizeof(value_type));
438  return nPos + nSizeSource;
439  }
440  }
441 
442  return npos;
443 }
444 
445 template<class char_t, class traits_t>
446 template<class fwd_it_t>
447 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::insert(
448  size_type nPos,
449  fwd_it_t itWhatBegin,
450  fwd_it_t itWhatEnd) noexcept
451 {
452  if constexpr (is_random_access_iterator<fwd_it_t>)
453  {
454  return insert(nPos, itWhatBegin.operator->(), static_cast<size_type>(itWhatEnd - itWhatBegin));
455  }
456  else
457  {
458  size_type nWhatSize = 0;
459  for (auto it = itWhatBegin; it != itWhatEnd; ++it)
460  ++nWhatSize;
461 
462  size_type nStartSymbols = size();
463  if (nWhatSize > 0 && _resize(nStartSymbols + nWhatSize))
464  {
465  std::memmove(data() + nPos + nWhatSize, data() + nPos, (nStartSymbols - nPos) * sizeof(value_type));
466 
467  size_type nWhatPos = 0;
468  for (auto it = itWhatBegin; it != itWhatEnd; ++it)
469  {
470  at(nPos + nWhatPos) = *it;
471  ++nWhatPos;
472  }
473 
474  return nPos + nWhatSize;
475  }
476  else
477  {
478  return npos;
479  }
480  }
481 }
482 
483 template<class char_t, class traits_t>
484 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::insert(
485  size_type nPos,
486  const basic_string& sWhat) noexcept
487 {
488  return insert(nPos, sWhat.data(), sWhat.size());
489 }
490 
491 template<class char_t, class traits_t>
492 template<range_of_t_c<char_t> string_t>
493 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::insert(
494  size_type nPos,
495  string_t sWhat) noexcept
496 {
497  return insert(static_cast<size_type>(nPos), sWhat.cbegin(), sWhat.cend());
498 }
499 
500 template<class char_t, class traits_t>
501 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::insert(
502  const_iterator itPos,
503  value_type chSymbol) noexcept
504 {
505  return insert(static_cast<size_type>(itPos - cbegin()), chSymbol);
506 }
507 
508 template<class char_t, class traits_t>
509 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::insert(
510  const_iterator itPos,
511  const_pointer pszWhat,
512  size_type nSymbols) noexcept
513 {
514  return insert(static_cast<size_type>(itPos - cbegin()), pszWhat, nSymbols);
515 }
516 
517 template<class char_t, class traits_t>
518 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::insert(
519  const_iterator itPos,
520  const basic_string& sWhat) noexcept
521 {
522  return insert(static_cast<size_type>(itPos - cbegin()), sWhat.data(), sWhat.size());
523 }
524 
525 template<class char_t, class traits_t>
526 template<class fwd_it_t>
527 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::insert(
528  const_iterator itPos,
529  fwd_it_t itWhatBegin,
530  fwd_it_t itWhatEnd) noexcept
531 {
532  return insert(static_cast<size_type>(itPos - begin()), itWhatBegin, itWhatEnd);
533 }
534 
535 template<class char_t, class traits_t>
536 template<range_of_t_c<char_t> string_t>
537 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::insert(
538  const_iterator itPos,
539  string_t sWhat) noexcept
540 {
541  return insert(static_cast<size_type>(itPos - begin()), sWhat.cbegin(), sWhat.cend());
542 }
543 
544 template<class char_t, class traits_t>
545 inline void basic_string<char_t, traits_t>::push_back(value_type chSymbol) noexcept
546 {
547  insert(size(), &chSymbol, 1);
548 }
549 
550 template<class char_t, class traits_t>
551 inline void basic_string<char_t, traits_t>::push_front(value_type chSymbol) noexcept
552 {
553  insert(0, &chSymbol, 1);
554 }
555 
556 template<class char_t, class traits_t>
557 inline void basic_string<char_t, traits_t>::erase(iterator itFirst, iterator itLast) noexcept
558 {
559  if (const typename iterator::difference_type nCharsToErase = itLast - itFirst; nCharsToErase > 0)
560  {
561  const size_type nStartSize = size();
562  const size_type nSymbolsToCopy = itLast != end() ? traits_t::length(itLast.operator->()) : 0;
563 
564  if (nSymbolsToCopy > 0)
565  {
566  std::memmove(itFirst.operator->(), itLast.operator->(), nSymbolsToCopy * sizeof(value_type));
567  }
568 
569  if (static_cast<typename iterator::difference_type>(nStartSize) >= nCharsToErase)
570  {
571  _resize(nStartSize - nCharsToErase);
572  }
573  }
574 }
575 
576 template<class char_t, class traits_t>
578 {
579  erase(itPos, itPos + 1);
580 }
581 
582 template<class char_t, class traits_t>
583 inline void basic_string<char_t, traits_t>::erase(size_type nPos) noexcept
584 {
585  erase(iterator(this, nPos), iterator(this, nPos + 1));
586 }
587 
588 template<class char_t, class traits_t>
589 inline void basic_string<char_t, traits_t>::erase(size_type nPos, size_type nSymbols) noexcept
590 {
591  erase(iterator(this, nPos), iterator(this, nPos + nSymbols));
592 }
593 
594 template<class char_t, class traits_t>
595 inline typename basic_string<char_t, traits_t>::value_type basic_string<char_t, traits_t>::pop_back() noexcept
596 {
597  value_type chRet = back();
598  erase(size() - 1);
599  return chRet;
600 }
601 
602 template<class char_t, class traits_t>
603 inline typename basic_string<char_t, traits_t>::value_type basic_string<char_t, traits_t>::pop_front() noexcept
604 {
605  value_type chRet = front();
606  erase(0);
607  return chRet;
608 }
609 
610 template<class char_t, class traits_t>
611 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim_left() noexcept
612 {
613  return _trim_left(
614  [](value_type ch)
615  {
616  return traits_t::is_space(ch);
617  });
618 }
619 
620 template<class char_t, class traits_t>
621 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim_left(
622  value_type chSymbol) noexcept
623 {
624  return _trim_left(
625  [chSymbol](value_type ch)
626  {
627  return ch == chSymbol;
628  });
629 }
630 
631 template<class char_t, class traits_t>
632 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim_left(
633  const_pointer pszStr) noexcept
634 {
635  if (pszStr)
636  {
637  return _trim_left(
638  [pszStr](value_type ch)
639  {
640  for (size_type j = 0; pszStr[j] != QX_CHAR_PREFIX(value_type, '\0'); ++j)
641  {
642  if (pszStr[j] == ch)
643  return true;
644  }
645 
646  return false;
647  });
648  }
649  else
650  {
651  return 0;
652  }
653 }
654 
655 template<class char_t, class traits_t>
656 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim_left(
657  const_pointer pszStr,
658  size_type nStrSize) noexcept
659 {
660  if (pszStr)
661  {
662  return _trim_left(
663  [pszStr, nStrSize](value_type ch)
664  {
665  for (size_type j = 0; j < nStrSize; ++j)
666  if (pszStr[j] == ch)
667  return true;
668 
669  return false;
670  });
671  }
672  else
673  {
674  return 0;
675  }
676 }
677 
678 template<class char_t, class traits_t>
679 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim_left(
680  const basic_string& sStr) noexcept
681 {
682  return trim_left(sStr.data(), sStr.size());
683 }
684 
685 template<class char_t, class traits_t>
686 template<class fwd_it_t>
687 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim_left(
688  fwd_it_t itBegin,
689  fwd_it_t itEnd) noexcept
690 {
691  return _trim_left(
692  [itBegin, itEnd](auto ch)
693  {
694  for (auto it = itBegin; it != itEnd; ++it)
695  if (*it == ch)
696  return true;
697 
698  return false;
699  });
700 }
701 
702 template<class char_t, class traits_t>
703 template<range_of_t_c<char_t> string_t>
704 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim_left(
705  const string_t& sStr) noexcept
706 {
707  return trim_left(sStr.cbegin(), sStr.cend());
708 }
709 
710 template<class char_t, class traits_t>
711 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim_right() noexcept
712 {
713  return _trim_right(
714  [](value_type ch)
715  {
716  return traits_t::is_space(ch);
717  });
718 }
719 
720 template<class char_t, class traits_t>
721 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim_right(
722  value_type chSymbol) noexcept
723 {
724  return _trim_right(
725  [chSymbol](value_type ch)
726  {
727  return ch == chSymbol;
728  });
729 }
730 
731 template<class char_t, class traits_t>
732 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim_right(
733  const_pointer pszStr) noexcept
734 {
735  if (pszStr)
736  {
737  return _trim_right(
738  [pszStr](value_type ch)
739  {
740  for (size_type j = 0; pszStr[j] != QX_CHAR_PREFIX(value_type, '\0'); ++j)
741  {
742  if (pszStr[j] == ch)
743  return true;
744  }
745 
746  return false;
747  });
748  }
749  else
750  {
751  return 0;
752  }
753 }
754 
755 template<class char_t, class traits_t>
756 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim_right(
757  const_pointer pszStr,
758  size_type nStrSize) noexcept
759 {
760  if (pszStr)
761  {
762  return _trim_right(
763  [pszStr, nStrSize](value_type ch)
764  {
765  for (size_type j = 0; j < nStrSize; ++j)
766  if (pszStr[j] == ch)
767  return true;
768 
769  return false;
770  });
771  }
772  else
773  {
774  return 0;
775  }
776 }
777 
778 template<class char_t, class traits_t>
779 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim_right(
780  const basic_string& sStr) noexcept
781 {
782  return trim_right(sStr.data(), sStr.size());
783 }
784 
785 template<class char_t, class traits_t>
786 template<class fwd_it_t>
787 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim_right(
788  fwd_it_t itBegin,
789  fwd_it_t itEnd) noexcept
790 {
791  return _trim_right(
792  [itBegin, itEnd](auto ch)
793  {
794  for (auto it = itBegin; it != itEnd; ++it)
795  if (*it == ch)
796  return true;
797 
798  return false;
799  });
800 }
801 
802 template<class char_t, class traits_t>
803 template<range_of_t_c<char_t> string_t>
804 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim_right(
805  const string_t& sStr) noexcept
806 {
807  return trim_right(sStr.cbegin(), sStr.cend());
808 }
809 
810 template<class char_t, class traits_t>
811 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim() noexcept
812 {
813  return _trim(
814  [](value_type ch)
815  {
816  return traits_t::is_space(ch);
817  });
818 }
819 
820 template<class char_t, class traits_t>
821 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim(
822  value_type chSymbol) noexcept
823 {
824  return _trim(
825  [chSymbol](value_type ch)
826  {
827  return ch == chSymbol;
828  });
829 }
830 
831 template<class char_t, class traits_t>
832 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim(
833  const_pointer pszStr) noexcept
834 {
835  if (pszStr)
836  {
837  return _trim(
838  [pszStr](value_type ch)
839  {
840  for (size_type j = 0; pszStr[j] != QX_CHAR_PREFIX(value_type, '\0'); ++j)
841  {
842  if (pszStr[j] == ch)
843  return true;
844  }
845 
846  return false;
847  });
848  }
849  else
850  {
851  return 0;
852  }
853 }
854 
855 template<class char_t, class traits_t>
856 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim(
857  const_pointer pszStr,
858  size_type nStrSize) noexcept
859 {
860  if (pszStr)
861  {
862  return _trim(
863  [pszStr, nStrSize](value_type ch)
864  {
865  for (size_type j = 0; j < nStrSize; ++j)
866  if (pszStr[j] == ch)
867  return true;
868 
869  return false;
870  });
871  }
872  else
873  {
874  return 0;
875  }
876 }
877 
878 template<class char_t, class traits_t>
879 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim(
880  const basic_string& sStr) noexcept
881 {
882  return trim(sStr.data(), sStr.size());
883 }
884 
885 template<class char_t, class traits_t>
886 template<class fwd_it_t>
887 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim(
888  fwd_it_t itBegin,
889  fwd_it_t itEnd) noexcept
890 {
891  return _trim(
892  [itBegin, itEnd](auto ch)
893  {
894  for (auto it = itBegin; it != itEnd; ++it)
895  if (*it == ch)
896  return true;
897 
898  return false;
899  });
900 }
901 
902 template<class char_t, class traits_t>
903 template<range_of_t_c<char_t> string_t>
904 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::trim(
905  const string_t& sStr) noexcept
906 {
907  return trim(sStr.cbegin(), sStr.cend());
908 }
909 
910 template<class char_t, class traits_t>
911 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::remove(
912  value_type chSymbol,
913  size_type nBegin,
914  size_type nEnd) noexcept
915 {
916  size_type nPos = find(chSymbol, nBegin, nEnd);
917 
918  if (nPos != npos)
919  erase(nPos, 1);
920 
921  return nPos;
922 }
923 
924 template<class char_t, class traits_t>
925 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::remove(
926  const_pointer pszStr,
927  size_type nBegin,
928  size_type nEnd,
929  size_type nStrSize) noexcept
930 {
931  if (pszStr)
932  {
933  const size_type nLocalStrSize = nStrSize != npos ? nStrSize : traits_t::length(pszStr);
934  const size_type nPos = find(pszStr, nBegin, nLocalStrSize, nEnd);
935 
936  if (nPos != npos)
937  erase(nPos, nLocalStrSize);
938 
939  return nPos;
940  }
941  else
942  {
943  return npos;
944  }
945 }
946 
947 template<class char_t, class traits_t>
948 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::remove(
949  const basic_string& sStr,
950  size_type nBegin,
951  size_type nEnd) noexcept
952 {
953  const size_type nPos = find(sStr, nBegin, nEnd);
954 
955  if (nPos != npos)
956  erase(nPos, sStr.size());
957 
958  return nPos;
959 }
960 
961 template<class char_t, class traits_t>
962 template<class fwd_it_t>
963 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::remove(
964  fwd_it_t itBegin,
965  fwd_it_t itEnd,
966  size_type nBegin,
967  size_type nEnd) noexcept
968 {
969  const size_type nPos = find(itBegin, itEnd, nBegin, nEnd);
970 
971  if (nPos != npos)
972  erase(nPos, static_cast<size_type>(std::distance(itBegin, itEnd)));
973 
974  return nPos;
975 }
976 
977 template<class char_t, class traits_t>
978 template<range_of_t_c<char_t> string_t>
979 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::remove(
980  const string_t& sStr,
981  size_type nBegin,
982  size_type nEnd) noexcept
983 {
984  return remove(sStr.cbegin(), sStr.cend(), nBegin, nEnd);
985 }
986 
987 template<class char_t, class traits_t>
988 inline bool basic_string<char_t, traits_t>::remove_prefix(value_type chSymbol) noexcept
989 {
990  return remove(chSymbol, static_cast<size_type>(0), static_cast<size_type>(1)) != npos;
991 }
992 
993 template<class char_t, class traits_t>
994 inline bool basic_string<char_t, traits_t>::remove_prefix(const_pointer pszStr, size_type nStrSize) noexcept
995 {
996  return remove(pszStr, static_cast<size_type>(0), nStrSize, nStrSize) != npos;
997 }
998 
999 template<class char_t, class traits_t>
1002  return remove(sStr, static_cast<size_type>(0), sStr.size()) != npos;
1003 }
1004 
1005 template<class char_t, class traits_t>
1006 template<class fwd_it_t>
1007 inline bool basic_string<char_t, traits_t>::remove_prefix(fwd_it_t itBegin, fwd_it_t itEnd) noexcept
1008 {
1009  return remove(itBegin, itEnd, static_cast<size_type>(0), static_cast<size_type>(std::distance(itBegin, itEnd)))
1010  != npos;
1011 }
1013 template<class char_t, class traits_t>
1014 template<range_of_t_c<char_t> string_t>
1015 inline bool basic_string<char_t, traits_t>::remove_prefix(const string_t& sStr) noexcept
1016 {
1017  return remove_prefix(sStr.cbegin(), sStr.cend());
1018 }
1019 
1020 template<class char_t, class traits_t>
1021 inline bool basic_string<char_t, traits_t>::remove_suffix(value_type chSymbol) noexcept
1022 {
1023  const size_type nSize = size();
1024  return remove(chSymbol, nSize - 1, nSize) != npos;
1025 }
1027 template<class char_t, class traits_t>
1028 inline bool basic_string<char_t, traits_t>::remove_suffix(const_pointer pszStr, size_type nStrSize) noexcept
1029 {
1030  if (pszStr)
1031  {
1032  const size_type nSize = size();
1033  const size_type nLocalStrSize = nStrSize != npos ? nStrSize : traits_t::length(pszStr);
1034 
1035  return remove(pszStr, nSize - nLocalStrSize, nSize, nLocalStrSize) != npos;
1036  }
1037  else
1038  {
1039  return false;
1040  }
1041 }
1042 
1043 template<class char_t, class traits_t>
1045 {
1046  return remove_suffix(sStr.data(), sStr.size());
1047 }
1049 template<class char_t, class traits_t>
1050 template<class fwd_it_t>
1051 inline bool basic_string<char_t, traits_t>::remove_suffix(fwd_it_t itBegin, fwd_it_t itEnd) noexcept
1052 {
1053  const size_type nSize = size();
1054  return remove(itBegin, itEnd, nSize - static_cast<size_type>(std::distance(itBegin, itEnd)), nSize) != npos;
1055 }
1056 
1057 template<class char_t, class traits_t>
1058 template<range_of_t_c<char_t> string_t>
1059 inline bool basic_string<char_t, traits_t>::remove_suffix(const string_t& sStr) noexcept
1060 {
1061  return remove_suffix(sStr.cbegin(), sStr.cend());
1062 }
1063 
1064 template<class char_t, class traits_t>
1065 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::remove_all(
1066  value_type chSymbol,
1067  size_type nBegin,
1068  size_type nEnd) noexcept
1069 {
1070  size_type nOccurrences = 0;
1071  size_type nLastOccurrencePos = nBegin;
1072 
1073  do
1074  {
1075  ++nOccurrences;
1076  nLastOccurrencePos = remove(chSymbol, nLastOccurrencePos, nEnd);
1077  } while (nLastOccurrencePos != npos);
1078 
1079  return nOccurrences - 1;
1081 
1082 template<class char_t, class traits_t>
1083 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::remove_all(
1084  const_pointer pszStr,
1085  size_type nBegin,
1086  size_type nEnd,
1087  size_type nStrSize) noexcept
1088 {
1089  if (pszStr)
1090  {
1091  size_type nOccurrences = 0;
1092  size_type nLastOccurrencePos = nBegin;
1093 
1094  do
1095  {
1096  ++nOccurrences;
1097  nLastOccurrencePos = remove(pszStr, nLastOccurrencePos, nEnd, nStrSize);
1098  } while (nLastOccurrencePos != npos);
1099 
1100  return nOccurrences - 1;
1101  }
1102  else
1103  {
1104  return 0;
1105  }
1106 }
1107 
1108 template<class char_t, class traits_t>
1109 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::remove_all(
1110  const basic_string& sStr,
1111  size_type nBegin,
1112  size_type nEnd) noexcept
1114  return remove_all(sStr.data(), nBegin, nEnd, sStr.size());
1115 }
1116 
1117 template<class char_t, class traits_t>
1118 template<class fwd_it_t>
1119 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::remove_all(
1120  fwd_it_t itFirst,
1121  fwd_it_t itLast,
1122  size_type nBegin,
1123  size_type nEnd) noexcept
1125  size_type nOccurrences = 0;
1126  size_type nLastOccurrencePos = nBegin;
1127 
1128  do
1129  {
1130  ++nOccurrences;
1131  nLastOccurrencePos = remove(itFirst, itLast, nLastOccurrencePos, nEnd);
1132  } while (nLastOccurrencePos != npos);
1133 
1134  return nOccurrences - 1;
1135 }
1136 
1137 template<class char_t, class traits_t>
1138 template<range_of_t_c<char_t> string_t>
1139 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::remove_all(
1140  const string_t& sStr,
1141  size_type nBegin,
1142  size_type nEnd) noexcept
1143 {
1144  return remove_all(sStr.cbegin(), sStr.cend(), nBegin, nEnd);
1145 }
1146 
1147 template<class char_t, class traits_t>
1148 typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::replace(
1149  size_type nBegin,
1150  size_type nSize,
1151  const_pointer pszReplace,
1152  size_t nReplaceSize) noexcept
1153 {
1154  const size_type nStartSize = size();
1155  const size_type nNewSize = nStartSize - nSize + nReplaceSize;
1156 
1157  _resize(nNewSize, string_resize_type::reserve);
1159  std::memmove(
1160  data() + nBegin + nReplaceSize,
1161  data() + nBegin + nSize,
1162  (nStartSize - nBegin - nSize) * sizeof(value_type));
1163 
1164  std::memcpy(data() + nBegin, pszReplace, nReplaceSize * sizeof(value_type));
1165 
1166  _resize(nNewSize);
1168  return nBegin + nReplaceSize;
1169 }
1170 
1171 template<class char_t, class traits_t>
1172 template<class replace_string_t>
1173 typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::replace(
1174  size_type nBegin,
1175  size_type nSize,
1176  const replace_string_t& sReplace) noexcept
1177 {
1178  return replace(nBegin, nSize, _get_string_view_like_data(sReplace), _get_string_view_like_size(sReplace));
1179 }
1180 
1181 template<class char_t, class traits_t>
1182 template<class find_string_t, class replace_string_t>
1183 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::replace(
1184  const find_string_t& sFind,
1185  const replace_string_t& sReplace,
1186  size_type nBegin,
1187  size_type nEnd) noexcept
1188 {
1189  if (size_type nPos = find(sFind, nBegin, nEnd); nPos != npos)
1190  {
1191  return replace(
1192  nPos,
1193  _get_string_view_like_size(sFind),
1194  _get_string_view_like_data(sReplace),
1195  _get_string_view_like_size(sReplace));
1196  }
1197  else
1198  {
1199  return npos;
1200  }
1201 }
1202 
1203 template<class char_t, class traits_t>
1204 template<class find_string_t, class replace_string_t>
1205 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::replace_all(
1206  const find_string_t& sFind,
1207  const replace_string_t& sReplace,
1208  size_type nBegin,
1209  size_type nEnd) noexcept
1210 {
1211  size_type nOccurrences = 0;
1212  size_type nPos = nBegin;
1213 
1214  do
1215  {
1216  nPos = replace(sFind, sReplace, nPos, nEnd);
1217  if (nPos != npos)
1218  ++nOccurrences;
1219  } while (nPos != npos);
1220 
1221  return nOccurrences;
1222 }
1223 
1224 template<class char_t, class traits_t>
1225 inline int basic_string<char_t, traits_t>::compare(value_type chSymbol) const noexcept
1226 {
1227  return compare(&chSymbol, 1);
1228 }
1230 template<class char_t, class traits_t>
1231 inline int basic_string<char_t, traits_t>::compare(const_pointer pszStr) const noexcept
1232 {
1233  return traits_t::compare(data(), pszStr);
1234 }
1235 
1236 template<class char_t, class traits_t>
1237 inline int basic_string<char_t, traits_t>::compare(const_pointer pStr, size_type nSymbols) const noexcept
1238 {
1239  return traits_t::compare_n(data(), pStr, nSymbols);
1240 }
1241 
1242 template<class char_t, class traits_t>
1243 inline int basic_string<char_t, traits_t>::compare(const basic_string& sStr) const noexcept
1244 {
1245  return compare(sStr.data(), sStr.size());
1246 }
1247 
1248 template<class char_t, class traits_t>
1249 template<class fwd_it_t>
1250 inline int basic_string<char_t, traits_t>::compare(fwd_it_t itBegin, fwd_it_t itEnd) const noexcept
1251 {
1252  return iter_strcmp(cbegin(), cend(), itBegin, itEnd);
1253 }
1254 
1255 template<class char_t, class traits_t>
1256 template<range_of_t_c<char_t> string_t>
1257 inline int basic_string<char_t, traits_t>::compare(const string_t& sStr) const noexcept
1259  return compare(sStr.cbegin(), sStr.cend());
1260 }
1261 
1262 template<class char_t, class traits_t>
1263 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find(
1264  value_type chSymbol,
1265  size_type nBegin,
1266  size_type nEnd) const noexcept
1267 {
1268  return _find(
1269  nBegin,
1270  nEnd,
1271  [chSymbol](const_pointer pCurrentChar)
1272  {
1273  return *pCurrentChar == chSymbol;
1274  });
1276 
1277 template<class char_t, class traits_t>
1278 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find(
1279  const_pointer pszWhat,
1280  size_type nBegin,
1281  size_type nWhatSize,
1282  size_type nEnd) const noexcept
1284  if (pszWhat)
1285  {
1286  const size_type nLocalWhatSize = nWhatSize != npos ? nWhatSize : traits_t::length(pszWhat);
1287 
1288  return _find(
1289  nBegin,
1290  nEnd,
1291  [pszWhat, nLocalWhatSize](const_pointer pCurrentChar)
1292  {
1293  return !traits_t::compare_n(pszWhat, pCurrentChar, nLocalWhatSize);
1294  });
1295  }
1296  else
1297  {
1298  return npos;
1299  }
1300 }
1301 
1302 template<class char_t, class traits_t>
1303 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find(
1304  const basic_string& sWhat,
1305  size_type nBegin,
1306  size_type nEnd) const noexcept
1307 {
1308  return find(sWhat.data(), nBegin, sWhat.size(), nEnd);
1309 }
1310 
1311 template<class char_t, class traits_t>
1312 template<class fwd_it_t>
1313 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find(
1314  fwd_it_t itWhatBegin,
1315  fwd_it_t itWhatEnd,
1316  size_type nBegin,
1317  size_type nEnd) const noexcept
1318 {
1319  return _find(
1320  nBegin,
1321  nEnd,
1322  [this, itWhatBegin, itWhatEnd, nEnd](const_pointer pCurrentChar)
1323  {
1324  return !iter_strcmp(
1325  const_iterator(this, static_cast<size_type>(pCurrentChar - data())),
1326  const_iterator(this, static_cast<size_type>(nEnd)),
1327  itWhatBegin,
1328  itWhatEnd);
1329  });
1330 }
1331 
1332 template<class char_t, class traits_t>
1333 template<range_of_t_c<char_t> string_t>
1334 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find(
1335  string_t sWhat,
1336  size_type nBegin,
1337  size_type nEnd) const noexcept
1338 {
1339  return find(sWhat.cbegin(), sWhat.cend(), nBegin, nEnd);
1340 }
1341 
1342 template<class char_t, class traits_t>
1343 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::rfind(
1344  value_type chSymbol,
1345  size_type nBegin,
1346  size_type nEnd) const noexcept
1347 {
1348  return _rfind(
1349  nBegin,
1350  nEnd,
1351  [chSymbol](const_pointer pCurrentChar)
1352  {
1353  return *pCurrentChar == chSymbol;
1354  });
1355 }
1357 template<class char_t, class traits_t>
1358 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::rfind(
1359  const_pointer pszWhat,
1360  size_type nBegin,
1361  size_type nWhatSize,
1362  size_type nEnd) const noexcept
1363 {
1364  if (pszWhat)
1365  {
1366  const size_type nLocalWhatSize = nWhatSize != npos ? nWhatSize : traits_t::length(pszWhat);
1367 
1368  return _rfind(
1369  nBegin,
1370  nEnd,
1371  [pszWhat, nLocalWhatSize](const_pointer pCurrentChar)
1372  {
1373  return !traits_t::compare_n(pszWhat, pCurrentChar, nLocalWhatSize);
1374  });
1375  }
1376  else
1377  {
1378  return npos;
1379  }
1380 }
1382 template<class char_t, class traits_t>
1383 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::rfind(
1384  const basic_string& sWhat,
1385  size_type nBegin,
1386  size_type nEnd) const noexcept
1387 {
1388  return rfind(sWhat.data(), nBegin, sWhat.size(), nEnd);
1389 }
1390 
1391 template<class char_t, class traits_t>
1392 template<class fwd_it_t>
1393 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::rfind(
1394  fwd_it_t itWhatBegin,
1395  fwd_it_t itWhatEnd,
1396  size_type nBegin,
1397  size_type nEnd) const noexcept
1399  return _rfind(
1400  nBegin,
1401  nEnd,
1402  [this, itWhatBegin, itWhatEnd, nEnd](const_pointer pCurrentChar)
1403  {
1404  return !iter_strcmp(
1405  const_iterator(this, static_cast<size_type>(pCurrentChar - data())),
1406  const_iterator(this, static_cast<size_type>(nEnd)),
1407  itWhatBegin,
1408  itWhatEnd);
1409  });
1410 }
1411 
1412 template<class char_t, class traits_t>
1413 template<range_of_t_c<char_t> string_t>
1414 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::rfind(
1415  string_t sWhat,
1416  size_type nBegin,
1417  size_type nEnd) const noexcept
1418 {
1419  return rfind(sWhat.cbegin(), sWhat.cend(), nBegin, nEnd);
1420 }
1421 
1422 template<class char_t, class traits_t>
1423 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_first_of(
1424  value_type chSymbol,
1425  size_type nBegin) const noexcept
1426 {
1427  return find(chSymbol, nBegin);
1428 }
1430 template<class char_t, class traits_t>
1431 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_first_of(
1432  const_pointer pszWhat,
1433  size_type nBegin,
1434  size_type nWhatSize) const noexcept
1435 {
1436  if (pszWhat)
1437  {
1438  return _find_first_of(
1439  pszWhat,
1440  pszWhat + nWhatSize,
1441  nBegin,
1442  [](const_pointer pChar)
1443  {
1444  return pChar + 1;
1445  });
1446  }
1447  else
1448  {
1449  return npos;
1450  }
1451 }
1452 
1453 template<class char_t, class traits_t>
1454 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_first_of(
1455  const_pointer pszWhat,
1456  size_type nBegin) const noexcept
1457 {
1458  if (pszWhat)
1459  {
1460  return _find_first_of(
1461  pszWhat,
1462  static_cast<const_pointer>(nullptr),
1463  nBegin,
1464  [](const_pointer pChar)
1465  {
1466  return *(pChar + 1) != QX_CHAR_PREFIX(value_type, '\0') ? pChar + 1 : nullptr;
1467  });
1468  }
1469  else
1470  {
1471  return npos;
1472  }
1473 }
1474 
1475 template<class char_t, class traits_t>
1476 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_first_of(
1477  const basic_string& sWhat,
1478  size_type nBegin) const noexcept
1479 {
1480  return find_first_of(sWhat.data(), nBegin, sWhat.size());
1481 }
1482 
1483 template<class char_t, class traits_t>
1484 template<class fwd_it_t>
1485 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_first_of(
1486  fwd_it_t itWhatBegin,
1487  fwd_it_t itWhatEnd,
1488  size_type nBegin) const noexcept
1490  return _find_first_of(
1491  itWhatBegin,
1492  itWhatEnd,
1493  nBegin,
1494  [](fwd_it_t itChar)
1495  {
1496  return ++itChar;
1497  });
1498 }
1499 
1500 template<class char_t, class traits_t>
1501 template<range_of_t_c<char_t> string_t>
1502 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_first_of(
1503  string_t sWhat,
1504  size_type nBegin) const noexcept
1505 {
1506  return find_first_of(sWhat.cbegin(), sWhat.cend(), nBegin);
1507 }
1508 
1509 template<class char_t, class traits_t>
1510 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_last_of(
1511  value_type chSymbol,
1512  size_type nEnd) const noexcept
1513 {
1514  return rfind(chSymbol, npos, nEnd);
1515 }
1516 
1517 template<class char_t, class traits_t>
1518 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_last_of(
1519  const_pointer pszWhat,
1520  size_type nEnd,
1521  size_type nWhatSize) const noexcept
1522 {
1523  if (pszWhat)
1524  {
1525  return _find_last_of(
1526  pszWhat,
1527  pszWhat + nWhatSize,
1528  nEnd,
1529  [](const_pointer pChar)
1530  {
1531  return pChar + 1;
1532  });
1533  }
1534  else
1535  {
1536  return npos;
1537  }
1538 }
1539 
1540 template<class char_t, class traits_t>
1541 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_last_of(
1542  const_pointer pszWhat,
1543  size_type nEnd) const noexcept
1544 {
1545  if (pszWhat)
1546  {
1547  return _find_last_of(
1548  pszWhat,
1549  static_cast<const_pointer>(nullptr),
1550  nEnd,
1551  [](const_pointer pChar)
1552  {
1553  return *(pChar + 1) != QX_CHAR_PREFIX(value_type, '\0') ? pChar + 1 : nullptr;
1554  });
1555  }
1556  else
1557  {
1558  return npos;
1559  }
1560 }
1561 
1562 template<class char_t, class traits_t>
1563 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_last_of(
1564  const basic_string& sWhat,
1565  size_type nEnd) const noexcept
1566 {
1567  return find_last_of(sWhat.data(), nEnd, sWhat.size());
1568 }
1569 
1570 template<class char_t, class traits_t>
1571 template<class fwd_it_t>
1572 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_last_of(
1573  fwd_it_t itWhatBegin,
1574  fwd_it_t itWhatEnd,
1575  size_type nEnd) const noexcept
1576 {
1577  return _find_last_of(
1578  itWhatBegin,
1579  itWhatEnd,
1580  nEnd,
1581  [](fwd_it_t itChar)
1582  {
1583  return ++itChar;
1584  });
1585 }
1586 
1587 template<class char_t, class traits_t>
1588 template<range_of_t_c<char_t> string_t>
1589 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_last_of(
1590  string_t sWhat,
1591  size_type nEnd) const noexcept
1592 {
1593  return find_last_of(sWhat.cbegin(), sWhat.cend(), nEnd);
1594 }
1595 
1596 template<class char_t, class traits_t>
1597 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_first_not_of(
1598  value_type chSymbol,
1599  size_type nBegin) const noexcept
1600 {
1601  return _find(
1602  nBegin,
1603  npos,
1604  [chSymbol](const_pointer pCurrentChar)
1605  {
1606  return *pCurrentChar != chSymbol;
1607  });
1608 }
1609 
1610 template<class char_t, class traits_t>
1611 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_first_not_of(
1612  const_pointer pszWhat,
1613  size_type nBegin,
1614  size_type nWhatSize) const noexcept
1615 {
1616  if (pszWhat)
1617  {
1618  return _find_first_not_of(
1619  pszWhat,
1620  pszWhat + nWhatSize,
1621  nBegin,
1622  [](const_pointer pChar)
1623  {
1624  return pChar + 1;
1625  });
1626  }
1627  else
1628  {
1629  return npos;
1630  }
1631 }
1632 
1633 template<class char_t, class traits_t>
1634 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_first_not_of(
1635  const_pointer pszWhat,
1636  size_type nBegin) const noexcept
1637 {
1638  if (pszWhat)
1639  {
1640  return _find_first_not_of(
1641  pszWhat,
1642  static_cast<const_pointer>(nullptr),
1643  nBegin,
1644  [](const_pointer pChar)
1645  {
1646  return *(pChar + 1) != QX_CHAR_PREFIX(value_type, '\0') ? pChar + 1 : nullptr;
1647  });
1648  }
1649  else
1650  {
1651  return npos;
1652  }
1653 }
1654 
1655 template<class char_t, class traits_t>
1656 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_first_not_of(
1657  const basic_string& sWhat,
1658  size_type nBegin) const noexcept
1659 {
1660  return find_first_not_of(sWhat.data(), nBegin, sWhat.size());
1661 }
1662 
1663 template<class char_t, class traits_t>
1664 template<class fwd_it_t>
1665 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_first_not_of(
1666  fwd_it_t itWhatBegin,
1667  fwd_it_t itWhatEnd,
1668  size_type nBegin) const noexcept
1669 {
1670  return _find_first_not_of(
1671  itWhatBegin,
1672  itWhatEnd,
1673  nBegin,
1674  [](fwd_it_t itChar)
1675  {
1676  return ++itChar;
1677  });
1678 }
1679 
1680 template<class char_t, class traits_t>
1681 template<range_of_t_c<char_t> string_t>
1682 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_first_not_of(
1683  string_t sWhat,
1684  size_type nBegin) const noexcept
1685 {
1686  return find_first_not_of(sWhat.cbegin(), sWhat.cend(), nBegin);
1687 }
1688 
1689 template<class char_t, class traits_t>
1690 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_last_not_of(
1691  value_type chSymbol,
1692  size_type nEnd) const noexcept
1693 {
1694  return _rfind(
1695  npos,
1696  nEnd,
1697  [chSymbol](const_pointer pCurrentChar)
1698  {
1699  return *pCurrentChar != chSymbol;
1700  });
1701 }
1702 
1703 template<class char_t, class traits_t>
1704 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_last_not_of(
1705  const_pointer pszWhat,
1706  size_type nEnd,
1707  size_type nWhatSize) const noexcept
1708 {
1709  if (pszWhat)
1710  {
1711  return _find_last_not_of(
1712  pszWhat,
1713  pszWhat + nWhatSize,
1714  nEnd,
1715  [](const_pointer pChar)
1716  {
1717  return pChar + 1;
1718  });
1719  }
1720  else
1721  {
1722  return npos;
1723  }
1724 }
1725 
1726 template<class char_t, class traits_t>
1727 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_last_not_of(
1728  const_pointer pszWhat,
1729  size_type nEnd) const noexcept
1730 {
1731  if (pszWhat)
1732  {
1733  return _find_last_not_of(
1734  pszWhat,
1735  static_cast<const_pointer>(nullptr),
1736  nEnd,
1737  [](const_pointer pChar)
1738  {
1739  return *(pChar + 1) != QX_CHAR_PREFIX(value_type, '\0') ? pChar + 1 : nullptr;
1740  });
1741  }
1742  else
1743  {
1744  return npos;
1745  }
1746 }
1747 
1748 template<class char_t, class traits_t>
1749 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_last_not_of(
1750  const basic_string& sWhat,
1751  size_type nEnd) const noexcept
1752 {
1753  return find_last_not_of(sWhat.data(), nEnd, sWhat.size());
1754 }
1755 
1756 template<class char_t, class traits_t>
1757 template<class fwd_it_t>
1758 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_last_not_of(
1759  fwd_it_t itWhatBegin,
1760  fwd_it_t itWhatEnd,
1761  size_type nEnd) const noexcept
1762 {
1763  return _find_last_not_of(
1764  itWhatBegin,
1765  itWhatEnd,
1766  nEnd,
1767  [](fwd_it_t itChar)
1768  {
1769  return ++itChar;
1770  });
1771 }
1772 
1773 template<class char_t, class traits_t>
1774 template<range_of_t_c<char_t> string_t>
1775 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::find_last_not_of(
1776  string_t sWhat,
1777  size_type nEnd) const noexcept
1778 {
1779  return find_last_not_of(sWhat.cbegin(), sWhat.cend(), nEnd);
1780 }
1781 
1782 template<class char_t, class traits_t>
1783 inline typename basic_string<char_t, traits_t>::views basic_string<char_t, traits_t>::split(
1784  const value_type chSeparator) const noexcept
1785 {
1786  views tokens;
1787 
1788  size_type nStart = 0;
1789  size_type nEnd = 0;
1790  while ((nEnd = find(chSeparator, nStart)) != npos)
1791  {
1792  tokens.emplace_back(substr(nStart, nEnd - nStart));
1793  nStart = nEnd;
1794  while (traits_t::compare_n(data() + nStart, &chSeparator, 1) == 0)
1795  ++nStart;
1796  }
1797 
1798  if (nStart != size())
1799  tokens.emplace_back(substr(nStart));
1800 
1801  return std::move(tokens);
1802 }
1803 
1804 template<class char_t, class traits_t>
1805 inline typename basic_string<char_t, traits_t>::views basic_string<char_t, traits_t>::split(
1806  const_pointer pszSeparator,
1807  size_type nSepLen) const noexcept
1808 {
1809  views tokens;
1810 
1811  if (!pszSeparator)
1812  return tokens;
1813 
1814  if (nSepLen == npos)
1815  nSepLen = traits_t::length(pszSeparator);
1816 
1817  size_type nStart = 0;
1818  size_type nEnd = 0;
1819  while ((nEnd = find(pszSeparator, nStart, nSepLen, npos)) != npos)
1820  {
1821  tokens.emplace_back(substr(nStart, nEnd - nStart));
1822  nStart = nEnd;
1823  while (traits_t::compare_n(data() + nStart, pszSeparator, nSepLen) == 0)
1824  nStart += nSepLen;
1825  }
1826 
1827  if (nStart != size())
1828  tokens.emplace_back(substr(nStart));
1829 
1830  return tokens;
1831 }
1832 
1833 template<class char_t, class traits_t>
1834 inline typename basic_string<char_t, traits_t>::views basic_string<char_t, traits_t>::split(
1835  const basic_string& sSeparator) const noexcept
1836 {
1837  return split(sSeparator.data(), sSeparator.size());
1838 }
1839 
1840 template<class char_t, class traits_t>
1841 template<class fwd_it_t>
1842 inline typename basic_string<char_t, traits_t>::views basic_string<char_t, traits_t>::split(
1843  fwd_it_t itSepFirst,
1844  fwd_it_t itSepLast) const noexcept
1845 {
1846  views tokens;
1847 
1848  const size_type nSepLen = static_cast<size_type>(std::distance(itSepFirst, itSepLast));
1849 
1850  size_type nStart = 0;
1851  size_type nEnd = 0;
1852  while ((nEnd = find(itSepFirst, itSepLast, nStart)) != npos)
1853  {
1854  tokens.emplace_back(substr(nStart, nEnd - nStart));
1855  nStart = nEnd + nSepLen;
1856  }
1857  tokens.emplace_back(substr(nStart));
1858 
1859  return tokens;
1860 }
1861 
1862 template<class char_t, class traits_t>
1863 template<range_of_t_c<char_t> string_t>
1864 inline typename basic_string<char_t, traits_t>::views basic_string<char_t, traits_t>::split(
1865  const string_t& sSeparator) const noexcept
1866 {
1867  return split(sSeparator.cbegin(), sSeparator.cend());
1868 }
1869 
1870 template<class char_t, class traits_t>
1871 inline bool basic_string<char_t, traits_t>::starts_with(value_type chSymbol) const noexcept
1872 {
1873  if (!empty())
1874  return at(0) == chSymbol;
1875  else
1876  return false;
1877 }
1878 
1879 template<class char_t, class traits_t>
1880 inline bool basic_string<char_t, traits_t>::starts_with(const_pointer pszStr, size_type nStrSize) const noexcept
1881 {
1882  if (pszStr)
1883  {
1884  if (size_type nThisSize = size(); nThisSize > 0)
1885  {
1886  if (nStrSize == npos)
1887  nStrSize = traits_t::length(pszStr);
1888 
1889  if (nStrSize <= nThisSize)
1890  return traits_t::compare_n(data(), pszStr, nStrSize) == 0;
1891  }
1892  }
1893 
1894  return false;
1895 }
1896 
1897 template<class char_t, class traits_t>
1898 inline bool basic_string<char_t, traits_t>::starts_with(const basic_string& sStr) const noexcept
1899 {
1900  return starts_with(sStr.data(), sStr.size());
1901 }
1902 
1903 template<class char_t, class traits_t>
1904 template<class fwd_it_t>
1905 inline bool basic_string<char_t, traits_t>::starts_with(fwd_it_t itBegin, fwd_it_t itEnd) const noexcept
1906 {
1907  auto nStrSize = std::distance(itBegin, itEnd);
1908  return iter_strcmp(cbegin(), cbegin() + static_cast<size_type>(nStrSize), itBegin, itEnd) == 0;
1909 }
1910 
1911 template<class char_t, class traits_t>
1912 template<range_of_t_c<char_t> string_t>
1913 inline bool basic_string<char_t, traits_t>::starts_with(const string_t& sStr) const noexcept
1914 {
1915  return starts_with(sStr.cbegin(), sStr.cend());
1916 }
1917 
1918 template<class char_t, class traits_t>
1919 inline bool basic_string<char_t, traits_t>::ends_with(value_type chSymbol) const noexcept
1920 {
1921  const size_type nSize = size();
1922  if (nSize > 0)
1923  return at(nSize - 1) == chSymbol;
1924  else
1925  return false;
1926 }
1927 
1928 template<class char_t, class traits_t>
1929 inline bool basic_string<char_t, traits_t>::ends_with(const_pointer pszStr, size_type nStrSize) const noexcept
1930 {
1931  if (pszStr)
1932  {
1933  if (size_type nThisSize = size(); nThisSize > 0)
1934  {
1935  if (nStrSize == npos)
1936  nStrSize = traits_t::length(pszStr);
1937 
1938  if (nStrSize <= nThisSize)
1939  return traits_t::compare_n(data() + nThisSize - nStrSize, pszStr, nStrSize) == 0;
1940  }
1941  }
1942 
1943  return false;
1944 }
1945 
1946 template<class char_t, class traits_t>
1947 inline bool basic_string<char_t, traits_t>::ends_with(const basic_string& sStr) const noexcept
1948 {
1949  return ends_with(sStr.data(), sStr.size());
1950 }
1951 
1952 template<class char_t, class traits_t>
1953 template<class fwd_it_t>
1954 inline bool basic_string<char_t, traits_t>::ends_with(fwd_it_t itBegin, fwd_it_t itEnd) const noexcept
1955 {
1956  return iter_strcmp(cend() - static_cast<size_type>(std::distance(itBegin, itEnd)), cend(), itBegin, itEnd) == 0;
1957 }
1958 
1959 template<class char_t, class traits_t>
1960 template<range_of_t_c<char_t> string_t>
1961 inline bool basic_string<char_t, traits_t>::ends_with(const string_t& sStr) const noexcept
1962 {
1963  return ends_with(sStr.cbegin(), sStr.cend());
1964 }
1965 
1966 template<class char_t, class traits_t>
1967 inline bool basic_string<char_t, traits_t>::contains(value_type chSymbol) const noexcept
1968 {
1969  return find(chSymbol) != npos;
1970 }
1971 
1972 template<class char_t, class traits_t>
1973 inline bool basic_string<char_t, traits_t>::contains(const_pointer pszStr, size_type nStrSize) const noexcept
1974 {
1975  return find(pszStr, 0, nStrSize) != npos;
1976 }
1977 
1978 template<class char_t, class traits_t>
1979 inline bool basic_string<char_t, traits_t>::contains(const basic_string& sStr) const noexcept
1980 {
1981  return find(sStr) != npos;
1982 }
1983 
1984 template<class char_t, class traits_t>
1985 template<class fwd_it_t>
1986 inline bool basic_string<char_t, traits_t>::contains(fwd_it_t itBegin, fwd_it_t itEnd) const noexcept
1987 {
1988  return find(itBegin, itEnd) != npos;
1989 }
1990 
1991 template<class char_t, class traits_t>
1992 template<range_of_t_c<char_t> string_t>
1993 inline bool basic_string<char_t, traits_t>::contains(const string_t& sStr) const noexcept
1994 {
1995  return find(sStr) != npos;
1996 }
1997 
1998 template<class char_t, class traits_t>
1999 inline basic_string<char_t, traits_t>& basic_string<char_t, traits_t>::operator=(const_pointer pszSource) noexcept
2000 {
2001  assign(pszSource);
2002  return *this;
2003 }
2004 
2005 template<class char_t, class traits_t>
2006 inline basic_string<char_t, traits_t>& basic_string<char_t, traits_t>::operator=(basic_string&& sStr) noexcept
2007 {
2008  assign(std::move(sStr));
2009  return *this;
2010 }
2011 
2012 template<class char_t, class traits_t>
2013 inline basic_string<char_t, traits_t>& basic_string<char_t, traits_t>::operator=(const basic_string& sStr) noexcept
2014 {
2015  assign(sStr);
2016  return *this;
2017 }
2018 
2019 template<class char_t, class traits_t>
2020 template<range_of_t_c<char_t> string_t>
2021 inline basic_string<char_t, traits_t>& basic_string<char_t, traits_t>::operator=(const string_t& sStr) noexcept
2022 {
2023  assign(sStr);
2024  return *this;
2025 }
2026 
2027 template<class char_t, class traits_t>
2028 inline basic_string<char_t, traits_t>& basic_string<char_t, traits_t>::operator+=(value_type chSymbol) noexcept
2029 {
2030  append(&chSymbol, 1);
2031  return *this;
2032 }
2033 
2034 template<class char_t, class traits_t>
2035 inline basic_string<char_t, traits_t>& basic_string<char_t, traits_t>::operator+=(const_pointer pszSource) noexcept
2036 {
2037  if (pszSource)
2038  append(pszSource, traits_t::length(pszSource));
2039 
2040  return *this;
2041 }
2042 
2043 template<class char_t, class traits_t>
2044 inline basic_string<char_t, traits_t>& basic_string<char_t, traits_t>::operator+=(const basic_string& sStr) noexcept
2045 {
2046  append(sStr.data(), sStr.size());
2047  return *this;
2048 }
2049 
2050 template<class char_t, class traits_t>
2051 template<range_of_t_c<char_t> string_t>
2052 inline basic_string<char_t, traits_t>& basic_string<char_t, traits_t>::operator+=(const string_t& sStr) noexcept
2053 {
2054  append(sStr.cbegin(), sStr.cend());
2055  return *this;
2056 }
2057 
2058 template<class char_t, class traits_t>
2059 inline bool basic_string<char_t, traits_t>::operator==(value_type chSymbol) const noexcept
2060 {
2061  return size() == 1 && at(0) == chSymbol;
2062 }
2063 
2064 template<class char_t, class traits_t>
2065 inline bool basic_string<char_t, traits_t>::operator==(const_pointer pszSource) const noexcept
2066 {
2067  return compare(pszSource) == 0;
2068 }
2069 
2070 template<class char_t, class traits_t>
2071 inline bool basic_string<char_t, traits_t>::operator==(const basic_string& sStr) const noexcept
2072 {
2073  return size() == sStr.size() && compare(sStr.data(), sStr.size()) == 0;
2074 }
2075 
2076 template<class char_t, class traits_t>
2077 template<range_of_t_c<char_t> string_t>
2078 inline bool basic_string<char_t, traits_t>::operator==(const string_t& sStr) const noexcept
2079 {
2080  return iter_strcmp(cbegin(), cend(), sStr.cbegin(), sStr.cend()) == 0;
2081 }
2082 
2083 template<class char_t, class traits_t>
2084 inline bool basic_string<char_t, traits_t>::operator!=(value_type chSymbol) const noexcept
2085 {
2086  return !operator==(chSymbol);
2087 }
2088 
2089 template<class char_t, class traits_t>
2090 inline bool basic_string<char_t, traits_t>::operator!=(const_pointer pszSource) const noexcept
2091 {
2092  return !operator==(pszSource);
2093 }
2094 
2095 template<class char_t, class traits_t>
2096 inline bool basic_string<char_t, traits_t>::operator!=(const basic_string& sStr) const noexcept
2097 {
2098  return !operator==(sStr);
2099 }
2100 
2101 template<class char_t, class traits_t>
2102 template<range_of_t_c<char_t> string_t>
2103 inline bool basic_string<char_t, traits_t>::operator!=(const string_t& sStr) const noexcept
2104 {
2105  return !operator==(sStr);
2106 }
2107 
2108 template<class char_t, class traits_t>
2109 inline bool basic_string<char_t, traits_t>::operator<(value_type chSymbol) const noexcept
2110 {
2111  return compare(&chSymbol, 1) < 0;
2112 }
2113 
2114 template<class char_t, class traits_t>
2115 inline bool basic_string<char_t, traits_t>::operator<(const_pointer pszSource) const noexcept
2116 {
2117  return compare(pszSource) < 0;
2118 }
2119 
2120 template<class char_t, class traits_t>
2121 inline bool basic_string<char_t, traits_t>::operator<(const basic_string& sStr) const noexcept
2122 {
2123  return compare(sStr.data(), sStr.size()) < 0;
2124 }
2125 
2126 template<class char_t, class traits_t>
2127 template<range_of_t_c<char_t> string_t>
2128 inline bool basic_string<char_t, traits_t>::operator<(const string_t& sStr) const noexcept
2129 {
2130  return iter_strcmp(cbegin(), cend(), sStr.cbegin(), sStr.cend()) < 0;
2131 }
2132 
2133 template<class char_t, class traits_t>
2134 inline bool basic_string<char_t, traits_t>::operator<=(value_type chSymbol) const noexcept
2135 {
2136  return compare(&chSymbol, 1) <= 0;
2137 }
2138 
2139 template<class char_t, class traits_t>
2140 inline bool basic_string<char_t, traits_t>::operator<=(const_pointer pszSource) const noexcept
2141 {
2142  return compare(pszSource) <= 0;
2143 }
2144 
2145 template<class char_t, class traits_t>
2146 inline bool basic_string<char_t, traits_t>::operator<=(const basic_string& sStr) const noexcept
2147 {
2148  return compare(sStr.data(), sStr.size()) <= 0;
2149 }
2150 
2151 template<class char_t, class traits_t>
2152 template<range_of_t_c<char_t> string_t>
2153 inline bool basic_string<char_t, traits_t>::operator<=(const string_t& sStr) const noexcept
2154 {
2155  return iter_strcmp(cbegin(), cend(), sStr.cbegin(), sStr.cend()) <= 0;
2156 }
2157 
2158 template<class char_t, class traits_t>
2159 inline bool basic_string<char_t, traits_t>::operator>(value_type chSymbol) const noexcept
2160 {
2161  return compare(&chSymbol, 1) > 0;
2162 }
2163 
2164 template<class char_t, class traits_t>
2165 inline bool basic_string<char_t, traits_t>::operator>(const_pointer pszSource) const noexcept
2166 {
2167  return compare(pszSource) > 0;
2168 }
2169 
2170 template<class char_t, class traits_t>
2171 inline bool basic_string<char_t, traits_t>::operator>(const basic_string& sStr) const noexcept
2172 {
2173  return compare(sStr.data(), sStr.size()) > 0;
2174 }
2175 
2176 template<class char_t, class traits_t>
2177 template<range_of_t_c<char_t> string_t>
2178 inline bool basic_string<char_t, traits_t>::operator>(const string_t& sStr) const noexcept
2179 {
2180  return iter_strcmp(cbegin(), cend(), sStr.cbegin(), sStr.cend()) > 0;
2181 }
2182 
2183 template<class char_t, class traits_t>
2184 inline bool basic_string<char_t, traits_t>::operator>=(value_type chSymbol) const noexcept
2185 {
2186  return compare(&chSymbol, 1) >= 0;
2187 }
2188 
2189 template<class char_t, class traits_t>
2190 inline bool basic_string<char_t, traits_t>::operator>=(const_pointer pszSource) const noexcept
2191 {
2192  return compare(pszSource) >= 0;
2193 }
2194 
2195 template<class char_t, class traits_t>
2196 inline bool basic_string<char_t, traits_t>::operator>=(const basic_string& sStr) const noexcept
2197 {
2198  return compare(sStr.data(), sStr.size()) >= 0;
2199 }
2200 
2201 template<class char_t, class traits_t>
2202 template<range_of_t_c<char_t> string_t>
2203 inline bool basic_string<char_t, traits_t>::operator>=(const string_t& sStr) const noexcept
2204 {
2205  return iter_strcmp(cbegin(), cend(), sStr.cbegin(), sStr.cend()) >= 0;
2206 }
2207 
2208 template<class char_t, class traits_t>
2209 inline typename basic_string<char_t, traits_t>::reference basic_string<char_t, traits_t>::operator[](
2210  size_type nSymbol) noexcept
2211 {
2212  return at(nSymbol);
2213 }
2214 
2215 template<class char_t, class traits_t>
2216 inline typename basic_string<char_t, traits_t>::const_reference basic_string<char_t, traits_t>::operator[](
2217  size_type nSymbol) const noexcept
2218 {
2219  return at(nSymbol);
2220 }
2221 
2222 template<class char_t, class traits_t>
2223 inline basic_string<char_t, traits_t>::operator std::basic_string_view<
2224  typename basic_string<char_t, traits_t>::value_type>() const noexcept
2225 {
2226  return string_view(data(), size());
2227 }
2228 
2229 template<class char_t, class traits_t>
2230 inline basic_string<char_t, traits_t>::operator bool() const noexcept
2231 {
2232  return !empty();
2233 }
2234 
2235 template<class char_t, class traits_t>
2236 inline bool basic_string<char_t, traits_t>::_resize(size_type nSymbols, string_resize_type eType) noexcept
2237 {
2238  const bool bRet =
2239  m_Data.resize(nSymbols, eType == string_resize_type::shrink_to_fit ? 0 : traits_t::align(), eType);
2240 
2241  if (bRet && eType == string_resize_type::common)
2242  at(nSymbols) = QX_CHAR_PREFIX(typename traits_t::value_type, '\0');
2243 
2244  return bRet;
2245 }
2246 
2247 template<class char_t, class traits_t>
2248 template<class searcher_t>
2249 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_trim_left(
2250  const searcher_t& searcher) noexcept
2251 {
2252  size_type nSymbols = 0;
2253 
2254  for (size_type i = 0; i < size(); ++i)
2255  {
2256  if (searcher(at(i)))
2257  ++nSymbols;
2258  else
2259  break;
2260  }
2261 
2262  erase(0, nSymbols);
2263  return nSymbols;
2264 }
2265 
2266 template<class char_t, class traits_t>
2267 template<class searcher_t>
2268 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_trim_right(
2269  const searcher_t& searcher) noexcept
2270 {
2271  size_type nSymbols = 0;
2272  size_type nSize = size();
2273 
2274  for (size_type i = nSize - 1; i != std::numeric_limits<size_type>::max(); --i)
2275  {
2276  if (searcher(at(i)))
2277  ++nSymbols;
2278  else
2279  break;
2280  }
2281 
2282  erase(nSize - nSymbols, nSymbols);
2283  return nSymbols;
2284 }
2285 
2286 template<class char_t, class traits_t>
2287 template<class searcher_t>
2288 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_trim(
2289  const searcher_t& searcher) noexcept
2290 {
2291  const size_type nSize = size();
2292  size_type nStartPos = 0;
2293  size_type nEndPos = nSize;
2294 
2295  while (nStartPos < nSize && searcher(at(nStartPos)))
2296  ++nStartPos;
2297 
2298  while (nEndPos > nStartPos && searcher(at(nEndPos - 1)))
2299  --nEndPos;
2300 
2301  size_type nNewSize = nEndPos - nStartPos;
2302 
2303  std::memmove(data(), data() + nStartPos, nNewSize * sizeof(value_type));
2304 
2305  _resize(nNewSize);
2306  return nSize - nNewSize;
2307 }
2308 
2309 template<class char_t, class traits_t>
2310 template<class comparator_t>
2311 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_find(
2312  size_type nBegin,
2313  size_type nEnd,
2314  const comparator_t& comparator) const noexcept
2315 {
2316  if (nEnd == npos)
2317  nEnd = size();
2318 
2319  const_pointer pData = data();
2320  const_pointer pCurrentChar = pData + nBegin;
2321  const_pointer pEnd = pData + nEnd;
2322 
2323  while (pCurrentChar < pEnd)
2324  {
2325  if (comparator(pCurrentChar))
2326  return static_cast<size_type>(pCurrentChar - pData);
2327  else
2328  ++pCurrentChar;
2329  }
2330 
2331  return npos;
2332 }
2333 
2334 template<class char_t, class traits_t>
2335 template<class comparator_t>
2336 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_rfind(
2337  size_type nBegin,
2338  size_type nEnd,
2339  const comparator_t& comparator) const noexcept
2340 {
2341  if (nBegin == npos)
2342  nBegin = size() - 1;
2343 
2344  const_pointer pData = data();
2345  const_pointer pCurrentChar = pData + nBegin;
2346  const_pointer pEnd = pData + nEnd;
2347 
2348  while (pCurrentChar >= pEnd)
2349  {
2350  if (comparator(pCurrentChar))
2351  return static_cast<size_type>(pCurrentChar - pData);
2352  else
2353  --pCurrentChar;
2354  }
2355 
2356  return npos;
2357 }
2358 
2359 template<class char_t, class traits_t>
2360 template<class incrementer_t, class fwd_it_t>
2361 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_find_first_of(
2362  fwd_it_t itBegin,
2363  fwd_it_t itEnd,
2364  size_type nBegin,
2365  const incrementer_t& incrementer) const noexcept
2366 {
2367  for (size_type i = nBegin; i < size(); ++i)
2368  for (fwd_it_t it = itBegin; it != itEnd; it = incrementer(it))
2369  if (*it == at(i))
2370  return i;
2371 
2372  return npos;
2373 }
2374 
2375 template<class char_t, class traits_t>
2376 template<class incrementer_t, class fwd_it_t>
2377 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_find_last_of(
2378  fwd_it_t itBegin,
2379  fwd_it_t itEnd,
2380  size_type nEnd,
2381  const incrementer_t& incrementer) const noexcept
2382 {
2383  for (size_type i = size() - 1; i != nEnd - 1; --i)
2384  for (fwd_it_t it = itBegin; it != itEnd; it = incrementer(it))
2385  if (*it == at(i))
2386  return i;
2387 
2388  return npos;
2389 }
2390 
2391 template<class char_t, class traits_t>
2392 template<class incrementer_t, class fwd_it_t>
2393 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_find_first_not_of(
2394  fwd_it_t itBegin,
2395  fwd_it_t itEnd,
2396  size_type nBegin,
2397  const incrementer_t& incrementer) const noexcept
2398 {
2399  for (size_type i = nBegin; i < size(); ++i)
2400  {
2401  bool bFoundOneOf = false;
2402  for (fwd_it_t it = itBegin; !bFoundOneOf && it != itEnd; it = incrementer(it))
2403  bFoundOneOf |= *it == at(i);
2404 
2405  if (!bFoundOneOf)
2406  return i;
2407  }
2408 
2409  return npos;
2410 }
2411 
2412 template<class char_t, class traits_t>
2413 template<class incrementer_t, class fwd_it_t>
2414 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_find_last_not_of(
2415  fwd_it_t itBegin,
2416  fwd_it_t itEnd,
2417  size_type nEnd,
2418  const incrementer_t& incrementer) const noexcept
2419 {
2420  for (size_type i = size() - 1; i != nEnd - 1; --i)
2421  {
2422  bool bFoundOneOf = false;
2423  for (fwd_it_t it = itBegin; !bFoundOneOf && it != itEnd; it = incrementer(it))
2424  bFoundOneOf |= *it == at(i);
2425 
2426  if (!bFoundOneOf)
2427  return i;
2428  }
2429 
2430  return npos;
2431 }
2432 
2433 template<class char_t, class traits_t>
2434 template<class string_view_like_t>
2435 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_get_string_view_like_size(
2436  const string_view_like_t& sValue) noexcept
2437 {
2438  if constexpr (std::is_same_v<string_view_like_t, value_type>)
2439  {
2440  return 1;
2441  }
2442  else if constexpr (std::is_convertible_v<string_view_like_t, const_pointer>)
2443  {
2444  return traits_t::length(sValue);
2445  }
2446  else if constexpr (range_of_t_c<string_view_like_t, char_t>)
2447  {
2448  return sValue.size();
2449  }
2450  else
2451  {
2452  QX_STATIC_ASSERT_NO_INSTANTIATION("Unexpected type");
2453  return 0;
2454  }
2455 }
2456 
2457 template<class char_t, class traits_t>
2458 template<class string_view_like_t>
2459 inline typename basic_string<char_t, traits_t>::const_pointer basic_string<char_t, traits_t>::
2460  _get_string_view_like_data(const string_view_like_t& sValue) noexcept
2461 {
2462  if constexpr (std::is_same_v<string_view_like_t, value_type>)
2463  {
2464  return &sValue;
2465  }
2466  else if constexpr (std::is_convertible_v<string_view_like_t, const_pointer>)
2467  {
2468  return sValue;
2469  }
2470  else if constexpr (range_of_t_c<string_view_like_t, char_t>)
2471  {
2472  return sValue.data();
2473  }
2474  else
2475  {
2476  QX_STATIC_ASSERT_NO_INSTANTIATION("Unexpected type");
2477  return nullptr;
2478  }
2479 }
2480 
2481 template<class char_t, class traits_t>
2482 basic_string<char_t, traits_t> operator+(
2483  const basic_string<char_t, traits_t>& lhs,
2484  const basic_string<char_t, traits_t>& rhs) noexcept
2485 {
2486  basic_string<char_t, traits_t> str(lhs);
2487  str += rhs;
2488  return str;
2489 }
2490 
2491 template<class char_t, class traits_t>
2492 basic_string<char_t, traits_t> operator+(
2493  basic_string<char_t, traits_t>&& lhs,
2494  const basic_string<char_t, traits_t>& rhs) noexcept
2495 {
2496  basic_string<char_t, traits_t> str(std::move(lhs));
2497  str += rhs;
2498  return str;
2499 }
2500 
2501 template<class char_t, class traits_t>
2502 basic_string<char_t, traits_t> operator+(
2503  const basic_string<char_t, traits_t>& lhs,
2504  typename traits_t::const_pointer rhs) noexcept
2505 {
2506  basic_string<char_t, traits_t> str(lhs);
2507  str += rhs;
2508  return str;
2509 }
2510 
2511 template<class char_t, class traits_t>
2512 basic_string<char_t, traits_t> operator+(
2513  basic_string<char_t, traits_t>&& lhs,
2514  typename traits_t::const_pointer rhs) noexcept
2515 {
2516  basic_string<char_t, traits_t> str(std::move(lhs));
2517  str += rhs;
2518  return str;
2519 }
2520 
2521 template<class char_t, class traits_t>
2522 basic_string<char_t, traits_t> operator+(
2523  typename traits_t::const_pointer lhs,
2524  const basic_string<char_t, traits_t>& rhs) noexcept
2525 {
2526  basic_string<char_t, traits_t> str(lhs);
2527  str += rhs;
2528  return str;
2529 }
2530 
2531 template<class char_t, class traits_t>
2532 basic_string<char_t, traits_t> operator+(
2533  const basic_string<char_t, traits_t>& lhs,
2534  typename traits_t::value_type rhs) noexcept
2535 {
2536  basic_string<char_t, traits_t> str(lhs);
2537  str += rhs;
2538  return str;
2539 }
2540 
2541 template<class char_t, class traits_t>
2542 basic_string<char_t, traits_t> operator+(
2543  basic_string<char_t, traits_t>&& lhs,
2544  typename traits_t::value_type rhs) noexcept
2545 {
2546  basic_string<char_t, traits_t> str(std::move(lhs));
2547  str += rhs;
2548  return str;
2549 }
2550 
2551 template<class char_t, class traits_t>
2552 basic_string<char_t, traits_t> operator+(
2553  typename traits_t::value_type lhs,
2554  const basic_string<char_t, traits_t>& rhs) noexcept
2555 {
2556  basic_string<char_t, traits_t> str(&lhs, 1);
2557  str += rhs;
2558  return str;
2559 }
2560 
2561 template<class char_t, class traits_t, range_of_t_c<char_t> string_t>
2562 basic_string<char_t, traits_t> operator+(const basic_string<char_t, traits_t>& lhs, const string_t& rhs) noexcept
2563 {
2564  basic_string<char_t, traits_t> str(lhs);
2565  str += rhs;
2566  return str;
2567 }
2568 
2569 template<class char_t, class traits_t, range_of_t_c<char_t> string_t>
2570 basic_string<char_t, traits_t> operator+(basic_string<char_t, traits_t>&& lhs, const string_t& rhs) noexcept
2571 {
2572  basic_string<char_t, traits_t> str(std::move(lhs));
2573  str += rhs;
2574  return str;
2575 }
2576 
2577 template<class char_t, class traits_t, range_of_t_c<char_t> string_t>
2578 basic_string<char_t, traits_t> operator+(const string_t& lhs, const basic_string<char_t, traits_t>& rhs) noexcept
2579 {
2580  basic_string<char_t, traits_t> str(lhs);
2581  str += rhs;
2582  return str;
2583 }
2584 
2585 /**
2586  @brief Get string size (excluding null terminator)
2587  @retval - string size (excluding null terminator)
2588 **/
2589 template<class char_t, class traits_t>
2590 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::size() const noexcept
2591 {
2592  return m_Data.size();
2593 }
2594 
2595 /**
2596  @brief Get c-string
2597  @retval - c-string
2598 **/
2599 template<class char_t, class traits_t>
2600 inline typename basic_string<char_t, traits_t>::pointer basic_string<char_t, traits_t>::data() noexcept
2601 {
2602  return m_Data.data();
2603 }
2604 
2605 /**
2606  @brief Get char at the ind position
2607  @param nIndex - char index
2608  @retval - char value
2609 **/
2610 template<class char_t, class traits_t>
2611 inline typename basic_string<char_t, traits_t>::reference basic_string<char_t, traits_t>::at(size_type nIndex) noexcept
2612 {
2613  return data()[nIndex];
2614 }
2615 
2616 /**
2617  @brief Clear string
2618 **/
2619 template<class char_t, class traits_t>
2620 inline void basic_string<char_t, traits_t>::clear() noexcept
2621 {
2622  assign(QX_STR_PREFIX(typename traits_t::value_type, ""));
2623 }
2624 
2625 } // namespace qx
2626 
2627 
2628 
2629 // -------------------------------------------------------- hash -------------------------------------------------------
2630 
2631 namespace std
2632 {
2633 
2634 template<class char_t, class traits_t>
2635 struct hash<qx::basic_string<char_t, traits_t>>
2636 {
2637  size_t operator()(const qx::basic_string<char_t, traits_t>& str) const noexcept
2638  {
2639  return traits_t::hash_function(str.data(), traits_t::hash_seed(), str.size());
2640  }
2641 };
2642 
2643 // -------------------------------------------------------- swap -------------------------------------------------------
2644 
2645 template<class char_t, class traits_t>
2647 {
2648  lhs.swap(rhs);
2649 }
2650 
2651 // ----------------------------------------------------- formatter -----------------------------------------------------
2652 
2653 template<class char_t, class traits_t>
2654 struct formatter<qx::basic_string<char_t, traits_t>, char_t> : qx::basic_formatter
2655 {
2656  template<class format_context_type>
2657  constexpr auto format(const qx::basic_string<char_t, traits_t>& value, format_context_type& ctx) const
2658  {
2659  return format_to(ctx.out(), QX_STR_PREFIX(char_t, "{}"), value.c_str());
2660  }
2661 };
2662 
2663 } // namespace std
2664 
2665 
2666 // ------------------------------------------- istream / ostream overloading -------------------------------------------
2667 
2668 template<class char_t, class traits_t>
2669 qx::details::ostream<char_t>& operator<<(
2670  qx::details::ostream<char_t>& os,
2672 {
2673  os << str.data();
2674  return os;
2675 }
2676 
2677 template<class char_t, class traits_t>
2678 qx::details::istream<char_t>& operator>>(qx::details::istream<char_t>& is, qx::basic_string<char_t, traits_t>& str)
2679 {
2680  typename qx::details::istream<traits_t>::iostate ret_bit = qx::details::istream<traits_t>::goodbit;
2681 
2682  auto try_push_back = [&str, &is, &ret_bit](char_t ch)
2683  {
2684  typename traits_t::size_type nCurrentSize = str.size();
2685  if (str._resize(nCurrentSize + 1))
2686  {
2687  str[nCurrentSize] = ch;
2688  return true;
2689  }
2690  else
2691  {
2692  is.unget();
2693  ret_bit |= qx::details::istream<traits_t>::failbit;
2694  return false;
2695  }
2696  };
2697 
2698  str.clear();
2699  char_t ch;
2700 
2701  // skip all space symbols and add first symbol is any
2702  while (is.get(ch))
2703  {
2704  if (!traits_t::is_space(ch))
2705  {
2706  try_push_back(ch);
2707  break;
2708  }
2709  }
2710 
2711  // add other symbols until space symbol
2712  while (is.get(ch))
2713  {
2714  if (!traits_t::is_space(ch))
2715  {
2716  if (!try_push_back(ch))
2717  break;
2718  }
2719  else
2720  {
2721  is.unget();
2722  break;
2723  }
2724  }
2725 
2726  is.setstate(ret_bit);
2727  return is;
2728 }
String class.
Definition: string.h:64
void push_back(value_type chSymbol) noexcept
Insert char in the end of the string.
Definition: string.inl:545
void erase(iterator itFirst, iterator itLast) noexcept
Erase substring.
Definition: string.inl:557
size_type find(value_type chSymbol, size_type nBegin=0, size_type nEnd=npos) const noexcept
Find substring.
Definition: string.inl:1263
void append(const basic_string &sStr) noexcept
Append string.
Definition: string.inl:395
bool remove_prefix(value_type chSymbol) noexcept
Remove string prefix if matches.
Definition: string.inl:988
size_type remove_all(value_type chSymbol, size_type nBegin=0, size_type nEnd=npos) noexcept
Remove all occurrences of a substring in a string.
Definition: string.inl:1065
std::optional< to_t > to(const_pointer pszFormat=nullptr) const noexcept
Convert string to specified type.
Definition: string.inl:272
requires static format_acceptable_args< char_t, args_t... > basic_string static_vformat(string_view svFormat, args_t &&... args)
Create a string by formatting it with the format string and the args.
int compare(value_type chSymbol) const noexcept
Performs a binary comparison of the characters.
Definition: string.inl:1225
size_type find_last_of(value_type chSymbol, size_type nEnd=0) const noexcept
Find last position of character.
Definition: string.inl:1510
void push_front(value_type chSymbol) noexcept
Insert char in the beginning of the string.
Definition: string.inl:551
size_type capacity() const noexcept
Get allocated memory size (including null terminator)
Definition: string.inl:258
value_type pop_back() noexcept
Erase last char and return it.
Definition: string.inl:595
size_type copy(pointer pDest, size_type nCount, size_type nPos=0) const noexcept
Copies a substring [nPos, nPos + nCount) to character string pointed to by pDest.
Definition: string.inl:319
views split(const value_type chSeparator) const noexcept
Split string by separator.
Definition: string.inl:1783
size_type rfind(value_type chSymbol, size_type nBegin=npos, size_type nEnd=0) const noexcept
Find substring (reverse direction)
Definition: string.inl:1343
size_type length() const noexcept
Get string length.
Definition: string.inl:246
void free() noexcept
Clear string and free allocated memory.
Definition: string.inl:206
void from(const from_t &data)
Construct string from custom type.
Definition: string.inl:337
size_type trim_right() noexcept
Trim the string to the right (whitespace characters)
Definition: string.inl:711
void assign(size_type nSymbols, value_type chSymbol) noexcept
Assign by filling.
Definition: string.inl:64
requires format_acceptable_args< char_t, args_t... > void vformat(string_view svFormat, args_t &&... args)
Clear the string and format it with the format string and the args.
Definition: string.inl:155
size_type replace_all(const find_string_t &sFind, const replace_string_t &sReplace, size_type nBegin=0, size_type nEnd=npos) noexcept
Replace all occurrences of sFind with sReplace.
Definition: string.inl:1205
bool ends_with(value_type chSymbol) const noexcept
Check if current string ends with char.
Definition: string.inl:1919
void swap(basic_string &sOther) noexcept
Swap this str and other.
Definition: string.inl:183
value_type pop_front() noexcept
Erase first char and return it.
Definition: string.inl:603
void append(value_type chSymbol) noexcept
Append char.
Definition: string.inl:376
bool contains(value_type chSymbol) const noexcept
Check if string contains char.
Definition: string.inl:1967
requires static format_acceptable_args< char_t, args_t... > basic_string static_format(const format_string_type< std::type_identity_t< args_t >... > sFormat, args_t &&... args)
Create a string by formatting it with the format string and the args.
size_type trim() noexcept
Trim the string to the both sides (whitespace characters)
Definition: string.inl:811
void to_upper() noexcept
Convert string to uppercase.
Definition: string.inl:227
void shrink_to_fit() noexcept
Fit allocated size to string's actual size.
Definition: string.inl:199
static basic_string static_from(const from_t &data)
Construct string from custom type and get it.
size_type find_last_not_of(value_type chSymbol, size_type nEnd=0) const noexcept
Finds the last character not equal to chSymbol.
Definition: string.inl:1690
size_type trim_left() noexcept
Trim the string to the left (whitespace characters)
Definition: string.inl:611
size_type reserve(size_type nCapacity) noexcept
Reserve memory for the string.
Definition: string.inl:189
string_view substr(size_type nPos, size_type nSymbols=npos) const noexcept
Get substring.
Definition: string.inl:212
void to_lower() noexcept
Convert string to lowercase.
Definition: string.inl:220
size_type insert(size_type nPos, value_type chSymbol) noexcept
Insert substring.
Definition: string.inl:416
bool remove_suffix(value_type chSymbol) noexcept
Remove string suffix if matches.
Definition: string.inl:1021
const_pointer c_str() const noexcept
Get pointer to string zero terminated.
Definition: string.inl:252
requires format_acceptable_args< char_t, args_t... > void append_vformat(string_view svFormat, args_t &&... args)
Append the formatted string to the current one.
Definition: string.inl:176
requires format_acceptable_args< char_t, args_t... > void format(const format_string_type< std::type_identity_t< args_t >... > sFormat, args_t &&... args)
Clear the string and format it with the format string and the args.
Definition: string.inl:125
size_type remove(value_type chSymbol, size_type nBegin=0, size_type nEnd=npos) noexcept
Remove the first occurrence of a substring in a string.
Definition: string.inl:911
static constexpr size_type max_size() noexcept
Get the theoretical maximum of string size.
Definition: string.inl:264
bool starts_with(value_type chSymbol) const noexcept
Check if current string starts with char.
Definition: string.inl:1871
value_type front() const noexcept
Get first char of the string.
Definition: string.inl:234
value_type back() const noexcept
Get last char of the string.
Definition: string.inl:240
size_type replace(size_type nBegin, size_type nSize, const_pointer pszReplace, size_t nReplaceSize) noexcept
Replace a substring with a given string.
Definition: string.inl:1148
size_type find_first_of(value_type chSymbol, size_type nBegin=0) const noexcept
Find first position of character.
Definition: string.inl:1423
requires format_acceptable_args< char_t, args_t... > void append_format(const format_string_type< std::type_identity_t< args_t >... > sFormat, args_t &&... args)
Append the formatted string to the current one.
Definition: string.inl:145
size_type find_first_not_of(value_type chSymbol, size_type nBegin=0) const noexcept
Finds the first character not equal to chSymbol.
Definition: string.inl:1597
Const random access iterator type.
Definition: iterator.h:74
Non-const random access iterator type.
Definition: iterator.h:35
@ append
append all
#define QX_CHAR_PREFIX(value_t, ch)
Chose witch of prefixes add to char : L or none.
Definition: string_utils.h:257
constexpr int iter_strcmp(fwd_it_1_t itBegin1, fwd_it_1_t itEnd1, fwd_it_2_t itBegin2, fwd_it_2_t itEnd2) noexcept
Compares string 1 with string 2.
Definition: string_utils.h:150
#define QX_STR_PREFIX(value_t, str)
Chose witch of prefixes add to string : L or none.
Definition: string_utils.h:249