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