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