9#include "Stroika/Foundation/Execution/Common.h"
10#include "Stroika/Foundation/Memory/Common.h"
20 template <
typename OPTIONS>
21 inline StringBuilder<OPTIONS>::StringBuilder (
const String& initialValue)
25 template <
typename OPTIONS>
26 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
27 inline StringBuilder<OPTIONS>::StringBuilder (span<const CHAR_T> initialValue)
31 template <
typename OPTIONS>
32 template <convertible_to<String> T>
33 inline auto StringBuilder<OPTIONS>::operator= (
const T& rhs) -> StringBuilder&
40 template <
typename OPTIONS>
41 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
45 size_t spanSize = s.size ();
47 if constexpr (same_as<CHAR_T, ASCII>) {
50 if constexpr (same_as<CHAR_T, BufferElementType> or (same_as<BufferElementType, char8_t> and same_as<CHAR_T, ASCII>) or
51 (
sizeof (CHAR_T) ==
sizeof (BufferElementType) and (same_as<CHAR_T, wchar_t> or same_as<BufferElementType, wchar_t>))) {
53 size_t i = fData_.size ();
54 fData_.GrowToSize_uninitialized (i + spanSize);
55 if constexpr (same_as<CHAR_T, BufferElementType>) {
56 Memory::CopyBytes (Memory::SpanBytesCast<span<const CHAR_T>> (s), span<CHAR_T>{fData_}.subspan (i));
59 Memory::CopyBytes (Memory::SpanBytesCast<span<const BufferElementType>> (s), span<BufferElementType>{fData_}.subspan (i));
75 auto charITodoHardWay = s.begin ();
76 for (; charITodoHardWay != s.end (); ++charITodoHardWay) {
82 if (s.begin () != charITodoHardWay) [[likely]] {
83 if constexpr (same_as<CHAR_T, Character>) {
84 for (
auto c : s.subspan (0, charITodoHardWay - s.begin ())) {
85 this->fData_.push_back (
static_cast<ASCII> (c.GetCharacterCode ()));
89 this->fData_.push_back_coerced (s.subspan (0, charITodoHardWay - s.begin ()));
92 if (charITodoHardWay != s.end ()) [[unlikely]] {
93 auto hardWaySpan = span{charITodoHardWay, s.end ()};
94 Memory::StackBuffer<BufferElementType> buf{Memory::eUninitialized,
95 UTFConvert::ComputeTargetBufferSize<BufferElementType> (hardWaySpan)};
101 template <
typename OPTIONS>
102 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
105 Append (Memory::ConstSpan (s));
107 template <
typename OPTIONS>
108 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
111 Append (span{s, CString::Length (s)});
113 template <
typename OPTIONS>
114 template <IStdBasicStringCompatibleCharacter CHAR_T>
116 requires (IUNICODECanUnambiguouslyConvertFrom<CHAR_T>)
120 template <
typename OPTIONS>
121 template <IStdBasicStringCompatibleCharacter CHAR_T>
123 requires (IUNICODECanUnambiguouslyConvertFrom<CHAR_T>)
125 if constexpr (same_as<CHAR_T, ASCII>) {
127 this->fData_.push_back_coerced (span{s});
133 template <
typename OPTIONS>
136 Memory::StackBuffer<BufferElementType> ignored;
137 span<const BufferElementType> p = s.GetData (&ignored);
138 if (not p.empty ()) {
142 template <
typename OPTIONS>
143 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
153 if constexpr (same_as<BufferElementType, char32_t>) {
154 if constexpr (same_as<CHAR_T, Character>) {
155 fData_.push_back (c.GetCharacterCode ());
158 fData_.push_back (c);
162 else if constexpr (same_as<BufferElementType, char8_t>) {
163 if constexpr (same_as<CHAR_T, Character>) {
164 if (c.IsASCII ()) [[likely]] {
165 fData_.push_back (c.GetAsciiCode ());
170 if (isascii (c)) [[likely]] {
171 fData_.push_back (
static_cast<ASCII> (c));
177 this->
Append (span{&c, 1});
179#if !qCompilerAndStdLib_template_Requires_templateDeclarationMatchesOutOfLine_Buggy
180 template <
typename OPTIONS>
181 template <
typename APPEND_ARG_T>
183 -> StringBuilder&
requires (
requires (StringBuilder& s, APPEND_ARG_T&& a) { s.Append (forward<APPEND_ARG_T> (a)); }) {
184 Append (forward<APPEND_ARG_T> (a));
186 }
template <
typename OPTIONS>
187 template <
typename APPEND_ARG_T>
189 -> StringBuilder&
requires (Characters::Private_::IToString<APPEND_ARG_T> or
190 requires (StringBuilder& s, APPEND_ARG_T&& a) { s.Append (forward<APPEND_ARG_T> (a)); }) {
191 if constexpr (
requires (StringBuilder& s, APPEND_ARG_T&& a) { s.Append (forward<APPEND_ARG_T> (a)); }) {
192 Append (forward<APPEND_ARG_T> (a));
200 template <
typename OPTIONS>
201 inline void StringBuilder<OPTIONS>::push_back (Character c)
205 template <
typename OPTIONS>
209 if constexpr (
sizeof (BufferElementType) == 4) {
210 return fData_.size ();
213 return Memory::ValueOf (
UTFConvert::kThe.ComputeCharacterLength<BufferElementType> (fData_));
216 template <
typename OPTIONS>
220 return fData_.empty ();
222 template <
typename OPTIONS>
226 if constexpr (same_as<BufferElementType, char32_t>) {
227 Require (index < fData_.size ());
228 return fData_[index];
233 span<const char32_t> sp = this->GetData (&probablyIgnoredBuf);
237 template <
typename OPTIONS>
241 if constexpr (same_as<BufferElementType, char32_t>) {
242 Require (index < fData_.size ());
243 fData_[index] = item.GetCharacterCode ();
248 span<const char32_t> sp = this->GetData (&probablyIgnoredBuf);
249 Require (index < sp.size ());
250 char32_t* p =
const_cast<char32_t*
> (sp.data ()) + index;
251 *p = item.GetCharacterCode ();
252 this->fData_.clear ();
256 template <
typename OPTIONS>
261 template <
typename OPTIONS>
262 template <Common::IAnyOf<
char, Character, String, span<const Character>, span<Character>> T>
267 String asStr = this->As<String> ();
270 template <
typename OPTIONS>
274 Require (sz <= this->size ());
277 template <
typename OPTIONS>
283 template <
typename OPTIONS>
287 return String{span{fData_}};
289 template <
typename OPTIONS>
290 template <Common::IAnyOf<String, w
string, u8
string, u16
string, u32
string> RESULT_T>
293 if constexpr (same_as<RESULT_T, String>) {
296 if constexpr (same_as<RESULT_T, wstring>) {
298 span<const wchar_t> p = this->GetData (&maybeIngored);
299 return wstring{p.data (), p.size ()};
301 if constexpr (same_as<RESULT_T, u8string>) {
302 Memory::StackBuffer<char8_t> maybeIngored;
303 span<const char8_t> p = this->GetData (&maybeIngored);
304 return u8string{p.data (), p.size ()};
306 if constexpr (same_as<RESULT_T, u16string>) {
307 Memory::StackBuffer<char16_t> maybeIngored;
308 span<const char16_t> p = this->GetData (&maybeIngored);
309 return u16string{p.data (), p.size ()};
311 if constexpr (same_as<RESULT_T, u32string>) {
312 Memory::StackBuffer<char32_t> maybeIngored;
313 span<const char32_t> p = this->GetData (&maybeIngored);
314 return u32string{p.data (), p.size ()};
317 template <
typename OPTIONS>
318 inline StringBuilder<OPTIONS>::operator String ()
const
320 return As<String> ();
322 template <
typename OPTIONS>
323 inline StringBuilder<OPTIONS>::operator wstring ()
const
325 return As<wstring> ();
327 template <
typename OPTIONS>
328 inline StringBuilder<OPTIONS>::operator u8string ()
const
330 return As<u8string> ();
332 template <
typename OPTIONS>
333 inline StringBuilder<OPTIONS>::operator u16string ()
const
335 return As<u16string> ();
337 template <
typename OPTIONS>
338 inline StringBuilder<OPTIONS>::operator u32string ()
const
340 return As<u32string> ();
342 template <
typename OPTIONS>
343 inline StringBuilder<OPTIONS>::operator span<const typename StringBuilder<OPTIONS>::BufferElementType> ()
const
347 template <
typename OPTIONS>
352 template <
typename OPTIONS>
356 return fData_.data ();
358 template <
typename OPTIONS>
362 return fData_.data ();
364 template <
typename OPTIONS>
365 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
367 requires (not is_const_v<CHAR_T>)
370 if constexpr (
sizeof (CHAR_T) ==
sizeof (BufferElementType)) {
371 return span{
reinterpret_cast<const CHAR_T*
> (fData_.data ()), fData_.size ()};
374 probablyIgnoredBuf->resize_uninitialized (UTFConvert::ComputeTargetBufferSize<CHAR_T> (span{fData_}));
379 template <
typename OPTIONS>
380 bool StringBuilder<OPTIONS>::operator== (
const String& rhs)
const
382 return As<String> () == rhs;
384 template <
typename OPTIONS>
385 bool StringBuilder<OPTIONS>::operator== (
const StringBuilder& rhs)
const
387 return As<String> () == rhs.As<String> ();
389 template <
typename OPTIONS>
390 void StringBuilder<OPTIONS>::erase (
size_t from)
392 erase (from, size () - from);
394 template <
typename OPTIONS>
395 void StringBuilder<OPTIONS>::erase (
size_t from,
size_t count)
399 *
this = a.RemoveAt (from, from + count);
#define RequireNotNull(p)
void Append(TARGET_CONTAINER *v)
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...
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
nonvirtual const Character operator[](size_t i) const noexcept
return (read-only) Character object
nonvirtual size_t size() const noexcept
nonvirtual span< BufferElementType > data()
nonvirtual RESULT_T As() const
nonvirtual auto operator+=(APPEND_ARG_T &&a) -> StringBuilder &
nonvirtual void ShrinkTo(size_t sz) noexcept
nonvirtual span< const CHAR_T > GetData(Memory::StackBuffer< CHAR_T > *probablyIgnoredBuf) const
access a span of data located inside the StringBuilder. Return internal pointer, or pointer internal ...
nonvirtual size_t length() const noexcept
number of characters, not bytes or code-points
nonvirtual auto operator<<(APPEND_ARG_T &&a) -> StringBuilder &
nonvirtual Character GetAt(size_t index) const noexcept
nonvirtual void Append(span< const CHAR_T > s)
nonvirtual bool empty() const noexcept
nonvirtual void SetAt(Character item, size_t index) noexcept
nonvirtual void InsertAt(T c, size_t at)
nonvirtual String str() const
String is like std::u32string, except it is much easier to use, often much more space efficient,...
nonvirtual String InsertAt(Character c, size_t at) const
static const UTFConvert kThe
Nearly always use this default UTFConvert.
nonvirtual span< TRG_T > ConvertSpan(span< const SRC_T > source, span< TRG_T > target) const
Convert between UTF-N encoded (including the special case of ASCII, and Latin1) character spans (e....
shared_lock< const AssertExternallySynchronizedMutex > ReadContext
Instantiate AssertExternallySynchronizedMutex::ReadContext to designate an area of code where protect...
unique_lock< AssertExternallySynchronizedMutex > WriteContext
Instantiate AssertExternallySynchronizedMutex::WriteContext to designate an area of code where protec...
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
char ASCII
Stroika's string/character classes treat 'char' as being an ASCII character.
String UnoverloadedToString(const T &t)
same as ToString()/1 - but without the potentially confusing multi-arg overloads (confused some templ...