Implements a Formatter according to the formatting standards of the Python language .
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] "}"
{:11.5,}
where Python allows only {:11,.5}
0
and is incremented each time automatic indexing is used. Occurrences of explict indexing have no influence on the automatic indexing.','
) 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 before 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.
'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.'f'
and 'F' types) are not supported to use an 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'.'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 before 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:
!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 '}' cannot be used with this conversion. To surround a placeholder's contents in this bracket type, add {{ and }} around the placeholder - resulting in {{{}}}!.
'<'
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.' '
. It can be changed with optional character 'C' plus the character wanted.' '
. 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 at the moment the actual contents exceeds the currently stored tab-position. An arbitrary number 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.
'<'
and '>'
. In the special case that search is empty (<>
), string replace will be inserted if the field argument is an empty string. <b>alib::lang::format::FMTExceptions</b> |
Definition at line 323 of file formatterpythonstyle.hpp.
#include <formatterpythonstyle.hpp>
Inner Type Index: | |
struct | PlaceholderAttributesPS |
Public Field Index: | |
AutoSizes * | Sizes |
AutoSizes | SizesDefaultInstance |
The default instance of field Sizes. This might be replaced with an external object. | |
Public Field Index: inherited from Formatter | |
NumberFormat | AlternativeNumberFormat |
NumberFormat | DefaultNumberFormat |
SharedPtr< Formatter > | Next |
Public Field Index: inherited from DbgCriticalSections | |
CallerInfo | DCSAcq |
Source location of acquirement. | |
AssociatedLock * | DCSLock {nullptr} |
const char * | DCSName |
The name of this DCS. Used for debug-output. | |
std::atomic< int > | DCSReaderCnt {0} |
Tracks enter/exit calls of readers. | |
CallerInfo | DCSRel |
Source location of the last "reader" seen. | |
CallerInfo | DCSSAcq |
Source location of acquirement. | |
CallerInfo | DCSSRel |
Source location of the last "reader" seen. | |
std::atomic< int > | DCSWriterCnt {0} |
Tracks enter/exit calls (including readers) | |
int | DCSYieldOrSleepTimeInNS = -1 |
Public Method Index: | |
ALIB_API | FormatterPythonStyle () |
virtual ALIB_API SPFormatter | Clone () override |
virtual BoxesMA & | Reset () override |
Public Method Index: inherited from FormatterStdImpl | |
FormatterStdImpl (const String &formatterClassName) | |
Public Method Index: inherited from Formatter | |
Formatter () | |
Default Constructor. | |
virtual | ~Formatter () |
virtual ALIB_API void | CloneSettings (Formatter &reference) |
template<typename... TArgs> | |
Formatter & | Format (AString &target, TArgs &&... args) |
Formatter & | FormatArgs (AString &target) |
template<typename TAllocator > | |
Formatter & | FormatArgs (AString &target, const boxing::TBoxes< TAllocator > &args) |
virtual BoxesMA & | GetArgContainer () |
Public Method Index: inherited from DbgCriticalSections | |
ALIB_FORCE_INLINE | DbgCriticalSections (const char *name) |
ALIB_FORCE_INLINE | ~DbgCriticalSections () |
Destructor. Checks that this instance is unused. | |
ALIB_API void | Acquire (const CallerInfo &ci) const |
ALIB_API void | AcquireShared (const CallerInfo &ci) const |
ALIB_API void | doAssert (bool cond, const CallerInfo &ciAssert, const CallerInfo &ci, const char *headline) const |
ALIB_API void | Release (const CallerInfo &ci) const |
ALIB_API void | ReleaseShared (const CallerInfo &ci) const |
ALIB_FORCE_INLINE void | yieldOrSleep () const |
Protected Field Index: | |
PlaceholderAttributesPS | placeholderPS |
The extended placeholder attributes. | |
Protected Field Index: inherited from FormatterStdImpl | |
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. | |
bool | argumentCountStartsWith1 |
const BoxesMA * | arguments |
The list of arguments provided with method Format. | |
AString | fieldBuffer |
A string buffer, used for example, when writing aligned fields. | |
String | formatString |
The format string as provided with method Format. | |
const String | formatterName |
int | nextAutoIdx |
Counter for auto-indexed arguments. | |
Substring | parser |
The current (remaining) format string. | |
PlaceholderAttributes | placeholder |
AString * | targetString |
The target string as provided with method Format. | |
integer | targetStringStartLength |
The length of the target string before adding the formatted contents. | |
Protected Field Index: inherited from Formatter | |
MonoAllocator | allocator |
This allocator is (exclusively) used for field boxes. | |
BoxesMA | boxes |
AString | formatStringBuffer |
A buffer used for conversion of the next argument if it is not of a string-type. | |
Protected Method Index: | |
virtual ALIB_API bool | checkStdFieldAgainstArgument () override |
virtual ALIB_API integer | findPlaceholder () override |
virtual void | initializeFormat () override |
Sets the actual auto tab stop index to 0 . | |
virtual ALIB_API bool | parsePlaceholder () override |
virtual ALIB_API bool | parseStdFormatSpec () override |
virtual ALIB_API bool | preAndPostProcess (integer startIdx, AString *target) override |
virtual ALIB_API void | resetPlaceholder () override |
virtual ALIB_API void | writeStringPortion (integer length) override |
Protected Method Index: inherited from FormatterStdImpl | |
virtual ALIB_API int | format (AString &targetString, const String &formatString, const BoxesMA &arguments, int argOffset) override |
virtual bool | setArgument (int pos) |
virtual bool | writeCustomFormat () |
virtual void | writeStdArgument () |
Protected Method Index: inherited from Formatter | |
template<typename TAllocator > | |
Formatter & | formatLoop (AString &target, const boxing::TBoxes< TAllocator > &args) |
Additional Inherited Members | |
Public Static Field Index: inherited from Formatter | |
static ALIB_API SPFormatter | Default |
static ALIB_API threads::RecursiveLock | DefaultLock |
Public Static Field Index: inherited from DbgCriticalSections | |
static ALIB_API const char * | ASSERTION_FORMAT |
Protected Type Index: inherited from FormatterStdImpl | |
enum class | PHTypes { NotGiven , String , Character , IntBase10 , IntBinary , IntOctal , IntHex , Float , Bool , HashCode , Fill } |
Denotes the type of placeholders (respectively the values they represent). More... | |
|
protected |
The extended placeholder attributes.
Definition at line 354 of file formatterpythonstyle.hpp.
AutoSizes* Sizes |
Storage of sizes for auto-tabulator feature {!ATab} and auto field width feature {!AWidth}
Definition at line 362 of file formatterpythonstyle.hpp.
AutoSizes SizesDefaultInstance |
The default instance of field Sizes. This might be replaced with an external object.
Definition at line 365 of file formatterpythonstyle.hpp.
Constructs this formatter. Inherited field DefaultNumberFormat is initialized to meet the formatting defaults of Python.
Definition at line 33 of file formatterpythonstyle.cpp.
|
overrideprotectedvirtual |
Makes some attribute adjustments and invokes standard implementation
true
if OK, false
if replacement should be aborted. Reimplemented from FormatterStdImpl.
Definition at line 556 of file formatterpythonstyle.cpp.
|
overridevirtual |
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.
Implements Formatter.
Definition at line 43 of file formatterpythonstyle.cpp.
|
overrideprotectedvirtual |
Searches for '{'
which is not '{{'.
Implements FormatterStdImpl.
Definition at line 79 of file formatterpythonstyle.cpp.
|
inlineoverrideprotectedvirtual |
Sets the actual auto tab stop index to 0
.
Reimplemented from Formatter.
Definition at line 411 of file formatterpythonstyle.hpp.
|
overrideprotectedvirtual |
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 92 of file formatterpythonstyle.cpp.
|
overrideprotectedvirtual |
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 161 of file formatterpythonstyle.cpp.
Processes "conversions" which are specified with '!'
.
startIdx | The index of the start of the field written in targetString. -1 indicates pre-phase. |
target | The 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 403 of file formatterpythonstyle.cpp.
|
inlineoverridevirtual |
Resets AutoSizes.
Reimplemented from Formatter.
Definition at line 397 of file formatterpythonstyle.hpp.
|
overrideprotectedvirtual |
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 58 of file formatterpythonstyle.cpp.
|
overrideprotectedvirtual |
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.
length | The number of characters to write. |
Implements FormatterStdImpl.
Definition at line 338 of file formatterpythonstyle.cpp.