ALib C++ Framework
by
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
formatterstdimpl.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//==================================================================================================
8
10
11//==================================================================================================
12/// This is a base class for \alib built-in formatters. The class implements abstract method
13/// #"Formatter::format;*" and introduces a set of
14/// new abstract methods that have to be implemented by descendants.
15///
16/// Derived types need to set default values for attributes in fields
17/// #"DefaultNumberFormat" and #"AlternativeNumberFormat" within their constructor once - according
18/// to defaults specified by the formatting syntax.
19/// This should not be repeated per format operation. This way users of the type are allowed
20/// to change such default setting (even if they this may the formatter deviates from the standard
21/// it implements).
22///
23/// All values aggregated in member #"placeholder", together comprise the set of formatting attributes
24/// which can be modified by placeholder semantics of the format string.
25/// Derived types might use extended attributes.
26/// Implementations provided with \alib define such extended attributes using a corresponding
27/// additional inner type.
28///
29/// When parsing a placeholder of a format string, abstract method #".parsePlaceholder"
30/// may set field #"PlaceholderAttributes;FormatSpec" to reflect
31/// a format-specific portion the placeholder string.
32/// It will be checked if the argument supports box-function #"FFormat",
33/// and if so, this string is passed to the box-function.
34/// If the argument does not support the interface, method #".parseStdFormatSpec" is invoked to
35/// now parse this portion of the placeholder string in a default way.<br>
36/// This concept allows customized format specifications for custom argument types! As an example,
37/// a format specification for date/time argument types may support a custom format string
38/// like \c "yyyy-MM-dd HH:mm:ss".
39/// \note
40/// This concept is implemented with class
41/// #"FormatterPythonStyle" as the
42/// "Python format mini language" supports such custom format specifications. Class
43/// #"FormatterJavaStyle" does \b not support
44/// this mechanism.
45///
46/// The following describes the formatting process in detail (the implementation of method
47/// #".format") and this way helps to understand what is required from the implementation of the
48/// abstract methods:
49///
50/// 1. Method parameters are stored in fields #"targetString", #".formatString", #".arguments" and
51/// #"argOffset". This way, the parameters can be accessed from any implemented method without
52/// the need of passing them as parameters once more.<br>
53/// In addition, field #".parser" is initialized. This \b Substring is used to parse
54/// the format string. Parsed portions will be consumed from the front of the string.
55/// Finally fields #"argsConsumed" and #"nextAutoIdx" are initialized to value \c 0.
56///
57/// 2. <b>Start of the loop</b> to find and process placeholders in the format string.
58///
59/// 3. Abstract method #".findPlaceholder" is invoked. If this fails (no further placeholder was
60/// found) parsing stops. If, and only if, a placeholder was found before, the method
61/// #"writeStringPortion" is invoked for the rest of the string before exiting the function.
62///
63/// 4. Method #"writeStringPortion" is invoked to write the current parser contents up to the
64/// placeholder position.
65///
66/// 5. Method #"resetPlaceholder" is invoked, to reset the attributes that will be parsed in the next
67/// step. The values that are set are implementation specific and need to reflect the
68/// default formatting options if no specific options are given in the format string.
69///
70/// 6. Abstract Method #".parsePlaceholder" is invoked to parse and consume tokens from string #".parser"
71/// and while doing this, to store the parsed format attributes in the fields with
72/// name prefix \c pha (or extended attributes of a derived formatter type).<br>
73/// If an argument (positional) index is found during parsing, then method
74/// #"setArgument" is to be invoked by abstract method \b %parsePlaceholder providing that index.<br>
75/// If the format syntax of the formatter contains a separated format specification string
76/// (a substring of the placeholder string), then the method may store such format
77/// substring in field
78/// #"PlaceholderAttributes;FormatSpec".
79///
80/// 7. Next, it is checked if an argument was set by \b %parsePlaceholder. If not, #"setArgument"
81/// is invoked providing \c -1 for the index to indicate auto-indexing.
82/// \note
83/// If auto-indexing should be implemented differently than done with default method
84/// #"setArgument", then a custom formatter might either override the method or,
85/// in the case no index is given in the format string, just
86/// set fields
87/// #"PlaceholderAttributes;Arg" and
88/// #"PlaceholderAttributes;ArgIdx"
89/// already in \b %parsePlaceholder according to its own strategy
90///
91/// 9. Method #"preAndPostProcess" is invoked with parameter \p{startIdx} equalling \c -1
92/// (indicating pre-processing). This allows, for example, to insert tab fill-characters
93/// (tab stops) before writing the contents of the field.
94///
95/// 9. Method #"writeCustomFormat" is invoked. This allows derived formatters to write arguments in a
96/// custom way. If the method returns \c true, the loop is continued ( &rarr; Step 4.). <br>
97/// The default implementation checks whether box-function #"FFormat" is defined for
98/// #"PlaceholderAttributes;Arg".
99/// In this case, the interface is invoked and \c true returned.
100///
101/// 10. Again, if a format specification was stored in
102/// #"PlaceholderAttributes;FormatSpec"
103/// method #".parseStdFormatSpec" is invoked which needs to set further attributes
104/// in the \b %Placeholder object according to the standard format specification of the formatter.
105///
106/// 11. Now, as all fields that represent formatting attributes are well set (or kept with their
107/// defaulted value), method #"checkStdFieldAgainstArgument" is invoked.
108/// This method is virtual but not abstract. Its default implementation checks the
109/// placeholder attributes against the provided argument type, and
110/// #"alib_mod_assert;raises an error" if the argument does not fit to the placeholder
111/// format specification.
112///
113/// 12. Method #writeStdArgument is invoked. This method is virtual but not abstract.
114/// Its default implementation writes the argument value formatted according to the attribute
115/// fields.
116///
117/// 13. Finally #preAndPostProcess is invoked with parameter \p{startIdx} pointing to the first
118/// character in #targetString of the argument written.
119/// Here, actions like case conversion might be done on the field written.
120///
121/// 14. End of loop ( &rarr; Step 4.)
122//==================================================================================================
124{
125 //################################################################################################
126 // Placeholder types and attributes
127 //################################################################################################
128 public: // needs to be public because it is resourced in Basecamp
129 /// Denotes the type of placeholders (respectively the values they represent).
130 enum class PHTypes
131 {
132 NotGiven , ///< The default
133 String , ///< %String-type requested.
134
135 Character, ///< Converts a given character or integer number to the corresponding
136 ///< unicode character before printing.
137
138 IntBase10, ///< Outputs a given number in base 10. The default.
139 IntBinary, ///< Outputs a given number in base 2.
140 IntOctal , ///< Outputs a given number in base 8.
141 IntHex , ///< Outputs a given number in base 16.
142
143 Float , ///< Outputs a number in floating point format.
144
145 Bool , ///< Writes "true" or "false".
146 HashCode , ///< Writes raw box data as hex.
147
148 Fill , ///< Writes #"PlaceholderAttributes;FillChar"
149 ///< x-times. Used with python-style conversion <b>{!Fill[C]}</b>.
150 };
151
152 protected:
153
154 /// Collection of attributes related to the current placeholder processed.
155 /// \note
156 /// The members of this inner class could as well be rightful members of the outer class.
157 /// One object of this inner type is created as a normal member. Hence, the only
158 /// reason for gathering the fields in this inner type is readability. (It has no influence
159 /// on the compilation result.)
160 ///
162 {
163 /// The current Box.
164 /// This is set by #parsePlaceholder if explicit indexing is used. Otherwise by #format
165 /// which invokes #setArgument if #parsePlaceholder did not set it yet.
166 /// Set to \c nullptr in the default implementation of #resetPlaceholder.
167 const Box* Arg;
168
169 /// The portion of the replacement field that represents the format specification.
170 /// This field might be set in method #parsePlaceholder and consumed in methods
171 /// #writeCustomFormat and #parseStdFormatSpec.<br>
172 /// This field is \e nulled in the default implementation of #resetPlaceholder.
174
175 /// The number format object for the actual attribute. With method #resetPlaceholder values
176 /// found in object #DefaultNumberFormat will be copied into this.
178
179 /// The type of the attribute as specified in the placeholder.
180 /// This is set to
181 /// #"alib::format::FormatterStdImpl::PHTypes::NotGiven;PHTypes::NotGiven"
182 /// in the default implementation of #resetPlaceholder.
184
185 /// The alignment of the contents within a field.
186 /// This is set to #"Alignment::Left" in the default implementation of
187 /// #resetPlaceholder.
189
190 /// The positional index of the current
191 /// #"Placeholder Arg;argument".
192 /// This is set by #parsePlaceholder if explicit indexing is used. Otherwise by #format
193 /// which invokes #setArgument if #parsePlaceholder did not set it yet.
194 /// Set to \c -1 in the default implementation of #resetPlaceholder.
196
197 /// The index of the previous argument. Used when addressing previous argument
198 /// number (eg. in Java formatting style this could be "%<$...").
199 /// This is set to #"PlaceholderAttributes;ArgIdx"
200 /// in the default implementation of #resetPlaceholder.
202
203 /// The (minimum) width of the output.
204 /// This is set to \c 0 in the default implementation of #resetPlaceholder.
205 int Width;
206
207
208 /// If not negative, the string representation of the argument is cut before
209 /// applying any field operation. It could be also named "precision", hence
210 /// the number of characters to show - even if the field will be wider.
211 /// This is set to \c -1 in the default implementation of #resetPlaceholder.
213
214 /// This is the position in the format string where the actual type code was read from.
215 /// Used for exception argument generation (FMTExceptions::IncompatibleTypeCode).
216 /// If -1, the actual parse position is used.
218
219 /// If true, an alignment was explicitly specified.
220 /// This is set to \c false in the default implementation of #resetPlaceholder.
222
223 /// Forces the padding to be placed after the sign (if any) but before the digits.
224 /// This is used for printing fields in the form ‘+000000120'.
225 /// This alignment option is only valid for numeric types.
226 /// Set to \c false in the default implementation of #resetPlaceholder.
228
229 /// Used with binary, octal, or hexadecimal output. Specifies that the output will be
230 /// prefixed by strings found in fields
231 /// #"TNumberFormat::BinLiteralPrefix",
232 /// #"TNumberFormat::HexLiteralPrefix" or
233 /// #"TNumberFormat::OctLiteralPrefix" which
234 /// default to \c "0b", \c "0o" and \c "0x".
235 /// Set to \c false in the default implementation of #resetPlaceholder.
237
238 /// Can be \c true for float-types. If \c true, the value is multiplied with 100 and
239 /// a percentage symbol \c '\%' is printed after the value.
240 /// Set to \c false in the default implementation of #resetPlaceholder.
242
243 /// The filling character for fields that are larger than their content.
244 /// Method #resetPlaceholder will set this to <c>' '</c>.
246
247 /// This is the (format-specific) type code of the current format operation.
248 /// Used only to display error messages. May be used differently in derived classes.
249 /// Is \e nulled in the default implementation of #resetPlaceholder.
251 };
252
253 //################################################################################################
254 // protected fields
255 //################################################################################################
256 protected:
257 /// A string buffer, used for example, when writing aligned fields.
259
260 /// The name of the formatter as provided in the constructor. Used for generating
261 /// error messages.
263
264 /// The format string as provided with method #Format.
266
267 /// The current (remaining) format string.
269
270 /// The target string as provided with method #Format.
272
273 /// The list of arguments provided with method #Format.
275
276 /// The length of the target string before adding the formatted contents.
278
279 /// The offset of the first argument to use. Provided with method #Format.
281
282 /// The number of arguments consumed by the current format string.
284
285 /// Counter for auto-indexed arguments.
287
288 /// If \c false the formatters specification expects argument to be numbered from
289 /// <c>0..N</c>. If \c true from <c>1..N</c>.
291
292 /// If \c false the formatters specification expects argument to be numbered from
293 /// <c>0..N</c>. If \c true from <c>1..N</c>.
295
296
297 //################################################################################################
298 // Constructor/destructor
299 //################################################################################################
300 public:
301 /// Constructor.
302 /// @param formatterClassName The name of the derived class. Used to generate error messages
303 /// including a link into the online documentation. (Therefore
304 /// has to be the exact name.
305 FormatterStdImpl( const String& formatterClassName );
306
307 //################################################################################################
308 // Implementation of abstract interface of parent class Formatter
309 //################################################################################################
310 protected:
311
312 /// Implemented abstract format method which invokes a set of new abstract methods
313 /// as described in the main documentation of this class.
314 ///
315 /// @param targetString An AString that takes the result.
316 /// @param formatString The format string.
317 /// @param arguments The objects to convert.
318 /// @param argOffset The first object in \p{arguments} to use.
319 ///
320 /// @return The number of args consumed.
322 virtual int format( AString& targetString,
323 const String& formatString,
324 const BoxesMA& arguments,
325 int argOffset ) override;
326
327
328 //################################################################################################
329 // Introduction of new, partly abstract methods to be implemented (or optionally overwritten)
330 // by descendents.
331 //################################################################################################
332 protected:
333
334 /// Abstract method to search the next index of an argument placeholder in the remaining
335 /// substring (field #parser) of the format string.
336 ///
337 /// @return The index found, \c -1 if not found.
339
340 /// Overridable method to clean and reset the fields representing the current placeholder
341 /// attributes (those with name prefix \c pha) before parsing them.
342 ///
343 /// The default implementation sets all pha-fields as documented per field.
344 /// \note
345 /// Derived classes (aka the specific formatter classes) are to invoke this (parent)
346 /// implementation first and then to make some own adjustments to meet the defaults that
347 /// apply to the formatting specification implemented by the derived class and - if this
348 /// applies - also to reset extended attributes of the derived formatter type.
349 virtual void resetPlaceholder();
350
351
352 /// Abstract method to parse the format definition at the start of string
353 /// #parser and set the placeholder attributes accordingly.<br>
354 /// Field #"PlaceholderAttributes;FormatSpec"
355 /// might be set by this method to portion of the placeholder format string.
356 /// If so, methods #writeCustomFormat and #parseStdFormatSpec are used to then parse
357 /// this portion of the placeholder string.
358 ///
359 /// @return \c true on success, \c false on errors.
360 virtual bool parsePlaceholder() =0;
361
362 /// Virtual method that may write an argument using a custom method/format.
363 /// The default implementation checks if object
364 /// #"PlaceholderAttributes;Arg" supports an own format specifier
365 /// by disposing about box-function #"FFormat".
366 /// If so, the function is invoked with passing
367 /// #"PlaceholderAttributes;FormatSpec", the result of the
368 /// formatting is written directly into the #targetString and \c true is returned.
369 /// The latter causes method #format (which invokes this method) to continue with the next
370 /// replacement field.<br>
371 /// If \c false is returned, method #format continues the field processing by invoking
372 /// #parseStdFormatSpec, #checkStdFieldAgainstArgument and #writeStdArgument.
373 ///
374 /// @return \c true if #"PlaceholderAttributes;Arg"
375 /// was written, \c false otherwise.
376 virtual bool writeCustomFormat();
377
378 /// Abstract method to parse the format specification for standard types (those that
379 /// are not processed by #writeCustomFormat). This method may be left empty
380 /// (just return constant \c true) if method #parsePlaceholder will never sets
381 /// field #"PlaceholderAttributes;FormatSpec".
382 ///
383 /// @return \c true on success, \c false on errors.
384 virtual bool parseStdFormatSpec() =0;
385
386 /// Virtual method invoked after #parseStdFormatSpec and before #writeStdArgument().
387 /// The default implementation checks the settings of placeholder attribute values
388 /// (fields with prefix \c pha), which were set by #parsePlaceholder and optionally by
389 /// #parseStdFormatSpec, against the type of the argument given.
390 ///
391 /// If type and format information is missing in the format string, reasonable default
392 /// values are set depending on the type of the argument.
393 ///
394 /// @throws
395 /// If the argument type contradicts the replacement field type, exception
396 /// #"FMTExceptions::IncompatibleTypeCode" is thrown.
397 ///
398 /// @return \c true if OK, \c false if replacement should be aborted.
399 virtual bool checkStdFieldAgainstArgument();
400
401 /// Virtual method to write the argument. The default implementation should be sufficient
402 /// for most derived formatter implementations, but of course can be overridden and extended.
403 virtual void writeStdArgument();
404
405 /// Virtual method to do pre- and post- processing of the field written.
406 /// Pre-processing could, for example, be adding tabulator spaces, letter case conversions,
407 ///
408 /// A negative given index \p{startIdx} indicates the pre-processing phase.
409 /// If \p{target} is given, this indicates an "intermediate phase": The argument has been
410 /// written, but no alignment or cutting has been done, yet. This phase should usually
411 /// be ignored, but is, for example, important for search and replacement actions.
412 /// If a field has a custom format implementation (e.g., time and date values), then
413 /// the intermediate phase is never called.
414 ///
415 /// \note
416 /// The reason why this method is \b not implemented as two different ones is that
417 /// derived classes might do some more complicated parsing of parts of the placeholder
418 /// string in this method. In this case, the parsing is needed to be implemented only
419 /// once, while the finally parsed commands are only conditionally executed depending
420 /// if executed as pre or post phase.
421 ///
422 /// @param startIdx If \c -1 pre-processing is indicated, otherwise post-processing and
423 /// the index of the start of the field written in #targetString is given.
424 /// @param target The target string, only if different from field #targetString, which
425 /// indicates intermediate phase.
426 /// @return \c false, if the placeholder should be skipped (nothing is written for it).
427 /// \c true otherwise.
428 virtual bool preAndPostProcess( integer startIdx,
429 AString* target = nullptr ) {
430 (void) startIdx;
431 (void) target;
432 return true;
433 }
434
435 /// Helper method (overridable) that usually is invoked by the implementation of
436 /// #parsePlaceholder when an argument index is read from the format string,
437 ///
438 /// If this does not happen, method #format will invoke this method providing \c -1 for
439 /// value of parameter \p{pos} to automatically choose the next argument.
440 ///
441 /// Consequently, this method sets the fields
442 /// #"PlaceholderAttributes;Arg" and
443 /// #"PlaceholderAttributes;ArgIdx".
444 /// For auto-values, it increments #nextAutoIdx.
445 /// Finally, this method is responsible for the correct book-keeping of #argsConsumed.
446 ///
447 /// @param pos The index of the argument.
448 /// If \c -1 is given, the index is auto-incremented using field #nextAutoIdx.
449 /// @return \c true on success, \c false on errors.
450 virtual bool setArgument( int pos );
451
452 /// Implementations of this abstract virtual method need to copy the given amount of
453 /// characters from sting #parser to \b AString #targetString. With that
454 /// "escaped" placeholder field characters (for example, these are \c "{{" in python style
455 /// or \c "%%" in JAVA style) as well as other escape sequences defined with the format are
456 /// to be replaced with this method.
457 ///
458 /// @param length The number of characters to write.
459 virtual void writeStringPortion( integer length ) =0;
460};
461
462} // namespace [alib::format]
463
#define ALIB_DLL
Definition alib.inl:573
#define ALIB_EXPORT
Definition alib.inl:562
AString * targetString
The target string as provided with method Format.
FormatterStdImpl(const String &formatterClassName)
virtual bool preAndPostProcess(integer startIdx, AString *target=nullptr)
Substring parser
The current (remaining) format string.
virtual bool parseStdFormatSpec()=0
integer targetStringStartLength
The length of the target string before adding the formatted contents.
PHTypes
Denotes the type of placeholders (respectively the values they represent).
@ Float
Outputs a number in floating point format.
@ IntBinary
Outputs a given number in base 2.
@ IntBase10
Outputs a given number in base 10. The default.
@ IntHex
Outputs a given number in base 16.
@ IntOctal
Outputs a given number in base 8.
const BoxesMA * arguments
The list of arguments provided with method Format.
AString fieldBuffer
A string buffer, used for example, when writing aligned fields.
int nextAutoIdx
Counter for auto-indexed arguments.
virtual bool parsePlaceholder()=0
virtual int format(AString &targetString, const String &formatString, const BoxesMA &arguments, int argOffset) override
String formatString
The format string as provided with method Format.
virtual void writeStringPortion(integer length)=0
int argOffset
The offset of the first argument to use. Provided with method Format.
int argsConsumed
The number of arguments consumed by the current format string.
virtual integer findPlaceholder()=0
Formatter()
Default Constructor.
#define ALIB_ENUMS_ASSIGN_RECORD(TEnum, TRecord)
Alignment
Denotes Alignments.
strings::TNumberFormat< character > NumberFormat
Type alias in namespace alib.
strings::TFill< character > Fill
Type alias in namespace alib.
Definition format.inl:577
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
strings::TSubstring< character > Substring
Type alias in namespace alib.
boxing::TBoxes< MonoAllocator > BoxesMA
Type alias in namespace alib.
Definition boxes.inl:193
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
characters::character character
Type alias in namespace alib.