4#include "Stroika/Foundation/StroikaPreComp.h"
15#include "Stroika/Foundation/Characters/SDKString.h"
19#include "Stroika/Foundation/Containers/Set.h"
20#include "Stroika/Foundation/Containers/Support/ReserveTweaks.h"
23#include "Stroika/Foundation/Execution/Exceptions.h"
24#include "Stroika/Foundation/Execution/Throw.h"
25#include "Stroika/Foundation/Math/Common.h"
27#include "Stroika/Foundation/Memory/Common.h"
37using Memory::MakeSharedPtr;
42static_assert (regular<String>);
44#if qStroika_Foundation_Characters_AsPathAutoMapMSYSAndCygwin
65 struct StringRepHelperAllFitInSize_ :
String {
66 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
67 struct Rep :
public _IRep {
69 using inherited = _IRep;
72 span<const CHAR_T> _fData;
74#if qStroika_Foundation_Debug_AssertionsChecked
76 mutable unsigned int fOutstandingIterators_{};
81 Rep (span<const CHAR_T> s)
82 requires (not same_as<CHAR_T, char8_t>)
85 if constexpr (same_as<CHAR_T, char> or same_as<CHAR_T, char8_t>) {
86 Require (Character::IsASCII (s));
89 if constexpr (same_as<CHAR_T, char16_t>) {
93 Rep& operator= (span<const CHAR_T> s)
95#if qStroika_Foundation_Debug_AssertionsChecked
96 Require (fOutstandingIterators_ == 0);
98 if constexpr (same_as<CHAR_T, char> or same_as<CHAR_T, char8_t>) {
99 Require (Character::IsASCII (s));
101 if constexpr (same_as<CHAR_T, char16_t>) {
110 virtual Character GetAt (
size_t index)
const noexcept override
112 Require (index < _fData.size ());
114 return Character{
static_cast<char32_t> (_fData[index])};
116 virtual PeekSpanData PeekData (optional<PeekSpanData::StorageCodePointType> )
const noexcept override
119 if constexpr (same_as<CHAR_T, ASCII>) {
120 return PeekSpanData{PeekSpanData::StorageCodePointType::eAscii, {.fAscii = _fData}};
122 if constexpr (same_as<CHAR_T, Latin1>) {
123 return PeekSpanData{PeekSpanData::StorageCodePointType::eSingleByteLatin1, {.fSingleByteLatin1 = _fData}};
125 else if constexpr (
sizeof (CHAR_T) == 2) {
127 return PeekSpanData{PeekSpanData::StorageCodePointType::eChar16,
128 {.fChar16 = span<const char16_t>{
reinterpret_cast<const char16_t*
> (_fData.data ()), _fData.size ()}}};
130 else if constexpr (
sizeof (CHAR_T) == 4) {
132 return PeekSpanData{PeekSpanData::StorageCodePointType::eChar32,
133 {.fChar32 = span<const char32_t>{
reinterpret_cast<const char32_t*
> (_fData.data ()), _fData.size ()}}};
140 virtual shared_ptr<Iterable<Character>::_IRep> Clone ()
const override
149 span<const CHAR_T> fData_;
151#if qStroika_Foundation_Debug_AssertionsChecked
152 const Rep* fOwningRep_;
154 MyIterRep_ (span<const CHAR_T> data
162 , fOwningRep_{dbgRep}
165#if qStroika_Foundation_Debug_AssertionsChecked
166 ++fOwningRep_->fOutstandingIterators_;
169#if qStroika_Foundation_Debug_AssertionsChecked
170 virtual ~MyIterRep_ ()
override
172 Require (fOwningRep_->fOutstandingIterators_ > 0);
173 --fOwningRep_->fOutstandingIterators_;
177 virtual unique_ptr<Iterator<Character>::IRep> Clone ()
const override
179 return make_unique<MyIterRep_> (fData_.subspan (fIdx_)
186 virtual bool AtEnd ()
const override
188 Assert (fIdx_ <= fData_.size ());
189 return fIdx_ == fData_.size ();
191 virtual optional<Character> Current ()
const override
193 if (fIdx_ < fData_.size ()) {
194 return Character{
static_cast<char32_t> (fData_[fIdx_])};
200 virtual optional<Character> More ()
override
202 Require (fIdx_ < fData_.size ());
204 if (fIdx_ < fData_.size ()) [[likely]] {
206 return Character{
static_cast<char32_t> (fData_[fIdx_])};
212 virtual bool Equals (
const IRep* rhs)
const override
216 const MyIterRep_* rrhs = Debug::UncheckedDynamicCast<const MyIterRep_*> (rhs);
217 return fData_.data () == rrhs->fData_.data () and fIdx_ == rrhs->fIdx_;
229 virtual size_t size ()
const override
231 return _fData.size ();
233 virtual bool empty ()
const override
235 return _fData.empty ();
240 return inherited::Find (findFirst, that, seq);
249 struct DynamicallyAllocatedString : StringRepHelperAllFitInSize_ {
250 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
253 using inherited = StringRepHelperAllFitInSize_::Rep<CHAR_T>;
256 Rep (span<const CHAR_T> t1)
257 : inherited{mkBuf_ (t1)}
261 Rep (
const Rep&) =
delete;
264 nonvirtual Rep& operator= (
const Rep&) =
delete;
267 virtual ~Rep ()
override
269 delete[] this->_fData.data ();
273 static span<CHAR_T> mkBuf_ (
size_t length)
275 size_t capacity = AdjustCapacity_ (length);
276 Assert (length <= capacity);
277 if constexpr (kAddNullTerminator_) {
278 Assert (length + 1 <= capacity);
280 CHAR_T* newBuf =
new CHAR_T[capacity];
281 return span{newBuf, capacity};
283 static span<CHAR_T> mkBuf_ (span<const CHAR_T> t1)
285 size_t len = t1.size ();
286 span<CHAR_T> buf = mkBuf_ (len);
287 Assert (buf.size () >= len);
288 auto result = Memory::CopyBytes (t1, buf);
289 if constexpr (kAddNullTerminator_) {
290 Assert (len + 1 <= buf.size ());
291 *(buf.data () + len) =
'\0';
298 virtual const wchar_t* c_str_peek () const noexcept
override
301 if constexpr (kAddNullTerminator_) {
302 Assert (*(this->_fData.data () + this->_fData.size ()) ==
'\0');
303 return reinterpret_cast<const wchar_t*
> (this->_fData.data ());
312 static constexpr bool kAddNullTerminator_ =
sizeof (CHAR_T) ==
sizeof (
wchar_t);
315 static size_t AdjustCapacity_ (
size_t initialCapacity)
317 size_t result = initialCapacity;
318 if constexpr (kAddNullTerminator_) {
332 struct FixedCapacityInlineStorageString_ : StringRepHelperAllFitInSize_ {
333 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T,
size_t CAPACITY>
334 struct Rep final :
public StringRepHelperAllFitInSize_::Rep<CHAR_T>,
337 using inherited = StringRepHelperAllFitInSize_::Rep<CHAR_T>;
340 bool IncludesNullTerminator_ ()
const
342 if constexpr (
sizeof (CHAR_T) ==
sizeof (
wchar_t)) {
343 return this->_fData.size () < CAPACITY;
351 CHAR_T fBuf_[CAPACITY];
354 Rep (span<const CHAR_T> t1)
360 Require (t1.size () <= CAPACITY);
361 inherited::operator= (Memory::CopyBytes (t1, span<CHAR_T>{fBuf_}));
362 if (IncludesNullTerminator_ ()) {
363 Assert (t1.size () + 1 <= CAPACITY);
364 fBuf_[t1.size ()] = CHAR_T{
'\0'};
368 Rep (
const Rep&) =
delete;
371 nonvirtual Rep& operator= (
const Rep&) =
delete;
375 virtual const wchar_t* c_str_peek () const noexcept
override
377 if (IncludesNullTerminator_ ()) {
378 Assert (*(this->_fData.data () + this->_fData.size ()) ==
'\0');
379 return reinterpret_cast<const wchar_t*
> (this->_fData.data ());
391 struct StringConstant_ :
public StringRepHelperAllFitInSize_ {
394 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
395 class DirectIndexRep final :
public StringRepHelperAllFitInSize_::Rep<CHAR_T>,
398 using inherited = StringRepHelperAllFitInSize_::Rep<CHAR_T>;
401 DirectIndexRep (span<const CHAR_T> s)
408 virtual const wchar_t* c_str_peek () const noexcept
override
418 struct StdStringDelegator_ :
public StringRepHelperAllFitInSize_ {
421 template <IStdBasicStringCompatibleCharacter CHAR_T>
424 using inherited = StringRepHelperAllFitInSize_::Rep<CHAR_T>;
427 Rep (basic_string<CHAR_T>&& s)
428 : inherited{span<const CHAR_T>{}}
429 , fMovedData_{move (s)}
431 inherited::operator= (span{fMovedData_.data (), fMovedData_.size ()});
436 virtual const wchar_t* c_str_peek () const noexcept
override
438 if constexpr (same_as<CHAR_T, wchar_t>) {
439 return fMovedData_.c_str ();
447 basic_string<CHAR_T> fMovedData_;
454 struct StringWithCStr_ :
public String {
458 shared_ptr<_IRep> fUnderlyingRep_;
463 Rep (
const shared_ptr<_IRep>& underlyingRep)
464 : fUnderlyingRep_{underlyingRep}
468 auto wideSpan = String::GetData<wchar_t> (underlyingRep->PeekData (nullopt), &possibleUsedBuf);
469 fCString_.assign (wideSpan.begin (), wideSpan.end ());
474 virtual shared_ptr<Iterable<Character>::_IRep> Clone ()
const override
476 return fUnderlyingRep_->Clone ();
480 return fUnderlyingRep_->MakeIterator ();
482 virtual size_t size ()
const override
484 return fUnderlyingRep_->size ();
486 virtual bool empty ()
const override
488 return fUnderlyingRep_->empty ();
493 return fUnderlyingRep_->Find (findFirst, that, seq);
498 virtual Character GetAt (
size_t index)
const noexcept override
500 return fUnderlyingRep_->GetAt (index);
502 virtual PeekSpanData PeekData ([[maybe_unused]] optional<PeekSpanData::StorageCodePointType> preferred)
const noexcept override
504 return fUnderlyingRep_->PeekData (preferred);
506 virtual const wchar_t* c_str_peek () const noexcept
override
508 return fCString_.c_str ();
515 template <
typename FACET>
516 struct deletable_facet_ final : FACET {
517 template <
typename... Args>
518 deletable_facet_ (Args&&... args)
519 : FACET{forward<Args> (args)...}
522 ~deletable_facet_ () =
default;
531const wregex& Characters::Private_::RegularExpression_GetCompiled (
const RegularExpression& regExp)
533 return regExp.GetCompiled ();
541shared_ptr<String::_IRep> String::CTORFromBasicStringView_ (
const basic_string_view<ASCII>& str)
547shared_ptr<String::_IRep> String::CTORFromBasicStringView_ (
const basic_string_view<char8_t>& str)
557shared_ptr<String::_IRep> String::CTORFromBasicStringView_ (
const basic_string_view<char16_t>& str)
563 return mk_ (span<const char16_t>{str.data (), str.size ()});
567shared_ptr<String::_IRep> String::CTORFromBasicStringView_ (
const basic_string_view<char32_t>& str)
572shared_ptr<String::_IRep> String::CTORFromBasicStringView_ (
const basic_string_view<wchar_t>& str)
612 codecvt_base::result result =
614 if (result != codecvt_base::ok) [[
unlikely]] {
621shared_ptr<String::_IRep> String::mkEmpty_ ()
628template <
typename CHAR_T>
629inline auto String::mk_nocheck_ (span<const CHAR_T> s) -> shared_ptr<_IRep>
630 requires (same_as<CHAR_T, ASCII> or same_as<CHAR_T, Latin1> or same_as<CHAR_T, char16_t> or same_as<CHAR_T, char32_t>)
633 if constexpr (same_as<CHAR_T, ASCII>) {
636 else if constexpr (same_as<CHAR_T, Latin1>) {
639 else if constexpr (
sizeof (CHAR_T) == 2) {
654 constexpr size_t kBaseOfFixedBufSize_ =
sizeof (StringRepHelperAllFitInSize_::Rep<CHAR_T>);
655 static_assert (kBaseOfFixedBufSize_ < 64);
657 static_assert (kBaseOfFixedBufSize_ == 3 *
sizeof (
void*));
658 if constexpr (
sizeof (
void*) == 4) {
659 static_assert (kBaseOfFixedBufSize_ == 12);
661 else if constexpr (
sizeof (
void*) == 8) {
662 static_assert (kBaseOfFixedBufSize_ == 24);
665 constexpr size_t kOverheadSizeForMakeShared_ =
666 qStroika_Foundation_Common_Platform_Windows ? (
sizeof (
void*) == 4 ? 12 : 16) :
sizeof (
unsigned long) * 2;
667#if qStroika_Foundation_Common_Platform_Windows
668 static_assert (kOverheadSizeForMakeShared_ ==
sizeof (_Ref_count_base));
670 static constexpr size_t kNElts1_ = (64 - kBaseOfFixedBufSize_ - kOverheadSizeForMakeShared_) /
sizeof (CHAR_T);
671 static constexpr size_t kNElts2_ = (96 - kBaseOfFixedBufSize_ - kOverheadSizeForMakeShared_) /
sizeof (CHAR_T);
672 static constexpr size_t kNElts3_ = (128 - kBaseOfFixedBufSize_ - kOverheadSizeForMakeShared_) /
sizeof (CHAR_T);
676 if constexpr (
sizeof (
void*) == 4) {
677 static_assert (kNElts1_ == 40);
678 static_assert (kNElts2_ == 72);
679 static_assert (kNElts3_ == 104);
681 if constexpr (
sizeof (
void*) == 8) {
682 static_assert (kNElts1_ == 24);
683 static_assert (kNElts2_ == 56);
684 static_assert (kNElts3_ == 88);
689 static_assert (kNElts2_ > kNElts1_);
690 static_assert (kNElts3_ > kNElts2_);
692 static_assert (
sizeof (FixedCapacityInlineStorageString_::Rep<CHAR_T, kNElts1_>) == 64 - kOverheadSizeForMakeShared_);
693 static_assert (
sizeof (FixedCapacityInlineStorageString_::Rep<CHAR_T, kNElts2_>) == 96 - kOverheadSizeForMakeShared_);
694 static_assert (
sizeof (FixedCapacityInlineStorageString_::Rep<CHAR_T, kNElts3_>) == 128 - kOverheadSizeForMakeShared_);
696 size_t sz = s.size ();
697 if (sz <= kNElts1_) {
698 return MakeSharedPtr<FixedCapacityInlineStorageString_::Rep<CHAR_T, kNElts1_>> (s);
700 else if (sz <= kNElts2_) {
701 return MakeSharedPtr<FixedCapacityInlineStorageString_::Rep<CHAR_T, kNElts2_>> (s);
703 else if (sz <= kNElts3_) {
704 return MakeSharedPtr<FixedCapacityInlineStorageString_::Rep<CHAR_T, kNElts3_>> (s);
706 return MakeSharedPtr<DynamicallyAllocatedString::Rep<CHAR_T>> (s);
710auto String::mk_ (basic_string<char>&& s) -> shared_ptr<_IRep>
713 return MakeSharedPtr<StdStringDelegator_::Rep<ASCII>> (move (s));
717auto String::mk_ (basic_string<char16_t>&& s) -> shared_ptr<_IRep>
720 return MakeSharedPtr<StdStringDelegator_::Rep<char16_t>> (move (s));
723 Memory::StackBuffer<char32_t> wideUnicodeBuf{Memory::eUninitialized, UTFConvert::ComputeTargetBufferSize<char32_t> (span{s.data (), s.size ()})};
724 return mk_nocheck_ (Memory::ConstSpan (
UTFConvert::kThe.ConvertSpan (span{s.data (), s.size ()}, span{wideUnicodeBuf})));
728auto String::mk_ (basic_string<char32_t>&& s) -> shared_ptr<_IRep>
730 return MakeSharedPtr<StdStringDelegator_::Rep<char32_t>> (move (s));
734auto String::mk_ (basic_string<wchar_t>&& s) -> shared_ptr<_IRep>
736 if constexpr (
sizeof (wchar_t) == 2) {
738 return MakeSharedPtr<StdStringDelegator_::Rep<wchar_t>> (move (s));
742 UTFConvert::ComputeTargetBufferSize<char32_t> (span{s.data (), s.size ()})};
743 return mk_nocheck_ (Memory::ConstSpan (
UTFConvert::kThe.ConvertSpan (span{s.data (), s.size ()}, span{wideUnicodeBuf})));
746 return MakeSharedPtr<StdStringDelegator_::Rep<wchar_t>> (move (s));
760 return mk_ (span{buf});
763void String::SetCharAt (
Character c,
size_t i)
768 Require (i <
size ());
771 Require (i <
size ());
779 Require (at <=
size ());
801 _SafeReadRepAccessor
accessor{
this};
811 span
s1 = d.subspan (0,
from);
812 span
s2 = d.subspan (
to);
814 Memory::CopyBytes (
s2,
bufSpan.subspan (
s1.size ()));
822 if (
auto o =
tmp.Find (c, eWithCase)) {
829 if (
auto o = this->
Find (subString, eWithCase)) {
840 while (
auto o =
tmp.Find (c, eWithCase)) {
863 if (
co == eWithCase) {
894 case eCaseInsensitive: {
897 if (i->ToLowerCase () ==
lcc) {
911optional<size_t>
String::Find (
const String& subString,
size_t startAt, CompareOptions co)
const
914 _SafeReadRepAccessor
accessor{
this};
927 case eCaseInsensitive: {
930 if (
accessor._ConstGetRep ().GetAt (i +
j).ToLowerCase () !=
subString[
j].ToLowerCase ()) {
961 if (
res.size () >= 1) {
970 vector<size_t> result;
1002 Assert (
match.size () != 0);
1003 size_t n =
match.size ();
1005 for (
size_t j = 1;
j <
n; ++
j) {
1026 _SafeReadRepAccessor accessor{
this};
1027 const _IRep& useRep = accessor._ConstGetRep ();
1028 size_t length = useRep.size ();
1029 for (
size_t i = length; i > 0; --i) {
1030 if (useRep.
GetAt (i - 1) == c) {
1049 for (
size_t i =
limit; i > 0; --i) {
1073 _SafeReadRepAccessor
accessor{
this};
1074 if (
accessor._ConstGetRep ().size () == 0) {
1086#if qStroika_Foundation_Debug_AssertionsChecked
1094#if qStroika_Foundation_Debug_AssertionsChecked
1102 _SafeReadRepAccessor
accessor{
this};
1115 _SafeReadRepAccessor
accessor{
this};
1121#if qStroika_Foundation_Debug_AssertionsChecked
1129#if qStroika_Foundation_Debug_AssertionsChecked
1159 for (
size_t i = 1; i <
base_match.size (); ++i) {
1256 for (
size_t i = 0; i !=
len; ++i) {
1288 Assert (
ofi->first <=
ofi->second);
1385String String::SubString_ (
const _SafeReadRepAccessor& thisAccessor,
size_t from,
size_t to)
const
1397 switch (
psd.fInCP) {
1412 return mk_ (
psd.fSingleByteLatin1.subspan (
from,
to -
from));
1414 case PeekSpanData::eChar16: {
1422 case PeekSpanData::eChar32: {
1444 return *
this + *
this;
1447 for (
unsigned int i = 0; i < count; ++i) {
1459 _SafeReadRepAccessor
accessor{
this};
1461 for (
size_t i = 0; i <
length; ++i) {
1475 for (
size_t i = 0; i <
length; ++i) {
1489#if qStroika_Foundation_Debug_AssertionsChecked
1495#if qStroika_Foundation_Debug_AssertionsChecked
1504 _SafeReadRepAccessor
accessor{
this};
1506 switch (
psd.fInCP) {
1513 case PeekSpanData::eChar32: {
1524 _SafeReadRepAccessor
accessor{
this};
1569#if qStroika_Foundation_Debug_AssertionsChecked
1575#if qStroika_Foundation_Debug_AssertionsChecked
1581#if qStroika_Foundation_Debug_AssertionsChecked
1588 _SafeReadRepAccessor
accessor{
this};
1590 switch (
psd.fInCP) {
1597 case PeekSpanData::eChar32: {
1642#if qStroika_Foundation_Debug_AssertionsChecked
1648#if qStroika_Foundation_Debug_AssertionsChecked
1654#if qStroika_Foundation_Debug_AssertionsChecked
1660 _SafeReadRepAccessor
accessor{
this};
1662 switch (
psd.fInCP) {
1669 case PeekSpanData::eChar32: {
1684 size_t n = result.
size ();
1685 for (
size_t i = 0; i <
n; ++i) {
1692 for (; i <
n; ++i) {
1707 for (
const String& i : list) {
1710 if (result.
empty ()) {
1711 return result.
str ();
1722 _SafeReadRepAccessor
accessor{
this};
1726 for (
auto c :
psd.fAscii) {
1732 result.push_back (c);
1744 result.push_back (c);
1749 return result.
str ();
1760 _SafeReadRepAccessor
accessor{
this};
1764 for (
auto c :
psd.fAscii) {
1770 result.push_back (c);
1782 result.push_back (c);
1787 return result.
str ();
1809 case StringShorteningPreference::ePreferKeepLeft:
1811 case StringShorteningPreference::ePreferKeepRight:
1813 case StringShorteningPreference::ePreferKeepMid:
1826 if (
keepPref == StringShorteningPreference::ePreferKeepMid) {
1838 case StringShorteningPreference::ePreferKeepLeft:
1840 case StringShorteningPreference::ePreferKeepRight:
1842 case StringShorteningPreference::ePreferKeepMid:
1866 codecvt_base::result result =
1868 if (result != codecvt_base::ok) [[
unlikely]] {
1895 if (result != codecvt_base::ok) [[
unlikely]] {
1906void String::erase (
size_t from)
1911void String::erase (
size_t from,
size_t count)
1922const wchar_t* String::c_str () const noexcept
1926 DISABLE_COMPILER_GCC_WARNING_START (
"GCC diagnostic ignored \"-Wdeprecated-declarations\"");
1927 DISABLE_COMPILER_CLANG_WARNING_START (
"clang diagnostic ignored \"-Wdeprecated-declarations\"");
1928 return const_cast<String*
> (
this)->c_str ();
1929 DISABLE_COMPILER_MSC_WARNING_END (4996);
1930 DISABLE_COMPILER_GCC_WARNING_END (
"GCC diagnostic ignored \"-Wdeprecated-declarations\"");
1931 DISABLE_COMPILER_CLANG_WARNING_END (
"clang diagnostic ignored \"-Wdeprecated-declarations\"");
1933const wchar_t* String::c_str ()
1937 _SafeReadRepAccessor
accessor{
this};
1938 const wchar_t* result =
accessor._ConstGetRep ().c_str_peek ();
1939 if (result ==
nullptr) {
1941 result = _SafeReadRepAccessor{
this}._ConstGetRep ().c_str_peek ();
1949[[noreturn]]
void String::ThrowInvalidAsciiException_ ()
1955#if qStroika_Foundation_Characters_AsPathAutoMapMSYSAndCygwin
1961 static const String kMSYSDrivePrefix_ =
"/"sv;
1962 static const String kCygrivePrefix_ =
"/cygdrive/"sv;
1963 if (StartsWith (kCygrivePrefix_)) {
1965 if (ss.
length () > 1 and ss[0].IsASCII () and ss[0].IsAlphabetic () and ss[1] ==
'/') {
1966 wstring w = ss.
As<wstring> ();
1967 w.insert (w.begin () + 1,
':');
1968 return filesystem::path{w};
1971 if (StartsWith (kMSYSDrivePrefix_)) {
1973 if (ss.
length () > 1 and ss[0].IsASCII () and ss[0].IsAlphabetic () and ss[1] ==
'/') {
1974 wstring w = ss.
As<wstring> ();
1975 w.insert (w.begin () + 1,
':');
1976 return filesystem::path{w};
1979 return filesystem::path{As<wstring> ()};
1992 if (isLast and fSpecialSeparatorForLastPair) [[unlikely]] {
1993 sb << *fSpecialSeparatorForLastPair;
2007namespace Stroika::Foundation::Traversal {
2012 using namespace Characters;
2013#if qStroika_Foundation_Debug_AssertionsChecked
2019 size_t cnt = this->size ();
2020 this->Apply ([&, idx = 0u] (
const String& i)
mutable {
2025 if (finalSeparator and idx + 1 == cnt) [[unlikely]] {
2026 sb << *finalSeparator;
2035#if qStroika_Foundation_Debug_AssertionsChecked
2036 Ensure (sb == referenceResult);
2050 span<const wchar_t> sData = s.
GetData (&maybeIgnoreBuf1);
2051 out.write (sData.data (), sData.size ());
2064size_t std::hash<String>::operator() (
const String& arg)
const
2066 using namespace Cryptography::Digest;
2067 using DIGESTER = Digester<Algorithm::SuperFastHash>;
2068 static constexpr DIGESTER kDigester_{};
2073 span<const char8_t> s = arg.
GetData (&maybeIgnoreBuf1);
2075 static const size_t kZeroDigest_ = kDigester_ (
nullptr,
nullptr);
2076 return kZeroDigest_;
2079 return kDigester_ (as_bytes (s));
#define RequireMember(p, c)
#define RequireNotReached()
#define qStroika_Foundation_Debug_AssertionsChecked
The qStroika_Foundation_Debug_AssertionsChecked flag determines if assertions are checked and validat...
#define RequireNotNull(p)
#define RequireExpression(c)
#define AssertNotReached()
conditional_t< qStroika_Foundation_Memory_PreferBlockAllocation and andTrueCheck, BlockAllocationUseHelper< T >, Common::Empty > UseBlockAllocationIfAppropriate
Use this to enable block allocation for a particular class. Beware of subclassing.
bool Equals(const T *lhs, const T *rhs)
strcmp or wsccmp() as appropriate == 0
constexpr bool IsASCII() const noexcept
Return true iff the given character (or all in span) is (are) in the ascii range [0....
static constexpr void CheckASCII(span< const CHAR_T > s)
if not IsASCII (arg) throw RuntimeException...
nonvirtual Character ToLowerCase() const noexcept
nonvirtual ASCII GetAsciiCode() const noexcept
static constexpr strong_ordering Compare(span< const CHAR_T, E1 > lhs, span< const CHAR_T, E2 > rhs, CompareOptions co) noexcept
nonvirtual bool IsLowerCase() const noexcept
constexpr char32_t GetCharacterCode() const noexcept
Return the char32_t UNICODE code-point associated with this character.
nonvirtual Character ToUpperCase() const noexcept
constexpr bool IsWhitespace() const noexcept
nonvirtual bool IsUpperCase() const noexcept
RegularExpression is a compiled regular expression which can be used to match on a String class.
virtual Character GetAt(size_t index) const noexcept=0
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
nonvirtual size_t size() const noexcept
nonvirtual RESULT_T As() const
nonvirtual void Append(span< const CHAR_T > s)
nonvirtual bool empty() const noexcept
nonvirtual String str() const
String is like std::u32string, except it is much easier to use, often much more space efficient,...
nonvirtual size_t length() const noexcept
nonvirtual String ToUpperCase() const
static String FromNarrowString(const char *from, const locale &l)
nonvirtual bool Matches(const RegularExpression ®Ex) const
nonvirtual bool IsWhitespace() const
nonvirtual String NormalizeTextToNL() const
static String Join(const Iterable< String > &list, const String &separator=", "sv)
static String FromStringConstant(const CHAR_T(&cString)[SIZE])
Take the given argument data (constant span) - which must remain unchanged - constant - for the appli...
nonvirtual String NormalizeSpace(Character useSpaceCharacter=' ') const
Replace sequences of whitespace characters (space, tab, newline etc) with a single space (or argument...
nonvirtual Containers::Sequence< pair< size_t, size_t > > FindEach(const RegularExpression ®Ex) const
nonvirtual String Repeat(unsigned int count) const
nonvirtual String LimitLength(size_t maxLen, StringShorteningPreference keepPref=StringShorteningPreference::ePreferKeepLeft) const
return the first maxLen (or fewer if string shorter) characters of this string (adding ellipsis if tr...
nonvirtual String RemoveAll(Character c) const
nonvirtual Containers::Sequence< RegularExpressionMatch > FindEachMatch(const RegularExpression ®Ex) const
nonvirtual String RemoveFirstIf(Character c) const
nonvirtual string AsNarrowSDKString() const
nonvirtual optional< String > Col(size_t i) const
Useful to replace 'awk print $3' - replace with Col(2) - zero based.
nonvirtual String InsertAt(Character c, size_t at) const
nonvirtual string AsNarrowString(const locale &l) const
nonvirtual size_t size() const noexcept
nonvirtual bool EndsWith(const Character &c, CompareOptions co=eWithCase) const
nonvirtual String ToLowerCase() const
nonvirtual String ReplaceAll(const RegularExpression ®Ex, const String &with) const
nonvirtual String Replace(size_t from, size_t to, const String &replacement) const
nonvirtual String SubString(SZ from) const
nonvirtual String Trim(bool(*shouldBeTrimmed)(Character)=Character::IsWhitespace) const
nonvirtual bool StartsWith(const Character &c, CompareOptions co=eWithCase) const
nonvirtual String StripAll(bool(*removeCharIf)(Character)) const
nonvirtual String AssureEndsWith(const Character &c, CompareOptions co=eWithCase) const
Return *this if it ends with argument character, or append 'c' so that it ends with a 'c'.
nonvirtual Containers::Sequence< String > AsLines() const
break the String into a series of lines;
nonvirtual String LTrim(bool(*shouldBeTrimmed)(Character)=Character::IsWhitespace) const
nonvirtual Containers::Sequence< String > Grep(const String &fgrepArg) const
Breaks this string into Lines, with AsLines (), and applies the argument filter (as if with ....
nonvirtual Containers::Sequence< String > FindEachString(const RegularExpression ®Ex) const
nonvirtual optional< size_t > RFind(Character c) const noexcept
static span< const CHAR_TYPE > GetData(const PeekSpanData &pds, Memory::StackBuffer< CHAR_TYPE, STACK_BUFFER_SZ > *possiblyUsedBuffer)
return the constant character data inside the string (rep) in the form of a span, possibly quickly an...
nonvirtual Containers::Sequence< String > Tokenize() const
nonvirtual String RemoveAt(size_t charAt) const
nonvirtual String RTrim(bool(*shouldBeTrimmed)(Character)=Character::IsWhitespace) const
nonvirtual optional< size_t > Find(Character c, CompareOptions co=eWithCase) const
static const UTFConvert kThe
Nearly always use this default UTFConvert.
static constexpr bool AllFitsInTwoByteEncoding(span< const CHAR_T > s) noexcept
Sequence_stdvector<T> is an std::vector-based concrete implementation of the Sequence<T> container pa...
A generalization of a vector: a container whose elements are keyed by the natural numbers.
nonvirtual void push_back(ArgByValueType< value_type > item)
nonvirtual void Append(ArgByValueType< value_type > item)
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
nonvirtual size_t size() const noexcept
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
nonvirtual RESULT_T Join(const CONVERT_TO_RESULT &convertToResult=kDefaultToStringConverter<>, const COMBINER &combiner=Characters::kDefaultStringCombiner) const
ape the JavaScript/python 'join' function - take the parts of 'this' iterable and combine them into a...
_SharedByValueRepType _fRep
nonvirtual size_t size() const
Returns the number of items contained.
nonvirtual Iterator< Character > MakeIterator() const
Create an iterator object which can be used to traverse the 'Iterable'.
An Iterator<T> is a copyable object which allows traversing the contents of some container.
concept - trivial shorthand for variadic same_as A or same_as B, or ...
char ASCII
Stroika's string/character classes treat 'char' as being an ASCII character.
StringShorteningPreference
DISABLE_COMPILER_MSC_WARNING_START(4996)
AllowMissingCharacterErrorsFlag
wostream & operator<<(wostream &out, const String &s)
conditional_t<(sizeof(CHECK_T)<=2 *sizeof(void *)) and is_trivially_copyable_v< CHECK_T >, CHECK_T, const CHECK_T & > ArgByValueType
This is an alias for 'T' - but how we want to pass it on stack as formal parameter.
SequencePolicy
equivalent which of 4 types being used std::execution::sequenced_policy, parallel_policy,...
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
Summary data for raw contents of rep - each rep will support at least one of these span forms.
StringCombiner is a simple function object used to combine two strings visually - used in Iterable<>:...
Memory::BLOB operator()(const T &t) const