I/O Formatting Manipulators | |||
| |||
1. | ||||||||||||||||||||
1.1. | ||||||||||||||||||||
1.2. | ||||||||||||||||||||
2. | ||||||||||||||||||||
2.1. | ||||||||||||||||||||
2.2. | ||||||||||||||||||||
2.3. | ||||||||||||||||||||
3. | ||||||||||||||||||||
3.1. | ||||||||||||||||||||
3.2. | ||||||||||||||||||||
3.3. | ||||||||||||||||||||
3.3.1. | ||||||||||||||||||||
3.3.2. | ||||||||||||||||||||
3.3.3. | ||||||||||||||||||||
3.3.4. | ||||||||||||||||||||
3.4. | ||||||||||||||||||||
4. | ||||||||||||||||||||
4.1. | ||||||||||||||||||||
4.1.1. | ||||||||||||||||||||
4.1.2. | ||||||||||||||||||||
4.1.3. | ||||||||||||||||||||
4.1.4. | ||||||||||||||||||||
4.2. | ||||||||||||||||||||
4.2.1. | ||||||||||||||||||||
4.2.2. | ||||||||||||||||||||
5. | ||||||||||||||||||||
5.1. | ||||||||||||||||||||
5.2. | ||||||||||||||||||||
5.3. | ||||||||||||||||||||
5.3.1. | ||||||||||||||||||||
5.4. | ||||||||||||||||||||
5.5. | ||||||||||||||||||||
5.5.1. | ||||||||||||||||||||
5.6. | ||||||||||||||||||||
5.6.1. | ||||||||||||||||||||
6. | ||||||||||||||||||||
7. | ||||||||||||||||||||
7.1. | ||||||||||||||||||||
7.2. | ||||||||||||||||||||
8. | ||||||||||||||||||||
|
1 |
Introduction |
1.1. The Problem |
The C++ Input/Output
library provides a mechanism for customizing the way a class is
represented on a linear text stream. There are output operations for the
basic data types as well as for std::complex and other data types in
the standard library. |
Having said that,
there are no output operations for any of the STL container types. There
is a reason for this: how do we represent the list? Different applications
would want different ways for the list to be represented, so there is no
easy way to specify a default format. What if you need to output a
sub-list? Or have the same format across different container types? Or
have different formatting for different objects that have the same
container type? |
1.2. The Solution |
Designing a library
that can cope with these problems, as well as others not considered here,
while remaining efficient is no easy task. There are other attempts to
solve these sorts of problems. |
The motivation behind
using manipulators is that they are already designed into the C++ I/O
library and require little overhead in the output process. They also give
the user maximum choice in how the
data being outputted is formatted. |
2 |
Getting Started |
In order to output a
container or C-style array, you need to work out what form the manipulator
will take. This section will outline how to construct this for most types.
[Note: Work
from the outermost part in when you have a complex type.] |
2.1. Outermost Construct |
For a container that
has a begin() and end() function returning a forward
iterator (including the STL-based containers and std::string), you can use
the formatlist manipulator
simply passing that container. |
For C-style arrays and
strings, you need to supply the start and end points as parameters to
fortmatlist. This form can also
be used for sub-lists. |
For other constructs
(such as std::pair), use fortmatob with the appropriate
outputter. See the std::pair and
std::complex output example to
see a usage of this. |
2.2. std::map; std::pair and
std::complex |
For std::pair, you
need to bind a pair_output outputter to the formatlist manipulator; for
std::complex, you only need to do this if you want to override the default
formatting behaviour. This is needed for std::map objects because they
iterate over std::pair types. |
examples: std::pair and std::complex output |
2.3. nD array and container types |
For array constructs,
you need to use an array_output outputter and specify the length of the
array. |
For container
constructs, you need to use an array_output outputter; this will output
the entire length of that container. |
[Note: You can mix array and
container constructs. ] |
3 |
Formatter Objects |
3.1. Overview |
The formatter object
forms the basis for all formatting configuration within this library.
|
[Example:
boost::io::formatter< char > fmt;
fmt.format( '(' , ')' ); |
[Example:
boost::io::formatter< char * > fmt2;
fmt2.format( "--" ).space( true, true
); |
3.2.
boost::io::details::format_traits |
include: <boost/io/detail/format_traits.hpp>
implementation: <boost/io/detail/format_traits.ipp> |
[Note: This class is part of
the implementation details, and should only be extended to support format
types not provided for here, such as std::basic_string types. It is also
not intended for general use. ] |
The format_traits class provides the
default values for the format constants in a formatter object. It has the
following form: |
template<> class boost::io::details::format_traits< FormatType
>
{
public:
static FormatType open_default;
static FormatType close_default;
static FormatType
separator_default; public:
static inline bool isok( FormatType )
throw(); }; |
|
3.3. boost::io::formatter_t |
include: <boost/io/formatter.hpp>
implementation: <boost/io/detail/formatter.ipp> |
[todo] |
3.3.1. Formatting Options |
[todo] |
3.3.2. Spacing Options |
[todo] |
3.3.3. Configuration From Another Formatter
Object |
[todo] |
3.3.4. Constructors |
[todo] |
3.4. boost::io::formatter |
include: <boost/io/formatter.hpp>
implementation: <boost/io/detail/formatter.ipp> |
[todo] |
4 |
The Manipulators |
4.1. Format List |
include: <boost/io/formatlist.hpp>
implementation: <boost/io/detail/formatlist.ipp> |
The list formatting
manipulators provide the mechanism for rendering lists to an output
stream. |
4.1.1. boost::io::formatlist_t |
[todo] |
4.1.2. boost::io::formatlist |
These are the basic
forms of the formatlist
manipulator. |
template< typename ForwardIterator >
inline boost::io::formatlist_t< ForwardIterator > boost::io::formatlist
(
ForwardIterator first,
ForwardIterator last ); |
This specifies a list
from first to last that is to be rendered to the
output stream. |
[Example:
int i[ 4
] = { 3, 6,
9, 12 };
std::cout << boost::io::formatlist( i, i + 4 ); |
template< class Container >
inline boost::io::formatlist_t< typename Container::iterator > boost::io::formatlist
(
Container & c ); |
This specifies a
container to be rendered to the output stream, and is equivalent to
boost::io::formatlist( c.begin(),
c.end()) |
[Example:
std::vector< int > v( 10
);
std::generate( v.begin(), v.end(), std::rand );
std::cout << boost::io::formatlist( v ); |
The following forms of
the list format manipulator accept a formatter object to specify how the
list is rendered. |
[Note: These manipulator forms
will inherit the format type from the formatter object, and thus it does
not need to be explicitly specified. ] |
template< typename ForwardIterator, typename FormatType, class RefType >
inline boost::io::formatlist_t< ForwardIterator,
FormatType > boost::io::formatlist
(
ForwardIterator first,
ForwardIterator last,
const boost::io::formatter_t< FormatType, RefType >
& fmt ); |
This specifies a list
from first to last that is to be rendered to the
output stream using the formatting specified in fmt as its default values. |
[Example:
std::cout << boost::io::formatlist( i, i + 4, fmt );
std::cout << boost::io::formatlist( i, i + 4, fmt2 ); |
template< class Container, typename FormatType, class RefType >
inline boost::io::formatlist_t< typename Container::iterator, FormatType >
boost::io::formatlist
(
Container & c,
const boost::io::formatter_t< FormatType, RefType >
& fmt ); |
This specifies a
container that is to be rendered to the output stream using the formatting
specified in fmt as its default
values. |
[Example:
std::cout << boost::io::formatlist( v, fmt );
std::cout << boost::io::formatlist( v, fmt2
); |
4.1.3. boost::io::formatlistex |
These variants on the
basic list format manipulator are to allow wide character and string types
to be used. |
template< typename FormatType, typename ForwardIterator >
inline boost::io::formatlist_t< ForwardIterator,
FormatList > boost::io::formatlistex
(
ForwardIterator first,
ForwardIterator last ); |
This specifies FormatType and should be used if you
need string or wide-character types. This is the list range version.
|
[Example:
char * str = "Hello World!" ;
std::cout << boost::io::formatlistex< char * >( str, str + std::strlen( str )).format( "==>" , "<=="
); |
template< typename FormatType, class Container >
inline boost::io::formatlist_t< typename Container::iterator, FormatList >
boost::io::formatlistex
(
Container & c ); |
This specifies FormatType and should be used if you
need string or wide-character types. This is the container version.
|
[Example:
std::list< char > l;
l.push_back( 'A' );
l.push_back( 'B' );
l.push_back( 'C' );
std::cout << boost::io::formatlistex< char * >( l ).format( "==" ).space( true,
true ); |
4.1.4. boost::io::formatlistfn |
These variants on the
basic list format manipulator allow the user to specify the way each item
in the list is rendered. For a more detailed description of what
outputters are, see the relevant section. |
For examples of these
manipulators, see the outputter section. |
[Note: These manipulator forms
will inherit the format type from the outputter object, and thus it does
not need to be explicitly specified. ] |
template< typename ForwardIterator, typename Outputter >
inline boost::io::formatlist_t< ForwardIterator, typename Outputter::listfmt_type, Outputter >
boost::io::formatlistfn
(
ForwardIterator first,
ForwardIterator last,
Outputter out ); |
This is the sub-list
variant. |
template< class Container, typename Outputter >
inline boost::io::formatlist_t< typename Container::iterator, typename Outputter::listfmt_type, Outputter >
boost::io::formatlistfn
(
Container c,
Outputter out ); |
This is the STL
container variant. |
These variants allow
both outputter and default formatting to be specified, completing the set.
|
[Note: These manipulator forms
will inherit the format type from the outputter object, and thus it does
not need to be explicitly specified. This must be the same as the format
type used in the formatter object used to inherit the string values. ] |
template< typename ForwardIterator, class Outputter, class RefType >
inline boost::io::formatlist_t< ForwardIterator, typename Outputter::listfmt_type, Outputter >
boost::io::formatlistfn
(
ForwardIterator first,
ForwardIterator last,
Outputter o,
const boost::io::formatter_t< typename Outputter::listfmt_type, RefType >
& fmt ); |
This is the sub-list
variant. |
template< class Container, class Outputter, class RefType >
inline boost::io::formatlist_t< typename Container::iterator, typename Outputter::listfmt_type, Outputter >
boost::io::formatlistfn
(
Container & c,
Outputter o,
const boost::io::formatter_t< typename Outputter::listfmt_type, RefType >
& fmt ); |
This is the STL
container variant. |
4.2. Format Object |
include: <boost/io/formatob.hpp>
implementation: <boost/io/detail/formatob.ipp> |
[to do] |
4.2.1. boost::io::formatob_t |
[todo] |
4.2.2. boost::io::formatob |
[todo] |
5 |
Outputters |
include: <boost/io/format_objects.hpp> |
5.1. Outputter Function Objects |
[todo] |
5.2. boost::io::basic_output |
implementation: <boost/io/format_objects/detail/basic_output.ipp> |
[todo] |
5.3. boost::io::pair_output |
5.4.
boost::io::detail::list_output |
implementation: <boost/io/format_objects/detail/list_output.ipp> |
[todo] |
[Note: This class is part of
the implementation details. It encapsulates the list rendering
functionality used by boost::io::formatlist_t, boost::io::array_output and boost::io::container_output. You
should use one of those classes if you want list rendering functionality.
] |
5.5. boost::io::container_output |
implementation: <boost/io/format_objects/detail/container_output.ipp> |
[todo] |
5.5.1. Generators |
[todo] |
5.6. boost::io::array_output |
6 |
Portability |
The code has been
succesfully tested on:
|
The code does not work
on the following:
|
[Note: I do not have the
facilities to test it on other machines/compilers. ] |
7 |
Future Directions |
7.1. Position/Context Information |
Adding support for
position information within a list. This would allow more advanced
formatting, like numbering each item or providing special formatting for
brace elements (i.e. the middle extension glyph). |
I am currently
thinking of supporting this as an extra (optional) parameter to the
function operator of the output functor. This parameter will be a
context-information object from the parent outputter that gives
information such as the length of the sub-list being outputted and the
current position within that sub-list. Other information may be added at a
future date. |
7.2. pre/post-separator output |
Add support for
outputting a string before and after a separator. This would simplify the
rendering of more more advanced constructs such as XML tags. |
8 |
Acknowledgements |
This library was
designed and implemented by Reece H. Dunn. |
The output functors
were based on a comment in the "IO for STL containers" thread on the boost
developers mailing list. |
Special thanks to:
|