7#if !defined(ALIB_STRINGS_TASTRING_INSTANTIATION)
8# error "ALib sources with ending '.inl' must not be included from outside."
37template<
typename TChar,
typename TAllocator>
38requires alib::lang::IsAllocator<TAllocator>
46 || base::length <= debugLastAllocRequest,
"STRINGS",
47 "Error: Previous allocation request was too short: {} < {} ",
48 debugLastAllocRequest, base::length )
51 "Error: Length greater than allocation size: {} > {}",
54 if( base::buffer && HasInternalBuffer() )
56 for (
integer i= -16 ; i < 0 ; ++i)
57 if ( base::buffer[i] != 2 )
59 ALIB_ERROR(
"STRINGS",
"Magic byte not found at start of buffer." )
62 for (
integer i= 1 ; i <= 16 ; ++i)
63 if ( base::buffer[ cap + i] != 3 )
65 ALIB_ERROR(
"STRINGS",
"Magic byte not found at end of buffer." )
78template<
typename TChar,
typename TAllocator>
79requires alib::lang::IsAllocator<TAllocator>
84 "Unnecessary invocation of Grow(): {} <= {}",
base::length + minimumGrowth, actCapacity )
87 if (actCapacity == 0 ) {
88 SetBuffer( minimumGrowth > 15 ? minimumGrowth : 15 );
89 #if ALIB_DEBUG_STRINGS
97 integer newCapacity= actCapacity + (actCapacity / 2);
99 newCapacity+= minimumGrowth;
101 if ( newCapacity < 15 )
105 #if ALIB_DEBUG_STRINGS
110template<
typename TChar,
typename TAllocator>
113 #if ALIB_DEBUG_STRINGS
117 sizeof(TChar) * (
size_t(
capacity + 1) + 32));
127 #if ALIB_DEBUG_STRINGS
132 if ( newCapacity == 0 ) {
134 "AString::SetBuffer(): removing an external buffer (setting string nulled). "
135 "This may not be wanted." )
142 ,
size_t(
capacity + 1) *
sizeof(TChar)
157 "Replacing an external buffer of size {} by an internally managed one of size {}."
158 " This may not be wanted: ", -
capacity +1, newCapacity +1,
164 size_t allocSize= size_t(newCapacity + 1) *
sizeof(TChar);
165 #if !ALIB_DEBUG_STRINGS
168 size_t(
capacity + 1) *
sizeof(TChar),
171 newCapacity=
integer(allocSize /
sizeof(TChar)) - 1;
175 allocSize+= 32 *
sizeof(TChar);
178 size_t(
capacity + 1 + 32) *
sizeof(TChar),
180 alignof(TChar) ) ) + 16;
181 newCapacity=
integer(allocSize /
sizeof(TChar)) - 32 -1;
196 size_t allocSize= size_t(newCapacity +1) *
sizeof(TChar);
197 #if !ALIB_DEBUG_STRINGS
199 newCapacity=
integer(allocSize /
sizeof(TChar)) - 1;
203 allocSize+= 32 *
sizeof(TChar);
205 newCapacity=
integer(allocSize /
sizeof(TChar)) - 32 - 1;
223 ,
size_t(
capacity + 1) *
sizeof(TChar)
240template<
typename TChar,
typename TAllocator>
245 && !(extBufferSize != 0 && extBuffer ==
nullptr) ,
"STRINGS",
246 "AString::SetBuffer(): Given buffer is nullptr while given alloc size is not 0 (or vice versa)")
254 ,
size_t(
capacity + 1) *
sizeof(TChar)
262 if ( extBufferSize < 1 ) {
263 ALIB_ERROR(
"STRINGS",
"allocation size < 1" )
269 #if ALIB_DEBUG_STRINGS
278 if ( extLength >= extBufferSize ) {
279 ALIB_ERROR(
"STRINGS",
"ext length {} >= ext allocation size {}", extLength, extBufferSize )
280 extLength= extBufferSize -1;
288 #if ALIB_DEBUG_STRINGS
299template<
typename TChar,
typename TAllocator>
308 if (regionStart < 0 )
311 integer regionEnd=
TCString<TChar>(
this).template IndexOfAny <lang::Inclusion::Exclude, NC>( trimChars, idx );
315 integer regionLength= regionEnd - regionStart;
316 if ( regionLength > 0 )
322template<
typename TChar,
typename TAllocator>
344template<
typename TChar,
typename TAllocator>
351 if ( startIdx < 0 ) startIdx= 0;
354 if ( startIdx >= endIdx )
return 0;
364 base::vbuffer[ startIdx ]= replacement;
367 while( ++startIdx < endIdx) ;
368 return cntReplacements;
371template<
typename TChar,
typename TAllocator>
382 if ( needle.
IsEmpty() )
return 0;
384 if ( startIdx >= endIdx )
return 0;
392 while ( cntReplacements < maxReplacements && startIdx < endIdx) {
401 if ( lenDiff != 0 ) {
406 base::vbuffer + idx + nLen + lenDiff );
416 startIdx= idx + rLen;
423 return cntReplacements;
430template<
typename TChar,
typename TAllocator>
439template<
typename TChar,
typename TAllocator>
442 target.EnsureRemainingCapacity(28);
443 integer length= target.Length();
445 target.SetLength( length );
449template<
typename TChar,
typename TAllocator>
452 target.EnsureRemainingCapacity(48);
453 integer length= target.Length();
455 target.SetLength( length );
465template<
typename TChar,
typename TAllocator>
468 integer reference= tab.reference;
469 if (reference < 0 ) {
472 target.Length() -1 );
480 reference= target.Length();
483 integer length= target.Length();
484 integer qtyChars= tab.minPad > 0 ? tab.minPad : 0;
486 if ( tab.tabSize > 1 )
487 qtyChars+= (tab.tabSize - ( (length + qtyChars - reference) % tab.tabSize ) ) % tab.tabSize;
490 target.template InsertChars<NC>( tab.tabChar, qtyChars );
498template<
typename TChar,
typename TAllocator>
504 integer padSize= field.fieldWidth
510 target.template _ <NC>( theContent );
511 if (padSize > 0 ) target.template InsertChars<NC>( field.padChar, padSize );
525 integer leftPadding= padSize / 2;
526 if( leftPadding > 0 )
527 target.template InsertChars<NC> ( field.padChar, leftPadding );
528 target.template Append<NC> ( theContent );
529 if( padSize > leftPadding ) target.template InsertChars<NC> ( field.padChar, padSize - leftPadding );
536template<
typename TChar,
typename TAllocator>
537void AppendableTraits<TEscape<TChar>, TChar,TAllocator>::operator()( TAString<TChar,TAllocator>& target,
538 const TEscape<TChar>& escape) {
539 if( target.AdjustRegion(
const_cast<TEscape<TChar>&
>(escape).startIdx,
540 const_cast<TEscape<TChar>&
>(escape).length ) )
543 integer regionEnd= escape.startIdx + escape.length;
549 for(
integer idx= escape.startIdx; idx < regionEnd ; ++idx ) {
550 TChar c= target.CharAt(idx);
552 TChar resultChar=
'\0';
554 case '\\' : resultChar=
'\\';
break;
555 case '\r' : resultChar=
'r' ;
break;
556 case '\n' : resultChar=
'n' ;
break;
557 case '\t' : resultChar=
't' ;
break;
558 case '\a' : resultChar=
'a' ;
break;
559 case '\b' : resultChar=
'b' ;
break;
560 case '\v' : resultChar=
'v' ;
break;
561 case '\f' : resultChar=
'f' ;
break;
563 case '"' : resultChar=
'"' ;
break;
568 if( resultChar !=
'\0') {
569 target.template InsertChars<NC>(
'\\', 1, idx);
570 target[++idx]= resultChar;
579 for(
integer idx= escape.startIdx; idx < regionEnd ; ++idx ) {
580 TChar c= target.CharAt(idx);
584 c= target.CharAt(idx + 1);
586 TChar resultChar=
'\0';
588 case '\\' : resultChar=
'\\';
break;
589 case 'r' : resultChar=
'\r' ;
break;
590 case 'n' : resultChar=
'\n' ;
break;
591 case 't' : resultChar=
'\t' ;
break;
592 case 'a' : resultChar=
'\a' ;
break;
593 case 'b' : resultChar=
'\b' ;
break;
594 case 'v' : resultChar=
'\v' ;
break;
595 case 'f' : resultChar=
'\f' ;
break;
597 case '"' : resultChar=
'"' ;
break;
602 if( resultChar !=
'\0') {
603 target.Delete( idx, 1);
604 target[idx]= resultChar;
611template<
typename TChar,
typename TAllocator>
618 target.EnsureRemainingCapacity( fmt.valueType== 3 ? 48
622 integer length= target.Length();
626 fmt.valueType == 2 ?
detail::
WriteDecUnsigned( uint64_t(fmt.v.value) , target.VBuffer(), length, fmt.width , *nf ) :
627 detail::
WriteFloat ( fmt.v.fpValue, target.VBuffer(), length, fmt.width , *nf );
629 target.SetLength( length );
634template<
typename TChar,
typename TAllocator>
641 target.EnsureRemainingCapacity( 80 );
643 integer length= target.Length();
645 length=
detail::WriteBin( fmt.theValue, target.VBuffer(), length, fmt.theWidth, *nf );
647 target.SetLength( length );
650template<
typename TChar,
typename TAllocator>
657 target.EnsureRemainingCapacity( 25 );
659 integer length= target.Length();
661 length=
detail::WriteHex( fmt.theValue, target.VBuffer(), length, fmt.theWidth, *nf );
663 target.SetLength( length );
666template<
typename TChar,
typename TAllocator>
673 target.EnsureRemainingCapacity( 30 );
675 integer length= target.Length();
677 length=
detail::WriteOct( fmt.theValue, target.VBuffer(), length, fmt.theWidth, *nf );
679 target.SetLength( length );
682template<
typename TChar,
typename TAllocator>
687 target.EnsureRemainingCapacity( fmt.count );
688 characters::Fill( target.VBuffer() + target.Length(), fmt.count, fmt.fillChar );
689 target.SetLength( target.Length() + fmt.count );
696template<
typename TChar,
typename TAllocator>
698 const std::type_info& type ) {
699 lang::DbgTypeDemangler dmg(type);
704 bool startedWithDoubleColon=
false;
707 if(
typeName.Substring(i, 7).Equals(
"struct ")) i+= 7;
708 if(
typeName.Substring(i, 6).Equals(
"class " )) i+= 6;
709 if(
typeName.Substring(i, 6).Equals(
"union " )) i+= 6;
718 if (!(isalnum(c) || c==
'_') || i == typeName.Length() - 1) {
719 if (startedWithDoubleColon)
721 result <<
typeName.Substring(nameStart, i-nameStart+1);
723 startedWithDoubleColon=
typeName.CharAt(nameStart) ==
':';
727 result.DeleteEnd<NC>(1);
730 if (!(isalnum(c) || c ==
'_' || c ==
'.')) {
738 result.SearchAndReplace(
"> >",
">>");
743#if ALIB_EXT_LIB_THREADS_AVAILABLE
744template<
typename TChar,
typename TAllocator>
747 const std::thread::id& threadID ) {
748 #if ALIB_EXT_LIB_THREADS_AVAILABLE
749 size_t nativeIDWidth;
751 if constexpr (
sizeof(std::thread::id) ==
sizeof(uint16_t) ) { nativeID= *
reinterpret_cast<const uint16_t*
>(&threadID); nativeIDWidth= 4; }
752 else if constexpr (
sizeof(std::thread::id) ==
sizeof(uint32_t) ) { nativeID= *
reinterpret_cast<const uint32_t*
>(&threadID); nativeIDWidth= 8; }
753 else { nativeID= *
reinterpret_cast<const uint64_t*
>(&threadID); nativeIDWidth=16; }
755 #if !ALIB_SINGLE_THREADED
757 integer length= target.Length();
759 target << thread->GetName()
760 <<
'(' << thread->GetID()
761 <<
",0x" <<
THex<TChar>(nativeID,
int(nativeIDWidth)) <<
')';
762 target.InsertChars(
' ', 30 + length - target.Length() );
765 target <<
"TID=0x" <<
THex<TChar>(nativeID,
int(nativeIDWidth) );
774template<
typename TChar,
typename TAllocator>
777 const lang::CallerInfo& ci ) {
780 if (ci.File) nbuf << ci.File <<
':' << ci.Line;
781 else nbuf <<
"<NULL>";
784 if (ci.TypeInfo) nbuf << *ci.TypeInfo <<
"::";
785 if(ci.Func) nbuf << ci.Func <<
"()";
786 else nbuf <<
"<NULL>";
789 #if ALIB_EXT_LIB_THREADS_AVAILABLE
790 nbuf <<
" by '"<< ci.ThreadID <<
'\'';
798template<
typename TChar,
typename TAllocator>
801 time::DateTime::Duration pSrc ) {
802 using Duration= DateTime::Duration;
804 auto nanos= src.InNanoseconds();
806 target <<
DT_UNITS[size_t(DayTimeUnits::TS_ZERO)];
812 src= Duration() - src;
816 nf.FractionalPartWidth= 2;
817 int64_t v= src.InAbsoluteDays();
819 target << TDec<TChar>( src.InDays(), &nf ) <<
DT_UNITS[size_t(DayTimeUnits::DayPlural)];
824 target << v << ( v != 1 ?
DT_UNITS[size_t(DayTimeUnits::DayPlural)]
825 :
DT_UNITS[size_t(DayTimeUnits::DaySingular)] );
827 Duration cpy= src - ( Duration::FromAbsoluteDays(v) );
829 target << ' ' << TDec<TChar>( cpy.InHours(), &nf ) <<
DT_UNITS[size_t(DayTimeUnits::HourPlural)];
833 v= src.InAbsoluteHours();
835 target << v << ( v != 1 ?
DT_UNITS[size_t(DayTimeUnits::HourPlural)]
836 :
DT_UNITS[size_t(DayTimeUnits::HourSingular)] );
838 Duration cpy= src - ( Duration::FromAbsoluteHours(v) );
840 auto minutes= cpy.InAbsoluteMinutes();
841 target <<
' ' << minutes << (minutes!= 1 ?
DT_UNITS[size_t(DayTimeUnits::MinPlural)]
842 :
DT_UNITS[size_t(DayTimeUnits::MinSingular)] );
846 v= src.InAbsoluteMinutes();
848 target << v << ( v != 1 ?
DT_UNITS[size_t(DayTimeUnits::MinPlural)]
849 :
DT_UNITS[size_t(DayTimeUnits::MinSingular)] );
851 Duration cpy= src - ( Duration::FromAbsoluteMinutes(v) );
853 auto seconds= cpy.InAbsoluteSeconds();
854 target <<
' ' << seconds << (seconds!= 1 ?
DT_UNITS[size_t(DayTimeUnits::SecPlural)]
855 :
DT_UNITS[size_t(DayTimeUnits::SecSingular)] );
859 v= src.InAbsoluteSeconds();
861 target << TDec<TChar>( src.InSeconds(), &nf ) <<
DT_UNITS[size_t(DayTimeUnits::SecPlural)];
865 nf.DecMinimumFieldWidth= 3;
867 auto val= src.InAbsoluteMilliseconds();
869 target << TDec<TChar>(val,&nf) << ( val!= 1 ?
DT_UNITS[size_t(DayTimeUnits::MlSecPlural)]
870 :
DT_UNITS[size_t(DayTimeUnits::MlSecSingular)]);
874 val= src.InAbsoluteMicroseconds();
876 target << TDec<TChar>(val,&nf) << ( val!= 1 ?
DT_UNITS[size_t(DayTimeUnits::McSecPlural)]
877 :
DT_UNITS[size_t(DayTimeUnits::McSecSingular)]);
881 val= src.InNanoseconds();
882 target << TDec<TChar>(val,&nf) << ( val!= 1 ?
DT_UNITS[size_t(DayTimeUnits::NSecPlural)]
883 :
DT_UNITS[size_t(DayTimeUnits::NSecSingular)] );
887template<
typename TChar,
typename TAllocator>
892 target, time::DateTime::Duration::FromNanoseconds( src.InNanoseconds() ));
#define ALIB_ASSERT(cond, domain)
#define ALIB_WARNING(domain,...)
#define ALIB_ASSERT_WARNING(cond, domain,...)
#define ALIB_ERROR(domain,...)
#define ALIB_ASSERT_ERROR(cond, domain,...)
#define ALIB_DEBUG_STRINGS
integer TrimAt(integer idx, const TCString< TChar > &trimChars=CStringConstantsTraits< TChar >::DefaultWhitespaces())
TAString & Delete(integer regionStart, integer regionLength=MAX_LEN)
integer SearchAndReplace(TChar needle, TChar replacement, integer startIdx=0, integer endIdx=strings::MAX_LEN)
bool dbgWarnWhenExternalBufferIsReplaced
constexpr TAString(TAllocator &pAllocator, TChar *extBuffer, integer extBufferSize)
void SetBuffer(integer newCapacity)
TAString & InsertChars(TChar c, integer qty)
integer debugLastAllocRequest
void GrowBufferAtLeastBy(integer minimumGrowth)
TAString & Append(const TCharSrc *src, integer srcLength)
TAString & Trim(const TCString< TChar > &trimChars=CStringConstantsTraits< TChar >::DefaultWhitespaces())
void EnsureRemainingCapacity(integer spaceNeeded)
void SetLength(integer newLength)
constexpr integer Length() const
constexpr bool IsEmpty() const
integer IndexOf(TChar needle, integer startIdx=0) const
integer IndexOfAny(const TString &needles, integer startIdx=0) const
constexpr const TChar * Buffer() const
integer WStringLength() const
constexpr TString() noexcept=default
integer IndexOfOrLength(TChar needle) const
integer LastIndexOfAny(const TString &needles, integer startIdx=MAX_LEN) const
static Thread * Get(std::thread::id nativeID)
void typeName(const detail::VTable *vtable, AString &result)
void Copy(const TChar *src, integer length, TChar *dest)
void Move(const TChar *src, integer length, TChar *dest)
void Fill(TChar *dest, integer length, TChar value)
@ Right
Chooses right alignment.
@ Left
Chooses left alignment.
@ On
Switch it on, switched on, etc.
Case
Denotes upper and lower case character treatment.
constexpr bool IsNotNull(const T &t)
@ Transfer
Transfers responsibility to the receiving party.
String DT_UNITS[size_t(DayTimeUnits::SIZE_OF_UNITS)]
This is a detail namespace of module ALib Strings.
integer WriteHex(uint64_t value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
integer WriteDecUnsigned(uint64_t value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
integer WriteDecSigned(int64_t value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
integer WriteOct(uint64_t value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
integer WriteBin(uint64_t value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
integer WriteFloat(double value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
strings::TString< nchar > NString
Type alias in namespace alib.
threads::Thread Thread
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
NLocalString< 2048 > NString2K
Type alias name for #"TLocalString;TLocalString<nchar,2048>".
#define ALIB_STRING_DBG_CHK(instance)
TAllocator & GetAllocator() const noexcept
void operator()(TAString< TChar > &target, const TAppendable &src)
static constexpr CString< TChar > NewLine