ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
tastringimpl.inl
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
7#if !defined(HPP_ALIB_STRINGS_TASTRING_INLINING)
8# error "ALib sources with ending '.inl' must not be included from outside."
9#endif
10
11#if !DOXYGEN
17# if ALIB_THREADS
19# elif ALIB_EXT_LIB_THREADS_AVAILABLE
20# include <thread>
21# endif
22#endif // !DOXYGEN
23
24#include <algorithm>
25
26
27namespace alib { namespace strings {
28
29/// \attention
30/// This is a non-existing namespace! It is exclusively defined for the
31/// \https{documentation parser,www.doxygen.nl}.
32///
33/// In this <b>"documentation namespace"</b>, you will find specializations of functor
34/// \alib{strings,T_Append} which in reality are implemented in parent
35/// namespace \ref alib::strings (as required by C++ language syntax).<br>
36/// The rationale for tricking the documentation to this pseude-namespace, is to twofold:
37/// On the one hand to keep namespace \b %alib::strings clean and on the other to have
38/// an overview of all specializations in one place.
39 namespace APPENDABLES {}
40
41
42// ####################################################################################################
43// AString::_dbgCheck()
44// ####################################################################################################
45//! @cond NO_DOX
46#if ALIB_DEBUG_STRINGS
47
48template<typename TChar, typename TAllocator>
50{
51 base::dbgCheck();
52
53 integer cap= Capacity();
54
55 ALIB_ASSERT_ERROR( debugLastAllocRequest == 0
56 || base::length <= debugLastAllocRequest, "STRINGS",
57 "Error: Previous allocation request was too short" )
58
59 ALIB_ASSERT_ERROR( base::length <= cap, "STRINGS",
60 "Error: Length greater than allocation size" )
61
63 if( base::buffer && HasInternalBuffer() )
64 {
65 for (integer i= -16 ; i < 0 ; ++i)
66 if ( base::buffer[i] != 2 )
67 {
68 ALIB_ERROR( "STRINGS", "Magic byte not found at start of buffer." )
69 break;
70 }
71 for (integer i= 1 ; i <= 16 ; ++i)
72 if ( base::buffer[ cap + i] != 3 )
73 {
74 ALIB_ERROR( "STRINGS", "Magic byte not found at end of buffer." )
75 break;
76 }
77 }
79}
80
81#endif
82//! @endcond
83
84
85// ####################################################################################################
86// Allocation
87// ####################################################################################################
88template<typename TChar, typename TAllocator>
90{
91 integer actCapacity= Capacity();
92
93 ALIB_ASSERT_WARNING ( base::length + minimumGrowth > actCapacity,
94 "STRINGS", "Unnecessary invocation of Grow()" )
95
96 // first allocation? Go with given growth as size
97 if (actCapacity == 0 )
98 {
99 SetBuffer( minimumGrowth > 15 ? minimumGrowth : 15 );
100 #if ALIB_DEBUG_STRINGS
101 debugLastAllocRequest= minimumGrowth;
102 #endif
103
104 return;
105 }
106
107 // calc new size: in general grow by 50%
108 integer newCapacity= actCapacity + (actCapacity / 2);
109 if ( newCapacity < base::length + minimumGrowth )
110 newCapacity+= minimumGrowth;
111
112 if ( newCapacity < 15 )
113 newCapacity= 15;
114
115 SetBuffer( newCapacity );
116 #if ALIB_DEBUG_STRINGS
117 debugLastAllocRequest= actCapacity + minimumGrowth;
118 #endif
119}
120
121template<typename TChar, typename TAllocator>
123{
124 #if ALIB_DEBUG_STRINGS
127 if(capacity > 0)
128 allocBase::GetAllocator().dbgCheckMemory( base::vbuffer - 16 ,
129 sizeof(TChar) * (size_t(capacity + 1) + 32));
131 #endif
132
133
134 ALIB_ASSERT( newCapacity >= 0 )
135
136 // do nothing if life-cycle is managed by us and same size,
137 if ( capacity >= 0 && capacity == newCapacity )
138 return;
139
140 #if ALIB_DEBUG_STRINGS
141 debugLastAllocRequest= newCapacity;
142 #endif
143
144 // set uninitialized (and return)
145 if ( newCapacity == 0 )
146 {
147 ALIB_ASSERT_WARNING( !dbgWarnWhenExternalBufferIsReplaced || capacity >= 0, "STRINGS",
148 "AString::SetBuffer(): removing an external buffer (setting string nulled). "
149 "This may not be wanted." )
150
152 if ( capacity > 0 )
153 allocBase::GetAllocator().free( base::vbuffer
155 - 16
156 #endif
157 , size_t(capacity + 1) * sizeof(TChar)
159 + 32 * sizeof(TChar)
160 #endif
161 );
162
163 capacity=
164 base::length= 0;
165 base::buffer= nullptr;
166 return;
168 }
169
170 #if ALIB_DEBUG
171 if( dbgWarnWhenExternalBufferIsReplaced && capacity < 0)
172 ALIB_WARNING( "STRINGS",
173 "AString::SetBuffer(): replacing an external buffer by an internally managed one. "
174 "This may not be wanted: ", reinterpret_cast<const char*>(Terminate()) )
175 #endif
176
177 // extend or shrink an existing buffer (and return)
178 if( capacity > 0 )
179 {
180 size_t allocSize= size_t(newCapacity + 1) * sizeof(TChar);
181 #if !ALIB_DEBUG_STRINGS
182 base::buffer= static_cast<TChar*>(
183 allocBase::GetAllocator().reallocate( base::vbuffer,
184 size_t(capacity + 1) * sizeof(TChar),
185 allocSize,
186 alignof(TChar) ) );
187 newCapacity= integer(allocSize / sizeof(TChar)) - 1;
188 allocBase::GetAllocator().dbgAcknowledgeIncreasedAllocSize( base::vbuffer, allocSize );
189 #else
191 // add 16 characters of padding at start/end
192 allocSize+= 32 * sizeof(TChar);
193 base::buffer= static_cast<TChar*>(
194 allocBase::GetAllocator().reallocate( base::vbuffer - 16,
195 size_t(capacity + 1 + 32) * sizeof(TChar),
196 allocSize,
197 alignof(TChar) ) ) + 16;
198 newCapacity= integer(allocSize / sizeof(TChar)) - 32 -1;
199
200 // write '\3' to end ('\0'= termination byte, '\1'= untermination byte )
201 characters::Fill( base::vbuffer + newCapacity + 1 , 16, TChar('\3') );
202 allocBase::GetAllocator().dbgAcknowledgeIncreasedAllocSize( base::vbuffer - 16, allocSize );
204 #endif
205
206 capacity= newCapacity;
207 if ( base::length > capacity )
208 base::length= capacity;
209
210 return;
211 }
212
213 // create new Buffer
214 size_t allocSize= size_t(newCapacity +1) * sizeof(TChar);
215 #if !ALIB_DEBUG_STRINGS
216 TChar* newBuffer= static_cast<TChar*>( allocBase::GetAllocator().allocate( allocSize, alignof(TChar)) );
217 newCapacity= integer(allocSize / sizeof(TChar)) - 1;
218 allocBase::GetAllocator().dbgAcknowledgeIncreasedAllocSize( newBuffer, allocSize );
219 #else
221 // add 16 characters of padding at start/end
222 allocSize+= 32 * sizeof(TChar);
223 TChar* newBuffer= static_cast<TChar*>( allocBase::GetAllocator().allocate( allocSize, alignof(TChar)) ) + 16;
224 newCapacity= integer(allocSize / sizeof(TChar)) - 32 - 1;
225
226 // write '\2' to start, '\3' to end ('\0'= termination byte, '\1'= untermination byte )
227 characters::Fill( newBuffer - 16, 16 , TChar('\2') );
228 characters::Fill( newBuffer + newCapacity + 1 , 16 , TChar('\3') );
229 allocBase::GetAllocator().dbgAcknowledgeIncreasedAllocSize( newBuffer - 16, allocSize );
231 #endif
232
233 // if we had a buffer before
234 if ( capacity != 0 )
235 {
236 // copy data and delete old buffer
237 characters::Copy( base::buffer, (std::min)( base::length + 1, newCapacity + 1),
238 newBuffer );
240 if ( capacity > 0 )
241 allocBase::GetAllocator().free( base::vbuffer
243 - 16
244 #endif
245 , size_t(capacity + 1) * sizeof(TChar)
247 + 32* sizeof(TChar)
248 #endif
249 );
251 }
252 else
253 {
254 ALIB_ASSERT( base::length == 0 )
255 }
256
257 // set new Buffer and adjust length
258 base::buffer= newBuffer;
259 capacity= newCapacity;
260 if ( base::length > capacity )
261 base::length= capacity;
262}
263
264
265template<typename TChar, typename TAllocator>
266void TAString<TChar, TAllocator>::SetBuffer( TChar* extBuffer, integer extBufferSize, integer extLength,
267 lang::Responsibility responsibility )
268{
269 ALIB_ASSERT_ERROR( !(extBufferSize == 0 && extBuffer != nullptr)
270 && !(extBufferSize != 0 && extBuffer == nullptr) , "STRINGS",
271 "AString::SetBuffer(): Given buffer is nullptr while given alloc size is not 0 (or vice versa)" )
272
273 // delete any existing
274 if ( capacity > 0 )
276 allocBase::GetAllocator().free( base::vbuffer
278 - 16
279 #endif
280 , size_t(capacity + 1) * sizeof(TChar)
282 + 32* sizeof(TChar)
283 #endif
284 );
286
287
288 // too small? treat as if a nullptr was given.
289 if ( extBufferSize < 1 )
290 {
291 ALIB_ERROR( "STRINGS", "allocation size < 1" )
292 extBuffer= nullptr;
293 }
294
295 // null buffer?
296 if ( (base::buffer= extBuffer) == nullptr )
297 {
298 #if ALIB_DEBUG_STRINGS
299 debugLastAllocRequest=
300 #endif
301 capacity=
302 base::length= 0;
303 return;
304 }
305
306
307 if ( extLength >= extBufferSize )
308 {
309 ALIB_ERROR( "STRINGS", "ext length >= ext allocation size" )
310 extLength= extBufferSize -1;
311 }
312
313
314 // save given buffer
315 --extBufferSize; // we count one less
316 capacity= responsibility==lang::Responsibility::Transfer ? extBufferSize
317 : -extBufferSize;
318 #if ALIB_DEBUG_STRINGS
319 debugLastAllocRequest= extBufferSize;
320 #endif
321 base::length= extLength;
322}
323
324
325
326// #############################################################################################
327// Trim
328// #############################################################################################
329
330template<typename TChar, typename TAllocator>
332{
333 if ( idx < 0 )
334 return 0;
335 if ( idx >= base::length )
336 return base::length;
337
338 integer regionStart= base::template LastIndexOfAny<lang::Inclusion::Exclude, NC>( trimChars, idx ) + 1;
339 if (regionStart < 0 )
340 regionStart= 0;
341
342 integer regionEnd= TCString<TChar>(this).template IndexOfAny <lang::Inclusion::Exclude, NC>( trimChars, idx );
343 if (regionEnd < 0 )
344 regionEnd= base::length;
345
346 integer regionLength= regionEnd - regionStart;
347 if ( regionLength > 0 )
348 Delete<NC>( regionStart, regionLength );
349
350 return regionStart;
351}
352
353template<typename TChar, typename TAllocator>
355{
356 // check
357 if (base::length == 0 || trimChars.IsEmpty() )
358 return *this;
359
360 // trim end
361 integer idx= base::template LastIndexOfAny<lang::Inclusion::Exclude, NC>( trimChars, base::length - 1 ) + 1;
362 if ( (base::length= idx) > 0 )
363 {
364 // trim front
365 idx= TCString<TChar>(this).template IndexOfAny<lang::Inclusion::Exclude, NC>( trimChars );
366 if ( idx > 0 )
367 Delete<NC>( 0, idx );
368 }
369
370 return *this;
371}
372
373
374// #################################################################################################
375// Replace()
376// #################################################################################################
377template<typename TChar, typename TAllocator>
379 TChar replacement,
380 integer startIdx,
381 integer endIdx )
382{
385 if ( startIdx < 0 ) startIdx= 0;
386 else if ( startIdx >= base::length ) return 0;
387 if ( endIdx > base::length ) endIdx= base::length;
388 if ( startIdx >= endIdx ) return 0;
389
390 // replacement loop
391 TCString<TChar> thisAsCString= this;
392 integer cntReplacements= 0;
393 do
394 {
395 startIdx= thisAsCString.template IndexOfOrLength<NC>( needle, startIdx );
396 if ( startIdx == base::length )
397 break;
398 base::vbuffer[ startIdx ]= replacement;
399 ++cntReplacements;
400 }
401 while( ++startIdx < endIdx) ;
402 return cntReplacements;
404}
405
406
407template<typename TChar, typename TAllocator>
409 const TString<TChar>& replacement,
410 integer startIdx,
411 integer maxReplacements,
412 lang::Case sensitivity,
413 integer endIdx )
414{
416
417 // check null arguments
418 if ( needle.IsEmpty() ) return 0;
419 endIdx= (std::min) (endIdx, base::length - needle.Length() + 1 );
420 if ( startIdx >= endIdx ) return 0;
421
422 integer nLen= needle.Length();
423 integer rLen= replacement.Length();
424 integer lenDiff= rLen - nLen;
425
426 // replacement loop
427 integer cntReplacements= 0;
428 while ( cntReplacements < maxReplacements && startIdx < endIdx)
429 {
431 // search next occurrence
432 integer idx= sensitivity == lang::Case::Sensitive
433 ? TString<TChar>(*this).template IndexOf<NC, lang::Case::Sensitive>( needle, startIdx, endIdx )
434 : TString<TChar>(*this).template IndexOf<NC, lang::Case::Ignore >( needle, startIdx, endIdx );
435 if ( idx < 0 )
436 break;
437
438 // copy rest up or down
439 if ( lenDiff != 0 )
440 {
441 if ( lenDiff > 0 )
442 EnsureRemainingCapacity( lenDiff );
443 characters::Move( base::vbuffer + idx + nLen,
444 base::length - idx - nLen,
445 base::vbuffer + idx + nLen + lenDiff );
446 base::length+= lenDiff;
447 endIdx+= lenDiff;
448 }
449
450 // fill replacement in
451 if( rLen > 0 )
452 characters::Copy( replacement.Buffer(), rLen, base::vbuffer + idx );
453
454 // set start index to first character behind current replacement
455 startIdx= idx + rLen;
456
457 // next
458 ++cntReplacements;
460 }
461
462 // that's it
463 return cntReplacements;
464}
465
466// #################################################################################################
467// T_Append<Integrals>
468// #################################################################################################
469
470template<typename TChar, typename TAllocator>
472 int64_t value )
473{
474 target.EnsureRemainingCapacity(28);// 20 digits, grouping symbol, sign and what have you
475 integer length= target.Length();
476 length= detail::WriteDecSigned ( value, target.VBuffer(), length, 0, TNumberFormat<TChar>::Computational );
477 target.SetLength( length );
478}
479
480template<typename TChar, typename TAllocator>
482 uint64_t value )
483{
484 target.EnsureRemainingCapacity(28);// 20 digits, grouping symbol, sign and what have you
485 integer length= target.Length();
486 length= detail::WriteDecUnsigned ( value, target.VBuffer(), length, 0, TNumberFormat<TChar>::Computational );
487 target.SetLength( length );
488}
489
490
491template<typename TChar, typename TAllocator>
492void T_Append<double,TChar,TAllocator>::operator()( TAString<TChar,TAllocator>& target,
493 double value )
494{
495 target.EnsureRemainingCapacity(48); // float: 2x15 + '.' + ',' + sign + fear
496 integer length= target.Length();
497 length= detail::WriteFloat( value, target.VBuffer(), length, 0, TNumberFormat<TChar>::Computational );
498 target.SetLength( length );
499}
500
501// #################################################################################################
502// T_Append<Format>
503// #################################################################################################
504
505// #################################################################################################
506// TFormat::Tab()
507// #################################################################################################
508template<typename TChar, typename TAllocator>
509void T_Append<typename TFormat<TChar>::Tab, TChar,TAllocator>::operator()( TAString<TChar,TAllocator>& target,
510 const typename TFormat<TChar>::Tab& tab)
511{
512 integer reference= tab.reference;
513 if (reference < 0 )
514 {
515 // search backwards
516 reference= target.template LastIndexOfAny<lang::Inclusion::Include>( TT_CStringConstants<TChar>::NewLine(),
517 target.Length() -1 );
518 if ( reference < 0 )
519 reference= 0;
520 else
521 {
522 // if new line has more than one character (windows) we have to now search the first
523 // character that is not in newline
524 reference= target.template IndexOfAny<lang::Inclusion::Exclude, NC>( TT_CStringConstants<TChar>::NewLine(), reference );
525 if (reference < 0 )
526 reference= target.Length();
527
528 }
529 }
530 integer length= target.Length();
531 integer qtyChars= tab.minPad > 0 ? tab.minPad : 0;
532
533 if ( tab.tabSize > 1 )
534 qtyChars+= (tab.tabSize - ( (length + qtyChars - reference) % tab.tabSize ) ) % tab.tabSize;
535
536 if ( qtyChars > 0 )
537 target.template InsertChars<NC>( tab.tabChar, qtyChars );
538}
539
540
541// #################################################################################################
542// TFormat::Field()
543// #################################################################################################
544template<typename TChar, typename TAllocator>
545void T_Append<typename TFormat<TChar>::Field, TChar,TAllocator>::operator()( TAString<TChar,TAllocator>& target,
546 const typename TFormat<TChar>::Field& field)
547{
548
549#if ALIB_BOXING
550 TString<TChar> theContent;
551
552 // buffer used for conversion (if none string)
553 TLocalString<TChar, 256> noneStringArgBuf;
554 noneStringArgBuf.DbgDisableBufferReplacementWarning();
555
556 // string-type box given?
557 if( !field.theContent.template IsType<void>() && field.theContent.template IsType<TString<TChar>>() )
558 theContent= field.theContent.template Unbox<TString<TChar>>();
559 else
560 {
561 // write box into local buffer
562 noneStringArgBuf << field.theContent;
563 theContent= noneStringArgBuf;
564 }
565
566#else
567 TString<TChar> theContent= field.theContent;
568#endif
569
570 integer padSize= field.fieldWidth
571 - theContent.WStringLength();
572
573 // check pad field.width
574 if (padSize <= 0 || field.alignment == lang::Alignment::Left )
575 {
576 target.template _ <NC>( theContent );
577 if (padSize > 0 ) target.template InsertChars<NC>( field.padChar, padSize );
578 return;
579 }
580
581 // align Right
582 if ( field.alignment == lang::Alignment::Right )
583 {
584 if( padSize > 0 )
585 target.template InsertChars<NC>( field.padChar, padSize );
586 target.template Append<NC>( theContent );
587 return;
588 }
589
590 // align Center
591 integer leftPadding= padSize / 2;
592 if( leftPadding > 0 )
593 target.template InsertChars<NC> ( field.padChar, leftPadding );
594 target.template Append<NC> ( theContent );
595 if( padSize > leftPadding ) target.template InsertChars<NC> ( field.padChar, padSize - leftPadding );
596}
597
598// #################################################################################################
599// TFormat::Escape()
600// #################################################################################################
601template<typename TChar, typename TAllocator>
602void T_Append<typename TFormat<TChar>::Escape, TChar,TAllocator>::operator()( TAString<TChar,TAllocator>& target,
603 const typename TFormat<TChar>::Escape& escape)
604{
605 if( target.AdjustRegion( const_cast<typename TFormat<TChar>::Escape&>(escape).startIdx,
606 const_cast<typename TFormat<TChar>::Escape&>(escape).length ) )
607 return;
608
609 integer regionEnd= escape.startIdx + escape.length;
610
611 //
612 // To escape sequences
613 //
614 if (escape.pSwitch == lang::Switch::On)
615 {
616 for( integer idx= escape.startIdx; idx < regionEnd ; ++idx )
617 {
618 TChar c= target.CharAt(idx);
619
620 TChar resultChar= '\0';
621 switch(c)
622 {
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;
631 // case '\e' : resultChar= 'e' ; break; Not C++ standard
632 case '"' : resultChar= '"' ; break;
633
634 default : break;
635 }
636
637 if( resultChar != '\0')
638 {
639 target.template InsertChars<NC>('\\', 1, idx);
640 target[++idx]= resultChar;
641 ++regionEnd;
642 }
643 }
644 }
645
646 //
647 // Un-escape escape sequences
648 //
649 else
650 {
651 --regionEnd; // we can go 1 over it!
652 for( integer idx= escape.startIdx; idx < regionEnd ; ++idx )
653 {
654 TChar c= target.CharAt(idx);
655 if( c != '\\' )
656 continue;
657
658 c= target.CharAt(idx + 1);
659
660 TChar resultChar= '\0';
661 switch(c)
662 {
663 case '\\' : resultChar= '\\'; break;
664 case 'r' : resultChar= '\r' ; break;
665 case 'n' : resultChar= '\n' ; break;
666 case 't' : resultChar= '\t' ; break;
667 case 'a' : resultChar= '\a' ; break;
668 case 'b' : resultChar= '\b' ; break;
669 case 'v' : resultChar= '\v' ; break;
670 case 'f' : resultChar= '\f' ; break;
671 // case 'e' : resultChar= '\e' ; break; Not C++ standard
672 case '"' : resultChar= '"' ; break;
673
674 default : break;
675 }
676
677 if( resultChar != '\0')
678 {
679 target.Delete( idx, 1);
680 target[idx]= resultChar;
681 --regionEnd;
682 }
683 }
684 }
685}
686
687// #################################################################################################
688// TFormat Integers
689// #################################################################################################
690template<typename TChar, typename TAllocator>
691void T_Append<TFormat<TChar>, TChar,TAllocator>::operator()( TAString<TChar,TAllocator>& target,
692 const TFormat<TChar>& fmt )
693{
694 const TNumberFormat<TChar>* nf= fmt.nf;
695 if( nf == nullptr )
697
698 target.EnsureRemainingCapacity( fmt.valueType== 3 ? 48 //float: 2x15 + '.' + ',' + sign + fear
699 : 28 //int: 20 digits, grouping symbol, sign and what have you
700 );
701
702 integer length= target.Length();
703
704 length=
705 fmt.valueType == 1 ? detail::WriteDecSigned ( fmt.v.value , target.VBuffer(), length, fmt.width , *nf ) :
706 fmt.valueType == 2 ? detail::WriteDecUnsigned( static_cast<uint64_t>(fmt.v.value) , target.VBuffer(), length, fmt.width , *nf ) :
707 detail::WriteFloat ( fmt.v.fpValue, target.VBuffer(), length, fmt.width , *nf );
708
709 target.SetLength( length );
710}
711
712
713
714template<typename TChar, typename TAllocator>
715void T_Append<typename TFormat<TChar>::Bin, TChar,TAllocator>::operator()( TAString<TChar,TAllocator>& target,
716 const typename TFormat<TChar>::Bin& fmt )
717{
718 TNumberFormat<TChar>* nf= fmt.nf;
719 if( nf == nullptr )
721
722 target.EnsureRemainingCapacity( 80 );
723
724 integer length= target.Length();
725
726 length= detail::WriteBin( fmt.theValue, target.VBuffer(), length, fmt.theWidth, *nf );
727
728 target.SetLength( length );
729}
730
731template<typename TChar, typename TAllocator>
732void T_Append<typename TFormat<TChar>::Hex, TChar,TAllocator>::operator()( TAString<TChar,TAllocator>& target,
733 const typename TFormat<TChar>::Hex& fmt )
734{
735 TNumberFormat<TChar>* nf= fmt.nf;
736 if( nf == nullptr )
738
739 target.EnsureRemainingCapacity( 25 );
740
741 integer length= target.Length();
742
743 length= detail::WriteHex( fmt.theValue, target.VBuffer(), length, fmt.theWidth, *nf );
744
745 target.SetLength( length );
746}
747
748template<typename TChar, typename TAllocator>
749void T_Append<typename TFormat<TChar>::Oct, TChar,TAllocator>::operator()( TAString<TChar,TAllocator>& target,
750 const typename TFormat<TChar>::Oct& fmt )
751{
752 TNumberFormat<TChar>* nf= fmt.nf;
753 if( nf == nullptr )
755
756 target.EnsureRemainingCapacity( 30 );
757
758 integer length= target.Length();
759
760 length= detail::WriteOct( fmt.theValue, target.VBuffer(), length, fmt.theWidth, *nf );
761
762 target.SetLength( length );
763}
765template<typename TChar, typename TAllocator>
766void T_Append<typename TFormat<TChar>::Fill, TChar,TAllocator>::operator()( TAString<TChar,TAllocator>& target,
767 const typename TFormat<TChar>::Fill& fmt )
768{
769 if (fmt.count <= 0)
770 return;
771 target.EnsureRemainingCapacity( fmt.count );
772 characters::Fill( target.VBuffer(), fmt.count, fmt.fillChar );
773 target.SetLength( target.Length() + fmt.count );
774}
775
776// #################################################################################################
777// ALIB_DEBUG: std::type_info, lang::CallerInfo
778// #################################################################################################
779#if ALIB_DEBUG
780template<typename TChar, typename TAllocator>
782 const std::type_info& type )
783{
784 NString2K buf;
785 lang::DbgTypeDemangler( type ).GetShort(buf);
786 target << buf;
787}
788#endif
789
790template<typename TChar, typename TAllocator>
791void T_Append<std::thread::id, TChar,TAllocator>::operator()( TAString<TChar,TAllocator>& target,
792 const std::thread::id& threadID )
793{
794 #if ALIB_EXT_LIB_THREADS_AVAILABLE
795 size_t nativeIDWidth;
796 uint64_t nativeID;
797 if constexpr ( sizeof(std::thread::id) == sizeof(uint16_t) ) { nativeID= *reinterpret_cast<const uint16_t*>(&threadID); nativeIDWidth= 4; }
798 else if constexpr ( sizeof(std::thread::id) == sizeof(uint32_t) ) { nativeID= *reinterpret_cast<const uint32_t*>(&threadID); nativeIDWidth= 8; }
799 else { nativeID= *reinterpret_cast<const uint64_t*>(&threadID); nativeIDWidth=16; }
800 if (lang::IsNotNull(threadID) )
801 #if ALIB_THREADS
802 {
803 integer length= target.Length();
804 Thread* thread= Thread::Get(threadID);
805 target << thread->GetName()
806 << '(' << thread->GetID()
807 << ",0x" << typename TFormat<TChar>::Hex(nativeID, int(nativeIDWidth)) <<')';
808 target.InsertChars( ' ', 30 + length - target.Length() );
809 }
810 #else
811 target << "TID=0x" << typename TFormat<TChar>::Hex(nativeID, int(nativeIDWidth) );
812 #endif
813 else
814 target << "<NULL>";
815
816 #endif
817}
818
819template<typename TChar, typename TAllocator>
820void T_Append<lang::CallerInfo, TChar,TAllocator>::operator()( TAString<TChar,TAllocator>& target,
821 const lang::CallerInfo& ci )
822{
823 NString2K nbuf;
824 nbuf << "[@ ";
825 if (ci.File) nbuf << ci.File << ':' << ci.Line;
826 else nbuf << "<NULL>";
827 #if ALIB_DEBUG
828 nbuf << " from '";
829 if (ci.TypeInfo) lang::DbgTypeDemangler(*ci.TypeInfo).GetShort(nbuf) << "::";
830 if(ci.Func) nbuf << ci.Func << "()";
831 else nbuf << "<NULL>";
832 nbuf << '\'';
833 #endif
834 #if ALIB_EXT_LIB_THREADS_AVAILABLE
835 nbuf << " by '"<< ci.ThreadID << '\'';
836 #endif
837 nbuf << ']';
838
839 target << nbuf;
840}
841
842}} // namespace [alib::strings]
843
ALIB_API NAString & GetShort(NAString &target)
ALIB_API integer SearchAndReplace(TChar needle, TChar replacement, integer startIdx=0, integer endIdx=strings::MAX_LEN)
ALIB_API void GrowBufferAtLeastBy(integer minimumGrowth)
ALIB_API integer TrimAt(integer idx, const TCString< TChar > &trimChars=TT_CStringConstants< TChar >::DefaultWhitespaces())
ALIB_API TAString & Trim(const TCString< TChar > &trimChars=TT_CStringConstants< TChar >::DefaultWhitespaces())
void EnsureRemainingCapacity(integer spaceNeeded)
Definition tastring.inl:742
TChar * VBuffer() const
Definition tastring.inl:843
ALIB_API void SetBuffer(integer newCapacity)
void SetLength(integer newLength)
Definition tastring.inl:924
constexpr bool IsEmpty() const
Definition string.hpp:383
constexpr integer Length() const
Definition string.hpp:326
constexpr const TChar * Buffer() const
Definition string.hpp:319
static ALIB_API Thread * Get(std::thread::id nativeID)
Definition thread.cpp:321
#define ALIB_WARNING(...)
Definition alib.hpp:1268
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:849
#define ALIB_ERROR(...)
Definition alib.hpp:1267
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:1271
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:760
#define ALIB_ASSERT_WARNING(cond,...)
Definition alib.hpp:1272
#define ALIB_STRING_DBG_CHK(instance)
#define ALIB_ASSERT(cond)
Definition alib.hpp:1270
#define ALIB_DEBUG_STRINGS
Definition prepro.md:42
void Move(const TChar *src, integer length, TChar *dest)
void Copy(const TChar *src, integer length, TChar *dest)
void Fill(TChar *dest, integer length, TChar value)
constexpr bool IsNotNull(const T &t)
Definition alib.hpp:1054
@ On
Switch it on, switched on, etc.
Case
Denotes upper and lower case character treatment.
@ Transfer
Transfers responsibility to the receiving party.
@ Right
Chooses right alignment.
@ Left
Chooses left alignment.
ALIB_API integer WriteFloat(double value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
ALIB_API integer WriteDecUnsigned(uint64_t value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
ALIB_API integer WriteOct(uint64_t value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
ALIB_API integer WriteDecSigned(int64_t value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
ALIB_API integer WriteHex(uint64_t value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
ALIB_API integer WriteBin(uint64_t value, TChar *buffer, integer idx, int minWidth, const TNumberFormat< TChar > &nf)
Definition alib.cpp:69
threads::Thread Thread
Type alias in namespace alib.
Definition thread.hpp:379
NLocalString< 2048 > NString2K
Type alias name for TLocalString<nchar,2048>.
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:273
static TNumberFormat Computational
static constexpr CString< TChar > NewLine
Definition cstring.hpp:505
void operator()(TAString< TChar > &target, const TAppendable &src)