285 _AssertRepValidType ();
287 template <IStdBasicStringCompatibleCharacter CHAR_T>
288 inline String::String (
const basic_string<CHAR_T>& s)
289 : inherited{mk_ (span<const CHAR_T>{
s.data (),
s.size ()})}
292 template <IStdBasicStringCompatibleCharacter CHAR_T>
294 : inherited{CTORFromBasicStringView_ (s)}
297 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
299 requires (not Memory::ISpan<CHAR_T>)
300 : inherited{mk_ (src)}
304 : String{span{&c, 1}}
307 template <IStdBasicStringCompatibleCharacter CHAR_T>
309 : inherited{mk_ (forward<basic_string<CHAR_T>> (s))}
312 template <IStdPathLike2UNICODEString PATHLIKE_TOSTRINGABLE>
315 : String{mkSTR_ (forward<PATHLIKE_TOSTRINGABLE> (s))}
318 template <IStdPathLike2UNICODEString PATHLIKE_TOSTRINGABLE>
319 String String::mkSTR_ (PATHLIKE_TOSTRINGABLE&& s)
321 if constexpr (
requires (PATHLIKE_TOSTRINGABLE t) {
322 { t.wstring () } -> same_as<wstring>;
324 return String{forward<PATHLIKE_TOSTRINGABLE> (s).wstring ()};
326 if constexpr (
requires (PATHLIKE_TOSTRINGABLE t) {
327 { t.u8string () } -> same_as<u8string>;
329 return String{forward<PATHLIKE_TOSTRINGABLE> (s).u8string ()};
331 if constexpr (
requires (PATHLIKE_TOSTRINGABLE t) {
332 { t.u16string () } -> same_as<u16string>;
334 return String{forward<PATHLIKE_TOSTRINGABLE> (s).u16string ()};
336 if constexpr (
requires (PATHLIKE_TOSTRINGABLE t) {
337 { t.u32string () } -> same_as<u32string>;
339 return String{forward<PATHLIKE_TOSTRINGABLE> (s).u32string ()};
345 return FromNarrowString (span{from, ::strlen (from)}, l);
349 return FromNarrowString (span{from.c_str (), from.length ()}, l);
351 template <IStdBasicStringCompatibleCharacter CHAR_T>
354 return FromLatin1 (span{s.data (), s.size ()});
356 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
360 return FromLatin1 (span{cString, Private_::StrLen_ (cString)});
362 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
369 if constexpr (
sizeof (CHAR_T) == 1) {
370 return mk_ (span<const Latin1>{
reinterpret_cast<const Latin1*
> (s.data ()), s.size ()});
373 const CHAR_T* b =
reinterpret_cast<const CHAR_T*
> (s.data ());
374 const CHAR_T* e = b + s.
size ();
376 Latin1* pOut = buf.begin ();
377 for (
const CHAR_T* i = b; i != e; ++i, ++pOut) {
379 static const auto kException_ = out_of_range{
"Error converting non-iso-latin-1 text to String"};
384 return mk_ (span<const Latin1>{buf.begin (), pOut});
387 template <
size_t SIZE, IUNICODECanUnambiguouslyConvertFrom CHAR_T>
390 return FromStringConstant (span<const CHAR_T>{cString, SIZE - 1});
392 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
395 return FromStringConstant (span<const CHAR_T>{str.data (), str.size ()});
397 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
403 if constexpr (same_as<CHAR_T, char8_t>) {
404 if (Character::IsASCII (str)) {
405 return FromStringConstant (Memory::SpanBytesCast<span<const ASCII>> (str));
413 if constexpr (
sizeof (wchar_t) == 2) {
414 return FromStringConstant (Memory::SpanBytesCast<span<const char16_t>> (s));
417 Assert (
sizeof (
wchar_t) == 4);
418 return FromStringConstant (Memory::SpanBytesCast<span<const char32_t>> (s));
421 template <
typename CHAR_T>
423 requires (same_as<remove_cv_t<CHAR_T>,
char8_t> or same_as<remove_cv_t<CHAR_T>,
char>)
425 if (Character::IsASCII (s)) [[likely]] {
426 return mk_ (span<const char>{
reinterpret_cast<const char*
> (s.data ()), s.size ()});
428 else if (UTFConvert::AllFitsInTwoByteEncoding (s)) [[likely]] {
430 return String{UTFConvert::kThe.ConvertSpan (s, span{buf})};
434 return String{UTFConvert::kThe.ConvertSpan (s, span{buf})};
437 template <
typename CHAR_T>
439 requires (same_as<remove_cv_t<CHAR_T>,
char8_t> or same_as<remove_cv_t<CHAR_T>,
char>)
441 return FromUTF8 (span{from.data (), from.length ()});
443 template <
typename CHAR_T>
445 requires (same_as<remove_cv_t<CHAR_T>,
char8_t> or same_as<remove_cv_t<CHAR_T>,
char>)
447 return FromUTF8 (span{from, ::strlen (
reinterpret_cast<const char*
> (from))});
452 return FromSDKString (span{from, CString::Length (from)});
456 if constexpr (same_as<SDKChar, wchar_t>) {
460 return String{SDK2Wide (s)};
465 if constexpr (same_as<SDKString, wstring>) {
469 return FromSDKString (span{from.c_str (), from.length ()});
475 return FromNarrowSDKString (span{from, ::strlen (from)});
483 return FromNarrowSDKString (span{from.c_str (), from.length ()});
485 template <
typename T>
487 requires (is_convertible_v<T, String>)
491 PeekSpanData lhsPSD = GetPeekSpanData<ASCII> ();
493 if (lhsPSD.fInCP == PeekSpanData::StorageCodePointType::eAscii) {
494 if constexpr (derived_from<remove_cvref_t<T>, String>) {
495 PeekSpanData rhsPSD = rhs.template GetPeekSpanData<ASCII> ();
496 if (rhsPSD.fInCP == PeekSpanData::StorageCodePointType::eAscii) {
497 Memory::StackBuffer<ASCII, 512> buf{Memory::eUninitialized, lhsPSD.fAscii.size () + rhsPSD.fAscii.size ()};
498 copy (lhsPSD.fAscii.begin (), lhsPSD.fAscii.end (), buf.data ());
499 copy (rhsPSD.fAscii.begin (), rhsPSD.fAscii.end (), buf.data () + lhsPSD.fAscii.size ());
500 return this->mk_nocheck_ (span<const ASCII>{buf});
506 return Concatenate_ (forward<T> (rhs));
508 inline void String::_AssertRepValidType ()
const
510 EnsureMember (&_SafeReadRepAccessor{
this}._ConstGetRep (), String::_IRep);
512 template <IUNICODECanAlwaysConvertTo CHAR_T>
514 requires (not is_const_v<CHAR_T>)
516 PeekSpanData psd = GetPeekSpanData<CHAR_T> ();
517 if (
auto p = PeekData<CHAR_T> (psd)) {
518 return Memory::CopySpanData (*p, s);
523 case PeekSpanData::StorageCodePointType::eAscii:
524 case PeekSpanData::StorageCodePointType::eSingleByteLatin1:
525 return UTFConvert::kThe.ConvertSpan (psd.fSingleByteLatin1, s);
526 case PeekSpanData::StorageCodePointType::eChar16:
527 return UTFConvert::kThe.ConvertSpan (psd.fChar16, s);
528 case PeekSpanData::StorageCodePointType::eChar32:
529 return UTFConvert::kThe.ConvertSpan (psd.fChar32, s);
532 return span<CHAR_T>{};
538 _SafeReadRepAccessor accessor{
this};
539 return accessor._ConstGetRep ().size ();
541 template <
unsigned_
integral T>
542 inline size_t String::SubString_adjust_ (T fromOrTo, [[maybe_unused]]
size_t myLength)
const
544 Require (fromOrTo <= numeric_limits<size_t>::max ());
545 return static_cast<size_t> (fromOrTo);
547 template <
signed_
integral T>
548 inline size_t String::SubString_adjust_ (T fromOrTo,
size_t myLength)
const
550 if (fromOrTo >= 0) [[likely]] {
551 Require (fromOrTo <= numeric_limits<ptrdiff_t>::max ());
552 return static_cast<size_t> (fromOrTo);
555 Require (fromOrTo >= numeric_limits<ptrdiff_t>::min ());
556 return static_cast<size_t> (myLength +
static_cast<ptrdiff_t
> (fromOrTo));
559 template <
typename SZ>
562 _SafeReadRepAccessor accessor{
this};
563 size_t myLength{accessor._ConstGetRep ().
size ()};
564 size_t f = SubString_adjust_ (from, myLength);
566 Require (f <= myLength);
567 return SubString_ (accessor, f, t);
569 template <
typename SZ1,
typename SZ2>
572 _SafeReadRepAccessor accessor{
this};
573 size_t myLength{accessor._ConstGetRep ().
size ()};
574 size_t f = SubString_adjust_ (from, myLength);
575 size_t t = SubString_adjust_ (to, myLength);
577 Require (t <= myLength);
578 return SubString_ (accessor, f, t);
580 template <
typename SZ>
583 _SafeReadRepAccessor accessor{
this};
584 size_t myLength{accessor._ConstGetRep ().
size ()};
585 size_t f = SubString_adjust_ (from, myLength);
586 f = min (f, myLength);
587 Assert (f <= myLength);
588 size_t useLength{myLength - f};
589 return SubString_ (accessor, f, f + useLength);
591 template <
typename SZ1,
typename SZ2>
594 _SafeReadRepAccessor accessor{
this};
595 size_t myLength{accessor._ConstGetRep ().
size ()};
596 size_t f = SubString_adjust_ (from, myLength);
597 size_t t = SubString_adjust_ (to, myLength);
598 f = min (f, myLength);
599 t = min (t, myLength);
602 Assert (t <= myLength);
603 size_t useLength = (t - f);
604 return SubString_ (accessor, f, f + useLength);
608 return SafeSubString (n);
612 return RemoveAt (charAt, charAt + 1);
616 return RemoveAt (fromTo.first, fromTo.second);
618 inline bool String::empty () const noexcept
620 _SafeReadRepAccessor accessor{
this};
621 return accessor._ConstGetRep ().size () == 0;
625 inline void ExtractMatches_ ([[maybe_unused]]
const wsmatch& base_match, [[maybe_unused]]
size_t currentUnpackIndex)
628 template <Common::IAnyOf<optional<String>*, String*,
nullptr_t> SUBMATCH,
typename... OPTIONAL_STRINGS>
629 void ExtractMatches_ (
const wsmatch& base_match,
size_t currentUnpackIndex, SUBMATCH subMatchI, OPTIONAL_STRINGS&&... remainingSubmatches)
631 if (currentUnpackIndex < base_match.size ()) [[likely]] {
632 if constexpr (not same_as<SUBMATCH, nullptr_t>) {
633 if (subMatchI !=
nullptr) {
634 *subMatchI = base_match[currentUnpackIndex].str ();
637 ExtractMatches_ (base_match, currentUnpackIndex + 1, forward<OPTIONAL_STRINGS> (remainingSubmatches)...);
640 const wregex& RegularExpression_GetCompiled (
const RegularExpression& regExp);
642 template <Common::IAnyOf<optional<String>*, String*,
nullptr_t>... OPTIONAL_STRINGS>
643 bool String::Matches (
const RegularExpression& regEx, OPTIONAL_STRINGS&&... subMatches)
const
645 wstring tmp{As<wstring> ()};
647 if (regex_match (tmp, baseMatch, Private_::RegularExpression_GetCompiled (regEx))) {
648 Private_::ExtractMatches_ (baseMatch, 1, forward<OPTIONAL_STRINGS> (subMatches)...);
654 optional<Common::RepeatedTuple_t<I, String>>
String::Matches (
const RegularExpression& regEx)
const
656 wstring tmp{As<wstring> ()};
658 if (regex_match (tmp, baseMatch, Private_::RegularExpression_GetCompiled (regEx))) {
660 if constexpr (I == 0) {
661 return make_tuple ();
663 else if constexpr (I == 1) {
664 return make_tuple (String{baseMatch[1].str ()});
666 else if constexpr (I == 2) {
667 return make_tuple (String{baseMatch[1].str ()}, String{baseMatch[2].str ()});
669 else if constexpr (I == 3) {
670 return make_tuple (String{baseMatch[1].str ()}, String{baseMatch[2].str ()}, String{baseMatch[3].str ()});
672 else if constexpr (I == 4) {
673 return make_tuple (String{baseMatch[1].str ()}, String{baseMatch[2].str ()}, String{baseMatch[3].str ()},
674 String{baseMatch[4].str ()});
676 else if constexpr (I == 5) {
677 return make_tuple (String{baseMatch[1].str ()}, String{baseMatch[2].str ()}, String{baseMatch[3].str ()},
678 String{baseMatch[4].str ()}, String{baseMatch[5].str ()});
689 return Find (c, 0, co);
691 inline optional<size_t>
String::Find (
const String& subString, CompareOptions co)
const
693 return Find (subString, 0, co);
697 return inherited::Find (that);
701 return static_cast<bool> (Find (c, co));
705 return static_cast<bool> (Find (subString, co));
707 inline bool String::ContainsAny (Iterable<Character> cs, CompareOptions co)
const
709 auto comparer = Character::EqualsComparer{co};
710 auto checkEachCharacter = [&] (Character c) ->
bool {
return cs.Any ([&] (
const Character c2) {
return comparer (c, c2); }); };
711 return Find (checkEachCharacter) !=
nullptr;
713 inline String
String::Replace (pair<size_t, size_t> fromTo,
const String& replacement)
const
715 return Replace (fromTo.first, fromTo.second, replacement);
719 return Col (i).value_or (valueIfMissing);
723 return InsertAt (span<const Character>{&c, 1}, at);
728 return InsertAt (s.
GetData (&ignored1), at);
732 return InsertAt (Memory::ConstSpan (s), at);
734 inline const Character String::GetCharAt (
size_t i)
const noexcept
736 _SafeReadRepAccessor accessor{
this};
738 Require (i < accessor._ConstGetRep ().size ());
739 return accessor._ConstGetRep ().GetAt (i);
744 Require (i < size ());
745 return GetCharAt (i);
749#if qCompiler_vswprintf_on_elispisStr_Buggy
750 static const String kELIPSIS_{
"..."_k};
752 static const String kELIPSIS_{u
"\u2026"sv};
754 return LimitLength (maxLen, keepPref, kELIPSIS_);
756 template <
typename T>
760 if constexpr (same_as<T, u8string>) {
763 else if constexpr (same_as<T, u16string>) {
764 return AsUTF16<T> ();
766 else if constexpr (same_as<T, u32string>) {
767 return AsUTF32<T> ();
769 else if constexpr (same_as<T, wstring>) {
770 if constexpr (
sizeof (wchar_t) == 2) {
771 return AsUTF16<T> ();
774 return AsUTF32<T> ();
777 else if constexpr (same_as<T, String>) {
780 else if constexpr (constructible_from<T, wstring>) {
781 return T{As<wstring> ()};
784 template <
typename T>
786 requires (same_as<T,
string> or same_as<T, u8string>)
788 Memory::StackBuffer<char8_t> maybeIgnoreBuf1;
789 span<const char8_t> thisData = GetData (&maybeIgnoreBuf1);
790 return T{
reinterpret_cast<const typename T::value_type*
> (thisData.data ()), thisData.size ()};
792 template <
typename T>
794 requires (same_as<T, u16string> or (sizeof (
wchar_t) == sizeof (
char16_t) and same_as<T, wstring>))
796 Memory::StackBuffer<char16_t> maybeIgnoreBuf1;
797 span<const char16_t> thisData = GetData (&maybeIgnoreBuf1);
798 return T{
reinterpret_cast<const typename T::value_type*
> (thisData.data ()), thisData.size ()};
800 template <
typename T>
802 requires (same_as<T, u32string> or (sizeof (
wchar_t) == sizeof (
char32_t) and same_as<T, wstring>))
804 Memory::StackBuffer<char32_t> maybeIgnoreBuf1;
805 span<const char32_t> thisData = GetData (&maybeIgnoreBuf1);
806 return T{
reinterpret_cast<const typename T::value_type*
> (thisData.data ()), thisData.size ()};
810#if qTargetPlatformSDKUseswchar_t
812 span<const wchar_t> thisData = GetData (&maybeIgnoreBuf1);
813 return SDKString{thisData.begin (), thisData.end ()};
814#elif qStroika_Foundation_Common_Platform_MacOS
816 span<const char8_t> thisData = GetData (&maybeIgnoreBuf1);
817 return SDKString{thisData.begin (), thisData.end ()};
819 return AsNarrowString (locale{});
824#if qTargetPlatformSDKUseswchar_t
826 span<const wchar_t> thisData = GetData (&maybeIgnoreBuf1);
827 return SDKString{thisData.begin (), thisData.end ()};
828#elif qStroika_Foundation_Common_Platform_MacOS
830 span<const char8_t> thisData = GetData (&maybeIgnoreBuf1);
831 return SDKString{thisData.begin (), thisData.end ()};
833 return AsNarrowString (locale{}, eIgnoreErrors);
842 return SDK2Narrow (AsSDKString (eIgnoreErrors), AllowMissingCharacterErrorsFlag::eIgnoreErrors);
844 template <
typename T>
846 requires requires (T* into) {
847 { into->empty () } -> same_as<bool>;
848 { into->push_back (ASCII{0}) };
852 if (
auto p = AsASCIIQuietly<T> ()) {
856 ThrowInvalidAsciiException_ ();
859 template <
typename T>
861 requires requires (T* into) {
862 { into->empty () } -> same_as<bool>;
863 { into->push_back (ASCII{0}) };
867 Memory::StackBuffer<wchar_t> ignored1;
868 auto thisSpan = GetData (&ignored1);
870 return Character::AsASCIIQuietly<T> (thisSpan, &s) ? s : optional<T>{};
872 template <IUNICODECanUnambiguouslyConvertFrom CHAR_TYPE>
875 using StorageCodePointType = PeekSpanData::StorageCodePointType;
876 StorageCodePointType preferredSCP{};
877 if constexpr (same_as<remove_cv_t<CHAR_TYPE>,
ASCII>) {
878 preferredSCP = StorageCodePointType::eAscii;
880 else if constexpr (same_as<remove_cv_t<CHAR_TYPE>, Latin1>) {
881 preferredSCP = StorageCodePointType::eSingleByteLatin1;
883 else if constexpr (same_as<remove_cv_t<CHAR_TYPE>,
char8_t>) {
884 preferredSCP = StorageCodePointType::eAscii;
886 else if constexpr (same_as<remove_cv_t<CHAR_TYPE>,
char16_t>) {
887 preferredSCP = StorageCodePointType::eChar16;
889 else if constexpr (same_as<remove_cv_t<CHAR_TYPE>,
char32_t> or same_as<remove_cv_t<CHAR_TYPE>, Character>) {
890 preferredSCP = StorageCodePointType::eChar32;
892 if constexpr (same_as<remove_cv_t<CHAR_TYPE>,
wchar_t>) {
893 if constexpr (
sizeof (wchar_t) == 2) {
894 preferredSCP = StorageCodePointType::eChar16;
896 else if constexpr (
sizeof (wchar_t) == 4) {
897 preferredSCP = StorageCodePointType::eChar32;
900 else if constexpr (same_as<remove_cv_t<CHAR_TYPE>, Character>) {
902 if constexpr (
sizeof (wchar_t) == 2) {
903 preferredSCP = StorageCodePointType::eChar16;
905 else if constexpr (
sizeof (wchar_t) == 4) {
906 preferredSCP = StorageCodePointType::eChar32;
909 return _SafeReadRepAccessor{
this}._ConstGetRep ().PeekData (preferredSCP);
911 template <IUNICODECanUnambiguouslyConvertFrom CHAR_TYPE>
912 inline optional<span<const CHAR_TYPE>> String::PeekData (
const PeekSpanData& pds)
915 if constexpr (same_as<CHAR_TYPE, ASCII>) {
916 if (pds.fInCP == StorageCodePointType::eAscii) {
920 else if constexpr (same_as<CHAR_TYPE, Latin1>) {
921 if (pds.fInCP == StorageCodePointType::eSingleByteLatin1) {
922 return pds.fSingleByteLatin1;
925 else if constexpr (same_as<CHAR_TYPE, char8_t>) {
926 if (pds.fInCP == StorageCodePointType::eAscii) {
930 else if constexpr (same_as<CHAR_TYPE, char16_t>) {
931 if (pds.fInCP == StorageCodePointType::eChar16) {
935 else if constexpr (same_as<CHAR_TYPE, char32_t>) {
936 if (pds.fInCP == StorageCodePointType::eChar32) {
940 else if constexpr (same_as<CHAR_TYPE, wchar_t>) {
941 if constexpr (
sizeof (wchar_t) == 2) {
942 if (pds.fInCP == StorageCodePointType::eChar16) {
943 return span<const wchar_t>{
reinterpret_cast<const wchar_t*
> (pds.fChar16.data ()), pds.fChar16.size ()};
946 else if constexpr (
sizeof (wchar_t) == 4) {
947 if (pds.fInCP == StorageCodePointType::eChar32) {
948 return span<const wchar_t>{
reinterpret_cast<const wchar_t*
> (pds.fChar32.data ()), pds.fChar32.size ()};
951 return span<const wchar_t>{};
953 else if constexpr (same_as<CHAR_TYPE, Character>) {
954 if (pds.fInCP == StorageCodePointType::eChar32) {
955 return span<const Character>{
reinterpret_cast<const Character*
> (pds.fChar32.data ()), pds.fChar32.size ()};
957 return span<const Character>{};
961 template <IUNICODECanUnambiguouslyConvertFrom CHAR_TYPE>
962 inline optional<span<const CHAR_TYPE>> String::PeekData ()
const
964 return PeekData<CHAR_TYPE> (GetPeekSpanData<CHAR_TYPE> ());
968 template <IUNICODECanAlwaysConvertTo CHAR_TYPE,
size_t STACK_BUFFER_SZ>
973 if constexpr (same_as<CHAR_TYPE, wchar_t>) {
974 if constexpr (
sizeof (CHAR_TYPE) == 2) {
976 return span<const CHAR_TYPE>{
reinterpret_cast<const CHAR_TYPE*
> (p.data ()), p.size ()};
978 else if constexpr (
sizeof (wchar_t) == 4) {
980 return span<const CHAR_TYPE>{
reinterpret_cast<const CHAR_TYPE*
> (p.data ()), p.size ()};
983 else if constexpr (same_as<CHAR_TYPE, Character>) {
985 return span<const CHAR_TYPE>{
reinterpret_cast<const CHAR_TYPE*
> (p.data ()), p.size ()};
987 if constexpr (same_as<CHAR_TYPE, char8_t>) {
989 case StorageCodePointType::eAscii:
991 return span{
reinterpret_cast<const char8_t*
> (pds.fAscii.data ()), pds.fAscii.size ()};
992 case StorageCodePointType::eSingleByteLatin1: {
994 possiblyUsedBuffer->
resize_uninitialized (UTFConvert::ComputeTargetBufferSize<CHAR_TYPE> (pds.fSingleByteLatin1));
995 return UTFConvert::kThe.ConvertSpan (pds.fSingleByteLatin1, span{*possiblyUsedBuffer});
997 case StorageCodePointType::eChar16: {
998 possiblyUsedBuffer->
resize_uninitialized (UTFConvert::ComputeTargetBufferSize<CHAR_TYPE> (pds.fChar16));
999 return UTFConvert::kThe.ConvertSpan (pds.fChar16, span{*possiblyUsedBuffer});
1001 case StorageCodePointType::eChar32: {
1002 possiblyUsedBuffer->
resize_uninitialized (UTFConvert::ComputeTargetBufferSize<CHAR_TYPE> (pds.fChar32));
1003 return UTFConvert::kThe.ConvertSpan (pds.fChar32, span{*possiblyUsedBuffer});
1007 return span<const CHAR_TYPE>{};
1010 else if constexpr (same_as<CHAR_TYPE, char16_t>) {
1011 switch (pds.fInCP) {
1012 case StorageCodePointType::eAscii:
1013 case StorageCodePointType::eSingleByteLatin1: {
1014 possiblyUsedBuffer->resize_uninitialized (UTFConvert::ComputeTargetBufferSize<CHAR_TYPE> (pds.fSingleByteLatin1));
1015 return UTFConvert::kThe.ConvertSpan (pds.fSingleByteLatin1, span{*possiblyUsedBuffer});
1017 case StorageCodePointType::eChar16:
1019 case StorageCodePointType::eChar32: {
1020 possiblyUsedBuffer->resize_uninitialized (UTFConvert::ComputeTargetBufferSize<CHAR_TYPE> (pds.fChar32));
1021 return UTFConvert::kThe.ConvertSpan (pds.fChar32, span{*possiblyUsedBuffer});
1025 return span<const CHAR_TYPE>{};
1028 else if constexpr (same_as<CHAR_TYPE, char32_t>) {
1029 switch (pds.fInCP) {
1030 case StorageCodePointType::eAscii:
1031 case StorageCodePointType::eSingleByteLatin1: {
1032 possiblyUsedBuffer->resize_uninitialized (UTFConvert::ComputeTargetBufferSize<CHAR_TYPE> (pds.fSingleByteLatin1));
1033 return UTFConvert::kThe.ConvertSpan (pds.fSingleByteLatin1, span{*possiblyUsedBuffer});
1035 case StorageCodePointType::eChar16: {
1036 possiblyUsedBuffer->resize_uninitialized (UTFConvert::ComputeTargetBufferSize<CHAR_TYPE> (pds.fChar16));
1037 return UTFConvert::kThe.ConvertSpan (pds.fChar16, span{*possiblyUsedBuffer});
1039 case StorageCodePointType::eChar32:
1043 return span<const CHAR_TYPE>{};
1047 template <IUNICODECanAlwaysConvertTo CHAR_TYPE,
size_t STACK_BUFFER_SZ>
1048 inline span<const CHAR_TYPE>
String::GetData (Memory::StackBuffer<CHAR_TYPE, STACK_BUFFER_SZ>* possiblyUsedBuffer)
const
1051 return GetData (GetPeekSpanData<CHAR_TYPE> (), possiblyUsedBuffer);
1063 wstring tmp{As<wstring> ()};
1065 copy (tmp.begin (), tmp.end (), possibleBackingStore->begin ());
1066 (*possibleBackingStore)[tmp.length ()] =
'\0';
1067 return make_tuple (possibleBackingStore->begin (), wstring_view{possibleBackingStore->begin (), tmp.length ()});
1071 return Find (c, startAt, eWithCase).value_or (npos);
1075 return Find (s, startAt, eWithCase).value_or (npos);
1079 return RFind (c).value_or (npos);
1083 Require (not empty ());
1084 _SafeReadRepAccessor accessor{
this};
1085 size_t thisLen = accessor._ConstGetRep ().size ();
1086 return accessor._ConstGetRep ().GetAt (thisLen - 1);
1090 Require (not empty ());
1091 _SafeReadRepAccessor accessor{
this};
1092 return accessor._ConstGetRep ().GetAt (0);
1096 _SafeReadRepAccessor accessor{
this};
1097 size_t thisLen = accessor._ConstGetRep ().
size ();
1098 if (from > thisLen) [[unlikely]] {
1099 static auto kException_ = out_of_range{
"string index out of range"};
1104 size_t to = (count == npos) ? thisLen : (from + min (thisLen, count));
1105 return SubString_ (accessor, from, to);
1109 return ThreeWayComparer{}(*
this, rhs);
1111 template <IConvertibleToString T>
1113 requires (not same_as<remove_cvref_t<T>,
String>)
1115 return ThreeWayComparer{}(*
this, forward<T> (rhs));
1121 template <IConvertibleToString T>
1123 requires (not same_as<remove_cvref_t<T>,
String>)
1125 return EqualsComparer{}(*
this, rhs);
1133 inline namespace Literals {
1134 inline String
operator""_k (
const ASCII* s,
size_t len)
1136 return String::FromStringConstant (span<const char>{s, len});
1138 inline String
operator""_k (
const char8_t* s,
size_t len)
1140 return String::FromStringConstant (span<const char8_t>{s, len});
1142 inline String
operator""_k (
const wchar_t* s,
size_t len)
1144 return String::FromStringConstant (span<const wchar_t>{s, len});
1146 inline String
operator""_k (
const char16_t* s,
size_t len)
1148 return String::FromStringConstant (span<const char16_t>{s, len});
1150 inline String
operator""_k (
const char32_t* s,
size_t len)
1152 return String::FromStringConstant (span<const char32_t>{s, len});
1162 : fCompareOptions{co}
1165 template <Private_::ICanBeTreatedAsSpanOfCharacter_ LT, Private_::ICanBeTreatedAsSpanOfCharacter_ RT>
1166 inline bool String::EqualsComparer::Cmp_ (
LT&&
lhs,
RT&&
rhs)
const
1172 if (fCompareOptions == eWithCase) {
1189 if (fCompareOptions == eWithCase) {
1202 template <Private_::ICanBeTreatedAsSpanOfCharacter_ LT, Private_::ICanBeTreatedAsSpanOfCharacter_ RT>
1203 bool String::EqualsComparer::Cmp_Generic_ (
LT&&
lhs,
RT&&
rhs)
const
1208 Memory::StackBuffer<Character, 256>
ignore1;
1209 Memory::StackBuffer<Character, 256>
ignore2;
1213 template <IConvertibleToString LT, IConvertibleToString RT>
1216 if constexpr (
requires {
lhs.size (); }
and requires {
rhs.size (); }) {
1217 if (
lhs.size () !=
rhs.size ()) {
1221 if constexpr (Private_::ICanBeTreatedAsSpanOfCharacter_<LT>
and Private_::ICanBeTreatedAsSpanOfCharacter_<RT>) {
1235 constexpr String::ThreeWayComparer::ThreeWayComparer (CompareOptions
co)
1236 : fCompareOptions{
co}
1239 template <Private_::ICanBeTreatedAsSpanOfCharacter_ LT, Private_::ICanBeTreatedAsSpanOfCharacter_ RT>
1252 template <Private_::ICanBeTreatedAsSpanOfCharacter_ LT, Private_::ICanBeTreatedAsSpanOfCharacter_ RT>
1258 Memory::StackBuffer<Character, 256>
ignore1;
1259 Memory::StackBuffer<Character, 256>
ignore2;
1263 template <IConvertibleToString LT, IConvertibleToString RT>
1266 if constexpr (Private_::ICanBeTreatedAsSpanOfCharacter_<LT>
and Private_::ICanBeTreatedAsSpanOfCharacter_<RT>) {
1280 constexpr String::LessComparer::LessComparer (CompareOptions
co)
1284 template <
typename T1,
typename T2>
1285 inline bool String::LessComparer::operator() (
T1 lhs,
T2 rhs)
const
1287 return fComparer_ (
lhs,
rhs) < 0;
1295 template <IConvertibleToString LHS_T, IConvertibleToString RHS_T>
1303 else if constexpr (Private_::ICanBeTreatedAsSpanOfCharacter_<LHS_T>
and Private_::ICanBeTreatedAsSpanOfCharacter_<RHS_T>) {
1323#if qStroika_HasComponent_googletest
1335 DISABLE_COMPILER_GCC_WARNING_START (
"GCC diagnostic ignored \"-Wdeprecated-declarations\"");
1336 DISABLE_COMPILER_CLANG_WARNING_START (
"clang diagnostic ignored \"-Wdeprecated-declarations\"");
1337 DISABLE_COMPILER_MSC_WARNING_START (4996)
1338 template <typename CHAR_T>
1339 inline
void String::Append (span<const CHAR_T> s)
1340 requires (same_as<CHAR_T, Character> or same_as<CHAR_T,
char32_t>)
1342 if (not s.empty ()) {
1343 Memory::StackBuffer<char32_t> ignored1;
1344 span<const char32_t> thisSpan = this->GetData (&ignored1);
1345 Memory::StackBuffer<char32_t> combinedBuf{Memory::eUninitialized, thisSpan.size () + s.size ()};
1346 Memory::CopySpanData (thisSpan, span{combinedBuf});
1347 char32_t* write2Buf = combinedBuf.data () + thisSpan.size ();
1349 if constexpr (same_as<CHAR_T, Character>) {
1350 *write2Buf = i.template As<char32_t> ();
1357 *
this = mk_ (span{combinedBuf});
1360 inline void String::Append (
const wchar_t* from,
const wchar_t* to)
1362 Require (from <= to);
1364 Memory::StackBuffer<wchar_t> ignored1;
1365 span<const wchar_t> thisSpan = this->GetData (&ignored1);
1366 Memory::StackBuffer<wchar_t> buf{Memory::eUninitialized, thisSpan.size () + (to - from)};
1367 span<wchar_t> bufSpan{buf};
1368 Memory::CopySpanData (thisSpan, bufSpan);
1369 Memory::CopySpanData (span{from, to}, bufSpan.subspan (thisSpan.size ()));
1370 *
this = mk_ (bufSpan);
1373 inline void String::Append (Character c)
1377 inline void String::Append (
const String& s)
1379 Memory::StackBuffer<char32_t> ignored1;
1380 auto rhsSpan = s.GetData (&ignored1);
1383 inline void String::Append (
const wchar_t* s)
1385 Append (s, s + ::wcslen (s));
1387 inline void String::Append (
const Character* from,
const Character* to)
1391 inline String& String::operator+= (Character appendage)
1396 inline String& String::operator+= (
const String& appendage)
1401 inline String& String::operator+= (
const wchar_t* appendageCStr)
1407 inline void String::push_back (
wchar_t c)
1411 inline void String::push_back (Character c)
1416 DISABLE_COMPILER_MSC_WARNING_END (4996)
1417 DISABLE_COMPILER_GCC_WARNING_END ("GCC diagnostic ignored \"-Wdeprecated-declarations\"");
1418 DISABLE_COMPILER_CLANG_WARNING_END ("clang diagnostic ignored \"-Wdeprecated-declarations\"");
1420 [[deprecated ("Since Stroika v3.0d1 - just use _k, sv, or nothing")]] inline String operator""_ASCII (const
char* str,
size_t len)
1422 return String{span{str, len}};
1424 class [[deprecated (
"Since Stroika v3.0 - just use String::FromStringConstant")]] String_Constant :
public String {
1426 template <
size_t SIZE>
1427 explicit String_Constant (
const wchar_t (&cString)[SIZE])
1428 : String{String::FromStringConstant (
std::basic_string_view<wchar_t>{cString, SIZE - 1})}
1432 String_Constant (
const wchar_t* start,
const wchar_t* end)
1433 : String{String::FromStringConstant (
std::basic_string_view<wchar_t>{start,
static_cast<size_t> (end - start)})}
1437 String_Constant (
const std::basic_string_view<wchar_t>& str)
1443namespace Stroika::Foundation::Characters::Concrete {
1444 class [[deprecated (
"Since Stroika v3.0 - just use String::FromStringConstant")]] String_ExternalMemoryOwnership_ApplicationLifetime :
public String {
1446 template <
size_t SIZE>
1447 explicit String_ExternalMemoryOwnership_ApplicationLifetime (
const wchar_t (&cString)[SIZE - 1])
1448 : String{String::FromStringConstant (basic_string_view<wchar_t>{cString, SIZE})}
1452 String_ExternalMemoryOwnership_ApplicationLifetime (
const wchar_t* start,
const wchar_t* end)
1453 : String{String::FromStringConstant (basic_string_view<wchar_t>{start,
static_cast<size_t> (end - start)})}
1457 String_ExternalMemoryOwnership_ApplicationLifetime (
const basic_string_view<wchar_t>& str)
1467 String StringCombiner<String>::operator() (
const String& lhs,
const String& rhs,
bool isLast)
const;
1469 template <
typename STRING>
1470 STRING StringCombiner<STRING>::operator() (
const STRING& lhs,
const STRING& rhs,
bool isLast)
const
1473 if (isLast and fSpecialSeparatorForLastPair) [[unlikely]] {
1474 sb = sb + *fSpecialSeparatorForLastPair;
1477 sb = sb + fSeparator;