ALib C++ Framework
by
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
formatter.cpp
1//##################################################################################################
2// ALib C++ Framework
3//
4// Copyright 2013-2025 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6//##################################################################################################
7#include "alib_precompile.hpp"
8#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
9# error "Configuration MACRO ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
10#endif
11#if ALIB_C20_MODULES
12 module;
13#endif
14//========================================= Global Fragment ========================================
15#include <cmath>
17//============================================== Module ============================================
18#if ALIB_C20_MODULES
19 module ALib.Format;
20 import ALib.Lang;
21 import ALib.Strings;
22 import ALib.Boxing;
23#else
24# include "ALib.Lang.H"
25# include "ALib.Strings.H"
26# include "ALib.Boxing.H"
27# include "ALib.Format.H"
28#endif
29//========================================== Implementation ========================================
31
32using namespace alib::strings;
33
34/// This is the reference documentation module \alib_format.<br>
35/// Extensive documentation for this namespace is provided with the
36/// #"alib_mod_format;Programmer's Manual" of that module.
37namespace alib::format {
38
40#if !ALIB_SINGLE_THREADED
41 threads::RecursiveLock Formatter::DEFAULT_LOCK;
42#endif
43
44
45
46#if !DOXYGEN
47
48template<>
51
52 // initialize formatters
53 Formatter* formatter= this;
54 do
55 formatter->initializeFormat();
56 while( (formatter= formatter->Next.Get()) != nullptr );
57
58 // loop over boxes
59 integer argIdx= 0;
60 while ( argIdx < args.Size() - 1 ) {
61 String formatString;
62 const Box& actual= args[size_t(argIdx++)];
63 if( actual.IsType<void>() )
64 continue;
65
66 // Either this is a string, or we convert the box to a string. This fetches anything
67 // that is string like, including string-types that are encapsulated in BoxedAs, etc.
68 if( actual.IsArrayOf<character>() )
69 formatString= actual.Unbox<String>();
70 else
71 formatString= formatStringBuffer.Reset( actual );
72
73 if( formatString.IsEmpty() )
74 continue;
75
76 // try each formatter unless one succeeds
77 integer qtyConsume= 0;
78 formatter= this;
79 while( ( qtyConsume= formatter->format( target, formatString, args, int(argIdx ) ) )
80 == 0
81 && (formatter= formatter->Next.Get()) != nullptr )
82 {}
83
84 // no formatter reacted?
85 if( qtyConsume == 0 )
86 // we append the unescaped string...
87 Formatter::writeStringPortion(target, formatString);
88 else
89 // ...otherwise arguments were consumed
90 argIdx+= size_t( qtyConsume );
91 }
92
93 // the last argument was not consumed?
94 if ( argIdx==args.Size() - 1 && !args.back().template IsType<void>() ){
96 lastArg._(args.back());
97 Formatter::writeStringPortion(target, lastArg);
98 }
99 return *this;
100}
101#endif // !DOXYGEN
102
103
104
106 DefaultNumberFormat .Set( &reference.DefaultNumberFormat );
108
109 // if both sub-formatters are of std type, we do the same for them.
110 if( Next && reference.Next )
111 Next->CloneSettings( *reference.Next );
112}
113
114#if !DOXYGEN
115template<>
117 boxes.clear();
118 boxes.Add( args );
119 formatLoop( target, boxes );
120 return *this;
121}
122
123template<>
125 boxes.clear();
126 boxes.Add( args );
127 formatLoop( target, boxes );
128 return *this;
129}
130#endif // !DOXYGEN
131
132void Formatter::writeStringPortion( AString& target, const String& escaped ) {
133 integer length= escaped.Length();
134 if( length == 0)
135 return;
136
137 target.EnsureRemainingCapacity( length );
138 auto* src = escaped.Buffer();
139 auto* dest= target.VBuffer() + target.Length();
140
141 character c1;
142 character c2= *src;
143 while( length > 1 ) {
144 c1= c2;
145 c2= *++src;
146 if( c1 == '\\' ) { switch(c2) {
147 case 'r': c1= '\r' ; break;
148 case 'n': c1= '\n' ; break;
149 case 't': c1= '\t' ; break;
150 case 'a': c1= '\a' ; break;
151 case 'b': c1= '\b' ; break;
152 case 'v': c1= '\v' ; break;
153 case 'f': c1= '\f' ; break;
154 case '"': c1= '"' ; break;
155 case '\\': c1= '\\' ; break;
156 default: c1= '?' ; break;
157 }
158 c2= *++src; --length;
159 }
160 *dest++= c1; --length;
161 }
162
163 // copy the last character and adjust target string length:
164 // Note: length usually is 1. Only if last character is an escape sequence, it is 0.
165 if( length == 1)
166 *dest= *src;
167
168 target.SetLength( dest - target.VBuffer() + length);
169}
170
171} // namespace [alib::format]
#define ALIB_DCS
Definition alib.inl:1466
#define ALIB_DBG_PREVENT_RECURSIVE_METHOD_CALLS
Definition alib.inl:1440
#define ALIB_BOXING_VTABLE_DEFINE(TMapped, Identifier)
bool IsArrayOf() const
Definition box.inl:562
bool IsType() const
TBoxes & Add()
Definition boxes.inl:55
integer Size() const
Definition boxes.inl:126
static threads::RecursiveLock DEFAULT_LOCK
NumberFormat DefaultNumberFormat
static SPFormatter DEFAULT
virtual void CloneSettings(Formatter &reference)
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.inl:77
TAString & _(const TAppendable &src)
TChar * VBuffer() const
Definition tastring.inl:637
void EnsureRemainingCapacity(integer spaceNeeded)
Definition tastring.inl:561
void DbgDisableBufferReplacementWarning()
Definition tastring.inl:241
void SetLength(integer newLength)
Definition tastring.inl:699
constexpr integer Length() const
Definition string.inl:304
constexpr bool IsEmpty() const
Definition string.inl:353
constexpr const TChar * Buffer() const
Definition string.inl:299
format::Formatter Formatter
Type alias in namespace alib.
containers::SharedPtr< format::Formatter > SPFormatter
Definition formatter.inl:42
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
boxing::Box Box
Type alias in namespace alib.
Definition box.inl:1135
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2172
boxing::TBoxes< MonoAllocator > BoxesMA
Type alias in namespace alib.
Definition boxes.inl:193
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.