ALox  V. 2402 R. 0
Home ALox for C++ ALox for C# ALox for Java Download
Public Fields | Public Static Methods | Public Methods | Protected Static Fields | Protected Fields | Protected Methods | List of all members
Formatter Class Referenceabstract
Inheritance diagram for Formatter:
[legend]
Collaboration diagram for Formatter:
[legend]

Class Description


Writes formatted text into an AString.

While this class is abstract, only derived classes that support a specific format syntax can be instantiated and used. Built-in formatters provided with ALib are:

One of the design goals of ALib is to provide a library for (currently) three programming languages C++, Java and C#, which allows to reach a certain level of source code compatibility if used in cross-platform/language projects. Now, why do we provide Python Style instead of to mimic what is coming with .Net languages like C#?

The answer is that we considered Python Style to be more powerful. It is also more powerful than the Java Style formatting syntax. But the latter is in its basics similar to good old printf format string style and hence for ALib a must have. The good news is that in its very basics, Python Style is similar to .Net formatting. This way, there is some "familiar basic syntax" available for everybody.
Finally, it is worth to mention that the ALib implementation of Python Style formatting is extending the original standard even a little.

Concatenated Formatters And Concatenated Format Operations

In comparison to "usual", similar classes that are found in other libraries/languages, there are two main differences with this class:

  1. This class supports the concatenation of formatters by passing an instance of a different derived type in the constructor. A formatter that has a (list of) concatenated other formatter(s) attached, allows to detect the provided format syntax by passing the format operation recursively to the concatenated formatter(s). Of-course this approach is limited to such syntax definitions that are not ambiguous. (...It works well with formatters FormatterPythonStyle and FormatterJavaStyle!)
  2. Usually (in other libraries) the interface of formatting methods accept a dedicated format string and list of arguments to format. Method Format of this class however expects just an argument list. The processing then is done as follows: The first argument in the list is tested to be a format string. If it is, method format will report how many arguments form the list have been "consumed" and formatting will continue with the first argument after the last consumed one. If the actual argument is not identified as a format string (tested with each concatenated formatter), the string is just appended to the target and formatting continues with the next argument in the list.
    If at the end of this processing loop a single argument is left, then this is not checked for being a format string. Instead, it will be just appended to the target as is. An argument that potentially could be a format string is simply skipped (ignored) if it evaluates to null.

This behaviour has the following consequences:

The biggest advantage of this implementation is that format strings and arguments might be collected prior to invoking the formatter. Collection might happen at different places and times in a process with the only restriction that not more or less arguments might be added to the overall list than referred to in the format string. In other words, format strings have to be well set in respect to the arguments they consume.

The biggest potential issue of this approach is that a string argument that is not meant to be a format string might be accidentally interpreted as one if it happens to contain one or more placeholder characters that are matched by one of the concatenated formatters. (In this case it it is likely that the format is invalid and an error is written. In debug mode, even an assertion might be raised). To avoid such ambiguity, the following considerations have to be taken into account when passing arguments:

Attention
The rule that results from this is:
If none of the conditions mentioned above can be guaranteed, then the argument in question should be passed together with a preceding simple formatting string, for example, "{}" for FormatterPythonStyle or "%s" in case of FormatterJavaStyle.

Choosing The Formatter

As elaborated above, there are two built-in formatter types and those can be concatenated. Finally, there is the option to implement an own, custom formatter. For the undecided, the recommendation is to use Java Style for simple, quick printf- like formatting and to choose Python Style in the moment formatting requirements get more complex. A special case and good sample for the use of ALib formatting features is found in the ALox Logging Library. Here the special situation is that ALox itself is a library and hence exposes its formatters used to users. Therefore ALox (by default) uses a Python Style formatter and a concatenated Java Style version. This way, simple samples will work from scratch for users of all three languages!

Usage

The class is abstract, hence only derived types can be instantiated. Those types are constructed with optionally providing a concatenated instance of another derived type. The optional concatenated formatter object has a lower priority in respect to detecting a format string.

Two overloaded methods Format exists:

Note
The use of this class is not "thread safe".

Implementing A Custom Formatter

To implement a custom formatter, the abstract methods found in this class have to be implemented. With class FormatterStdImpl a - still abstract - descendant class is provided. This class implements method format but introduces a set of new abstract methods to overwrite. Although, those are more methods, these methods are probably more simple to implement and therefore deriving from this class might be considered for new custom types.

