ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
No Matches
FormatterPythonStyle Class Reference


Implements a Formatter according to the formatting standards of the Python language .

Inherited, public fields of parent class FormatterStdImpl provide important possibilities for changing the formatting behavior of instances of this class. Therefore, do not forget to consult the parent classes documentation.

In general, the original Python specification is covered quite well. However, there are some differences, some things are not possible (considering python being a scripting language) but then there are also found some very helpful extensions to that standard. Instead of repeating a complete documentation, please refer to the Python Documentation as the foundation and then take note of the following list of differences, extensions and general hints:

  • General Notes: Python defines a placeholder field as follows
       "{" [field_name] ["!" conversion] [":" format_spec] "}"
    • This formatter is less strict in respect to the order of the format symbols. E.g. it allows {:11.5,} where Python allows only {:11,.5}
    • With this class being derived from FormatterStdImpl, features of the parent are available to this formatter as well. This is especially true and sometimes useful in respect to setting default values number formatting. For example, this allows to modify all number output without explicitly repeating the settings in each placeholder of format strings. Other options for example the grouping characters used with hexadecimal numbers, can not be even changed with the Python Style formatting options. The only way of doing so is modifying the properties of the formatter object prior to the format operation.
    • Nested replacements in format specification fields are (by nature of this implementation language) not supported.
  • Positional arguments and field name:
    • By the nature of the implementation language (C++, no introspection) of this class, field_name can not be the name of an identifier, an attribute name or an array element index. It can only be a positional argument index, hence a number that chooses a different index in the provided argument list.
      However, the use of field names is often a requirement in use cases that offer configurable format string setup to the "end user". Therefore, there are two alternatives to cope with the limitation:
      • In simple cases, it is possible to just add all optionally needed data in the argument list, document their index position and let the user use positional argument notation to choose the right value from the list.
      • More elegant however, is the use of class PropertyFormatter which extends the format specification by custom identifiers which control the placement of corresponding data in the format argument list. This class uses a translator table from identifier strings to custom callback functions. This way, much more than just simple field names are allowed.
    • When using positional arguments in a format string placeholders, the Python formatter implementation does not allow to switch from automatic field indexing to explicit indexing. This Aib implementation does allow it. The automatic index (aka no positional argument is given for a next placeholder) always starts with index 0 and is incremented each time automatic indexing is used. Occurrences of explict indexing have no influence on the automatic indexing.
  • Binary, Hexadecimal and Octal Numbers:
    • Binary, hexadecimal and octal output is cut in size (!) when a field width is given that is smaller than the resulting amount of digits of the number arguments provided.
      This implies that a value written might not be equal to the value given. This is not a bug but a design decision. The rationale behind this is that with this behavior, there is no need to mask lower digits when passing the arguments to the format invocation. In other words, the formatter "assumes" that the given field width indicates that only a corresponding number of lower digits are of interest.
    • If no width is given and the argument contains a boxed pointer, then the platform-dependent full output width of pointer types is used.
    • The number grouping option (',') can also be used with binary, hexadecimal and octal output. The types support different grouping separators for nibbles, bytes, 16-bit and 32-bit words. Changing the separator symbols, is not possible with the format fields of the format strings (if it was, this would become very incompatible to Python standards). Changes have to be made prior to the format operation by modifying field FormatterStdImpl::AlternativeNumberFormat which is provided through parent class FormatterStdImpl.
    • Alternative form ('#') adds prefixes as specified in members

      For upper case formats, those are taken from field FormatterStdImpl::DefaultNumberFormat , for lower case formats from FormatterStdImpl::AlternativeNumberFormat . However, in alignment with the Python specification, both default to lower case literals "0b", "0o" and "0x". All defaults may be changed by the user.

  • Floating point values:
    • If floating point values are provided without a type specification in the format string, then all values of FormatterStdImpl::DefaultNumberFormat are used to format the number
    • For lower case floating point format types ('f' and 'e'), the values specified in attributes ExponentSeparator, NANLiteral and INFLiteral of object FormatterStdImpl::AlternativeNumberFormat are used. For upper case types ('F' and 'E') the corresponding attributes in FormatterStdImpl::DefaultNumberFormat apply.
    • Fixed point formats ('f' and 'F' types) are not supported to use arbitrary length. See class NumberFormat for the limits. Also, very high values and values close to zero may be converted to scientific format. Finally, if flag ForceScientific field Flags in member DefaultNumberFormat is true, types 'f' and 'F' behave like types 'e' and 'E'.
    • When both, a width and a precision is given, then the precision determines the fractional part, even if the type is 'g' or 'G'. This is different than specified with Python formatter, which uses precision as the overall width in case of types 'g' or 'G'.
    • The 'general format' type for floats, specified with 'g' or 'G' in the python implementation limits the precision of the fractional part, even if precision is not further specified. This implementation does limit the precision only if type is 'f' or 'F'.
  • String Conversion:
    If type 's' (or no type) is given in the format_spec of the replacement field, a string representation of the given argument is used. In Java and C# such representation is received by invoking Object.[t|T]oString(). Consequently, to support string representations of custom types, in these languages the corresponding [t|T]oString() methods of the type have to be implemented.

    In C++ the arguments are "boxed" into objects of type Box. For the string representation, the formatter invokes box-function FAppend . A default implementation exists which for custom types appends the type name and the memory address of the object in hexadecimal format. To support custom string representations (for custom types), this box-function needs to be implemented for the type in question. Information and sample code on how to do this is found in the documentation of ALib Boxing , chapter 10.3 Box-Function FAppend.

  • Hash-Value Output:
    In extension (and deviation) of the Python specification, format specification type 'h' and its upper case version 'H' is implemented. The hash-values of the argument object is written in hexadecimal format. Options of the type are identical to those of 'x', respectively 'X'.

    In the C++ language implementation of ALib , instead of hash-values of objects, the pointer found in method Box::Data is printed. In case of boxed class-types and default default boxing mechanics are used with such class types, this will show the memory address of the given instance.

  • Boolean output:
    In extension (and deviation) of the Python specification, format specification type 'B' is implemented. The word "true" is written if the given value represents a boolean true value, "false" otherwise.

    In the C++ language implementation of ALib , the argument is evaluated to boolean by invoking box-function FIsTrue .

  • Custom Format Specifications:
    With Python formatting syntax, placeholders have the following syntax:

       "{" [field_name] ["!" conversion] [":" format_spec] "}"

    The part that follows the colon is called format_spec. Python passes this portion of the placeholder to a built-in function format(). Now, each type may interpret this string in a type specific way. But most built-in Python types do it along what they call the "Format Specification Mini Language" .

    With this implementation, the approach is very similar. The only difference is that the "Format Specification Mini Language" is implemented for standard types right within this class. But before processing format_spec, this class will check if the argument type assigned to the placeholder disposes about a custom implementation of box function FFormat . If so, this function is invoked and string format_spec is passed for custom processing.

    Information and sample code on how to adopt custom types to support this interface is found in the Programmer's Manual of this module, with chapter 4.3. Formatting Custom Types.

    For example, ALib class DateTime supports custom formatting with box-function FFormat_DateTime which uses helper class CalendarDateTime that provides a very common specific mini language for formatting date and time values .

  • Conversions:
    In the Python placeholder syntax specification:
       "{" [field_name] ["!" conversion] [":" format_spec] "}"
    symbol '!' if used prior to the colon ':' defines what is called the conversion. With Python, three options are given: '!s' which calls str() on the value, '!r' which calls repr() and '!a' which calls ascii(). This is of-course not applicable to this formatter. As a replacement, this class extends the original specification of that conversion using '!'. The following provides a list of conversions supported. The names given can be abbreviated at any point and ignore letter case, e.g. !Upper can be !UP or just !u. In addition, multiple conversions can be given by concatenating them, each repeating character '!'.
    The conversions supported are:
    • !Upper
      Converts the contents of the field to upper case.
    • !Lower
      Converts the contents of the field to lower case.
    • !Quote[O[C]]
      Puts quote characters around the field. Note that these characters are not respecting any optional given field width but instead are added to such. An alias name for !Quote is given with !Str. As the alias can be abbreviated to !s, this provides compatibility with the Python specification.

      In extension to the python syntax specification, one or two optional characters might be given after the (optionally abreviated) terms "Quote" respectively "str". If one character is given, this is used as the open and closing character. If two are given, the first is used as the open character, the second as the closing one. For example {!Q'} uses single quotes, or {!Q[]} uses rectangular brackets. Bracket types '{' and '}' can not be used with this conversion. To surround a placeholder's contents in this bracket type, add {{ and }} around the placeholder - resulting in {{{}}}!.

    • !ESC[<|>]
      In its default behavior or if '<' is specified, certain characters are converted to escape sequences. If '>' is given, escape sequences are converted to their (ascii) value. See Format::Escape for details about the conversion that is performed.
      An alias name for !ESC< is given with !a which provides compatibility with the Python specification.
      If !ESC< is used in combination with !Quote, then !ESC< should be the first conversion specifier. Otherwise, the quotes inserted might be escaped as well.
    • !Fill[Cc]
      Inserts as many characters as denoted by the integer type argument. By default the fill character is space ' '. It can be changed with optional character 'C' plus the character wanted.
    • !Tab[Cc][NNN]
      Inserts fill characters to extend the length of the string to be a multiple of a tab width. By default the fill character is space ' '. It can be changed with optional character 'C' plus the character wanted. The tab width defaults to 8. It can be changed by adding an unsigned decimal number.
    • !ATab[[Cc][NNN]|Reset]
      Inserts an "automatic tabulator stop". These are tabulator positions that are stored internally and are automatically extended in the moment the actual contents exceeds the currently stored tab-position. An arbitrary amount of auto tab stop and field width (see !AWith below) values is maintained by the formatter.

      Which each new invocation of Formatter , the first auto value is chosen and with each use of !ATab or !AWidth, the next value is used.
      However the stored values are cleared, whenever Format is invoked on a non-acquired formatter! This means, to preserve the auto-positions across multiple format invocations, a formatter has to be acquired explicitly before the format operations and released afterwards.

      Alternatively to this, the positions currently stored with the formatter can be reset with providing argument Reset in the format string.

      By default, the fill character is space ' '. It can be changed with optional character 'C' plus the character wanted. The optional number provided gives the growth value by which the tab will grow if its position is exceeded. This value defaults to 3.

      Both, auto tab and auto width conversions may be used to increase readability of multiple output lines. Of-course, output is not completely tabular, only if those values that result in the biggest sizes are formatted first. If a perfect tabular output is desired, the data to be formatted may be processed twice: Once to temporary buffer which is disposed and then a second time to the desired output AString.

    • !AWidth[NNN|Reset]
      Increases field width with repetitive invocations of format whenever a field value did not fit to the actually stored width. Optional decimal number NNN is added as a padding value. for more information, see !ATab above.
    • !Xtinguish
      Does not print anything. This is useful if format strings are externalized, e.g defined in library resources . Modifications of such resources might use this conversion to suppress the display of arguments (which usually are hard-coded).
    • !Replace<search><replace>
      Searches string search and replaces with replace . Both values have to be given enclosed by characters '<' and '>'. In the special case that search is empty (<>), string replace will be inserted if the field argument is an empty string.

Reference Documentation


Definition at line 327 of file formatterpythonstyle.hpp.

#include <formatterpythonstyle.hpp>

Inheritance diagram for FormatterPythonStyle:
Collaboration diagram for FormatterPythonStyle:

Inner Type Index:

struct  PlaceholderAttributesPS

Public Field Index:

AutoSizes Sizes
- Public Field Index: inherited from Formatter
NumberFormat AlternativeNumberFormat
NumberFormat DefaultNumberFormat
std::shared_ptr< FormatterNext
- Public Field Index: inherited from ThreadLock
NCString DbgOwnerFile =nullptr
NCString DbgOwnerFunc =nullptr
int DbgOwnerLine
uint16_t DbgRecursionWarningThreshold =10
integer DbgWarningAfterWaitTimeInMillis =2000L

Public Method Index:

ALIB_API FormatterPythonStyle ()
virtual ALIB_API FormatterStdImplClone () override
- Public Method Index: inherited from FormatterStdImpl
 FormatterStdImpl (const String &formatterClassName)
- Public Method Index: inherited from Formatter
virtual ~Formatter ()
ALIB_API BoxesAcquire (const NCString &dbgFile, int dbgLine, const NCString &dbgFunc)
virtual ALIB_API void CloneSettings (Formatter &reference)
int CountAcquirements () const
template<typename... TArgs>
FormatterFormat (AString &target, TArgs &&... args)
ALIB_API FormatterFormatArgs (AString &target)
FormatterFormatArgs (AString &target, const Boxes &args)
ALIB_API void Release ()
ALIB_API void ReplaceDefault (Formatter *newFormatter)
- Public Method Index: inherited from ThreadLock
ALIB_API ThreadLock (lang::Safeness safeness=lang::Safeness::Safe)
ALIB_API ~ThreadLock ()
ALIB_API void Acquire (const NCString &dbgFile, int dbgLine, const NCString &dbgFunc)
int CountAcquirements () const
ThreadGetOwner () const
lang::Safeness GetSafeness () const
bool IsOwnedByCurrentThread () const
ALIB_API void Release ()
ALIB_API void SetSafeness (lang::Safeness safeness)
bool WillRelease () const

Additional Inherited Members

- Public Static Method Index: inherited from Formatter
static SPFormatter AcquireDefault (const NCString &dbgFile, int dbgLine, const NCString &dbgFunc)
static SPFormatter GetDefault ()

Field Details:

◆ placeholderPS

PlaceholderAttributesPS placeholderPS

The extended placeholder attributes.

Definition at line 362 of file formatterpythonstyle.hpp.

◆ Sizes

AutoSizes Sizes

Storage of sizes for auto-tabulator feature {!ATab} and auto field width feature {!AWidth}

Definition at line 370 of file formatterpythonstyle.hpp.

Constructor(s) / Destructor Details::

◆ FormatterPythonStyle()

Constructs this formatter. Inherited field DefaultNumberFormat is initialized to meet the formatting defaults of Python.

Definition at line 40 of file formatterpythonstyle.cpp.

Method Details:

◆ checkStdFieldAgainstArgument()

bool checkStdFieldAgainstArgument ( )

Makes some attribute adjustments and invokes standard implementation

true if OK, false if replacement should be aborted.

Reimplemented from FormatterStdImpl.

Definition at line 592 of file formatterpythonstyle.cpp.

Here is the call graph for this function:

◆ Clone()

FormatterStdImpl * Clone ( )

Clones and returns a copy of this formatter.

If the formatter attached to field Formatter::Next is of type FormatterStdImpl, then that formatter is copied as well.

An object of type FormatterPythonStyle and with the same custom settings than this.

Implements Formatter.

Definition at line 49 of file formatterpythonstyle.cpp.

Here is the call graph for this function:

◆ findPlaceholder()

integer findPlaceholder ( )

Searches for '{' which is not '{{'.

The index found, -1 if not found.

Implements FormatterStdImpl.

Definition at line 98 of file formatterpythonstyle.cpp.

Here is the call graph for this function:

◆ initializeFormat()

void initializeFormat ( )

Sets the actual auto tab stop index to 0.

Reimplemented from Formatter.

Definition at line 70 of file formatterpythonstyle.cpp.

Here is the call graph for this function:

◆ parsePlaceholder()

bool parsePlaceholder ( )

Parses placeholder field in python notation. The portion format_spec is not parsed but stored in member FormatSpec .

true on success, false on errors.

Implements FormatterStdImpl.

Definition at line 111 of file formatterpythonstyle.cpp.

Here is the call graph for this function:

◆ parseStdFormatSpec()

bool parseStdFormatSpec ( )

Parses the format specification for standard types as specified in "Format Specification Mini Language" .

true on success, false on errors.

Implements FormatterStdImpl.

Definition at line 206 of file formatterpythonstyle.cpp.

Here is the call graph for this function:

◆ preAndPostProcess()

bool preAndPostProcess ( integer startIdx,
AString * target )

Processes "conversions" which are specified with '!'.

startIdxThe index of the start of the field written in targetString. -1 indicates pre-phase.
targetThe target string, only if different from field targetString, which indicates intermediate phase.
false, if the placeholder should be skipped (nothing is written for it). true otherwise.

Reimplemented from FormatterStdImpl.

Definition at line 438 of file formatterpythonstyle.cpp.

Here is the call graph for this function:

◆ reset()

void reset ( )

Resets AutoSizes.

Reimplemented from Formatter.

Definition at line 64 of file formatterpythonstyle.cpp.

Here is the call graph for this function:

◆ resetPlaceholder()

void resetPlaceholder ( )

Invokes parent implementation and then applies some changes to reflect what is defined as default in the Python string format specification.

Reimplemented from FormatterStdImpl.

Definition at line 77 of file formatterpythonstyle.cpp.

Here is the call graph for this function:

◆ writeStringPortion()

void writeStringPortion ( integer length)

Implementation of abstract method FormatterStdImpl::writeStringPortion .
While writing, replaces "{{" with "{" and "}}" with "}" as well as standard codes like "\\n", "\\r" or "\\t" with corresponding ascii codes.

lengthThe number of characters to write.

Implements FormatterStdImpl.

Definition at line 381 of file formatterpythonstyle.cpp.

Here is the call graph for this function:

The documentation for this class was generated from the following files: