13 template<
class char_t,
class traits_t>
16 assign(nSymbols, chSymbol);
19 template<
class char_t,
class traits_t>
22 assign(pszSource, nSymbols);
25 template<
class char_t,
class traits_t>
31 template<
class char_t,
class traits_t>
34 assign(std::move(sAnother));
37 template<
class char_t,
class traits_t>
43 template<
class char_t,
class traits_t>
44 template<
class fwd_it_t>
47 assign(itFirst, itLast);
50 template<
class char_t,
class traits_t>
51 template<range_of_t_c<
char_t>
string_t>
57 template<
class char_t,
class traits_t>
60 if (_resize(nSymbols))
61 std::fill(begin(), end(), chSymbol);
64 template<
class char_t,
class traits_t>
67 if (pszSource && _resize(nSymbols))
68 std::memmove(data(), pszSource, nSymbols *
sizeof(value_type));
71 template<
class char_t,
class traits_t>
74 if (pszSource != data())
75 assign(pszSource, traits_t::length(pszSource));
78 template<
class char_t,
class traits_t>
84 template<
class char_t,
class traits_t>
87 if (sAnother.data() != data())
88 assign(sAnother.data());
91 template<
class char_t,
class traits_t>
92 template<
class fwd_it_t>
97 for (fwd_it_t it = itFirst; it != itLast; ++it)
99 _resize(nPos + 1, sbo_resize_type::reserve);
104 _resize(nPos, sbo_resize_type::common);
107 template<
class char_t,
class traits_t>
108 template<range_of_t_c<
char_t>
string_t>
111 assign(sAnother.cbegin(), sAnother.cend());
114 template<
class char_t,
class traits_t>
115 template<
class... args_t>
116 requires format_acceptable_args_c<char_t, args_t...>
118 const format_string_type<std::type_identity_t<args_t>...> sFormat,
121 vformat(sFormat.get(), std::forward<args_t>(args)...);
124 template<
class char_t,
class traits_t>
125 template<
class... args_t>
126 requires format_acceptable_args_c<char_t, args_t...>
128 const format_string_type<std::type_identity_t<args_t>...> sFormat,
131 return static_vformat(sFormat.get(), std::forward<args_t>(args)...);
134 template<
class char_t,
class traits_t>
135 template<
class... args_t>
136 requires format_acceptable_args_c<char_t, args_t...>
138 const format_string_type<std::type_identity_t<args_t>...> sFormat,
141 append_vformat(sFormat.get(), std::forward<args_t>(args)...);
144 template<
class char_t,
class traits_t>
145 template<
class... args_t>
146 requires format_acceptable_args_c<char_t, args_t...>
150 append_vformat(svFormat, std::forward<args_t>(args)...);
153 template<
class char_t,
class traits_t>
154 template<
class... args_t>
155 requires format_acceptable_args_c<char_t, args_t...>
157 string_view svFormat,
161 sTemp.
vformat(svFormat, std::forward<args_t>(args)...);
165 template<
class char_t,
class traits_t>
166 template<
class... args_t>
167 requires format_acceptable_args_c<char_t, args_t...>
170 if (!svFormat.empty())
171 traits_t::format_to(std::back_inserter(*
this), svFormat, std::forward<args_t>(args)...);
174 template<
class char_t,
class traits_t>
177 std::swap(m_Data, sOther.m_Data);
180 template<
class char_t,
class traits_t>
182 size_type nCapacity) noexcept
184 if (nCapacity > capacity())
185 _resize(nCapacity, sbo_resize_type::reserve);
190 template<
class char_t,
class traits_t>
193 if (!m_Data.is_small() && capacity() > size())
194 _resize(size(), sbo_resize_type::shrink_to_fit);
197 template<
class char_t,
class traits_t>
203 template<
class char_t,
class traits_t>
206 size_type nSymbols)
const noexcept
208 return string_view(data() + nPos, nSymbols != npos ? nSymbols : size() - nPos);
211 template<
class char_t,
class traits_t>
214 for (value_type& ch : *
this)
215 ch = traits_t::to_lower(ch);
218 template<
class char_t,
class traits_t>
221 for (value_type& ch : *
this)
222 ch = traits_t::to_upper(ch);
225 template<
class char_t,
class traits_t>
231 template<
class char_t,
class traits_t>
234 return at(size() - 1);
237 template<
class char_t,
class traits_t>
243 template<
class char_t,
class traits_t>
249 template<
class char_t,
class traits_t>
252 return m_Data.capacity() /
sizeof(value_type) - 1;
255 template<
class char_t,
class traits_t>
258 return std::numeric_limits<size_type>::max() - 1
262 template<
class char_t,
class traits_t>
266 std::optional<to_t> optResult = std::nullopt;
269 std::is_trivial_v<to_t> && std::is_standard_layout_v<to_t> || std::is_pointer_v<to_t>
270 || std::is_same_v<to_t, std::nullptr_t>)
272 if constexpr (std::is_same_v<to_t, std::nullptr_t>)
274 if (compare(
QX_STR_PREFIX(
typename traits_t::value_type,
"nullptr")) == 0)
279 else if constexpr (std::is_same_v<to_t, bool>)
281 if (compare(
QX_STR_PREFIX(
typename traits_t::value_type,
"true")) == 0)
285 else if (compare(
QX_STR_PREFIX(
typename traits_t::value_type,
"false")) == 0)
290 else if (
const auto pszSelectedFormat = pszFormat ? pszFormat : get_format_specifier<value_type, to_t>())
292 constexpr string_view svNSpecifier(
QX_STR_PREFIX(value_type,
"%n"));
293 constexpr
size_t nBufferSize = 256;
295 const size_t nFormatSpecifierLength = traits_t::length(pszSelectedFormat);
296 if (nFormatSpecifierLength <= nBufferSize - svNSpecifier.size() - 1)
298 value_type formatBuffer[nBufferSize];
299 std::memcpy(formatBuffer, pszSelectedFormat, nFormatSpecifierLength *
sizeof(value_type));
301 formatBuffer + nFormatSpecifierLength,
303 svNSpecifier.size() *
sizeof(value_type));
304 formatBuffer[nFormatSpecifierLength + svNSpecifier.size()] =
QX_CHAR_PREFIX(value_type,
'\0');
308 const int nConvertedArgs = traits_t::sscanf(data(), formatBuffer, &result, &nSymbolsRead);
310 if (
static_cast<size_type
>(nSymbolsRead) == size() && nConvertedArgs == 1)
318 sstream_type ss(data());
326 template<
class char_t,
class traits_t>
330 size_type nPos)
const noexcept
332 size_type nCharsToCopy = 0;
334 if (pDest && nCount > 0 && nPos < size())
336 nCharsToCopy = std::min(nPos + nCount, size()) - nPos;
337 std::memcpy(pDest, data() + nPos, nCharsToCopy *
sizeof(value_type));
343 template<
class char_t,
class traits_t>
344 template<
class from_t>
348 std::is_trivial_v<from_t> && std::is_standard_layout_v<from_t> || std::is_pointer_v<from_t>
349 || std::is_same_v<from_t, std::nullptr_t>)
351 if constexpr (std::is_same_v<from_t, std::nullptr_t>)
353 assign(
QX_STR_PREFIX(
typename traits_t::value_type,
"nullptr"));
355 else if constexpr (std::is_same_v<from_t, bool>)
374 template<
class char_t,
class traits_t>
375 template<
class from_t>
380 return std::move(sTemp);
383 template<
class char_t,
class traits_t>
389 template<
class char_t,
class traits_t>
394 const size_type nSize = size();
395 const size_type nSizeSource = nSymbols == npos ? traits_t::length(pszStr) : nSymbols;
397 if (_resize(nSize + nSizeSource))
398 std::memcpy(data() + nSize, pszStr, nSizeSource *
sizeof(value_type));
402 template<
class char_t,
class traits_t>
405 append(sStr.data(), sStr.size());
408 template<
class char_t,
class traits_t>
409 template<
class fwd_it_t>
412 for (
auto it = itBegin; it != itEnd; ++it)
416 template<
class char_t,
class traits_t>
417 template<range_of_t_c<
char_t>
string_t>
420 append(sStr.cbegin(), sStr.cend());
423 template<
class char_t,
class traits_t>
426 value_type chSymbol) noexcept
428 return insert(nPos, &chSymbol, 1);
431 template<
class char_t,
class traits_t>
434 const_pointer pszWhat,
435 size_type nSymbols) noexcept
439 const size_type nSize = size();
440 const size_type nSizeSource = nSymbols == npos ? traits_t::length(pszWhat) : nSymbols;
442 if (nSizeSource > 0 && _resize(nSize + nSizeSource))
444 std::memmove(data() + nPos + nSizeSource, data() + nPos, (nSize - nPos) *
sizeof(value_type));
445 std::memcpy(data() + nPos, pszWhat, nSizeSource *
sizeof(value_type));
446 return nPos + nSizeSource;
453 template<
class char_t,
class traits_t>
454 template<
class fwd_it_t>
457 fwd_it_t itWhatBegin,
458 fwd_it_t itWhatEnd) noexcept
460 if constexpr (is_random_access_iterator<fwd_it_t>)
462 return insert(nPos, itWhatBegin.operator->(),
static_cast<size_type
>(itWhatEnd - itWhatBegin));
466 size_type nWhatSize = 0;
467 for (
auto it = itWhatBegin; it != itWhatEnd; ++it)
470 size_type nStartSymbols = size();
471 if (nWhatSize > 0 && _resize(nStartSymbols + nWhatSize))
473 std::memmove(data() + nPos + nWhatSize, data() + nPos, (nStartSymbols - nPos) *
sizeof(value_type));
475 size_type nWhatPos = 0;
476 for (
auto it = itWhatBegin; it != itWhatEnd; ++it)
478 at(nPos + nWhatPos) = *it;
482 return nPos + nWhatSize;
491 template<
class char_t,
class traits_t>
496 return insert(nPos, sWhat.data(), sWhat.size());
499 template<
class char_t,
class traits_t>
500 template<range_of_t_c<
char_t>
string_t>
503 string_t sWhat) noexcept
505 return insert(
static_cast<size_type
>(nPos), sWhat.cbegin(), sWhat.cend());
508 template<
class char_t,
class traits_t>
511 value_type chSymbol) noexcept
513 return insert(
static_cast<size_type
>(itPos - cbegin()), chSymbol);
516 template<
class char_t,
class traits_t>
519 const_pointer pszWhat,
520 size_type nSymbols) noexcept
522 return insert(
static_cast<size_type
>(itPos - cbegin()), pszWhat, nSymbols);
525 template<
class char_t,
class traits_t>
530 return insert(
static_cast<size_type
>(itPos - cbegin()), sWhat.data(), sWhat.size());
533 template<
class char_t,
class traits_t>
534 template<
class fwd_it_t>
537 fwd_it_t itWhatBegin,
538 fwd_it_t itWhatEnd) noexcept
540 return insert(
static_cast<size_type
>(itPos - begin()), itWhatBegin, itWhatEnd);
543 template<
class char_t,
class traits_t>
544 template<range_of_t_c<
char_t>
string_t>
547 string_t sWhat) noexcept
549 return insert(
static_cast<size_type
>(itPos - begin()), sWhat.cbegin(), sWhat.cend());
552 template<
class char_t,
class traits_t>
555 insert(size(), &chSymbol, 1);
558 template<
class char_t,
class traits_t>
561 insert(0, &chSymbol, 1);
564 template<
class char_t,
class traits_t>
567 if (
const typename iterator::difference_type nCharsToErase = itLast - itFirst; nCharsToErase > 0)
569 const size_type nStartSize = size();
570 const size_type nSymbolsToCopy = itLast != end() ? traits_t::length(itLast.operator->()) : 0;
572 if (nSymbolsToCopy > 0)
574 std::memmove(itFirst.operator->(), itLast.operator->(), nSymbolsToCopy *
sizeof(value_type));
577 if (
static_cast<typename iterator::difference_type
>(nStartSize) >= nCharsToErase)
579 _resize(nStartSize - nCharsToErase);
584 template<
class char_t,
class traits_t>
587 erase(itPos, itPos + 1);
590 template<
class char_t,
class traits_t>
596 template<
class char_t,
class traits_t>
602 template<
class char_t,
class traits_t>
605 value_type chRet = back();
610 template<
class char_t,
class traits_t>
613 value_type chRet = front();
618 template<
class char_t,
class traits_t>
624 return traits_t::is_space(ch);
628 template<
class char_t,
class traits_t>
630 value_type chSymbol) noexcept
633 [chSymbol](value_type ch)
635 return ch == chSymbol;
639 template<
class char_t,
class traits_t>
641 const_pointer pszStr) noexcept
646 [pszStr](value_type ch)
648 for (size_type j = 0; pszStr[j] !=
QX_CHAR_PREFIX(value_type,
'\0'); ++j)
663 template<
class char_t,
class traits_t>
665 const_pointer pszStr,
666 size_type nStrSize) noexcept
671 [pszStr, nStrSize](value_type ch)
673 for (size_type j = 0; j < nStrSize; ++j)
686 template<
class char_t,
class traits_t>
690 return trim_left(sStr.data(), sStr.size());
693 template<
class char_t,
class traits_t>
694 template<
class fwd_it_t>
697 fwd_it_t itEnd) noexcept
700 [itBegin, itEnd](
auto ch)
702 for (
auto it = itBegin; it != itEnd; ++it)
710 template<
class char_t,
class traits_t>
711 template<range_of_t_c<
char_t>
string_t>
713 const string_t& sStr) noexcept
715 return trim_left(sStr.cbegin(), sStr.cend());
718 template<
class char_t,
class traits_t>
724 return traits_t::is_space(ch);
728 template<
class char_t,
class traits_t>
730 value_type chSymbol) noexcept
733 [chSymbol](value_type ch)
735 return ch == chSymbol;
739 template<
class char_t,
class traits_t>
741 const_pointer pszStr) noexcept
746 [pszStr](value_type ch)
763 template<
class char_t,
class traits_t>
765 const_pointer pszStr,
766 size_type nStrSize) noexcept
771 [pszStr, nStrSize](value_type ch)
773 for (size_type j = 0; j < nStrSize; ++j)
786 template<
class char_t,
class traits_t>
790 return trim_right(sStr.data(), sStr.size());
793 template<
class char_t,
class traits_t>
794 template<
class fwd_it_t>
797 fwd_it_t itEnd) noexcept
800 [itBegin, itEnd](
auto ch)
802 for (
auto it = itBegin; it != itEnd; ++it)
810 template<
class char_t,
class traits_t>
811 template<range_of_t_c<
char_t>
string_t>
813 const string_t& sStr) noexcept
815 return trim_right(sStr.cbegin(), sStr.cend());
818 template<
class char_t,
class traits_t>
824 return traits_t::is_space(ch);
828 template<
class char_t,
class traits_t>
830 value_type chSymbol) noexcept
833 [chSymbol](value_type ch)
835 return ch == chSymbol;
839 template<
class char_t,
class traits_t>
841 const_pointer pszStr) noexcept
846 [pszStr](value_type ch)
848 for (size_type j = 0; pszStr[j] !=
QX_CHAR_PREFIX(value_type,
'\0'); ++j)
863 template<
class char_t,
class traits_t>
865 const_pointer pszStr,
866 size_type nStrSize) noexcept
871 [pszStr, nStrSize](value_type ch)
873 for (size_type j = 0; j < nStrSize; ++j)
886 template<
class char_t,
class traits_t>
890 return trim(sStr.data(), sStr.size());
893 template<
class char_t,
class traits_t>
894 template<
class fwd_it_t>
897 fwd_it_t itEnd) noexcept
900 [itBegin, itEnd](
auto ch)
902 for (
auto it = itBegin; it != itEnd; ++it)
910 template<
class char_t,
class traits_t>
911 template<range_of_t_c<
char_t>
string_t>
913 const string_t& sStr) noexcept
915 return trim(sStr.cbegin(), sStr.cend());
918 template<
class char_t,
class traits_t>
922 size_type nEnd) noexcept
924 size_type nPos = find(chSymbol, nBegin, nEnd);
932 template<
class char_t,
class traits_t>
934 const_pointer pszStr,
937 size_type nStrSize) noexcept
941 const size_type nLocalStrSize = nStrSize != npos ? nStrSize : traits_t::length(pszStr);
942 const size_type nPos = find(pszStr, nBegin, nLocalStrSize, nEnd);
945 erase(nPos, nLocalStrSize);
955 template<
class char_t,
class traits_t>
959 size_type nEnd) noexcept
961 const size_type nPos = find(sStr, nBegin, nEnd);
964 erase(nPos, sStr.size());
969 template<
class char_t,
class traits_t>
970 template<
class fwd_it_t>
975 size_type nEnd) noexcept
977 const size_type nPos = find(itBegin, itEnd, nBegin, nEnd);
980 erase(nPos,
static_cast<size_type
>(std::distance(itBegin, itEnd)));
985 template<
class char_t,
class traits_t>
986 template<range_of_t_c<
char_t>
string_t>
988 const string_t& sStr,
990 size_type nEnd) noexcept
992 return remove(sStr.cbegin(), sStr.cend(), nBegin, nEnd);
995 template<
class char_t,
class traits_t>
998 return remove(chSymbol,
static_cast<size_type
>(0),
static_cast<size_type
>(1)) != npos;
1001 template<
class char_t,
class traits_t>
1004 return remove(pszStr,
static_cast<size_type
>(0), nStrSize, nStrSize) != npos;
1007 template<
class char_t,
class traits_t>
1010 return remove(sStr,
static_cast<size_type
>(0), sStr.size()) != npos;
1013 template<
class char_t,
class traits_t>
1014 template<
class fwd_it_t>
1017 return remove(itBegin, itEnd,
static_cast<size_type
>(0),
static_cast<size_type
>(std::distance(itBegin, itEnd)))
1021 template<
class char_t,
class traits_t>
1022 template<range_of_t_c<
char_t>
string_t>
1025 return remove_prefix(sStr.cbegin(), sStr.cend());
1028 template<
class char_t,
class traits_t>
1031 const size_type nSize = size();
1032 return remove(chSymbol, nSize - 1, nSize) != npos;
1035 template<
class char_t,
class traits_t>
1040 const size_type nSize = size();
1041 const size_type nLocalStrSize = nStrSize != npos ? nStrSize : traits_t::length(pszStr);
1043 return remove(pszStr, nSize - nLocalStrSize, nSize, nLocalStrSize) != npos;
1051 template<
class char_t,
class traits_t>
1054 return remove_suffix(sStr.data(), sStr.size());
1057 template<
class char_t,
class traits_t>
1058 template<
class fwd_it_t>
1061 const size_type nSize = size();
1062 return remove(itBegin, itEnd, nSize -
static_cast<size_type
>(std::distance(itBegin, itEnd)), nSize) != npos;
1065 template<
class char_t,
class traits_t>
1066 template<range_of_t_c<
char_t>
string_t>
1069 return remove_suffix(sStr.cbegin(), sStr.cend());
1072 template<
class char_t,
class traits_t>
1074 value_type chSymbol,
1076 size_type nEnd) noexcept
1078 size_type nOccurrences = 0;
1079 size_type nLastOccurrencePos = nBegin;
1084 nLastOccurrencePos = remove(chSymbol, nLastOccurrencePos, nEnd);
1085 }
while (nLastOccurrencePos != npos);
1087 return nOccurrences - 1;
1090 template<
class char_t,
class traits_t>
1092 const_pointer pszStr,
1095 size_type nStrSize) noexcept
1099 size_type nOccurrences = 0;
1100 size_type nLastOccurrencePos = nBegin;
1105 nLastOccurrencePos = remove(pszStr, nLastOccurrencePos, nEnd, nStrSize);
1106 }
while (nLastOccurrencePos != npos);
1108 return nOccurrences - 1;
1116 template<
class char_t,
class traits_t>
1120 size_type nEnd) noexcept
1122 return remove_all(sStr.data(), nBegin, nEnd, sStr.size());
1125 template<
class char_t,
class traits_t>
1126 template<
class fwd_it_t>
1131 size_type nEnd) noexcept
1133 size_type nOccurrences = 0;
1134 size_type nLastOccurrencePos = nBegin;
1139 nLastOccurrencePos = remove(itFirst, itLast, nLastOccurrencePos, nEnd);
1140 }
while (nLastOccurrencePos != npos);
1142 return nOccurrences - 1;
1145 template<
class char_t,
class traits_t>
1146 template<range_of_t_c<
char_t>
string_t>
1148 const string_t& sStr,
1150 size_type nEnd) noexcept
1152 return remove_all(sStr.cbegin(), sStr.cend(), nBegin, nEnd);
1155 template<
class char_t,
class traits_t>
1159 const_pointer pszReplace,
1160 size_t nReplaceSize) noexcept
1162 const size_type nStartSize = size();
1163 const size_type nNewSize = nStartSize - nSize + nReplaceSize;
1165 _resize(nNewSize, sbo_resize_type::reserve);
1168 data() + nBegin + nReplaceSize,
1169 data() + nBegin + nSize,
1170 (nStartSize - nBegin - nSize) *
sizeof(value_type));
1172 std::memcpy(data() + nBegin, pszReplace, nReplaceSize *
sizeof(value_type));
1176 return nBegin + nReplaceSize;
1179 template<
class char_t,
class traits_t>
1180 template<
class replace_
string_t>
1184 const replace_string_t& sReplace) noexcept
1186 return replace(nBegin, nSize, _get_string_view_like_data(sReplace), _get_string_view_like_size(sReplace));
1189 template<
class char_t,
class traits_t>
1190 template<
class find_
string_t,
class replace_
string_t>
1192 const find_string_t& sFind,
1193 const replace_string_t& sReplace,
1195 size_type nEnd) noexcept
1197 if (size_type nPos = find(sFind, nBegin, nEnd); nPos != npos)
1201 _get_string_view_like_size(sFind),
1202 _get_string_view_like_data(sReplace),
1203 _get_string_view_like_size(sReplace));
1211 template<
class char_t,
class traits_t>
1212 template<
class find_
string_t,
class replace_
string_t>
1214 const find_string_t& sFind,
1215 const replace_string_t& sReplace,
1217 size_type nEnd) noexcept
1219 size_type nOccurrences = 0;
1220 size_type nPos = nBegin;
1224 nPos = replace(sFind, sReplace, nPos, nEnd);
1227 }
while (nPos != npos);
1229 return nOccurrences;
1232 template<
class char_t,
class traits_t>
1235 return compare(&chSymbol, 1);
1238 template<
class char_t,
class traits_t>
1241 return traits_t::compare(data(), pszStr);
1244 template<
class char_t,
class traits_t>
1247 return traits_t::compare_n(data(), pStr, nSymbols);
1250 template<
class char_t,
class traits_t>
1253 return compare(sStr.data(), sStr.size());
1256 template<
class char_t,
class traits_t>
1257 template<
class fwd_it_t>
1260 return iter_strcmp(cbegin(), cend(), itBegin, itEnd);
1263 template<
class char_t,
class traits_t>
1264 template<range_of_t_c<
char_t>
string_t>
1267 return compare(sStr.cbegin(), sStr.cend());
1270 template<
class char_t,
class traits_t>
1272 value_type chSymbol,
1274 size_type nEnd)
const noexcept
1279 [chSymbol](const_pointer pCurrentChar)
1281 return *pCurrentChar == chSymbol;
1285 template<
class char_t,
class traits_t>
1287 const_pointer pszWhat,
1289 size_type nWhatSize,
1290 size_type nEnd)
const noexcept
1294 const size_type nLocalWhatSize = nWhatSize != npos ? nWhatSize : traits_t::length(pszWhat);
1299 [pszWhat, nLocalWhatSize](const_pointer pCurrentChar)
1301 return !traits_t::compare_n(pszWhat, pCurrentChar, nLocalWhatSize);
1310 template<
class char_t,
class traits_t>
1314 size_type nEnd)
const noexcept
1316 return find(sWhat.data(), nBegin, sWhat.size(), nEnd);
1319 template<
class char_t,
class traits_t>
1320 template<
class fwd_it_t>
1322 fwd_it_t itWhatBegin,
1325 size_type nEnd)
const noexcept
1327 const size_t nWhatSize = itWhatEnd - itWhatBegin;
1331 [
this, itWhatBegin, itWhatEnd, nWhatSize](const_pointer pCurrentChar)
1333 const size_t nStart =
static_cast<size_type
>(pCurrentChar - data());
1342 template<
class char_t,
class traits_t>
1343 template<range_of_t_c<
char_t>
string_t>
1347 size_type nEnd)
const noexcept
1349 return find(sWhat.cbegin(), sWhat.cend(), nBegin, nEnd);
1352 template<
class char_t,
class traits_t>
1354 value_type chSymbol,
1356 size_type nEnd)
const noexcept
1361 [chSymbol](const_pointer pCurrentChar)
1363 return *pCurrentChar == chSymbol;
1367 template<
class char_t,
class traits_t>
1369 const_pointer pszWhat,
1371 size_type nWhatSize,
1372 size_type nEnd)
const noexcept
1376 const size_type nLocalWhatSize = nWhatSize != npos ? nWhatSize : traits_t::length(pszWhat);
1381 [pszWhat, nLocalWhatSize](const_pointer pCurrentChar)
1383 return !traits_t::compare_n(pszWhat, pCurrentChar, nLocalWhatSize);
1392 template<
class char_t,
class traits_t>
1396 size_type nEnd)
const noexcept
1398 return rfind(sWhat.data(), nBegin, sWhat.size(), nEnd);
1401 template<
class char_t,
class traits_t>
1402 template<
class fwd_it_t>
1404 fwd_it_t itWhatBegin,
1407 size_type nEnd)
const noexcept
1409 const size_t nWhatSize = itWhatEnd - itWhatBegin;
1413 [
this, itWhatBegin, itWhatEnd, nWhatSize](const_pointer pCurrentChar)
1415 const size_t nStart =
static_cast<size_type
>(pCurrentChar - data());
1424 template<
class char_t,
class traits_t>
1425 template<range_of_t_c<
char_t>
string_t>
1429 size_type nEnd)
const noexcept
1431 return rfind(sWhat.cbegin(), sWhat.cend(), nBegin, nEnd);
1434 template<
class char_t,
class traits_t>
1436 value_type chSymbol,
1437 size_type nBegin)
const noexcept
1439 return find(chSymbol, nBegin);
1442 template<
class char_t,
class traits_t>
1444 const_pointer pszWhat,
1446 size_type nWhatSize)
const noexcept
1450 return _find_first_of(
1452 pszWhat + nWhatSize,
1454 [](const_pointer pChar)
1465 template<
class char_t,
class traits_t>
1467 const_pointer pszWhat,
1468 size_type nBegin)
const noexcept
1472 return _find_first_of(
1474 static_cast<const_pointer
>(
nullptr),
1476 [](const_pointer pChar)
1478 return *(pChar + 1) !=
QX_CHAR_PREFIX(value_type,
'\0') ? pChar + 1 :
nullptr;
1487 template<
class char_t,
class traits_t>
1490 size_type nBegin)
const noexcept
1492 return find_first_of(sWhat.data(), nBegin, sWhat.size());
1495 template<
class char_t,
class traits_t>
1496 template<
class fwd_it_t>
1498 fwd_it_t itWhatBegin,
1500 size_type nBegin)
const noexcept
1502 return _find_first_of(
1512 template<
class char_t,
class traits_t>
1513 template<range_of_t_c<
char_t>
string_t>
1516 size_type nBegin)
const noexcept
1518 return find_first_of(sWhat.cbegin(), sWhat.cend(), nBegin);
1521 template<
class char_t,
class traits_t>
1523 value_type chSymbol,
1524 size_type nEnd)
const noexcept
1526 return rfind(chSymbol, npos, nEnd);
1529 template<
class char_t,
class traits_t>
1531 const_pointer pszWhat,
1533 size_type nWhatSize)
const noexcept
1537 return _find_last_of(
1539 pszWhat + nWhatSize,
1541 [](const_pointer pChar)
1552 template<
class char_t,
class traits_t>
1554 const_pointer pszWhat,
1555 size_type nEnd)
const noexcept
1559 return _find_last_of(
1561 static_cast<const_pointer
>(
nullptr),
1563 [](const_pointer pChar)
1565 return *(pChar + 1) !=
QX_CHAR_PREFIX(value_type,
'\0') ? pChar + 1 :
nullptr;
1574 template<
class char_t,
class traits_t>
1577 size_type nEnd)
const noexcept
1579 return find_last_of(sWhat.data(), nEnd, sWhat.size());
1582 template<
class char_t,
class traits_t>
1583 template<
class fwd_it_t>
1585 fwd_it_t itWhatBegin,
1587 size_type nEnd)
const noexcept
1589 return _find_last_of(
1599 template<
class char_t,
class traits_t>
1600 template<range_of_t_c<
char_t>
string_t>
1603 size_type nEnd)
const noexcept
1605 return find_last_of(sWhat.cbegin(), sWhat.cend(), nEnd);
1608 template<
class char_t,
class traits_t>
1610 value_type chSymbol,
1611 size_type nBegin)
const noexcept
1616 [chSymbol](const_pointer pCurrentChar)
1618 return *pCurrentChar != chSymbol;
1622 template<
class char_t,
class traits_t>
1624 const_pointer pszWhat,
1626 size_type nWhatSize)
const noexcept
1630 return _find_first_not_of(
1632 pszWhat + nWhatSize,
1634 [](const_pointer pChar)
1645 template<
class char_t,
class traits_t>
1647 const_pointer pszWhat,
1648 size_type nBegin)
const noexcept
1652 return _find_first_not_of(
1654 static_cast<const_pointer
>(
nullptr),
1656 [](const_pointer pChar)
1658 return *(pChar + 1) !=
QX_CHAR_PREFIX(value_type,
'\0') ? pChar + 1 :
nullptr;
1667 template<
class char_t,
class traits_t>
1670 size_type nBegin)
const noexcept
1672 return find_first_not_of(sWhat.data(), nBegin, sWhat.size());
1675 template<
class char_t,
class traits_t>
1676 template<
class fwd_it_t>
1678 fwd_it_t itWhatBegin,
1680 size_type nBegin)
const noexcept
1682 return _find_first_not_of(
1692 template<
class char_t,
class traits_t>
1693 template<range_of_t_c<
char_t>
string_t>
1696 size_type nBegin)
const noexcept
1698 return find_first_not_of(sWhat.cbegin(), sWhat.cend(), nBegin);
1701 template<
class char_t,
class traits_t>
1703 value_type chSymbol,
1704 size_type nEnd)
const noexcept
1709 [chSymbol](const_pointer pCurrentChar)
1711 return *pCurrentChar != chSymbol;
1715 template<
class char_t,
class traits_t>
1717 const_pointer pszWhat,
1719 size_type nWhatSize)
const noexcept
1723 return _find_last_not_of(
1725 pszWhat + nWhatSize,
1727 [](const_pointer pChar)
1738 template<
class char_t,
class traits_t>
1740 const_pointer pszWhat,
1741 size_type nEnd)
const noexcept
1745 return _find_last_not_of(
1747 static_cast<const_pointer
>(
nullptr),
1749 [](const_pointer pChar)
1751 return *(pChar + 1) !=
QX_CHAR_PREFIX(value_type,
'\0') ? pChar + 1 :
nullptr;
1760 template<
class char_t,
class traits_t>
1763 size_type nEnd)
const noexcept
1765 return find_last_not_of(sWhat.data(), nEnd, sWhat.size());
1768 template<
class char_t,
class traits_t>
1769 template<
class fwd_it_t>
1771 fwd_it_t itWhatBegin,
1773 size_type nEnd)
const noexcept
1775 return _find_last_not_of(
1785 template<
class char_t,
class traits_t>
1786 template<range_of_t_c<
char_t>
string_t>
1789 size_type nEnd)
const noexcept
1791 return find_last_not_of(sWhat.cbegin(), sWhat.cend(), nEnd);
1794 template<
class char_t,
class traits_t>
1796 const value_type chSeparator)
const noexcept
1800 size_type nStart = 0;
1802 while ((nEnd = find(chSeparator, nStart)) != npos)
1804 tokens.emplace_back(substr(nStart, nEnd - nStart));
1806 while (traits_t::compare_n(data() + nStart, &chSeparator, 1) == 0)
1810 if (nStart != size())
1811 tokens.emplace_back(substr(nStart));
1813 return std::move(tokens);
1816 template<
class char_t,
class traits_t>
1818 const_pointer pszSeparator,
1819 size_type nSepLen)
const noexcept
1826 if (nSepLen == npos)
1827 nSepLen = traits_t::length(pszSeparator);
1829 size_type nStart = 0;
1831 while ((nEnd = find(pszSeparator, nStart, nSepLen, npos)) != npos)
1833 tokens.emplace_back(substr(nStart, nEnd - nStart));
1835 while (traits_t::compare_n(data() + nStart, pszSeparator, nSepLen) == 0)
1839 if (nStart != size())
1840 tokens.emplace_back(substr(nStart));
1845 template<
class char_t,
class traits_t>
1849 return split(sSeparator.data(), sSeparator.size());
1852 template<
class char_t,
class traits_t>
1853 template<
class fwd_it_t>
1855 fwd_it_t itSepFirst,
1856 fwd_it_t itSepLast)
const noexcept
1860 const size_type nSepLen =
static_cast<size_type
>(std::distance(itSepFirst, itSepLast));
1862 size_type nStart = 0;
1864 while ((nEnd = find(itSepFirst, itSepLast, nStart)) != npos)
1866 tokens.emplace_back(substr(nStart, nEnd - nStart));
1867 nStart = nEnd + nSepLen;
1869 tokens.emplace_back(substr(nStart));
1874 template<
class char_t,
class traits_t>
1875 template<range_of_t_c<
char_t>
string_t>
1877 const string_t& sSeparator)
const noexcept
1879 return split(sSeparator.cbegin(), sSeparator.cend());
1882 template<
class char_t,
class traits_t>
1886 return at(0) == chSymbol;
1891 template<
class char_t,
class traits_t>
1896 if (size_type nThisSize = size(); nThisSize > 0)
1898 if (nStrSize == npos)
1899 nStrSize = traits_t::length(pszStr);
1901 if (nStrSize <= nThisSize)
1902 return traits_t::compare_n(data(), pszStr, nStrSize) == 0;
1909 template<
class char_t,
class traits_t>
1912 return starts_with(sStr.data(), sStr.size());
1915 template<
class char_t,
class traits_t>
1916 template<
class fwd_it_t>
1919 auto nStrSize = std::distance(itBegin, itEnd);
1920 return iter_strcmp(cbegin(), cbegin() +
static_cast<size_type
>(nStrSize), itBegin, itEnd) == 0;
1923 template<
class char_t,
class traits_t>
1924 template<range_of_t_c<
char_t>
string_t>
1927 return starts_with(sStr.cbegin(), sStr.cend());
1930 template<
class char_t,
class traits_t>
1933 const size_type nSize = size();
1935 return at(nSize - 1) == chSymbol;
1940 template<
class char_t,
class traits_t>
1946 if (nStrSize == npos)
1947 nStrSize = traits_t::length(pszStr);
1949 return ends_with(pszStr, pszStr + nStrSize);
1952 template<
class char_t,
class traits_t>
1955 return ends_with(sStr.data(), sStr.size());
1958 template<
class char_t,
class traits_t>
1959 template<
class fwd_it_t>
1962 const size_t nOtherSize =
static_cast<size_type
>(std::distance(itBegin, itEnd));
1963 if (nOtherSize > size())
1966 return iter_strcmp(cend() - nOtherSize, cend(), itBegin, itEnd) == 0;
1969 template<
class char_t,
class traits_t>
1970 template<range_of_t_c<
char_t>
string_t>
1973 return ends_with(sStr.cbegin(), sStr.cend());
1976 template<
class char_t,
class traits_t>
1979 return find(chSymbol) != npos;
1982 template<
class char_t,
class traits_t>
1985 return find(pszStr, 0, nStrSize) != npos;
1988 template<
class char_t,
class traits_t>
1991 return find(sStr) != npos;
1994 template<
class char_t,
class traits_t>
1995 template<
class fwd_it_t>
1998 return find(itBegin, itEnd) != npos;
2001 template<
class char_t,
class traits_t>
2002 template<range_of_t_c<
char_t>
string_t>
2005 return find(sStr) != npos;
2008 template<
class char_t,
class traits_t>
2015 template<
class char_t,
class traits_t>
2016 inline basic_string<char_t, traits_t>& basic_string<char_t, traits_t>::operator=(basic_string&& sStr) noexcept
2018 assign(std::move(sStr));
2022 template<
class char_t,
class traits_t>
2023 inline basic_string<char_t, traits_t>& basic_string<char_t, traits_t>::operator=(
const basic_string& sStr) noexcept
2029 template<
class char_t,
class traits_t>
2030 template<range_of_t_c<
char_t>
string_t>
2031 inline basic_string<char_t, traits_t>& basic_string<char_t, traits_t>::operator=(
const string_t& sStr) noexcept
2037 template<
class char_t,
class traits_t>
2038 inline basic_string<char_t, traits_t>& basic_string<char_t, traits_t>::operator+=(value_type chSymbol) noexcept
2044 template<
class char_t,
class traits_t>
2045 inline basic_string<char_t, traits_t>& basic_string<char_t, traits_t>::operator+=(const_pointer pszSource) noexcept
2048 append(pszSource, traits_t::length(pszSource));
2053 template<
class char_t,
class traits_t>
2054 inline basic_string<char_t, traits_t>& basic_string<char_t, traits_t>::operator+=(
const basic_string& sStr) noexcept
2056 append(sStr.data(), sStr.size());
2060 template<
class char_t,
class traits_t>
2061 template<range_of_t_c<
char_t>
string_t>
2062 inline basic_string<char_t, traits_t>& basic_string<char_t, traits_t>::operator+=(
const string_t& sStr) noexcept
2064 append(sStr.cbegin(), sStr.cend());
2068 template<
class char_t,
class traits_t>
2069 inline bool basic_string<char_t, traits_t>::operator==(value_type chSymbol)
const noexcept
2071 return size() == 1 && at(0) == chSymbol;
2074 template<
class char_t,
class traits_t>
2075 inline bool basic_string<char_t, traits_t>::operator==(const_pointer pszSource)
const noexcept
2077 return compare(pszSource) == 0;
2080 template<
class char_t,
class traits_t>
2081 inline bool basic_string<char_t, traits_t>::operator==(
const basic_string& sStr)
const noexcept
2083 return size() == sStr.size() && compare(sStr.data(), sStr.size()) == 0;
2086 template<
class char_t,
class traits_t>
2087 template<range_of_t_c<
char_t>
string_t>
2088 inline bool basic_string<char_t, traits_t>::operator==(
const string_t& sStr)
const noexcept
2090 return iter_strcmp(cbegin(), cend(), sStr.cbegin(), sStr.cend()) == 0;
2093 template<
class char_t,
class traits_t>
2094 inline bool basic_string<char_t, traits_t>::operator!=(value_type chSymbol)
const noexcept
2096 return !operator==(chSymbol);
2099 template<
class char_t,
class traits_t>
2100 inline bool basic_string<char_t, traits_t>::operator!=(const_pointer pszSource)
const noexcept
2102 return !operator==(pszSource);
2105 template<
class char_t,
class traits_t>
2106 inline bool basic_string<char_t, traits_t>::operator!=(
const basic_string& sStr)
const noexcept
2108 return !operator==(sStr);
2111 template<
class char_t,
class traits_t>
2112 template<range_of_t_c<
char_t>
string_t>
2113 inline bool basic_string<char_t, traits_t>::operator!=(
const string_t& sStr)
const noexcept
2115 return !operator==(sStr);
2118 template<
class char_t,
class traits_t>
2119 inline bool basic_string<char_t, traits_t>::operator<(value_type chSymbol)
const noexcept
2121 return compare(&chSymbol, 1) < 0;
2124 template<
class char_t,
class traits_t>
2125 inline bool basic_string<char_t, traits_t>::operator<(const_pointer pszSource)
const noexcept
2127 return compare(pszSource) < 0;
2130 template<
class char_t,
class traits_t>
2131 inline bool basic_string<char_t, traits_t>::operator<(
const basic_string& sStr)
const noexcept
2133 return compare(sStr.data(), sStr.size()) < 0;
2136 template<
class char_t,
class traits_t>
2137 template<range_of_t_c<
char_t>
string_t>
2138 inline bool basic_string<char_t, traits_t>::operator<(
const string_t& sStr)
const noexcept
2140 return iter_strcmp(cbegin(), cend(), sStr.cbegin(), sStr.cend()) < 0;
2143 template<
class char_t,
class traits_t>
2144 inline bool basic_string<char_t, traits_t>::operator<=(value_type chSymbol)
const noexcept
2146 return compare(&chSymbol, 1) <= 0;
2149 template<
class char_t,
class traits_t>
2150 inline bool basic_string<char_t, traits_t>::operator<=(const_pointer pszSource)
const noexcept
2152 return compare(pszSource) <= 0;
2155 template<
class char_t,
class traits_t>
2156 inline bool basic_string<char_t, traits_t>::operator<=(
const basic_string& sStr)
const noexcept
2158 return compare(sStr.data(), sStr.size()) <= 0;
2161 template<
class char_t,
class traits_t>
2162 template<range_of_t_c<
char_t>
string_t>
2163 inline bool basic_string<char_t, traits_t>::operator<=(
const string_t& sStr)
const noexcept
2165 return iter_strcmp(cbegin(), cend(), sStr.cbegin(), sStr.cend()) <= 0;
2168 template<
class char_t,
class traits_t>
2169 inline bool basic_string<char_t, traits_t>::operator>(value_type chSymbol)
const noexcept
2171 return compare(&chSymbol, 1) > 0;
2174 template<
class char_t,
class traits_t>
2175 inline bool basic_string<char_t, traits_t>::operator>(const_pointer pszSource)
const noexcept
2177 return compare(pszSource) > 0;
2180 template<
class char_t,
class traits_t>
2181 inline bool basic_string<char_t, traits_t>::operator>(
const basic_string& sStr)
const noexcept
2183 return compare(sStr.data(), sStr.size()) > 0;
2186 template<
class char_t,
class traits_t>
2187 template<range_of_t_c<
char_t>
string_t>
2188 inline bool basic_string<char_t, traits_t>::operator>(
const string_t& sStr)
const noexcept
2190 return iter_strcmp(cbegin(), cend(), sStr.cbegin(), sStr.cend()) > 0;
2193 template<
class char_t,
class traits_t>
2194 inline bool basic_string<char_t, traits_t>::operator>=(value_type chSymbol)
const noexcept
2196 return compare(&chSymbol, 1) >= 0;
2199 template<
class char_t,
class traits_t>
2200 inline bool basic_string<char_t, traits_t>::operator>=(const_pointer pszSource)
const noexcept
2202 return compare(pszSource) >= 0;
2205 template<
class char_t,
class traits_t>
2206 inline bool basic_string<char_t, traits_t>::operator>=(
const basic_string& sStr)
const noexcept
2208 return compare(sStr.data(), sStr.size()) >= 0;
2211 template<
class char_t,
class traits_t>
2212 template<range_of_t_c<
char_t>
string_t>
2213 inline bool basic_string<char_t, traits_t>::operator>=(
const string_t& sStr)
const noexcept
2215 return iter_strcmp(cbegin(), cend(), sStr.cbegin(), sStr.cend()) >= 0;
2218 template<
class char_t,
class traits_t>
2219 inline typename basic_string<char_t, traits_t>::reference basic_string<char_t, traits_t>::operator[](
2220 size_type nSymbol) noexcept
2222 return data()[nSymbol];
2225 template<
class char_t,
class traits_t>
2226 inline typename basic_string<char_t, traits_t>::const_reference basic_string<char_t, traits_t>::operator[](
2227 size_type nSymbol)
const noexcept
2229 return data()[nSymbol];
2232 template<
class char_t,
class traits_t>
2233 inline basic_string<char_t, traits_t>::operator std::basic_string_view<
2234 typename basic_string<char_t, traits_t>::value_type>()
const noexcept
2236 return string_view(data(), size());
2239 template<
class char_t,
class traits_t>
2240 inline basic_string<char_t, traits_t>::operator bool() const noexcept
2245 template<
class char_t,
class traits_t>
2246 inline bool basic_string<char_t, traits_t>::_resize(size_type nSymbols, sbo_resize_type eType) noexcept
2248 const bool bRet = m_Data.resize(
2249 (nSymbols > 0 ? nSymbols + 1 : 0) *
sizeof(value_type),
2250 traits_t::align() *
sizeof(value_type),
2254 if (bRet && eType != sbo_resize_type::reserve)
2255 (*this)[nSymbols] =
QX_CHAR_PREFIX(
typename traits_t::value_type,
'\0');
2260 template<
class char_t,
class traits_t>
2261 template<
class searcher_t>
2262 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_trim_left(
2263 const searcher_t& searcher) noexcept
2265 size_type nSymbols = 0;
2267 for (size_type i = 0; i < size(); ++i)
2269 if (searcher(at(i)))
2279 template<
class char_t,
class traits_t>
2280 template<
class searcher_t>
2281 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_trim_right(
2282 const searcher_t& searcher) noexcept
2284 size_type nSymbols = 0;
2285 size_type nSize = size();
2287 for (size_type i = nSize - 1; i != std::numeric_limits<size_type>::max(); --i)
2289 if (searcher(at(i)))
2295 erase(nSize - nSymbols, nSymbols);
2299 template<
class char_t,
class traits_t>
2300 template<
class searcher_t>
2301 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_trim(
2302 const searcher_t& searcher) noexcept
2304 const size_type nSize = size();
2305 size_type nStartPos = 0;
2306 size_type nEndPos = nSize;
2308 while (nStartPos < nSize && searcher(at(nStartPos)))
2311 while (nEndPos > nStartPos && searcher(at(nEndPos - 1)))
2314 size_type nNewSize = nEndPos - nStartPos;
2316 std::memmove(data(), data() + nStartPos, nNewSize *
sizeof(value_type));
2319 return nSize - nNewSize;
2322 template<
class char_t,
class traits_t>
2323 template<
class comparator_t>
2324 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_find(
2327 const comparator_t& comparator)
const noexcept
2332 const_pointer pData = data();
2333 const_pointer pCurrentChar = pData + nBegin;
2334 const_pointer pEnd = pData + nEnd;
2336 while (pCurrentChar < pEnd)
2338 if (comparator(pCurrentChar))
2339 return static_cast<size_type
>(pCurrentChar - pData);
2347 template<
class char_t,
class traits_t>
2348 template<
class comparator_t>
2349 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_rfind(
2352 const comparator_t& comparator)
const noexcept
2355 nBegin = size() - 1;
2357 const_pointer pData = data();
2358 const_pointer pCurrentChar = pData + nBegin;
2359 const_pointer pEnd = pData + nEnd;
2361 while (pCurrentChar >= pEnd)
2363 if (comparator(pCurrentChar))
2364 return static_cast<size_type
>(pCurrentChar - pData);
2372 template<
class char_t,
class traits_t>
2373 template<
class incrementer_t,
class fwd_it_t>
2374 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_find_first_of(
2378 const incrementer_t& incrementer)
const noexcept
2380 for (size_type i = nBegin; i < size(); ++i)
2381 for (fwd_it_t it = itBegin; it != itEnd; it = incrementer(it))
2388 template<
class char_t,
class traits_t>
2389 template<
class incrementer_t,
class fwd_it_t>
2390 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_find_last_of(
2394 const incrementer_t& incrementer)
const noexcept
2396 for (size_type i = size() - 1; i != nEnd - 1; --i)
2397 for (fwd_it_t it = itBegin; it != itEnd; it = incrementer(it))
2404 template<
class char_t,
class traits_t>
2405 template<
class incrementer_t,
class fwd_it_t>
2406 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_find_first_not_of(
2410 const incrementer_t& incrementer)
const noexcept
2412 for (size_type i = nBegin; i < size(); ++i)
2414 bool bFoundOneOf =
false;
2415 for (fwd_it_t it = itBegin; !bFoundOneOf && it != itEnd; it = incrementer(it))
2416 bFoundOneOf |= *it == at(i);
2425 template<
class char_t,
class traits_t>
2426 template<
class incrementer_t,
class fwd_it_t>
2427 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_find_last_not_of(
2431 const incrementer_t& incrementer)
const noexcept
2433 for (size_type i = size() - 1; i != nEnd - 1; --i)
2435 bool bFoundOneOf =
false;
2436 for (fwd_it_t it = itBegin; !bFoundOneOf && it != itEnd; it = incrementer(it))
2437 bFoundOneOf |= *it == at(i);
2446 template<
class char_t,
class traits_t>
2447 template<
class string_view_like_t>
2448 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::_get_string_view_like_size(
2449 const string_view_like_t& sValue) noexcept
2451 if constexpr (std::is_same_v<string_view_like_t, value_type>)
2455 else if constexpr (std::is_convertible_v<string_view_like_t, const_pointer>)
2457 return traits_t::length(sValue);
2459 else if constexpr (range_of_t_c<string_view_like_t, char_t>)
2461 return sValue.size();
2470 template<
class char_t,
class traits_t>
2471 template<
class string_view_like_t>
2472 inline typename basic_string<char_t, traits_t>::const_pointer basic_string<char_t, traits_t>::
2473 _get_string_view_like_data(
const string_view_like_t& sValue) noexcept
2475 if constexpr (std::is_same_v<string_view_like_t, value_type>)
2479 else if constexpr (std::is_convertible_v<string_view_like_t, const_pointer>)
2483 else if constexpr (range_of_t_c<string_view_like_t, char_t>)
2485 return sValue.data();
2494 template<
class T,
class char_t,
class traits_t>
2500 template<
class char_t,
class traits_t>
2501 basic_string<char_t, traits_t> operator+(
2502 const basic_string<char_t, traits_t>& lhs,
2503 const basic_string<char_t, traits_t>& rhs) noexcept
2505 basic_string<char_t, traits_t> str(lhs);
2510 template<
class char_t,
class traits_t>
2511 basic_string<char_t, traits_t> operator+(
2512 basic_string<char_t, traits_t>&& lhs,
2513 const basic_string<char_t, traits_t>& rhs) noexcept
2515 basic_string<char_t, traits_t> str(std::move(lhs));
2520 template<
class char_t,
class traits_t>
2521 basic_string<char_t, traits_t> operator+(
2522 const basic_string<char_t, traits_t>& lhs,
2523 typename traits_t::const_pointer rhs) noexcept
2525 basic_string<char_t, traits_t> str(lhs);
2530 template<
class char_t,
class traits_t>
2531 basic_string<char_t, traits_t> operator+(
2532 basic_string<char_t, traits_t>&& lhs,
2533 typename traits_t::const_pointer rhs) noexcept
2535 basic_string<char_t, traits_t> str(std::move(lhs));
2540 template<
class char_t,
class traits_t>
2541 basic_string<char_t, traits_t> operator+(
2542 typename traits_t::const_pointer lhs,
2543 const basic_string<char_t, traits_t>& rhs) noexcept
2545 basic_string<char_t, traits_t> str(lhs);
2550 template<
class char_t,
class traits_t>
2551 basic_string<char_t, traits_t> operator+(
2552 const basic_string<char_t, traits_t>& lhs,
2553 typename traits_t::value_type rhs) noexcept
2555 basic_string<char_t, traits_t> str(lhs);
2560 template<
class char_t,
class traits_t>
2561 basic_string<char_t, traits_t> operator+(
2562 basic_string<char_t, traits_t>&& lhs,
2563 typename traits_t::value_type rhs) noexcept
2565 basic_string<char_t, traits_t> str(std::move(lhs));
2570 template<
class char_t,
class traits_t>
2571 basic_string<char_t, traits_t> operator+(
2572 typename traits_t::value_type lhs,
2573 const basic_string<char_t, traits_t>& rhs) noexcept
2575 basic_string<char_t, traits_t> str(&lhs, 1);
2580 template<
class char_t,
class traits_t, range_of_t_c<
char_t>
string_t>
2581 basic_string<char_t, traits_t> operator+(
const basic_string<char_t, traits_t>& lhs,
const string_t& rhs) noexcept
2583 basic_string<char_t, traits_t> str(lhs);
2588 template<
class char_t,
class traits_t, range_of_t_c<
char_t>
string_t>
2589 basic_string<char_t, traits_t> operator+(basic_string<char_t, traits_t>&& lhs,
const string_t& rhs) noexcept
2591 basic_string<char_t, traits_t> str(std::move(lhs));
2596 template<
class char_t,
class traits_t, range_of_t_c<
char_t>
string_t>
2597 basic_string<char_t, traits_t> operator+(
const string_t& lhs,
const basic_string<char_t, traits_t>& rhs) noexcept
2599 basic_string<char_t, traits_t> str(lhs);
2608 template<
class char_t,
class traits_t>
2609 inline typename basic_string<char_t, traits_t>::size_type basic_string<char_t, traits_t>::size() const noexcept
2611 const size_type nSize = m_Data.size() /
sizeof(value_type);
2612 return nSize == 0 ? 0 : nSize - 1;
2619 template<
class char_t,
class traits_t>
2620 inline typename basic_string<char_t, traits_t>::pointer basic_string<char_t, traits_t>::data() noexcept
2622 return reinterpret_cast<pointer
>(m_Data.data());
2630 template<
class char_t,
class traits_t>
2631 inline typename basic_string<char_t, traits_t>::reference basic_string<char_t, traits_t>::at(size_type nIndex)
2636 return data()[nIndex];
2642 template<
class char_t,
class traits_t>
2643 inline void basic_string<char_t, traits_t>::clear() noexcept
2657 template<
class char_t,
class traits_t>
2658 struct hash<qx::basic_string<char_t, traits_t>>
2662 return traits_t::hash_function(str.data(), traits_t::hash_seed(), str.size());
2668 template<
class char_t,
class traits_t>
2676 template<
class char_t,
class traits_t>
2679 template<
class format_context_type>
2691 template<
class char_t,
class traits_t>
2692 qx::details::ostream<char_t>& operator<<(
2693 qx::details::ostream<char_t>& os,
2700 template<
class char_t,
class traits_t>
2703 typename qx::details::istream<traits_t>::iostate ret_bit = qx::details::istream<traits_t>::goodbit;
2705 auto try_push_back = [&str, &is, &ret_bit](char_t ch)
2707 typename traits_t::size_type nCurrentSize = str.size();
2708 if (str._resize(nCurrentSize + 1))
2710 str[nCurrentSize] = ch;
2716 ret_bit |= qx::details::istream<traits_t>::failbit;
2727 if (!traits_t::is_space(ch))
2737 if (!traits_t::is_space(ch))
2739 if (!try_push_back(ch))
2749 is.setstate(ret_bit);
void push_back(value_type chSymbol) noexcept
Insert char in the end of the string.
void erase(iterator itFirst, iterator itLast) noexcept
Erase substring.
size_type find(value_type chSymbol, size_type nBegin=0, size_type nEnd=npos) const noexcept
Find substring.
bool remove_prefix(value_type chSymbol) noexcept
Remove string prefix if matches.
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.
std::optional< to_t > to(const_pointer pszFormat=nullptr) const noexcept
Convert string to specified type.
int compare(value_type chSymbol) const noexcept
Performs a binary comparison of the characters.
size_type find_last_of(value_type chSymbol, size_type nEnd=0) const noexcept
Find last position of character.
void push_front(value_type chSymbol) noexcept
Insert char in the beginning of the string.
size_type capacity() const noexcept
Get allocated memory size (including null terminator)
value_type pop_back() noexcept
Erase last char and return it.
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.
views split(const value_type chSeparator) const noexcept
Split string by separator.
size_type rfind(value_type chSymbol, size_type nBegin=npos, size_type nEnd=0) const noexcept
Find substring (reverse direction)
size_type length() const noexcept
Get string length.
void free() noexcept
Clear string and free allocated memory.
void from(const from_t &data)
Construct string from custom type.
size_type trim_right() noexcept
Trim the string to the right (whitespace characters)
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.
void assign(size_type nSymbols, value_type chSymbol) noexcept
Assign by filling.
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.
bool ends_with(value_type chSymbol) const noexcept
Check if current string ends with char.
void swap(basic_string &sOther) noexcept
Swap this str and other.
value_type pop_front() noexcept
Erase first char and return it.
void append(value_type chSymbol) noexcept
Append char.
bool contains(value_type chSymbol) const noexcept
Check if string contains char.
size_type trim() noexcept
Trim the string to the both sides (whitespace characters)
void to_upper() noexcept
Convert string to uppercase.
void shrink_to_fit() noexcept
Fit allocated size to string's actual size.
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.
size_type trim_left() noexcept
Trim the string to the left (whitespace characters)
size_type reserve(size_type nCapacity) noexcept
Reserve memory for the string.
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.
string_view substr(size_type nPos, size_type nSymbols=npos) const noexcept
Get substring.
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.
void to_lower() noexcept
Convert string to lowercase.
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.
size_type insert(size_type nPos, value_type chSymbol) noexcept
Insert substring.
bool remove_suffix(value_type chSymbol) noexcept
Remove string suffix if matches.
const_pointer c_str() const noexcept
Get pointer to string zero terminated.
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.
static constexpr size_type max_size() noexcept
Get the theoretical maximum of string size.
bool starts_with(value_type chSymbol) const noexcept
Check if current string starts with char.
value_type front() const noexcept
Get first char of the string.
value_type back() const noexcept
Get last char of the string.
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.
size_type find_first_of(value_type chSymbol, size_type nBegin=0) const noexcept
Find first position of character.
size_type insert(const_iterator itPos, const basic_string &sWhat) noexcept
Insert substring.
size_type find_first_not_of(value_type chSymbol, size_type nBegin=0) const noexcept
Finds the first character not equal to chSymbol.
Const random access iterator type.
Non-const random access iterator type.
requires(same_variadic_args_v< args_t... >) const expr auto coalesce(args_t &&... args)
Coalesce function, C# a ?? b analogue.
#define QX_STATIC_ASSERT_NO_INSTANTIATION(Message)
This static assert will fail if block it placed in must not be instantiated.
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.
#define QX_CHAR_PREFIX(value_t, ch)
Chose witch of prefixes add to char : L or none.
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.
#define QX_STR_PREFIX(value_t, str)
Chose witch of prefixes add to string : L or none.