ecl_formatters Documentation

ecl_formatters

The formatters here simply format various input types to a specified text format. They can be used with most streaming types (including both ecl and stl streams).

packageSummary

The formatters here simply format various input types to a specified text format. If you wish to just do fast type to text conversion without formatting, use the converters supplied in ecl_utilities.

History

Type to text formatting is usually bundled with both streaming and device manipulation. Although this makes it very simple to do the most basic of type formatting, it also has the unfortunate consequence in that the formatter types (printf, sprintf, iostreams) are very heavyweight and subsequently slow. Especially for a simple task, they bring a sledge hammer when all that is needed is a gentle push.

What the formatters attempt to do is to split the functionality of formatting from the concepts of device manipulation, streaming. This ensures that any simple task is not overdone with a heavyweight object (really important for logging) and it greatly enhances the efficiency and speed. The classes here also bring in type safety, something which is not guaranteed by either printf or sprintf.

CompilingLinking

Include the following at the top of any translation unit which requires this library:

        #include <ecl/formatters.hpp>

        // The formatter template family
        using ecl::Format;

        // Common formatter parameters
        using ecl::NoAlign;
        using ecl::LeftAlign;
        using ecl::CentreAlign;
        using ecl::RightAlign;

        // Integral formatter parameters
        using ecl::Bin;
        using ecl::Dec;
        using ecl::Hex;

        // Float formatter parameters
        using ecl::Fixed;
        using ecl::Sci;

You will also need to link to -lecl_formatters.

usage

Instantiation

Formatters are functors - functions with state. You instantiate a formatter type and then make use of it as if it were a function call.

                Format<int> format(); // Default format initialisation
                Format<int> format(8,RightAlign,Hex); // Custom format initialisation

Changing the Format Parameters

The format parameters can be changed singly with appropriately named setters, or collectively via:: a bundled operator () call. Sometimes common combinations are also provided with a convenient setter via the operator ().

                format.base(Hex)
                format(8,RightAlign,Dec)

Changing the format parameters in this way will set the default formatting for any input values given to the formatter in the future.

Streaming

The formatters are primarily intended to be used with streams. For convenience they have been designed to be used with any stream that implemenents the << operator. Subsequently they are useful with either TextStreams (ECL-IO) or the usual c++ streams. When used in conjunction with TextStreams they provide a very fast streaming interface.

Permanent Formatting

To format with the parameters stored in the formatter, you simply provide the formatter with the input value. Note that the formatter will only accept a value of the type specified in the formatter's template argument.

                ostream << format(i) << " " << format(9);

For convenience, you can also change the format parameter on the fly (this is recorded permanently).

                ostream << format.base(Hex)(i) << " " << format(10,LeftAlign,Dec)(9);

Temporary Formatting

Occasionally you will only need to change the format for one instance. To effect a temporary change in this way, supply the input value along with the specified formatting options.

                ostream << format(i,6,CentreAlign,Hex);

Functionality

Always check the formatter's interface to see what setters are available to the type you wish to format. Although there are common formatting parameters, they are few and these will usually vary from type to type.

Performance

Some results from tests on a 64 bit gentoo installed on a dual core II computer while formatting both integer and float types indicate that when used in conjunction with TextStream, the formatters are 7-30x faster than their printf and iostream equivalents (which perform roughly as well as each other). Run the test program for evaluation on your machine.

Health Hazards

There are some awkward aspects of streaming that make it difficult for the formatters to function perfectly. Without going into the details, there are various issues with the unspecifiedness of function arguments that mean its impossible to format several objects on the same line differently, and expect the result to come back in the correct order. I haven't currently got a solution for this, so there are two options:

The second option is no good - it just turns TextStream into a heavyweight iostream. A priority for us is fast logging, so we must keep TextStream lightweight and since 1) is merely a coding style issue, that's easy to handle so long as we are aware of it.

Permitted Usage

                ostream << "[" << format(q.x());
                ostream << ", " << format(q.y());
                ostream << ", " << format(q.z()) << "]";

Not permitted Usage

                ostream << "[" << format(q.x()) << ", " << format(q.y()) ostream << ", " << format(q.z()) << "]";

In debug mode, formatters use an exception throwing assert to check that multiple formatters aren't used in the one line when streaming.

Types

Formatters cover all the basic fundamental types (char, float, double, int...). They also cover a few special types, including arrays - refer to the documentation for ecl_containers for more information.

Writing Your Own Formatters

Formatters must implement

                class MatrixFormatter {
                  public:
                          MatrixFormatter& precision(int p);     // Setter
                          MatrixFormatter& operator()(Matrix M); // Input Operator
                          MatrixFormatter& operator(int p, int w ... ); // Combination setter
                          MatrixFormatter& operator(Matrix M, int p, int w ...); //Temporary formatting operator
                          template <typename OutputStream, typename N> friend OutputStream& operator << (OutputStream& ostream, MatrixFormatter& formatter);
                }

Note that the setters and operators must return the formatter so that the friend function can implement the formatting.

For the Format<Type> class to automagically find this formatter, you can implement one of two methods. If you have access to the class's internals, simply typedef it as "Formatter" inside the class, otherwise simply specialise the Format<> class for your type and inherit the formatter.

                // Method one, if you have access to the classes internals
                class Matrix {
                public:
                    typedef MatrixFormatter Formatter;
                };
                // Method two
                template <>
                class Format<Matrix> : public MatrixFormatter {};

ConverterList

Each standard formatter is a template specialisation of the form Format<inputType> where the available input types are:

Note, as with any string based object, avoid it if you need speed with your streaming.

unitTests

ChangeLog



ecl_formatters
Author(s): Daniel Stonier
autogenerated on Sun Oct 5 2014 23:35:27