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>
85 "Unnecessary invocation of Grow(): {} <= {}",
base::length + minimumGrowth, actCapacity )
88 if (actCapacity == 0 )
90 SetBuffer( minimumGrowth > 15 ? minimumGrowth : 15 );
91 #if ALIB_DEBUG_STRINGS
99 integer newCapacity= actCapacity + (actCapacity / 2);
101 newCapacity+= minimumGrowth;
103 if ( newCapacity < 15 )
107 #if ALIB_DEBUG_STRINGS
112template<
typename TChar,
typename TAllocator>
116 #if ALIB_DEBUG_STRINGS
120 sizeof(TChar) * (
size_t(
capacity + 1) + 32));
130 #if ALIB_DEBUG_STRINGS
135 if ( newCapacity == 0 )
138 "AString::SetBuffer(): removing an external buffer (setting string nulled). "
139 "This may not be wanted." )
146 ,
size_t(
capacity + 1) *
sizeof(TChar)
161 "Replacing an external buffer by an internally managed one. This may not be wanted: ",
168 size_t allocSize= size_t(newCapacity + 1) *
sizeof(TChar);
169 #if !ALIB_DEBUG_STRINGS
172 size_t(
capacity + 1) *
sizeof(TChar),
175 newCapacity=
integer(allocSize /
sizeof(TChar)) - 1;
179 allocSize+= 32 *
sizeof(TChar);
182 size_t(
capacity + 1 + 32) *
sizeof(TChar),
184 alignof(TChar) ) ) + 16;
185 newCapacity=
integer(allocSize /
sizeof(TChar)) - 32 -1;
200 size_t allocSize= size_t(newCapacity +1) *
sizeof(TChar);
201 #if !ALIB_DEBUG_STRINGS
203 newCapacity=
integer(allocSize /
sizeof(TChar)) - 1;
207 allocSize+= 32 *
sizeof(TChar);
209 newCapacity=
integer(allocSize /
sizeof(TChar)) - 32 - 1;
228 ,
size_t(
capacity + 1) *
sizeof(TChar)
247template<
typename TChar,
typename TAllocator>
253 && !(extBufferSize != 0 && extBuffer ==
nullptr) ,
"STRINGS",
254 "AString::SetBuffer(): Given buffer is nullptr while given alloc size is not 0 (or vice versa)")
262 ,
size_t(
capacity + 1) *
sizeof(TChar)
270 if ( extBufferSize < 1 )
272 ALIB_ERROR(
"STRINGS",
"allocation size < 1" )
279 #if ALIB_DEBUG_STRINGS
288 if ( extLength >= extBufferSize )
290 ALIB_ERROR(
"STRINGS",
"ext length {} >= ext allocation size {}", extLength, extBufferSize )
291 extLength= extBufferSize -1;
299 #if ALIB_DEBUG_STRINGS
310template<
typename TChar,
typename TAllocator>
320 if (regionStart < 0 )
323 integer regionEnd=
TCString<TChar>(
this).template IndexOfAny <lang::Inclusion::Exclude, NC>( trimChars, idx );
327 integer regionLength= regionEnd - regionStart;
328 if ( regionLength > 0 )
334template<
typename TChar,
typename TAllocator>
358template<
typename TChar,
typename TAllocator>
366 if ( startIdx < 0 ) startIdx= 0;
369 if ( startIdx >= endIdx )
return 0;
379 base::vbuffer[ startIdx ]= replacement;
382 while( ++startIdx < endIdx) ;
383 return cntReplacements;
386template<
typename TChar,
typename TAllocator>
398 if ( needle.
IsEmpty() )
return 0;
400 if ( startIdx >= endIdx )
return 0;
408 while ( cntReplacements < maxReplacements && startIdx < endIdx)
424 base::vbuffer + idx + nLen + lenDiff );
434 startIdx= idx + rLen;
441 return cntReplacements;
448template<
typename TChar,
typename TAllocator>
458template<
typename TChar,
typename TAllocator>
469template<
typename TChar,
typename TAllocator>
473 target.EnsureRemainingCapacity(48);
474 integer length= target.Length();
476 target.SetLength( length );
486template<
typename TChar,
typename TAllocator>
487void AppendableTraits<TTab<TChar>, TChar,TAllocator>::operator()( TAString<TChar,TAllocator>& target,
488 const TTab<TChar>& tab)
490 integer reference= tab.reference;
495 target.Length() -1 );
504 reference= target.Length();
508 integer length= target.Length();
509 integer qtyChars= tab.minPad > 0 ? tab.minPad : 0;
511 if ( tab.tabSize > 1 )
512 qtyChars+= (tab.tabSize - ( (length + qtyChars - reference) % tab.tabSize ) ) % tab.tabSize;
515 target.template InsertChars<NC>( tab.tabChar, qtyChars );
523template<
typename TChar,
typename TAllocator>
529 integer padSize= field.fieldWidth
535 target.template _ <NC>( theContent );
536 if (padSize > 0 ) target.template InsertChars<NC>( field.padChar, padSize );
544 target.template InsertChars<NC>( field.padChar, padSize );
545 target.template Append<NC>( theContent );
550 integer leftPadding= padSize / 2;
551 if( leftPadding > 0 )
552 target.template InsertChars<NC> ( field.padChar, leftPadding );
553 target.template Append<NC> ( theContent );
554 if( padSize > leftPadding ) target.template InsertChars<NC> ( field.padChar, padSize - leftPadding );
561template<
typename TChar,
typename TAllocator>
569 integer regionEnd= escape.startIdx + escape.length;
576 for(
integer idx= escape.startIdx; idx < regionEnd ; ++idx )
578 TChar c= target.CharAt(idx);
580 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')
600 target[++idx]= resultChar;
612 for(
integer idx= escape.startIdx; idx < regionEnd ; ++idx )
614 TChar c= target.CharAt(idx);
618 c= target.CharAt(idx + 1);
620 TChar resultChar=
'\0';
623 case '\\' : resultChar=
'\\';
break;
624 case 'r' : resultChar=
'\r' ;
break;
625 case 'n' : resultChar=
'\n' ;
break;
626 case 't' : resultChar=
'\t' ;
break;
627 case 'a' : resultChar=
'\a' ;
break;
628 case 'b' : resultChar=
'\b' ;
break;
629 case 'v' : resultChar=
'\v' ;
break;
630 case 'f' : resultChar=
'\f' ;
break;
632 case '"' : resultChar=
'"' ;
break;
637 if( resultChar !=
'\0')
639 target.Delete( idx, 1);
640 target[idx]= resultChar;
650template<
typename TChar,
typename TAllocator>
658 target.EnsureRemainingCapacity( fmt.valueType== 3 ? 48
662 integer length= target.Length();
666 fmt.valueType == 2 ?
detail::
WriteDecUnsigned( uint64_t(fmt.v.value) , target.VBuffer(), length, fmt.width , *nf ) :
667 detail::
WriteFloat ( fmt.v.fpValue, target.VBuffer(), length, fmt.width , *nf );
669 target.SetLength( length );
674template<
typename TChar,
typename TAllocator>
682 target.EnsureRemainingCapacity( 80 );
684 integer length= target.Length();
686 length=
detail::WriteBin( fmt.theValue, target.VBuffer(), length, fmt.theWidth, *nf );
688 target.SetLength( length );
691template<
typename TChar,
typename TAllocator>
699 target.EnsureRemainingCapacity( 25 );
701 integer length= target.Length();
703 length=
detail::WriteHex( fmt.theValue, target.VBuffer(), length, fmt.theWidth, *nf );
705 target.SetLength( length );
708template<
typename TChar,
typename TAllocator>
716 target.EnsureRemainingCapacity( 30 );
718 integer length= target.Length();
720 length=
detail::WriteOct( fmt.theValue, target.VBuffer(), length, fmt.theWidth, *nf );
722 target.SetLength( length );
725template<
typename TChar,
typename TAllocator>
731 target.EnsureRemainingCapacity( fmt.count );
733 target.SetLength( target.Length() + fmt.count );
740template<
typename TChar,
typename TAllocator>
742 const std::type_info& type )
744 lang::DbgTypeDemangler dmg(type);
749 bool startedWithDoubleColon=
false;
753 if(
typeName.Substring(i, 7).Equals(
"struct ")) i+= 7;
754 if(
typeName.Substring(i, 6).Equals(
"class " )) i+= 6;
755 if(
typeName.Substring(i, 6).Equals(
"union " )) i+= 6;
765 if (!(isalnum(c) || c==
'_') || i == typeName.Length() - 1)
767 if (startedWithDoubleColon)
769 result <<
typeName.Substring(nameStart, i-nameStart+1);
771 startedWithDoubleColon=
typeName.CharAt(nameStart) ==
':';
776 result.DeleteEnd<NC>(1);
779 if (!(isalnum(c) || c ==
'_' || c ==
'.'))
792 result.SearchAndReplace(
"> >",
">>");
797#if ALIB_EXT_LIB_THREADS_AVAILABLE
798template<
typename TChar,
typename TAllocator>
800 const std::thread::id& threadID )
802 #if ALIB_EXT_LIB_THREADS_AVAILABLE
803 size_t nativeIDWidth;
805 if constexpr (
sizeof(std::thread::id) ==
sizeof(uint16_t) ) { nativeID= *
reinterpret_cast<const uint16_t*
>(&threadID); nativeIDWidth= 4; }
806 else if constexpr (
sizeof(std::thread::id) ==
sizeof(uint32_t) ) { nativeID= *
reinterpret_cast<const uint32_t*
>(&threadID); nativeIDWidth= 8; }
807 else { nativeID= *
reinterpret_cast<const uint64_t*
>(&threadID); nativeIDWidth=16; }
809 #if !ALIB_SINGLE_THREADED
811 integer length= target.Length();
813 target << thread->GetName()
814 <<
'(' << thread->GetID()
815 <<
",0x" <<
THex<TChar>(nativeID,
int(nativeIDWidth)) <<
')';
816 target.InsertChars(
' ', 30 + length - target.Length() );
819 target <<
"TID=0x" <<
THex<TChar>(nativeID,
int(nativeIDWidth) );
828template<
typename TChar,
typename TAllocator>
830 const lang::CallerInfo& ci )
834 if (ci.File) nbuf << ci.File <<
':' << ci.Line;
835 else nbuf <<
"<NULL>";
838 if (ci.TypeInfo) nbuf << *ci.TypeInfo <<
"::";
839 if(ci.Func) nbuf << ci.Func <<
"()";
840 else nbuf <<
"<NULL>";
843 #if ALIB_EXT_LIB_THREADS_AVAILABLE
844 nbuf <<
" by '"<< ci.ThreadID <<
'\'';
852template<
typename TChar,
typename TAllocator>
854 time::DateTime::Duration pSrc )
856 using Duration= DateTime::Duration;
858 auto nanos= src.InNanoseconds();
861 target <<
DT_UNITS[size_t(DayTimeUnits::TS_ZERO)];
868 src= Duration() - src;
872 nf.FractionalPartWidth= 2;
873 int64_t v= src.InAbsoluteDays();
876 target << TDec<TChar>( src.InDays(), &nf ) <<
DT_UNITS[size_t(DayTimeUnits::DayPlural)];
882 target << v << ( v != 1 ?
DT_UNITS[size_t(DayTimeUnits::DayPlural)]
883 :
DT_UNITS[size_t(DayTimeUnits::DaySingular)] );
885 Duration cpy= src - ( Duration::FromAbsoluteDays(v) );
887 target << ' ' << TDec<TChar>( cpy.InHours(), &nf ) <<
DT_UNITS[size_t(DayTimeUnits::HourPlural)];
891 v= src.InAbsoluteHours();
894 target << v << ( v != 1 ?
DT_UNITS[size_t(DayTimeUnits::HourPlural)]
895 :
DT_UNITS[size_t(DayTimeUnits::HourSingular)] );
897 Duration cpy= src - ( Duration::FromAbsoluteHours(v) );
899 auto minutes= cpy.InAbsoluteMinutes();
900 target <<
' ' << minutes << (minutes!= 1 ?
DT_UNITS[size_t(DayTimeUnits::MinPlural)]
901 :
DT_UNITS[size_t(DayTimeUnits::MinSingular)] );
905 v= src.InAbsoluteMinutes();
908 target << v << ( v != 1 ?
DT_UNITS[size_t(DayTimeUnits::MinPlural)]
909 :
DT_UNITS[size_t(DayTimeUnits::MinSingular)] );
911 Duration cpy= src - ( Duration::FromAbsoluteMinutes(v) );
913 auto seconds= cpy.InAbsoluteSeconds();
914 target <<
' ' << seconds << (seconds!= 1 ?
DT_UNITS[size_t(DayTimeUnits::SecPlural)]
915 :
DT_UNITS[size_t(DayTimeUnits::SecSingular)] );
919 v= src.InAbsoluteSeconds();
922 target << TDec<TChar>( src.InSeconds(), &nf ) <<
DT_UNITS[size_t(DayTimeUnits::SecPlural)];
926 nf.DecMinimumFieldWidth= 3;
928 auto val= src.InAbsoluteMilliseconds();
931 target << TDec<TChar>(val,&nf) << ( val!= 1 ?
DT_UNITS[size_t(DayTimeUnits::MlSecPlural)]
932 :
DT_UNITS[size_t(DayTimeUnits::MlSecSingular)] );
936 val= src.InAbsoluteMicroseconds();
939 target << TDec<TChar>(val,&nf) << ( val!= 1 ?
DT_UNITS[size_t(DayTimeUnits::McSecPlural)]
940 :
DT_UNITS[size_t(DayTimeUnits::McSecSingular)] );
944 val= src.InNanoseconds();
945 target << TDec<TChar>(val,&nf) << ( val!= 1 ?
DT_UNITS[size_t(DayTimeUnits::NSecPlural)]
946 :
DT_UNITS[size_t(DayTimeUnits::NSecSingular)] );
950template<
typename TChar,
typename TAllocator>
952 time::Ticks::Duration src )
956 target, time::DateTime::Duration::FromNanoseconds( src.InNanoseconds() ));
TAString & Delete(integer regionStart, integer regionLength=MAX_LEN)
bool dbgWarnWhenExternalBufferIsReplaced
constexpr TAString(TAllocator &pAllocator, TChar *extBuffer, integer extBufferSize)
TAString & InsertChars(character c, integer qty)
ALIB_DLL integer SearchAndReplace(TChar needle, TChar replacement, integer startIdx=0, integer endIdx=strings::MAX_LEN)
integer debugLastAllocRequest
ALIB_DLL void SetBuffer(integer newCapacity)
ALIB_DLL integer TrimAt(integer idx, const TCString< TChar > &trimChars=CStringConstantsTraits< TChar >::DefaultWhitespaces())
ALIB_DLL TAString & Trim(const TCString< TChar > &trimChars=CStringConstantsTraits< TChar >::DefaultWhitespaces())
void EnsureRemainingCapacity(integer spaceNeeded)
ALIB_DLL void GrowBufferAtLeastBy(integer minimumGrowth)
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 ALIB_DLL Thread * Get(std::thread::id nativeID)
#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_STRING_DBG_CHK(instance)
#define ALIB_DEBUG_STRINGS
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.
constexpr bool IsNotNull(const T &t)
Case
Denotes upper and lower case character treatment.
@ 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.
ALIB_DLL integer WriteDecUnsigned(uint64_t value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
ALIB_DLL integer WriteDecSigned(int64_t value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
ALIB_DLL integer WriteBin(uint64_t value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
ALIB_DLL integer WriteHex(uint64_t value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
ALIB_DLL integer WriteOct(uint64_t value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
ALIB_DLL integer WriteFloat(double value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
NLocalString< 2048 > NString2K
Type alias name for TLocalString<nchar,2048>.
lang::integer integer
Type alias in namespace alib.
strings::TString< nchar > NString
Type alias in namespace alib.
threads::Thread Thread
Type alias in namespace alib.
TAllocator & GetAllocator() const noexcept
void operator()(TAString< TChar > &target, const TAppendable &src)
static constexpr CString< TChar > NewLine
integer length
The length of the region to convert.
integer startIdx
The start of the region to convert.