ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
formatter.cpp
2
3using namespace alib::strings;
4
5/// This is the reference documentation module \alib_format.<br>
6/// Extensive documentation for this namespace is provided with the
7/// #"alib_mod_format;Programmer's Manual" of that module.
8namespace alib::format {
9
11#if !ALIB_SINGLE_THREADED
12 threads::RecursiveLock Formatter::DEFAULT_LOCK;
13#endif
14
15
16
17#if !DOXYGEN
18
19template<>
22
23 // initialize formatters
24 Formatter* formatter= this;
25 do
26 formatter->initializeFormat();
27 while( (formatter= formatter->Next.Get()) != nullptr );
28
29 // loop over boxes
30 integer argIdx= 0;
31 while ( argIdx < args.Size() - 1 ) {
32 String formatString;
33 const Box& actual= args[size_t(argIdx++)];
34 if( actual.IsType<void>() )
35 continue;
36
37 // Either this is a string, or we convert the box to a string. This fetches anything
38 // that is string like, including string-types that are encapsulated in BoxedAs, etc.
39 if( actual.IsArrayOf<character>() )
40 formatString= actual.Unbox<String>();
41 else
42 formatString= formatStringBuffer.Reset( actual );
43
44 if( formatString.IsEmpty() )
45 continue;
46
47 // try each formatter unless one succeeds
48 integer qtyConsume= 0;
49 formatter= this;
50 while( ( qtyConsume= formatter->format( target, formatString, args, int(argIdx ) ) )
51 == 0
52 && (formatter= formatter->Next.Get()) != nullptr )
53 {}
54
55 // no formatter reacted?
56 if( qtyConsume == 0 )
57 // we append the unescaped string...
58 Formatter::writeStringPortion(target, formatString);
59 else
60 // ...otherwise arguments were consumed
61 argIdx+= size_t( qtyConsume );
62 }
63
64 // the last argument was not consumed?
65 if ( argIdx==args.Size() - 1 && !args.back().template IsType<void>() ){
67 lastArg._(args.back());
68 Formatter::writeStringPortion(target, lastArg);
69 }
70 return *this;
71}
72#endif // !DOXYGEN
73
74
75
79
80 // if both sub-formatters are of std type, we do the same for them.
81 if( Next && reference.Next )
82 Next->CloneSettings( *reference.Next );
83}
84
85#if !DOXYGEN
86template<>
88 boxes.clear();
89 boxes.Add( args );
90 formatLoop( target, boxes );
91 return *this;
92}
93
94template<>
96 boxes.clear();
97 boxes.Add( args );
98 formatLoop( target, boxes );
99 return *this;
100}
101#endif // !DOXYGEN
102
103void Formatter::writeStringPortion( AString& target, const String& escaped ) {
104 integer length= escaped.Length();
105 if( length == 0)
106 return;
107
108 target.EnsureRemainingCapacity( length );
109 auto* src = escaped.Buffer();
110 auto* dest= target.VBuffer() + target.Length();
111
112 character c1;
113 character c2= *src;
114 while( length > 1 ) {
115 c1= c2;
116 c2= *++src;
117 if( c1 == '\\' ) { switch(c2) {
118 case 'r': c1= '\r' ; break;
119 case 'n': c1= '\n' ; break;
120 case 't': c1= '\t' ; break;
121 case 'a': c1= '\a' ; break;
122 case 'b': c1= '\b' ; break;
123 case 'v': c1= '\v' ; break;
124 case 'f': c1= '\f' ; break;
125 case '"': c1= '"' ; break;
126 case '\\': c1= '\\' ; break;
127 default: c1= '?' ; break;
128 }
129 c2= *++src; --length;
130 }
131 *dest++= c1; --length;
132 }
133
134 // copy the last character and adjust target string length:
135 // Note: length usually is 1. Only if last character is an escape sequence, it is 0.
136 if( length == 1)
137 *dest= *src;
138
139 target.SetLength( dest - target.VBuffer() + length);
140}
141
142} // namespace [alib::format]
#define ALIB_DCS
#define ALIB_DBG_PREVENT_RECURSIVE_METHOD_CALLS
#define ALIB_BOXING_VTABLE_DEFINE(TMapped, Identifier)
bool IsArrayOf() const
Definition box.hpp:555
bool IsType() const
TBoxes & Add()
Definition boxes.hpp:54
integer Size() const
Definition boxes.hpp:125
static threads::RecursiveLock DEFAULT_LOCK
NumberFormat DefaultNumberFormat
static SPFormatter DEFAULT
virtual void CloneSettings(Formatter &reference)
Definition formatter.cpp:76
NumberFormat AlternativeNumberFormat
static void writeStringPortion(AString &target, const String &escaped)
Formatter & formatLoop(AString &target, const boxing::TBoxes< TAllocator > &args)
SharedPtr< Formatter > Next
Formatter()
Default Constructor.
AString formatStringBuffer
A buffer used for conversion of the next argument if it is not of a string-type.
Definition formatter.hpp:76
TAString & _(const TAppendable &src)
TChar * VBuffer() const
Definition tastring.hpp:631
void EnsureRemainingCapacity(integer spaceNeeded)
Definition tastring.hpp:555
void DbgDisableBufferReplacementWarning()
Definition tastring.hpp:236
void SetLength(integer newLength)
Definition tastring.hpp:693
constexpr integer Length() const
Definition string.hpp:300
constexpr bool IsEmpty() const
Definition string.hpp:349
constexpr const TChar * Buffer() const
Definition string.hpp:295
format::Formatter Formatter
Type alias in namespace #"%alib".
containers::SharedPtr< format::Formatter > SPFormatter
Definition formatter.hpp:41
lang::integer integer
Type alias in namespace #"%alib".
Definition integers.hpp:149
boxing::Box Box
Type alias in namespace #"%alib".
Definition box.hpp:1128
strings::TString< character > String
Type alias in namespace #"%alib".
Definition string.hpp:2165
boxing::TBoxes< MonoAllocator > BoxesMA
Type alias in namespace #"%alib".
Definition boxes.hpp:192
LocalString< 256 > String256
Type alias name for #"TLocalString;TLocalString<character,256>".
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace #"%alib".
characters::character character
Type alias in namespace #"%alib".