I/O Formatting Manipulators

1.   Introduction
1.1.   The Problem
1.2.   The Solution
2.   Formatter Objects
2.1.   Overview
2.2.   boost::io::format_traits
2.3.   boost::io::formatter_t
2.3.1.   Formatting Options
2.3.2.   Spacing Options
2.3.3.   Configuration From Another Formatter Object
2.3.4.   Constructors
2.4.   boost::io::formatter
3.   The Manipulators
3.1.   Overview
3.2.   boost::io::formatlist_t
3.3.   boost::io::formatlist
3.4.   boost::io::formatlistex
3.5.   boost::io::formatlistfn
4.   Outputters
4.1.   Outputter Function Objects
4.2.   boost::io::basic_output
4.3.   boost::io::stdpair_output
4.4.   boost::io::detail::list_output
4.5.   boost::io::container_output
4.6.   boost::io::array_output
5.   Portability
6.   Future Directions
6.1.   Position/Context Information
6.2.   boost::io::stdpair_output manipulators
7.   Acknowledgements

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

Formatter Objects
2.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 );
]
2.2. boost::io::format_traits
 
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::format_traits< FormatType >
{
public:
static FormatType open_default;
static FormatType close_default;
static FormatType separator_default;
public:
static inline bool isok( FormatType ) throw();
};
 
attribute/method description
open_default The default value for the open list parameter.
close_default The default value for the close list parameter.
separator_default The default value for the separator parameter.
isok Checks to see if the FormatType value is ok to be rendered.
 
[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. ]
2.3. boost::io::formatter_t
 
[todo]
2.3.1. Formatting Options
 
[todo]
2.3.2. Spacing Options
 
[todo]
2.3.3. Configuration From Another Formatter Object
 
[todo]
2.3.4. Constructors
 
[todo]
2.4. boost::io::formatter
 
[todo]
3

The Manipulators
3.1. Overview
 
The list formatting manipulators provide the mechanism for rendering lists to an output stream.
3.2. boost::io::formatlist_t
 
[todo]
3.3. 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())
but is shorter to write.
 
[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 );
[Note: This example makes use of variables defined in earlier examples. ]]
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 );
[Note: This example makes use of variables defined in earlier examples. ]]
3.4. 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 );
]
3.5. 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.
4

Outputters
4.1. Outputter Function Objects
 
[todo]
4.2. boost::io::basic_output
 
[todo]
4.3. boost::io::stdpair_output
 
[todo]
4.4. boost::io::detail::list_output
 
[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. ]
4.5. boost::io::container_output
 
[todo]
4.6. boost::io::array_output
 
[todo]
5

Portability
 
The code has been succesfully tested on:
  1. MSVC 7.0;
  2. Borland C++Compiler 5.5.1;
  3. GNU G++ 3.0.3 (under the i686-pc-cygwin environment)
in the Win32 environment on a Windows XP/Pentium II machine.
 
The code does not work on the following:
  1. GNU G++ 2.95.3-5 (under the i686-pc-cygwin environment).
 
[Note: I do not have the facilities to test it on other machines/compilers. ]
6

Future Directions
6.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.
6.2. boost::io::stdpair_output manipulators
 
Add support for being able to output std::pair and std::complex objects that are the root object and are not contained within lists.
7

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:
[1]
Paul A. Bristow: For his comments and suggestions, especially getting me to think about supporting nD constructs.
[2]
Terje Slettebø: For his feedback on standard/boost issues in my code.
[3]
Gennadiy Rozental: For issues relating to the documentation.
[4]
Martin Henson: For giving me a reason to create the library in the first place!

Copyright © 2003 Reece H. Dunn