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 void More (optional<Character>* result,
bool advance)
override
189 if (advance) [[likely]] {
190 Require (fIdx_ < fData_.size ());
193 if (fIdx_ < fData_.size ()) [[likely]] {
195 *result =
Character{
static_cast<char32_t> (fData_[fIdx_])};
201 virtual bool Equals (
const IRep* rhs)
const override
205 const MyIterRep_* rrhs = Debug::UncheckedDynamicCast<const MyIterRep_*> (rhs);
206 return fData_.data () == rrhs->fData_.data () and fIdx_ == rrhs->fIdx_;
218 virtual size_t size ()
const override
220 return _fData.size ();
222 virtual bool empty ()
const override
224 return _fData.empty ();
229 return inherited::Find (that, seq);
238 struct DynamicallyAllocatedString : StringRepHelperAllFitInSize_ {
239 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
242 using inherited = StringRepHelperAllFitInSize_::Rep<CHAR_T>;
245 Rep (span<const CHAR_T> t1)
246 : inherited{mkBuf_ (t1)}
250 Rep (
const Rep&) =
delete;
253 nonvirtual Rep& operator= (
const Rep&) =
delete;
256 virtual ~Rep ()
override
258 delete[] this->_fData.data ();
262 static span<CHAR_T> mkBuf_ (
size_t length)
264 size_t capacity = AdjustCapacity_ (length);
265 Assert (length <= capacity);
266 if constexpr (kAddNullTerminator_) {
267 Assert (length + 1 <= capacity);
269 CHAR_T* newBuf =
new CHAR_T[capacity];
270 return span{newBuf, capacity};
272 static span<CHAR_T> mkBuf_ (span<const CHAR_T> t1)
274 size_t len = t1.size ();
275 span<CHAR_T> buf = mkBuf_ (len);
276 Assert (buf.size () >= len);
277 auto result = Memory::CopyBytes (t1, buf);
278 if constexpr (kAddNullTerminator_) {
279 Assert (len + 1 <= buf.size ());
280 *(buf.data () + len) =
'\0';
287 virtual const wchar_t* c_str_peek () const noexcept
override
290 if constexpr (kAddNullTerminator_) {
291 Assert (*(this->_fData.data () + this->_fData.size ()) ==
'\0');
292 return reinterpret_cast<const wchar_t*
> (this->_fData.data ());
301 static constexpr bool kAddNullTerminator_ =
sizeof (CHAR_T) ==
sizeof (
wchar_t);
304 static size_t AdjustCapacity_ (
size_t initialCapacity)
306 size_t result = initialCapacity;
307 if constexpr (kAddNullTerminator_) {
321 struct FixedCapacityInlineStorageString_ : StringRepHelperAllFitInSize_ {
322 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T,
size_t CAPACITY>
323 struct Rep final :
public StringRepHelperAllFitInSize_::Rep<CHAR_T>,
326 using inherited = StringRepHelperAllFitInSize_::Rep<CHAR_T>;
329 bool IncludesNullTerminator_ ()
const
331 if constexpr (
sizeof (CHAR_T) ==
sizeof (
wchar_t)) {
332 return this->_fData.size () < CAPACITY;
340 CHAR_T fBuf_[CAPACITY];
343 Rep (span<const CHAR_T> t1)
349 Require (t1.size () <= CAPACITY);
350 inherited::operator= (Memory::CopyBytes (t1, span<CHAR_T>{fBuf_}));
351 if (IncludesNullTerminator_ ()) {
352 Assert (t1.size () + 1 <= CAPACITY);
353 fBuf_[t1.size ()] = CHAR_T{
'\0'};
357 Rep (
const Rep&) =
delete;
360 nonvirtual Rep& operator= (
const Rep&) =
delete;
364 virtual const wchar_t* c_str_peek () const noexcept
override
366 if (IncludesNullTerminator_ ()) {
367 Assert (*(this->_fData.data () + this->_fData.size ()) ==
'\0');
368 return reinterpret_cast<const wchar_t*
> (this->_fData.data ());
380 struct StringConstant_ :
public StringRepHelperAllFitInSize_ {
383 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
384 class DirectIndexRep final :
public StringRepHelperAllFitInSize_::Rep<CHAR_T>,
387 using inherited = StringRepHelperAllFitInSize_::Rep<CHAR_T>;
390 DirectIndexRep (span<const CHAR_T> s)
397 virtual const wchar_t* c_str_peek () const noexcept
override
407 struct StdStringDelegator_ :
public StringRepHelperAllFitInSize_ {
410 template <IStdBasicStringCompatibleCharacter CHAR_T>
413 using inherited = StringRepHelperAllFitInSize_::Rep<CHAR_T>;
416 Rep (basic_string<CHAR_T>&& s)
417 : inherited{span<const CHAR_T>{}}
418 , fMovedData_{move (s)}
420 inherited::operator= (span{fMovedData_.data (), fMovedData_.size ()});
425 virtual const wchar_t* c_str_peek () const noexcept
override
427 if constexpr (same_as<CHAR_T, wchar_t>) {
428 return fMovedData_.c_str ();
436 basic_string<CHAR_T> fMovedData_;
443 struct StringWithCStr_ :
public String {
447 shared_ptr<_IRep> fUnderlyingRep_;
452 Rep (
const shared_ptr<_IRep>& underlyingRep)
453 : fUnderlyingRep_{underlyingRep}
457 auto wideSpan = String::GetData<wchar_t> (underlyingRep->PeekData (nullopt), &possibleUsedBuf);
458 fCString_.assign (wideSpan.begin (), wideSpan.end ());
463 virtual shared_ptr<Iterable<Character>::_IRep> Clone ()
const override
465 return fUnderlyingRep_->Clone ();
469 return fUnderlyingRep_->MakeIterator ();
471 virtual size_t size ()
const override
473 return fUnderlyingRep_->size ();
475 virtual bool empty ()
const override
477 return fUnderlyingRep_->empty ();
482 return fUnderlyingRep_->Find (that, seq);
487 virtual Character GetAt (
size_t index)
const noexcept override
489 return fUnderlyingRep_->GetAt (index);
491 virtual PeekSpanData PeekData ([[maybe_unused]] optional<PeekSpanData::StorageCodePointType> preferred)
const noexcept override
493 return fUnderlyingRep_->PeekData (preferred);
495 virtual const wchar_t* c_str_peek () const noexcept
override
497 return fCString_.c_str ();
504 template <
typename FACET>
505 struct deletable_facet_ final : FACET {
506 template <
typename... Args>
507 deletable_facet_ (Args&&... args)
508 : FACET{forward<Args> (args)...}
511 ~deletable_facet_ () =
default;
520const wregex& Characters::Private_::RegularExpression_GetCompiled (
const RegularExpression& regExp)
522 return regExp.GetCompiled ();
530shared_ptr<String::_IRep> String::CTORFromBasicStringView_ (
const basic_string_view<ASCII>& str)
536shared_ptr<String::_IRep> String::CTORFromBasicStringView_ (
const basic_string_view<char8_t>& str)
546shared_ptr<String::_IRep> String::CTORFromBasicStringView_ (
const basic_string_view<char16_t>& str)
552 return mk_ (span<const char16_t>{str.data (), str.size ()});
556shared_ptr<String::_IRep> String::CTORFromBasicStringView_ (
const basic_string_view<char32_t>& str)
561shared_ptr<String::_IRep> String::CTORFromBasicStringView_ (
const basic_string_view<wchar_t>& str)
601 codecvt_base::result result =
603 if (result != codecvt_base::ok) [[
unlikely]] {
610shared_ptr<String::_IRep> String::mkEmpty_ ()
617template <
typename CHAR_T>
618inline auto String::mk_nocheck_ (span<const CHAR_T> s) -> shared_ptr<_IRep>
619 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>)
622 if constexpr (same_as<CHAR_T, ASCII>) {
625 else if constexpr (same_as<CHAR_T, Latin1>) {
628 else if constexpr (
sizeof (CHAR_T) == 2) {
643 constexpr size_t kBaseOfFixedBufSize_ =
sizeof (StringRepHelperAllFitInSize_::Rep<CHAR_T>);
644 static_assert (kBaseOfFixedBufSize_ < 64);
646 static_assert (kBaseOfFixedBufSize_ == 3 *
sizeof (
void*));
647 if constexpr (
sizeof (
void*) == 4) {
648 static_assert (kBaseOfFixedBufSize_ == 12);
650 else if constexpr (
sizeof (
void*) == 8) {
651 static_assert (kBaseOfFixedBufSize_ == 24);
654 constexpr size_t kOverheadSizeForMakeShared_ =
655 qStroika_Foundation_Common_Platform_Windows ? (
sizeof (
void*) == 4 ? 12 : 16) :
sizeof (
unsigned long) * 2;
656#if qStroika_Foundation_Common_Platform_Windows
657 static_assert (kOverheadSizeForMakeShared_ ==
sizeof (_Ref_count_base));
659 static constexpr size_t kNElts1_ = (64 - kBaseOfFixedBufSize_ - kOverheadSizeForMakeShared_) /
sizeof (CHAR_T);
660 static constexpr size_t kNElts2_ = (96 - kBaseOfFixedBufSize_ - kOverheadSizeForMakeShared_) /
sizeof (CHAR_T);
661 static constexpr size_t kNElts3_ = (128 - kBaseOfFixedBufSize_ - kOverheadSizeForMakeShared_) /
sizeof (CHAR_T);
665 if constexpr (
sizeof (
void*) == 4) {
666 static_assert (kNElts1_ == 40);
667 static_assert (kNElts2_ == 72);
668 static_assert (kNElts3_ == 104);
670 if constexpr (
sizeof (
void*) == 8) {
671 static_assert (kNElts1_ == 24);
672 static_assert (kNElts2_ == 56);
673 static_assert (kNElts3_ == 88);
678 static_assert (kNElts2_ > kNElts1_);
679 static_assert (kNElts3_ > kNElts2_);
681 static_assert (
sizeof (FixedCapacityInlineStorageString_::Rep<CHAR_T, kNElts1_>) == 64 - kOverheadSizeForMakeShared_);
682 static_assert (
sizeof (FixedCapacityInlineStorageString_::Rep<CHAR_T, kNElts2_>) == 96 - kOverheadSizeForMakeShared_);
683 static_assert (
sizeof (FixedCapacityInlineStorageString_::Rep<CHAR_T, kNElts3_>) == 128 - kOverheadSizeForMakeShared_);
685 size_t sz = s.size ();
686 if (sz <= kNElts1_) {
687 return MakeSharedPtr<FixedCapacityInlineStorageString_::Rep<CHAR_T, kNElts1_>> (s);
689 else if (sz <= kNElts2_) {
690 return MakeSharedPtr<FixedCapacityInlineStorageString_::Rep<CHAR_T, kNElts2_>> (s);
692 else if (sz <= kNElts3_) {
693 return MakeSharedPtr<FixedCapacityInlineStorageString_::Rep<CHAR_T, kNElts3_>> (s);
695 return MakeSharedPtr<DynamicallyAllocatedString::Rep<CHAR_T>> (s);
699auto String::mk_ (basic_string<char>&& s) -> shared_ptr<_IRep>
702 return MakeSharedPtr<StdStringDelegator_::Rep<ASCII>> (move (s));
706auto String::mk_ (basic_string<char16_t>&& s) -> shared_ptr<_IRep>
709 return MakeSharedPtr<StdStringDelegator_::Rep<char16_t>> (move (s));
712 Memory::StackBuffer<char32_t> wideUnicodeBuf{Memory::eUninitialized, UTFConvert::ComputeTargetBufferSize<char32_t> (span{s.data (), s.size ()})};
713 return mk_nocheck_ (Memory::ConstSpan (
UTFConvert::kThe.ConvertSpan (span{s.data (), s.size ()}, span{wideUnicodeBuf})));
717auto String::mk_ (basic_string<char32_t>&& s) -> shared_ptr<_IRep>
719 return MakeSharedPtr<StdStringDelegator_::Rep<char32_t>> (move (s));
723auto String::mk_ (basic_string<wchar_t>&& s) -> shared_ptr<_IRep>
725 if constexpr (
sizeof (wchar_t) == 2) {
727 return MakeSharedPtr<StdStringDelegator_::Rep<wchar_t>> (move (s));
731 UTFConvert::ComputeTargetBufferSize<char32_t> (span{s.data (), s.size ()})};
732 return mk_nocheck_ (Memory::ConstSpan (
UTFConvert::kThe.ConvertSpan (span{s.data (), s.size ()}, span{wideUnicodeBuf})));
735 return MakeSharedPtr<StdStringDelegator_::Rep<wchar_t>> (move (s));
749 return mk_ (span{buf});
752void String::SetCharAt (
Character c,
size_t i)
757 Require (i <
size ());
760 Require (i <
size ());
768 Require (at <=
size ());
790 _SafeReadRepAccessor
accessor{
this};
800 span
s1 = d.subspan (0,
from);
801 span
s2 = d.subspan (
to);
803 Memory::CopyBytes (
s2,
bufSpan.subspan (
s1.size ()));
811 if (
auto o =
tmp.Find (c, eWithCase)) {
818 if (
auto o = this->
Find (subString, eWithCase)) {
829 while (
auto o =
tmp.Find (c, eWithCase)) {
852 if (
co == eWithCase) {
883 case eCaseInsensitive: {
886 if (i->ToLowerCase () ==
lcc) {
900optional<size_t>
String::Find (
const String& subString,
size_t startAt, CompareOptions co)
const
903 _SafeReadRepAccessor
accessor{
this};
916 case eCaseInsensitive: {
919 if (
accessor._ConstGetRep ().GetAt (i +
j).ToLowerCase () !=
subString[
j].ToLowerCase ()) {
950 if (
res.size () >= 1) {
959 vector<size_t> result;
991 Assert (
match.size () != 0);
994 for (
size_t j = 1;
j <
n; ++
j) {
1015 _SafeReadRepAccessor accessor{
this};
1016 const _IRep& useRep = accessor._ConstGetRep ();
1017 size_t length = useRep.size ();
1018 for (
size_t i = length; i > 0; --i) {
1019 if (useRep.
GetAt (i - 1) == c) {
1038 for (
size_t i =
limit; i > 0; --i) {
1062 _SafeReadRepAccessor
accessor{
this};
1063 if (
accessor._ConstGetRep ().size () == 0) {
1075#if qStroika_Foundation_Debug_AssertionsChecked
1083#if qStroika_Foundation_Debug_AssertionsChecked
1091 _SafeReadRepAccessor
accessor{
this};
1104 _SafeReadRepAccessor
accessor{
this};
1110#if qStroika_Foundation_Debug_AssertionsChecked
1118#if qStroika_Foundation_Debug_AssertionsChecked
1148 for (
size_t i = 1; i <
base_match.size (); ++i) {
1245 for (
size_t i = 0; i !=
len; ++i) {
1277 Assert (
ofi->first <=
ofi->second);
1374String String::SubString_ (
const _SafeReadRepAccessor& thisAccessor,
size_t from,
size_t to)
const
1386 switch (
psd.fInCP) {
1401 return mk_ (
psd.fSingleByteLatin1.subspan (
from,
to -
from));
1403 case PeekSpanData::eChar16: {
1411 case PeekSpanData::eChar32: {
1433 return *
this + *
this;
1436 for (
unsigned int i = 0; i <
count; ++i) {
1448 _SafeReadRepAccessor
accessor{
this};
1450 for (
size_t i = 0; i <
length; ++i) {
1464 for (
size_t i = 0; i <
length; ++i) {
1478#if qStroika_Foundation_Debug_AssertionsChecked
1484#if qStroika_Foundation_Debug_AssertionsChecked
1493 _SafeReadRepAccessor
accessor{
this};
1495 switch (
psd.fInCP) {
1502 case PeekSpanData::eChar32: {
1513 _SafeReadRepAccessor
accessor{
this};
1558#if qStroika_Foundation_Debug_AssertionsChecked
1564#if qStroika_Foundation_Debug_AssertionsChecked
1570#if qStroika_Foundation_Debug_AssertionsChecked
1577 _SafeReadRepAccessor
accessor{
this};
1579 switch (
psd.fInCP) {
1586 case PeekSpanData::eChar32: {
1631#if qStroika_Foundation_Debug_AssertionsChecked
1637#if qStroika_Foundation_Debug_AssertionsChecked
1643#if qStroika_Foundation_Debug_AssertionsChecked
1649 _SafeReadRepAccessor
accessor{
this};
1651 switch (
psd.fInCP) {
1658 case PeekSpanData::eChar32: {
1673 size_t n = result.
size ();
1674 for (
size_t i = 0; i <
n; ++i) {
1681 for (; i <
n; ++i) {
1696 for (
const String& i : list) {
1699 if (result.
empty ()) {
1700 return result.
str ();
1711 _SafeReadRepAccessor
accessor{
this};
1715 for (
auto c :
psd.fAscii) {
1721 result.push_back (c);
1733 result.push_back (c);
1738 return result.
str ();
1749 _SafeReadRepAccessor
accessor{
this};
1753 for (
auto c :
psd.fAscii) {
1759 result.push_back (c);
1771 result.push_back (c);
1776 return result.
str ();
1798 case StringShorteningPreference::ePreferKeepLeft:
1800 case StringShorteningPreference::ePreferKeepRight:
1802 case StringShorteningPreference::ePreferKeepMid:
1815 if (
keepPref == StringShorteningPreference::ePreferKeepMid) {
1827 case StringShorteningPreference::ePreferKeepLeft:
1829 case StringShorteningPreference::ePreferKeepRight:
1831 case StringShorteningPreference::ePreferKeepMid:
1855 codecvt_base::result result =
1857 if (result != codecvt_base::ok) [[
unlikely]] {
1884 if (result != codecvt_base::ok) [[
unlikely]] {
1895void String::erase (
size_t from)
1900void String::erase (
size_t from,
size_t count)
1911const wchar_t* String::c_str () const noexcept
1915 DISABLE_COMPILER_GCC_WARNING_START (
"GCC diagnostic ignored \"-Wdeprecated-declarations\"");
1916 DISABLE_COMPILER_CLANG_WARNING_START (
"clang diagnostic ignored \"-Wdeprecated-declarations\"");
1917 return const_cast<String*
> (
this)->c_str ();
1918 DISABLE_COMPILER_MSC_WARNING_END (4996);
1919 DISABLE_COMPILER_GCC_WARNING_END (
"GCC diagnostic ignored \"-Wdeprecated-declarations\"");
1920 DISABLE_COMPILER_CLANG_WARNING_END (
"clang diagnostic ignored \"-Wdeprecated-declarations\"");
1922const wchar_t* String::c_str ()
1926 _SafeReadRepAccessor
accessor{
this};
1927 const wchar_t* result =
accessor._ConstGetRep ().c_str_peek ();
1928 if (result ==
nullptr) {
1930 result = _SafeReadRepAccessor{
this}._ConstGetRep ().c_str_peek ();
1938[[noreturn]]
void String::ThrowInvalidAsciiException_ ()
1944#if qStroika_Foundation_Characters_AsPathAutoMapMSYSAndCygwin
1950 static const String kMSYSDrivePrefix_ =
"/"sv;
1951 static const String kCygrivePrefix_ =
"/cygdrive/"sv;
1952 if (StartsWith (kCygrivePrefix_)) {
1954 if (ss.
length () > 1 and ss[0].IsASCII () and ss[0].IsAlphabetic () and ss[1] ==
'/') {
1955 wstring w = ss.
As<wstring> ();
1956 w.insert (w.begin () + 1,
':');
1957 return filesystem::path{w};
1960 if (StartsWith (kMSYSDrivePrefix_)) {
1962 if (ss.
length () > 1 and ss[0].IsASCII () and ss[0].IsAlphabetic () and ss[1] ==
'/') {
1963 wstring w = ss.
As<wstring> ();
1964 w.insert (w.begin () + 1,
':');
1965 return filesystem::path{w};
1968 return filesystem::path{As<wstring> ()};
1981 if (isLast and fSpecialSeparatorForLastPair) [[unlikely]] {
1982 sb << *fSpecialSeparatorForLastPair;
1996namespace Stroika::Foundation::Traversal {
2001 using namespace Characters;
2002#if qStroika_Foundation_Debug_AssertionsChecked
2008 size_t cnt = this->size ();
2009 this->Apply ([&, idx = 0u] (
const String& i)
mutable {
2014 if (finalSeparator and idx + 1 == cnt) [[unlikely]] {
2015 sb << *finalSeparator;
2024#if qStroika_Foundation_Debug_AssertionsChecked
2025 Ensure (sb == referenceResult);
2039 span<const wchar_t> sData = s.
GetData (&maybeIgnoreBuf1);
2040 out.write (sData.data (), sData.size ());
2053size_t std::hash<String>::operator() (
const String& arg)
const
2055 using namespace Cryptography::Digest;
2056 using DIGESTER = Digester<Algorithm::SuperFastHash>;
2057 static constexpr DIGESTER kDigester_{};
2062 span<const char8_t> s = arg.
GetData (&maybeIgnoreBuf1);
2064 static const size_t kZeroDigest_ = kDigester_ (
nullptr,
nullptr);
2065 return kZeroDigest_;
2068 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