7#if !defined(ALIB_STRINGS_TASTRING_INSTANTIATION)
8# error "ALib sources with ending '.inc' 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() ) {
55 for (
integer i= -16 ; i < 0 ; ++i)
56 if ( base::buffer[i] != 2 ) {
57 ALIB_ERROR(
"STRINGS",
"Magic byte not found at start of buffer." )
60 for (
integer i= 1 ; i <= 16 ; ++i)
61 if ( base::buffer[ cap + i] != 3 ) {
62 ALIB_ERROR(
"STRINGS",
"Magic byte not found at end of buffer." )
73template<
typename TChar,
typename TAllocator>
74requires alib::lang::IsAllocator<TAllocator>
79 "Unnecessary invocation of Grow(): {} <= {}",
base::length + minimumGrowth, actCapacity )
82 if (actCapacity == 0 ) {
83 SetBuffer( minimumGrowth > 15 ? minimumGrowth : 15 );
84 #if ALIB_DEBUG_STRINGS
92 integer newCapacity= actCapacity + (actCapacity / 2);
94 newCapacity+= minimumGrowth;
96 if ( newCapacity < 15 )
100 #if ALIB_DEBUG_STRINGS
105template<
typename TChar,
typename TAllocator>
108 #if ALIB_DEBUG_STRINGS
112 sizeof(TChar) * (
size_t(
capacity + 1) + 32));
122 #if ALIB_DEBUG_STRINGS
127 if ( newCapacity == 0 ) {
129 "AString::SetBuffer(): removing an external buffer (setting string nulled). "
130 "This may not be wanted." )
137 ,
size_t(
capacity + 1) *
sizeof(TChar)
152 "Replacing an external buffer of size {} by an internally managed one of size {}."
153 " This may not be wanted: ", -
capacity +1, newCapacity +1,
159 size_t allocSize= size_t(newCapacity + 1) *
sizeof(TChar);
160 #if !ALIB_DEBUG_STRINGS
163 size_t(
capacity + 1) *
sizeof(TChar),
166 newCapacity=
integer(allocSize /
sizeof(TChar)) - 1;
170 allocSize+= 32 *
sizeof(TChar);
173 size_t(
capacity + 1 + 32) *
sizeof(TChar),
175 alignof(TChar) ) ) + 16;
176 newCapacity=
integer(allocSize /
sizeof(TChar)) - 32 -1;
191 size_t allocSize= size_t(newCapacity +1) *
sizeof(TChar);
192 #if !ALIB_DEBUG_STRINGS
194 newCapacity=
integer(allocSize /
sizeof(TChar)) - 1;
198 allocSize+= 32 *
sizeof(TChar);
200 newCapacity=
integer(allocSize /
sizeof(TChar)) - 32 - 1;
218 ,
size_t(
capacity + 1) *
sizeof(TChar)
235template<
typename TChar,
typename TAllocator>
240 && !(extBufferSize != 0 && extBuffer ==
nullptr) ,
"STRINGS",
241 "AString::SetBuffer(): Given buffer is nullptr while given alloc size is not 0 (or vice versa)")
249 ,
size_t(
capacity + 1) *
sizeof(TChar)
257 if ( extBufferSize < 1 ) {
258 ALIB_ERROR(
"STRINGS",
"allocation size < 1" )
264 #if ALIB_DEBUG_STRINGS
273 if ( extLength >= extBufferSize ) {
274 ALIB_ERROR(
"STRINGS",
"ext length {} >= ext allocation size {}", extLength, extBufferSize )
275 extLength= extBufferSize -1;
283 #if ALIB_DEBUG_STRINGS
294template<
typename TChar,
typename TAllocator>
303 if (regionStart < 0 )
306 integer regionEnd=
TCString<TChar>(
this).template IndexOfAny <lang::Inclusion::Exclude, NC>( trimChars, idx );
310 integer regionLength= regionEnd - regionStart;
311 if ( regionLength > 0 )
317template<
typename TChar,
typename TAllocator>
339template<
typename TChar,
typename TAllocator>
346 if ( startIdx < 0 ) startIdx= 0;
349 if ( startIdx >= endIdx )
return 0;
359 base::vbuffer[ startIdx ]= replacement;
362 while( ++startIdx < endIdx) ;
363 return cntReplacements;
366template<
typename TChar,
typename TAllocator>
377 if ( needle.
IsEmpty() )
return 0;
379 if ( startIdx >= endIdx )
return 0;
387 while ( cntReplacements < maxReplacements && startIdx < endIdx) {
396 if ( lenDiff != 0 ) {
401 base::vbuffer + idx + nLen + lenDiff );
411 startIdx= idx + rLen;
418 return cntReplacements;
425template<
typename TChar,
typename TAllocator>
434template<
typename TChar,
typename TAllocator>
437 target.EnsureRemainingCapacity(28);
438 integer length= target.Length();
440 target.SetLength( length );
444template<
typename TChar,
typename TAllocator>
447 target.EnsureRemainingCapacity(48);
448 integer length= target.Length();
450 target.SetLength( length );
460template<
typename TChar,
typename TAllocator>
463 integer reference= tab.reference;
464 if (reference < 0 ) {
467 target.Length() -1 );
475 reference= target.Length();
478 integer length= target.Length();
479 integer qtyChars= tab.minPad > 0 ? tab.minPad : 0;
481 if ( tab.tabSize > 1 )
482 qtyChars+= (tab.tabSize - ( (length + qtyChars - reference) % tab.tabSize ) ) % tab.tabSize;
485 target.template InsertChars<NC>( tab.tabChar, qtyChars );
493template<
typename TChar,
typename TAllocator>
499 integer padSize= field.fieldWidth
505 target.template _ <NC>( theContent );
506 if (padSize > 0 ) target.template InsertChars<NC>( field.padChar, padSize );
520 integer leftPadding= padSize / 2;
521 if( leftPadding > 0 )
522 target.template InsertChars<NC> ( field.padChar, leftPadding );
523 target.template Append<NC> ( theContent );
524 if( padSize > leftPadding ) target.template InsertChars<NC> ( field.padChar, padSize - leftPadding );
531template<
typename TChar,
typename TAllocator>
532void AppendableTraits<TEscape<TChar>, TChar,TAllocator>::operator()( TAString<TChar,TAllocator>& target,
533 const TEscape<TChar>& escape) {
534 if( target.AdjustRegion(
const_cast<TEscape<TChar>&
>(escape).startIdx,
535 const_cast<TEscape<TChar>&
>(escape).length ) )
538 integer regionEnd= escape.startIdx + escape.length;
544 for(
integer idx= escape.startIdx; idx < regionEnd ; ++idx ) {
545 TChar c= target.CharAt(idx);
547 TChar resultChar=
'\0';
549 case '\\' : resultChar=
'\\';
break;
550 case '\r' : resultChar=
'r' ;
break;
551 case '\n' : resultChar=
'n' ;
break;
552 case '\t' : resultChar=
't' ;
break;
553 case '\a' : resultChar=
'a' ;
break;
554 case '\b' : resultChar=
'b' ;
break;
555 case '\v' : resultChar=
'v' ;
break;
556 case '\f' : resultChar=
'f' ;
break;
558 case '"' : resultChar=
'"' ;
break;
563 if( resultChar !=
'\0') {
564 target.template InsertChars<NC>(
'\\', 1, idx);
565 target[++idx]= resultChar;
574 for(
integer idx= escape.startIdx; idx < regionEnd ; ++idx ) {
575 TChar c= target.CharAt(idx);
579 c= target.CharAt(idx + 1);
581 TChar resultChar=
'\0';
583 case '\\' : resultChar=
'\\';
break;
584 case 'r' : resultChar=
'\r' ;
break;
585 case 'n' : resultChar=
'\n' ;
break;
586 case 't' : resultChar=
'\t' ;
break;
587 case 'a' : resultChar=
'\a' ;
break;
588 case 'b' : resultChar=
'\b' ;
break;
589 case 'v' : resultChar=
'\v' ;
break;
590 case 'f' : resultChar=
'\f' ;
break;
592 case '"' : resultChar=
'"' ;
break;
597 if( resultChar !=
'\0') {
598 target.Delete( idx, 1);
599 target[idx]= resultChar;
606template<
typename TChar,
typename TAllocator>
613 target.EnsureRemainingCapacity( fmt.valueType== 3 ? 48
617 integer length= target.Length();
621 fmt.valueType == 2 ?
detail::
WriteDecUnsigned( uint64_t(fmt.v.value) , target.VBuffer(), length, fmt.width , *nf ) :
622 detail::
WriteFloat ( fmt.v.fpValue, target.VBuffer(), length, fmt.width , *nf );
624 target.SetLength( length );
629template<
typename TChar,
typename TAllocator>
636 target.EnsureRemainingCapacity( 80 );
638 integer length= target.Length();
640 length=
detail::WriteBin( fmt.theValue, target.VBuffer(), length, fmt.theWidth, *nf );
642 target.SetLength( length );
645template<
typename TChar,
typename TAllocator>
652 target.EnsureRemainingCapacity( 25 );
654 integer length= target.Length();
656 length=
detail::WriteHex( fmt.theValue, target.VBuffer(), length, fmt.theWidth, *nf );
658 target.SetLength( length );
661template<
typename TChar,
typename TAllocator>
668 target.EnsureRemainingCapacity( 30 );
670 integer length= target.Length();
672 length=
detail::WriteOct( fmt.theValue, target.VBuffer(), length, fmt.theWidth, *nf );
674 target.SetLength( length );
677template<
typename TChar,
typename TAllocator>
682 target.EnsureRemainingCapacity( fmt.count );
683 characters::Fill( target.VBuffer() + target.Length(), fmt.count, fmt.fillChar );
684 target.SetLength( target.Length() + fmt.count );
691template<
typename TChar,
typename TAllocator>
693 const std::type_info& type ) {
694 lang::DbgTypeDemangler dmg(type);
699 bool startedWithDoubleColon=
false;
702 if(
typeName.Substring(i, 7).Equals(
"struct ")) i+= 7;
703 if(
typeName.Substring(i, 6).Equals(
"class " )) i+= 6;
704 if(
typeName.Substring(i, 6).Equals(
"union " )) i+= 6;
713 if (!(isalnum(c) || c==
'_') || i == typeName.Length() - 1) {
714 if (startedWithDoubleColon)
716 result <<
typeName.Substring(nameStart, i-nameStart+1);
718 startedWithDoubleColon=
typeName.CharAt(nameStart) ==
':';
722 result.DeleteEnd<NC>(1);
725 if (!(isalnum(c) || c ==
'_' || c ==
'.')) {
733 result.SearchAndReplace(
"> >",
">>");
738#if ALIB_EXT_LIB_THREADS_AVAILABLE
739template<
typename TChar,
typename TAllocator>
742 const std::thread::id& threadID ) {
743 #if ALIB_EXT_LIB_THREADS_AVAILABLE
744 size_t nativeIDWidth;
746 if constexpr (
sizeof(std::thread::id) ==
sizeof(uint16_t) ) { nativeID= *
reinterpret_cast<const uint16_t*
>(&threadID); nativeIDWidth= 4; }
747 else if constexpr (
sizeof(std::thread::id) ==
sizeof(uint32_t) ) { nativeID= *
reinterpret_cast<const uint32_t*
>(&threadID); nativeIDWidth= 8; }
748 else { nativeID= *
reinterpret_cast<const uint64_t*
>(&threadID); nativeIDWidth=16; }
750 #if !ALIB_SINGLE_THREADED
752 integer length= target.Length();
754 target << thread->GetName()
755 <<
'(' << thread->GetID()
756 <<
",0x" <<
THex<TChar>(nativeID,
int(nativeIDWidth)) <<
')';
757 target.InsertChars(
' ', 30 + length - target.Length() );
760 target <<
"TID=0x" <<
THex<TChar>(nativeID,
int(nativeIDWidth) );
770template<
typename TChar,
typename TAllocator>
773 const lang::CallerInfo& ci ) {
776 if (ci.File) nbuf << ci.File <<
':' << ci.Line;
777 else nbuf <<
"<NULL>";
780 if (ci.TypeInfo) nbuf << *ci.TypeInfo <<
"::";
781 if(ci.Func) nbuf << ci.Func <<
"()";
782 else nbuf <<
"<NULL>";
785 #if ALIB_EXT_LIB_THREADS_AVAILABLE
786 nbuf <<
" by '"<< ci.ThreadID <<
'\'';
794template<
typename TChar,
typename TAllocator>
797 time::DateTime::Duration pSrc ) {
798 using Duration= DateTime::Duration;
800 auto nanos= src.InNanoseconds();
802 target <<
DT_UNITS[size_t(DayTimeUnits::TS_ZERO)];
808 src= Duration() - src;
812 nf.FractionalPartWidth= 2;
813 int64_t v= src.InAbsoluteDays();
815 target << TDec<TChar>( src.InDays(), &nf ) <<
DT_UNITS[size_t(DayTimeUnits::DayPlural)];
820 target << v << ( v != 1 ?
DT_UNITS[size_t(DayTimeUnits::DayPlural)]
821 :
DT_UNITS[size_t(DayTimeUnits::DaySingular)] );
823 Duration cpy= src - ( Duration::FromAbsoluteDays(v) );
825 target << ' ' << TDec<TChar>( cpy.InHours(), &nf ) <<
DT_UNITS[size_t(DayTimeUnits::HourPlural)];
829 v= src.InAbsoluteHours();
831 target << v << ( v != 1 ?
DT_UNITS[size_t(DayTimeUnits::HourPlural)]
832 :
DT_UNITS[size_t(DayTimeUnits::HourSingular)] );
834 Duration cpy= src - ( Duration::FromAbsoluteHours(v) );
836 auto minutes= cpy.InAbsoluteMinutes();
837 target <<
' ' << minutes << (minutes!= 1 ?
DT_UNITS[size_t(DayTimeUnits::MinPlural)]
838 :
DT_UNITS[size_t(DayTimeUnits::MinSingular)] );
842 v= src.InAbsoluteMinutes();
844 target << v << ( v != 1 ?
DT_UNITS[size_t(DayTimeUnits::MinPlural)]
845 :
DT_UNITS[size_t(DayTimeUnits::MinSingular)] );
847 Duration cpy= src - ( Duration::FromAbsoluteMinutes(v) );
849 auto seconds= cpy.InAbsoluteSeconds();
850 target <<
' ' << seconds << (seconds!= 1 ?
DT_UNITS[size_t(DayTimeUnits::SecPlural)]
851 :
DT_UNITS[size_t(DayTimeUnits::SecSingular)] );
855 v= src.InAbsoluteSeconds();
857 target << TDec<TChar>( src.InSeconds(), &nf ) <<
DT_UNITS[size_t(DayTimeUnits::SecPlural)];
861 nf.DecMinimumFieldWidth= 3;
863 auto val= src.InAbsoluteMilliseconds();
865 target << TDec<TChar>(val,&nf) << ( val!= 1 ?
DT_UNITS[size_t(DayTimeUnits::MlSecPlural)]
866 :
DT_UNITS[size_t(DayTimeUnits::MlSecSingular)]);
870 val= src.InAbsoluteMicroseconds();
872 target << TDec<TChar>(val,&nf) << ( val!= 1 ?
DT_UNITS[size_t(DayTimeUnits::McSecPlural)]
873 :
DT_UNITS[size_t(DayTimeUnits::McSecSingular)]);
877 val= src.InNanoseconds();
878 target << TDec<TChar>(val,&nf) << ( val!= 1 ?
DT_UNITS[size_t(DayTimeUnits::NSecPlural)]
879 :
DT_UNITS[size_t(DayTimeUnits::NSecSingular)] );
883template<
typename TChar,
typename TAllocator>
888 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