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