ALib C++ Library
Library Version: 2510 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 \ref mainpage_license "Boost Software License".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace format {
9
10//==============================================================================================
11/// This struct declares the signature of the \ref 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/// \ref 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 \alib{format;Formatter;standard formatters}.
41/// \see Static member \alib{format;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/// \alib{format;FormatterPythonStyle;FormatterPythonStyle} and
57/// \alib{format;FormatterJavaStyle;FormatterJavaStyle}.
58//==================================================================================================
62#endif
63{
64
65 // #############################################################################################
66 // Internal fields
67 // #############################################################################################
68 protected:
69 /// This allocator is (exclusively) used for field #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 // public fields
83 // #############################################################################################
84 public:
85 /// Stores default attributes for formatting numbers.
86 /// Likewise #AlternativeNumberFormat, it usually is not used directly for formatting by
87 /// descendants.
88 /// Instead, at the beginning of parsing a next placeholder field, values are copied to
89 /// a local copy. During the parsing process, values are then modified only in this local
90 /// copy, probably taken from #AlternativeNumberFormat.
91 ///
92 /// This object is to be initialized in the constructor (of descendants) once to meet the
93 /// formatting defaults of the corresponding specification.
94 /// If after construction, attribute values of this object are changed, such changes are
95 /// applied to all number formatting.
97
98 /// This number format is used to store alternative attributes. Likewise #DefaultNumberFormat,
99 /// it is never used directly for formatting.
100 /// Instead, when processing the placeholder syntax, alternatives get copied from either this
101 /// object or from #DefaultNumberFormat.
102 ///
103 /// This object is initialized in the constructor (of descendants) once to meet the
104 /// formatting defaults of the corresponding specification.
105 ///
106 /// With the implementations of this class provided with \alib, not all fields in this object
107 /// are used. The fields used are:
108 /// <p>
109 /// - Locale-specific versions of floating point separators:
110 /// - \alib{strings;TNumberFormat::DecimalPointChar;NumberFormat::DecimalPointChar}
111 /// - \alib{strings;TNumberFormat::ThousandsGroupChar;NumberFormat::ThousandsGroupChar}
112 ///
113 /// These are retrieved according to the current locale once in the constructor. To
114 /// change the locale, these fields can be changed.
115 ///
116 /// - Lower case versions of floating point literals:
117 /// - \alib{strings;TNumberFormat::ExponentSeparator;NumberFormat::ExponentSeparator}
118 /// - \alib{strings;TNumberFormat::INFLiteral;NumberFormat::INFLiteral}
119 /// - \alib{strings;TNumberFormat::NANLiteral;NumberFormat::NANLiteral}
120 ///
121 /// - Lower case versions of prefix literals that indicate the base of integral values:
122 /// - \alib{strings;TNumberFormat::BinLiteralPrefix;BinLiteralPrefix}
123 /// - \alib{strings;TNumberFormat::HexLiteralPrefix;HexLiteralPrefix}
124 /// - \alib{strings;TNumberFormat::OctLiteralPrefix;OctLiteralPrefix}
126
127 /// An optional, next formatter. If set, this formatter will be invoked for a format string
128 /// that does not contain recognized placeholders.
129 /// \attention
130 /// This field is public and not further maintained by this class. Setting the field lies
131 /// completely in the responsibility of the user. E.g., cyclic settings must be avoided.
132 /// Also, object life-cycle management is completely up to the user.
134
135 // #############################################################################################
136 // Constructor/destructor
137 // #############################################################################################
138 public:
139 /// Default Constructor.
141 :
143 lang::DbgCriticalSections("Formatter")
144 ,
145 #endif
146 allocator(ALIB_DBG("Formatter",) 1)
147 , boxes( allocator )
148 {}
149
150 //==========================================================================================
151 /// Destructs an object of this class.
152 /// Note that concatenated formatters are not deleted automatically.
153 //==========================================================================================
154 virtual ~Formatter()
155 {}
156
157 // #############################################################################################
158 // Interface
159 // #############################################################################################
160
161 //==========================================================================================
162 /// Variadic template method that accepts a target \b %AString and a list of arguments.
163 /// This is a convenience method to allow single-line format invocations.
164 ///
165 /// \note
166 /// This method uses <c>static_assert</c> to disallow the invocation with one
167 /// variadic argument of type \alib{boxing;TBoxes} or a derived type.
168 /// This is to ensure that for these box containers, the more efficient method #FormatArgs
169 /// is used.
170 ///
171 /// @tparam TArgs Variadic template type list.
172 /// @param target An AString that takes the result.
173 /// @param args The variadic list of arguments to be used with formatters.
174 /// @return A reference to this formatter to allow concatenated operations.
175 //==========================================================================================
176 template <typename... TArgs>
177 Formatter& Format( AString& target, TArgs&&... args )
178 {
179 // assert that this method is not used with Boxes containers.
180 // Those are to be processed with FormatArgs
181 constexpr bool Argument_has_type_Boxes=
182 (sizeof...(TArgs) == 1)
183 && ( std::is_base_of_v< BoxesHA, std::decay< std::tuple_element<0, std::tuple<TArgs...>>>>
184 || std::is_base_of_v< BoxesMA, std::decay< std::tuple_element<0, std::tuple<TArgs...>>>>
185 || std::is_base_of_v< BoxesPA, std::decay< std::tuple_element<0, std::tuple<TArgs...>>>> );
186 static_assert( !Argument_has_type_Boxes,
187 "To pass a container of type Boxes to a formatter, use method FormatArgs." );
188
189 // create argument objects using implicit constructor invocation
190 boxes.clear();
191 boxes.Add( std::forward<TArgs>( args )... );
192
193 // invoke format
194 formatLoop( target, boxes );
195 return *this;
196 }
197
198 //==========================================================================================
199 /// Formats the internal list of arguments that is returned by methods #GetArgContainer
200 /// and #Reset.
201 ///
202 /// This method may be more efficient than using inlined variadic method \b Format
203 /// and should be preferred if:
204 /// - Format arguments cannot be collected in a single invocation, for example, if those
205 /// are to be collected in a loop.
206 /// - A sequence of different format operations is to be performed.
207 ///
208 /// @param target An AString that takes the result.
209 /// @return A reference to this formatter to allow concatenated operations.
210 //==========================================================================================
211 inline
212 Formatter& FormatArgs( AString& target ); // implementation below
213
214
215 //==========================================================================================
216 /// Same as Format(AString&) but allows specifying an external list of arguments instead of
217 /// the internally allocated object, which is returned by methods #GetArgContainer
218 /// and #Reset.
219 ///
220 /// @param args The arguments to be used with formatters.
221 /// @param target An AString that takes the result.
222 /// @return A reference to this formatter to allow concatenated operations.
223 //==========================================================================================
224 template<typename TAllocator>
226 {
228 return formatLoop( target, args );
229 }
230
231
232 //==========================================================================================
233 /// Clones and returns a copy of this formatter.
234 ///
235 /// If a formatter is attached to field \alib{format;Formatter::Next}, it is
236 /// cloned as well (recursively).
237 ///
238 /// @returns An object of the same (derived) type and the same custom settings.
239 //==========================================================================================
240 virtual SPFormatter Clone() = 0;
241
242 //==========================================================================================
243 /// Clones the settings from the given formatter.
244 /// @param reference The formatter to copy settings from.
245 //==========================================================================================
247 virtual void CloneSettings( Formatter& reference );
248
249 //==========================================================================================
250 /// Virtual method used to reset internal states.
251 ///
252 /// It is formatter-depended, which state information is reset. As a sample, derived type
253 /// \alib{format;FormatterPythonStyle;FormatterPythonStyle} clears its auto-tab
254 /// and auto-width positions.
255 ///
256 /// The default implementation does nothing.
257 /// @return An internally allocated container of boxes that may be used to collect
258 /// formatter arguments.
259 //==========================================================================================
260 virtual BoxesMA& Reset() {ALIB_DCS boxes.clear(); return boxes; }
261
262 //==========================================================================================
263 /// Returns an empty vector of arguments, which can be passed to the format interface.<br>
264 /// Note: This is nothing more than a recycling strategy.
265 /// @return An internally allocated container of boxes that may be used to collect
266 /// formatter arguments.
267 //==========================================================================================
268 virtual BoxesMA& GetArgContainer() {ALIB_DCS boxes.clear(); return boxes; }
269
270
271 // #############################################################################################
272 // Static Interface methods (default formatter)
273 // #############################################################################################
274 /// A publicly accessible static singleton instance which is can be freely used.
275 /// Racing conditions in multithreaded applications have to be avoided by locking mutex
276 /// #DefaultLock.
279
280 #if !ALIB_SINGLE_THREADED
281 /// The lock to be set with multithreaded use of #Default.
282 /// If the compiler-symbol \ref ALIB_DEBUG_CRITICAL_SECTIONS is set, this lock will be
283 /// attached to the \alib{lang;DbgCriticalSections} instance in #Default during
284 /// bootstrap.
285 /// Thus, an assertion will be raised if #Default is used without locking this.
286 ///
287 /// \par Availability
288 /// This object is available only if symbol \ref ALIB_SINGLE_THREADED is not set.
289 ///
290 /// @see Chapter \ref alib_threads_intro_assert_locks of the Programmer's Manual of
291 /// module \alib_threads.
294 #endif
295
296 // #############################################################################################
297 // Protected methods
298 // #############################################################################################
299 protected:
300 //==========================================================================================
301 /// Virtual method which is invoked with each invocation of #Format.
302 /// The default implementation does nothing.
303 //==========================================================================================
304 virtual void initializeFormat() {}
305
306 //==========================================================================================
307 /// The abstract format method that needs to be implemented by descendants.
308 /// Note that parameter \p{startIdx} and the demanded return value together comprise the
309 /// possibility to use more than one formatter in parallel and to perform multiple format
310 /// operations on suitable argument lists. This demands the implementation of this method to
311 /// \b not copy the format string to the \p{target} in the case that no 'escape sequence'
312 /// was found. For further information, see the general documentation of this class.
313 ///
314 /// @param target The %AString that takes the result.
315 /// @param formatString The format string.
316 /// @param args The objects to be used with formatters.
317 /// @param startArgument The first object in \p{args} to convert.
318 ///
319 /// @return The number of args consumed.
320 //==========================================================================================
321 virtual int format( AString& target,
322 const String& formatString,
323 const BoxesMA& args,
324 int startArgument ) = 0;
325
326 //==========================================================================================
327 /// The format loop implementation. Searches format strings in \p{args} and tests
328 /// if \c this or #Next is capable of processing it.
329 ///
330 /// @param target An AString that takes the result.
331 /// @param args The objects to be used with formatters.
332 /// @return A reference to this formatter to allow concatenated operations.
333 //==========================================================================================
334 template<typename TAllocator>
336};
337
338#if !DOXYGEN
342#endif // !DOXYGEN
343
344
345 inline
347 {
349 return formatLoop( target, boxes );
350 }
351
352} // namespace alib[::format]
353
354// #################################################################################################
355// Alias types in namespace #alib.
356// #################################################################################################
357/// Type alias in namespace \b alib.
359
360} // namespace [alib]
virtual void initializeFormat()
NumberFormat DefaultNumberFormat
Definition formatter.inl:96
Formatter & FormatArgs(AString &target)
static ALIB_DLL threads::RecursiveLock DefaultLock
Formatter & Format(AString &target, TArgs &&... args)
MonoAllocator allocator
This allocator is (exclusively) used for field boxes.
Definition formatter.inl:70
virtual ALIB_DLL void CloneSettings(Formatter &reference)
virtual SPFormatter Clone()=0
NumberFormat AlternativeNumberFormat
Formatter & formatLoop(AString &target, const boxing::TBoxes< TAllocator > &args)
static ALIB_DLL SPFormatter Default
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)
#define ALIB_DLL
Definition alib.inl:496
#define ALIB_DCS
Definition alib.inl:1375
#define ALIB_EXPORT
Definition alib.inl:488
#define ALIB_DBG(...)
Definition alib.inl:836
#define ALIB_DBG_PREVENT_RECURSIVE_METHOD_CALLS_MEMBER_DECL
Definition alib.inl:1346
#define ALIB_DEBUG_CRITICAL_SECTIONS
Definition prepro.md:43
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
strings::TNumberFormat< character > NumberFormat
Type alias in namespace alib.
boxing::TBoxes< PoolAllocator > BoxesPA
Type alias in namespace alib.
Definition boxes.inl:248
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
format::Formatter Formatter
Type alias in namespace alib.
boxing::Box Box
Type alias in namespace alib.
Definition box.inl:1216
boxing::TBoxes< MonoAllocator > BoxesMA
Type alias in namespace alib.
Definition boxes.inl:245
containers::SharedPtr< format::Formatter > SPFormatter
Definition formatter.inl:42
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2381
boxing::TBoxes< lang::HeapAllocator > BoxesHA
Type alias in namespace alib.
Definition boxes.inl:241
containers::SharedPtr< T, TAllocator > SharedPtr
Type alias in namespace alib.
void(*)(const Box &self, const String &formatSpec, NumberFormat &nf, AString &target) Signature
Definition formatter.inl:30