The two built-in Formatters provided with ALib, FormatterPythonStyle and FormatterJavaStyle derive from FormatterStdImpl and copying the source code of one of them might be a good start for implementing a custom type.

Public Fields

Formatter Next
 

Public Static Methods

static Formatter AcquireDefault ()
 
static void ReleaseDefault ()
 

Public Methods

virtual void Format (AString target, List< Object > args)
 
virtual void Format (AString target, params Object[] args)
 
virtual void Reset ()
 

Protected Static Fields

static Formatter defaultFormatter
 
static ThreadLock defaultFormatterLock = new ThreadLock()
 

Protected Fields

List< Object > boxes
 
Substring lamFormatString = new Substring()
 

Protected Methods

abstract int format (AString target, Substring formatString, List< Object > args, int startArgument)
 
virtual void initializeFormat ()
 

Member Function Documentation

◆ AcquireDefault()

static Formatter AcquireDefault ( )
inlinestatic

Locks and returns the global, default formatter for general purpose use. A subsequent call to ReleaseDefault has to follow. The formatter is of type FormatterPythonStyle. Other formatters might be attached to the one returned (chained) to support different format standards.

Returns
The global formatter singleton.

◆ Format() [1/2]

virtual void Format ( AString  target,
List< Object >  args 
)
inlinevirtual

Applies the given arguments to the target using this and optionally provided sub-formatter(s).

Parameters
targetAn AString that takes the result.
argsThe objects to apply.

◆ Format() [2/2]

virtual void Format ( AString  target,
params Object[]  args 
)
inlinevirtual

Variadic template method that accepts an target AString and a list of applicable arguments.

Parameters
targetAn AString that takes the result.
argsThe variadic list of arguments to be used with formatters.
Template Parameters
BoxedObjectsVariadic template type list.

◆ format()

abstract int format ( AString  target,
Substring  formatString,
List< Object >  args,
int  startArgument 
)
protectedpure virtual

The abstract format method that needs to be implemented by descendants. Note that parameter startIdx and the demanded return value together comprise the possibility to use more than one formatter in parallel and to perform multiple format operations on suitable argument lists. This demands the implementation of this method to not copy the format string to the target in the case that no 'escape sequence' was found. For further information, see the general documentation of this class.

Parameters
targetThe AString that takes the result.
formatStringThe format string.
argsThe objects to apply.
startArgumentThe first object in args to convert.
Returns
The number of args consumed.

Implemented in FormatterStdImpl.

◆ initializeFormat()

virtual void initializeFormat ( )
inlineprotectedvirtual

Virtual bot not abstract method which is invoked with each invocation of Formatter.Format. The default implementation does nothing.

Reimplemented in FormatterPythonStyle.

◆ ReleaseDefault()

static void ReleaseDefault ( )
inlinestatic

Releases the previously default formatter singleton, previously retrieved with AcquireDefault.

If finally released (no recursive acquirements had been done), method Formatter.Reset is invoked.

◆ Reset()

virtual void Reset ( )
inlinevirtual

Virtual but not abstract method to used to reset internal states which are otherwise kept between invocations of Format.

As a sample, derived type FormatterPythonStyle clears its auto-tab and auto-width positions.

The default implementation does nothing.

Reimplemented in FormatterPythonStyle.

Member Data Documentation

◆ boxes

List<Object> boxes
protected

A list of boxes. This is reset with every new invocation of variadic argument version of method Format

◆ defaultFormatter

Formatter defaultFormatter
staticprotected

A static, global instance which is used by ALib internally (e.g. for formatting Report messages). Applications can acquire and use this instance using AcquireDefault and ReleaseDefault.

◆ defaultFormatterLock

ThreadLock defaultFormatterLock = new ThreadLock()
staticprotected

Lock to protect access to defaultFormatter. Used by AcquireDefault and ReleaseDefault.

◆ lamFormatString

Substring lamFormatString = new Substring()
protected

The currently parsed formatted string (local as member/reused object).

◆ Next

Formatter Next

An optional, next formatter. If set, this formatter will be invoked for a format string that does not contain recognized placeholders.

Attention
This field is public and not further maintained by this class. Setting the field lies completely in the responsibility of the user. E.g. cyclic settings must be avoided.

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