ALib C++ Framework
by
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
formatter.inl
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_format of the \aliblong.
4///
5/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
6/// Published under #"mainpage_license".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace format {
9
10//==================================================================================================
11/// This struct declares the signature of the #"alib_boxing_functions;box-function"
12/// \b FFormat. It can be implemented to write the contents of a boxed type the given
13/// \b %AString instance, in accordance with a custom format specification.
14///
15/// \see
16/// For more information about this class see chapter
17/// #"alib_format_custom_types" of the Programmer's Manual of module \alib_format_nl.
18//==================================================================================================
19struct FFormat
20{
21 /// Signature of the invokable function.<br>
22 /// Implementations write the content of \p{box} to the given \b %AString object \p{target} in
23 /// accordance to the type-specific format specification \p{formatSpec}.
24 ///
25 /// @param self The box that the function was invoked on.
26 /// @param formatSpec The specification of the format (type specific). If empty, a default
27 /// specification string might have to be chosen.
28 /// @param nf A copy of the number format of the formatter (allowed to be modified).
29 /// @param target The AString object receiving the formatted string.
30 using Signature = void (*) ( const Box& self, const String& formatSpec, NumberFormat& nf,
31 AString& target );
32};
33
34
35// forward declaration
36class Formatter;
37
38} // namespace alib[::format]
39
40/// A shared pointer to instances of #"format::Formatter;standard formatters".
41/// \see Static member #"Formatter::DEFAULT;*".
43
44namespace format {
45
46//==================================================================================================
47/// This is an abstract base class to implement an \alib string formatter. A string formatter
48/// uses a "format string" to transform arguments into formatted text. The format string defines
49/// how the arguments are transformed by offering a "placeholder syntax".
50///
51/// With this information, it becomes clear that different formatter types (derived types that offer
52/// a concrete placeholder syntax) all can have the same interface methods.
53/// This class defines this abstract interface.
54///
55/// Built-in formatters derived from this class, are
56/// #"FormatterPythonStyle" and
57/// #"FormatterJavaStyle".
58//==================================================================================================
62#endif
63{
64
65 //################################################################################################
66 // Internal fields
67 //################################################################################################
68 protected:
69 /// This allocator is (exclusively) used for field #"Formatter::boxes".
71
72 /// A list of boxes. This is reset with every new invocation of variadic template method
73 /// #".Format"
75
76 /// A buffer used for conversion of the next argument if it is not of a string-type.
78
80
81 //################################################################################################
82 // Protected methods
83 //################################################################################################
84 /// Virtual method which is invoked with each invocation of #".Format".
85 /// The default implementation does nothing.
86 virtual void initializeFormat() {}
87
88 /// The abstract format method that needs to be implemented by descendants.
89 /// Note that parameter \p{startIdx} and the demanded return value together comprise the
90 /// possibility to use more than one formatter in parallel and to perform multiple format
91 /// operations on suitable argument lists. This demands the implementation of this method to
92 /// \b not copy the format string to the \p{target} in the case that no 'escape sequence'
93 /// was found. For further information, see the general documentation of this class.
94 ///
95 /// @param target The %AString that takes the result.
96 /// @param formatString The format string.
97 /// @param args The objects to be used with formatters.
98 /// @param startArgument The first object in \p{args} to convert.
99 ///
100 /// @return The number of args consumed.
101 virtual int format( AString& target,
102 const String& formatString,
103 const BoxesMA& args,
104 int startArgument ) =0;
105
106 /// The format loop implementation. Searches format strings in \p{args} and tests
107 /// if \c this or #"Next" is capable of processing it.
108 ///
109 /// @param target An AString that takes the result.
110 /// @param args The objects to be used with formatters.
111 /// @return A reference to this formatter to allow concatenated operations.
112 template<typename TAllocator>
114
115 /// Writes the given string \p{escaped} to the target, converting escaped characters to their
116 /// native values.
117 /// @param target The target.
118 /// @param escaped The string to write.
119 static
120 void writeStringPortion( AString& target, const String& escaped );
121
122
123 //################################################################################################
124 // public fields
125 //################################################################################################
126 public:
127 /// Stores default attributes for formatting numbers.
128 /// Likewise #"AlternativeNumberFormat", it usually is not used directly for formatting by
129 /// descendants.
130 /// Instead, at the beginning of parsing a next placeholder field, values are copied to
131 /// a local copy. During the parsing process, values are then modified only in this local
132 /// copy, probably taken from #"AlternativeNumberFormat".
133 ///
134 /// This object is to be initialized in the constructor (of descendants) once to meet the
135 /// formatting defaults of the corresponding specification.
136 /// If after construction, attribute values of this object are changed, such changes are
137 /// applied to all number formatting.
139
140 /// This number format is used to store alternative attributes. Likewise #"DefaultNumberFormat",
141 /// it is never used directly for formatting.
142 /// Instead, when processing the placeholder syntax, alternatives get copied from either this
143 /// object or from #"DefaultNumberFormat".
144 ///
145 /// This object is initialized in the constructor (of descendants) once to meet the
146 /// formatting defaults of the corresponding specification.
147 ///
148 /// With the implementations of this class provided with \alib, not all fields in this object
149 /// are used. The fields used are:
150 /// <p>
151 /// - Locale-specific versions of floating point separators:
152 /// - #"TNumberFormat::DecimalPointChar;NumberFormat::DecimalPointChar"
153 /// - #"TNumberFormat::ThousandsGroupChar;NumberFormat::ThousandsGroupChar"
154 ///
155 /// These are retrieved according to the current locale once in the constructor. To
156 /// change the locale, these fields can be changed.
157 ///
158 /// - Lower case versions of floating point literals:
159 /// - #"TNumberFormat::ExponentSeparator;NumberFormat::ExponentSeparator"
160 /// - #"TNumberFormat::INFLiteral;NumberFormat::INFLiteral"
161 /// - #"TNumberFormat::NANLiteral;NumberFormat::NANLiteral"
162 ///
163 /// - Lower case versions of prefix literals that indicate the base of integral values:
164 /// - #"TNumberFormat::BinLiteralPrefix;BinLiteralPrefix"
165 /// - #"TNumberFormat::HexLiteralPrefix;HexLiteralPrefix"
166 /// - #"TNumberFormat::OctLiteralPrefix;OctLiteralPrefix"
168
169 /// An optional, next formatter. If set, this formatter will be invoked for a format string
170 /// that does not contain recognized placeholders.
171 /// \attention
172 /// This field is public and not further maintained by this class. Setting the field lies
173 /// completely in the responsibility of the user. E.g., cyclic settings must be avoided.
174 /// Also, object life-cycle management is completely up to the user.
176
177 //################################################################################################
178 // Constructor/destructor
179 //################################################################################################
180 public:
181 /// Default Constructor.
183 :
185 lang::DbgCriticalSections("Formatter")
186 ,
187 #endif
188 allocator(ALIB_DBG("Formatter",) 1)
189 , boxes( allocator ) {}
190
191 /// Destructs an object of this class.
192 /// Note that concatenated formatters are not deleted automatically.
193 virtual ~Formatter() {}
194
195 //################################################################################################
196 // Interface
197 //################################################################################################
198
199 /// Variadic template method that accepts a target \b %AString and a list of arguments.
200 /// This is a convenience method to allow single-line format invocations.
201 ///
202 /// \note
203 /// This method uses <c>static_assert</c> to disallow the invocation with one
204 /// variadic argument of type #"TBoxes" or a derived type.
205 /// This is to ensure that for these box containers, the more efficient method
206 /// #".FormatArgs(AString&, const boxing::TBoxes<TAllocator>&)" is used.
207 ///
208 /// @tparam TArgs Variadic template type list.
209 /// @param target An AString that takes the result.
210 /// @param args The variadic list of arguments to be used with formatters.
211 /// @return A reference to this formatter to allow concatenated operations.
212 template <typename... TArgs>
213 Formatter& Format( AString& target, TArgs&&... args ) {
214 // assert that this method is not used with Boxes containers.
215 // Those are to be processed with FormatArgs
216 constexpr bool Argument_has_type_Boxes=
217 (sizeof...(TArgs) == 1)
218 && ( std::is_base_of_v< Boxes , std::decay< std::tuple_element<0, std::tuple<TArgs...>>>>
219 || std::is_base_of_v< BoxesMA, std::decay< std::tuple_element<0, std::tuple<TArgs...>>>>
220 || std::is_base_of_v< BoxesPA, std::decay< std::tuple_element<0, std::tuple<TArgs...>>>> );
221 static_assert( !Argument_has_type_Boxes,
222 "To pass a container of type Boxes to a formatter, use method FormatArgs." );
223
224 // create argument objects using implicit constructor invocation
225 boxes.clear();
226 boxes.Add( std::forward<TArgs>( args )... );
227
228 // invoke format
229 formatLoop( target, boxes );
230 return *this;
231 }
232
233 /// Formats the internal list of arguments that is returned by methods #"GetArgContainer"
234 /// and #".Reset".
235 ///
236 /// This method may be more efficient than using inlined variadic method \b Format
237 /// and should be preferred if:
238 /// - Format arguments cannot be collected in a single invocation, for example, if those
239 /// are to be collected in a loop.
240 /// - A sequence of different format operations is to be performed.
241 ///
242 /// @param target An AString that takes the result.
243 /// @return A reference to this formatter to allow concatenated operations.
244 inline
245 Formatter& FormatArgs( AString& target ); // implementation below
246
247
248 /// Same as Format(AString&) but allows specifying an external list of arguments instead of
249 /// the internally allocated object, which is returned by methods #"GetArgContainer"
250 /// and #".Reset".
251 ///
252 /// @param args The arguments to be used with formatters.
253 /// @param target An AString that takes the result.
254 /// @return A reference to this formatter to allow concatenated operations.
255 template<typename TAllocator>
257 {
259 return formatLoop( target, args );
260 }
261
262
263 /// Clones and returns a copy of this formatter.
264 ///
265 /// If a formatter is attached to field #"Formatter::Next;*", it is
266 /// cloned as well (recursively).
267 ///
268 /// @returns An object of the same (derived) type and the same custom settings.
269 virtual SPFormatter Clone() =0;
270
271 /// Clones the settings from the given formatter.
272 /// @param reference The formatter to copy settings from.
274 virtual void CloneSettings( Formatter& reference );
275
276 /// Virtual method used to reset internal states.
277 ///
278 /// It is formatter-depended, which state information is reset. As a sample, derived type
279 /// #"FormatterPythonStyle" clears its auto-tab
280 /// and auto-width positions.
281 ///
282 /// The default implementation does nothing.
283 /// @return An internally allocated container of boxes that may be used to collect
284 /// formatter arguments.
285 virtual BoxesMA& Reset() { ALIB_DCS boxes.clear(); return boxes; }
286
287 /// Returns an empty vector of arguments, which can be passed to the format interface.<br>
288 /// Note: This is nothing more than a recycling strategy.
289 /// @return An internally allocated container of boxes that may be used to collect
290 /// formatter arguments.
291 virtual BoxesMA& GetArgContainer() { ALIB_DCS boxes.clear(); return boxes; }
292
293
294 //################################################################################################
295 // Static Interface (default formatter)
296 //################################################################################################
297 /// A publicly accessible static singleton instance which is can be freely used.
298 /// Racing conditions in multithreaded applications have to be avoided by locking mutex
299 /// #DEFAULT_LOCK.
302
303 #if !ALIB_SINGLE_THREADED
304 /// The lock to be set with multithreaded use of #DEFAULT.
305 /// If the configuration macro #"ALIB_DEBUG_CRITICAL_SECTIONS" is set, this lock will be
306 /// attached to the instance of type #"lang::DbgCriticalSections" in #DEFAULT during
307 /// bootstrap.
308 /// Thus, an assertion will be raised if #DEFAULT is used without locking this.
309 ///
310 /// \par Availability
311 /// This object is available only if symbol #"ALIB_SINGLE_THREADED" is not set.
312 ///
313 /// @see Chapter #"alib_threads_intro_assert_locks" of the Programmer's Manual of
314 /// module \alib_threads.
317 #endif
318};
319
320#if !DOXYGEN
324#endif // !DOXYGEN
325
326
327inline
329{
331 return formatLoop( target, boxes );
332}
333
334} // namespace alib[::format]
335
336//##################################################################################################
337// Alias types in namespace #alib.
338//##################################################################################################
339/// Type alias in namespace \b alib.
341
342} // namespace [alib]
#define ALIB_DLL
Definition alib.inl:573
#define ALIB_DCS
Definition alib.inl:1466
#define ALIB_DEBUG_CRITICAL_SECTIONS
Definition alib.inl:58
#define ALIB_EXPORT
Definition alib.inl:562
#define ALIB_DBG(...)
Definition alib.inl:931
#define ALIB_DBG_PREVENT_RECURSIVE_METHOD_CALLS_MEMBER_DECL
Definition alib.inl:1437
static threads::RecursiveLock DEFAULT_LOCK
NumberFormat DefaultNumberFormat
Formatter & FormatArgs(AString &target)
Formatter & Format(AString &target, TArgs &&... args)
static SPFormatter DEFAULT
MonoAllocator allocator
This allocator is (exclusively) used for field #"Formatter::boxes".
Definition formatter.inl:70
virtual void CloneSettings(Formatter &reference)
virtual SPFormatter Clone()=0
NumberFormat AlternativeNumberFormat
static void writeStringPortion(AString &target, const String &escaped)
Formatter & formatLoop(AString &target, const boxing::TBoxes< TAllocator > &args)
virtual ALIB_DBG_PREVENT_RECURSIVE_METHOD_CALLS_MEMBER_DECL void initializeFormat()
Definition formatter.inl:86
SharedPtr< Formatter > Next
virtual BoxesMA & GetArgContainer()
virtual int format(AString &target, const String &formatString, const BoxesMA &args, int startArgument)=0
virtual BoxesMA & Reset()
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
Formatter & FormatArgs(AString &target, const boxing::TBoxes< TAllocator > &args)
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
strings::TNumberFormat< character > NumberFormat
Type alias in namespace alib.
format::Formatter Formatter
Type alias in namespace alib.
containers::SharedPtr< format::Formatter > SPFormatter
Definition formatter.inl:42
boxing::TBoxes< lang::HeapAllocator > Boxes
Type alias in namespace alib.
Definition boxes.inl:189
containers::SharedPtr< T, TAllocator > SharedPtr
Type alias in namespace alib.
boxing::Box Box
Type alias in namespace alib.
Definition box.inl:1135
boxing::TBoxes< PoolAllocator > BoxesPA
Type alias in namespace alib.
Definition boxes.inl:196
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
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
void(*)(const Box &self, const String &formatSpec, NumberFormat &nf, AString &target) Signature
Definition formatter.inl:30