This library contains various utilities for the standard I/O library.
IO State Savers, <boost/io/ios_state.hpp>
Description
The header <boost/io/ios_state.hpp>
covers saving the stream state of objects
in the C++ IOStreams system.
Rationale
Sometimes a certain value has to change only for a limited scope. Saver classes save a copy of the current state of some object (or an aspect of an object), and reset the object’s state at destruction time, undoing any change the object may have gone through.
The saver class strategy is helpful when using I/O stream objects. Manipulator objects can change some aspect of a stream during input or output. The state changed by the manipulator usually sticks to its new value after the I/O transaction. This can be a problem if manipulators are used in a function that is not supposed to externally change a stream’s state.
#include <ostream>
#include <ios>
void hex_my_byte(std::ostream& os, char byte)
{
os << std::hex << static_cast<unsigned>(byte);
}
The os
stream will retain its new hexadecimal printing mode after the call to
hex_my_byte
. The stream’s printing mode can be saved and restored with manual
calls to the stream’s state inspecting and mutating member functions. The
manual method becomes unwieldy if the main functionality is complex and/or
needs to be exception safe. A saver class can implement the better
"resource acquisition is initialization" strategy.
See the example below for better code, using saver classes.
Header Synopsis
namespace boost {
namespace io {
class ios_flags_saver;
class ios_precision_saver;
class ios_width_saver;
class ios_base_all_saver;
template<class Ch, class Tr = std::char_traits<Ch> >
class basic_ios_iostate_saver;
template<class Ch, class Tr = std::char_traits<Ch> >
class basic_ios_exception_saver;
template<class Ch, class Tr = std::char_traits<Ch> >
class basic_ios_tie_saver;
template<class Ch, class Tr = std::char_traits<Ch> >
class basic_ios_rdbuf_saver;
template<class Ch, class Tr = std::char_traits<Ch> >
class basic_ios_fill_saver;
template<class Ch, class Tr = std::char_traits<Ch> >
class basic_ios_locale_saver;
template<class Ch, class Tr = std::char_traits<Ch> >
class basic_ios_all_saver;
typedef basic_ios_iostate_saver<char> ios_iostate_saver;
typedef basic_ios_iostate_saver<wchar_t> wios_iostate_saver;
typedef basic_ios_exception_saver<char> ios_exception_saver;
typedef basic_ios_exception_saver<wchar_t> wios_exception_saver;
typedef basic_ios_tie_saver<char> ios_tie_saver;
typedef basic_ios_tie_saver<wchar_t> wios_tie_saver;
typedef basic_ios_rdbuf_saver<char> ios_rdbuf_saver;
typedef basic_ios_rdbuf_saver<wchar_t> wios_rdbuf_saver;
typedef basic_ios_fill_saver<char> ios_fill_saver;
typedef basic_ios_fill_saver<wchar_t> wios_fill_saver;
typedef basic_ios_locale_saver<char> ios_locale_saver;
typedef basic_ios_locale_saver<wchar_t> wios_locale_saver;
typedef basic_ios_all_saver<char> ios_all_saver;
typedef basic_ios_all_saver<wchar_t> wios_all_saver;
class ios_iword_saver;
class ios_pword_saver;
class ios_all_word_saver;
} // io
} // boost
Savers for Basic Standard Attributes
The basic saver classes have this format:
class saver {
public:
typedef std::ios_base state_type;
typedef implementation_defined
aspect_type;
explicit saver(state_type& s);
saver(state_type& s, const aspect_type& new_value);
~saver();
void restore();
};
The state_type
is the IOStreams base class std::ios_base
. The user would
usually place an actual input, output, or combined stream object for the
state-type parameter, and not a base class object. The first constructor takes
a stream object and saves a reference to the stream and the current value of a
particular stream attribute. The second constructor works like the first, and
uses its second argument to change the stream’s attribute to the new
aspect_type
value given. The destructor restores the stream’s attribute to
the saved value. The restoration can be activated early (and often) with the
restore
member function.
Class | Saved Attribute | Attribute Type | Reading Method | Writing Method |
---|---|---|---|---|
|
Format control flags |
|
|
|
|
Number of digits to print after decimal point |
|
|
|
|
Minimum field width for printing objects |
|
|
|
Savers for Advanced Standard Attributes
The saver class templates have this format:
template<class Ch, class Tr>
class saver {
public:
typedef std::basic_ios<Ch, Tr> state_type;
typedef implementation-defined
aspect_type;
explicit saver(state_type& s);
saver(state_type& s, const aspect_type& new_value);
~saver();
void restore();
};
The state_type
is a version of the IOStreams base class template
std::basic_ios<Ch, Tr>
, where Ch
is a character type and Tr
is a
character traits class. The user would usually place an actual input,
output, or combined stream object for the state-type parameter, and not a base
class object. The first constructor takes a stream object and saves a reference
to the stream and the current value of a particular stream attribute. The
second constructor works like the first, and uses its second argument to change
the stream’s attribute to the new aspect_type
value given. The destructor
restores the stream’s attribute to the saved value. The restoration can be
activated early (and often) with the restore
member function.
Class | Saved Attribute | Attribute Type | Reading Method | Writing Method |
---|---|---|---|---|
|
Failure state of the stream [1], [2] |
|
|
|
|
Which failure states trigger an exception [1] |
|
|
|
|
Output stream synchronized with the stream |
|
|
|
|
Stream buffer associated with the stream [2] |
|
|
|
|
Character used to pad oversized field widths |
|
|
|
|
Locale information associated with the stream [3] |
|
|
|
Notes
-
When the failure state flags and/or the failure state exception watching flags are changed, an exception is thrown if a match occurs among the two sets of flags. This could mean that the constructor or destructor of these class templates may throw.
-
When the associated stream buffer is changed, the stream’s failure state set is reset to "good" if the given stream buffer’s address is non-NULL, but the "bad" failure state is set if that address is NULL. This means that a saved failure state of "good" may be restored as "bad" if the stream is stripped of an associated stream buffer. Worse, given a NULL stream buffer address, an exception is thrown if the "bad" failure state is being watched. This could mean that the constructor or destructor of these class templates may throw.
-
The saver for the locale uses the
std::basic_ios<Ch, Tr>
class to extract their information, although it could have used the functionality instd::ios_base
. The problem is that the versions of the needed member functions inios_base
are not polymorphically related to the ones inbasic_ios
. The stream classes that will be used with the saver classes should use the versions of the member functions closest to them by inheritance, which means the ones inbasic_ios
.
Savers for User-Defined Attributes
There are three class (templates) for combined attribute savers. The
ios_base_all_saver
saver class combines the functionality of all the basic
attribute saver classes. It has a constructor that takes the stream to have its
state preserved. The basic_ios_all_saver
combines the functionality of all
the advanced attribute saver class templates and the combined basic attribute
saver class. It has a constructor that takes the stream to have its state
preserved. The ios_all_word_saver
saver class combines the saver classes that
preserve user-defined formatting information. Its constructor takes the stream
to have its attributes saved and the index of the user-defined attributes. The
destructor for each class restores the saved state. Restoration can be
activated early (and often) for a class with the restore member function.
Example
The code used in the rationale can be improved at two places. The printing function could use a saver around the code that changes the formatting state. Or the calling function can surround the call with a saver. Or both can be done, especially if the user does not know if the printing function uses a state saver. If the user wants a series of changes back and forth, without surrounding each change within a separate block, the restore member function can be called between each trial.
#include <boost/io/ios_state.hpp>
#include <ios>
#include <iostream>
#include <ostream>
void new_hex_my_byte(std::ostream& os, char byte)
{
boost::io::ios_flags_saver ifs(os);
os << std::hex << static_cast<unsigned>(byte);
}
int main()
{
// ...
{
boost::io::ios_all_saver ias(std::cout);
new_hex_my_byte(std::cout, 'A');
}
// ...
{
boost::io::ios_all_saver ias(std::cerr);
new_hex_my_byte(std::cerr, 'b');
ias.restore();
new_hex_my_byte(std::cerr, 'C');
}
// ...
}
Credits
Daryle Walker
Started the library. Contributed the initial versions of the format flags,
precision, width, and user-defined format flags saver classes. Contributed the
initial versions of the success state, success state exception flags, output
stream tie, stream buffer, character fill, and locale saver class templates.
Contributed the combined attribute classes and class template. Contributed the
test file ios_state_test.cpp
.
History
20 Dec 2019
Glen Fernandes made all the saver classes non-copyable.
28 Feb 2005
Daryle Walker added the restore member functions, based on suggestions by Gennadiy Rozental and Rob Stewart.
13 Mar 2002
Daryle Walker implemented the initial version.
Quoted Manipulators, <boost/io/quoted.hpp>
Introduction
C++ Standard library stream I/O for strings that contain embedded spaces can produce unexpected results. For example,
std::stringstream ss;
std::string original = "fooled you";
std::string roundtrip;
ss << original;
ss >> roundtrip;
std::cout << original; // outputs: fooled you
std::cout << roundtrip; // outputs: fooled
assert(original == roundtrip); // assert will fire
The Boost quoted stream I/O manipulator places delimiters, defaulted to the double-quote ("), around strings on output, and strips off the delimiters on input. This ensures strings with embedded spaces round-trip as desired. For example,
std::stringstream ss;
std::string original = "fooled you";
std::string roundtrip;
ss << quoted(original);
ss >> quoted(roundtrip);
std::cout << quoted(original); // outputs: "fooled you"
std::cout << roundtrip; // outputs: fooled you
assert(original == roundtrip); // assert will not fire
If the string contains the delimiter character, on output that character will be preceded by an escape character, as will the escape character itself:
std::cout << quoted("'Jack & Jill'", '&', '\''); // outputs: '&'Jack && Jill&''
Header synopsis
namespace boost {
namespace io {
template<class Char, class Traits, class Alloc>
unspecified-type1
quoted(const std::basic_string<Char, Traits, Alloc>& string,
Char escape='\\', Char delim='\"');
template<class Char>
unspecified-type2
quoted(const Char* string, Char escape='\\', Char delim='\"');
template<class Char, class Traits, class Alloc>
unspecified-type3
quoted(std::basic_string<Char, Traits, Alloc>& string,
Char escape='\\', Char delim='\"');
} // io
} // boost
unspecified-type1, unspecified-type2, and unspecified-type3 are
implementation supplied types with implementation supplied operator<<
:
template<class Char, class Traits>
std::basic_ostream<Char, Traits>&
operator<<(std::basic_ostream<Char, Traits>& os,
const unspecified-typeN
& proxy);
- Effects
-
Inserts characters into
os
:-
delim
-
Each character in
string
. If the character to be output is equal toescape
ordelim
, as determined byoperator==
, first outputescape
. -
delim
-
- Remarks
-
string
,escape
, anddelim
have the type and value of the corresponding arguments of the call to thequoted
function that constructedproxy
. - Returns
-
os
.
unspecified-type3 is an implementation supplied type with an implementation
supplied operator>>
:
template<class Char, class Traits>
std::basic_istream<Char, Traits>&
operator>>(std::basic_istream<Char, Traits>& is,
const unspecified-type3
& proxy);
- Effects
-
Extracts characters from
os
:-
If the first character extracted is equal to
delim
, as determined byoperator==
, then:-
Turn off the
skipws
flag. -
string.clear()
-
Until an unescaped
delim
character is reached oris.not_good()
, extract characters fromos
and append them to string, except that if an escape is reached, ignore it and append the next character to string. -
Discard the final
delim
character. -
Restore the
skipws
flag to its original value.
-
-
Otherwise,
os >> string
.
-
- Remarks
-
string
,escape
, anddelim
have the type and value of the corresponding arguments of the call to thequoted
function that constructedproxy
. - Returns
-
is
.
Acknowledgements
The quoted()
stream manipulator emerged from discussions on the Boost
developers mailing list. Participants included Beman Dawes, Rob Stewart,
Alexander Lamaison, Eric Niebler, Vicente Botet, Andrey Semashev,
Phil Richards, and Rob Murray. Eric Niebler’s suggestions provided the basis
for the name and form of the templates.
Beman Dawes started the implementation of quoted()
as a private detail
header. Glen Fernandes updated the implementation and also made it public.
Glen Fernandes corrected the implementation to properly account for stream width and fill, and optimized it to write directly to the stream buffer.
Delimited Iterators, <boost/io/ostream_joiner.hpp>
Description
The header <boost/io/ostream_joiner.hpp>
provides the class template
boost::io::ostream_joiner
which is an output iterator that writes objects to
a std::basic_ostream
separated by a delimiter. It is an implementation of
the Library Fundamentals TS std::ostream_joiner
which supports C++03 and
higher.
Example
The following program writes the contents of a vector to standard output, with each element separated by a comma.
#include <boost/io/ostream_joiner.hpp>
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v;
v.push_back(2);
v.push_back(4);
v.push_back(6);
v.push_back(8);
std::copy(v.begin(), v.end(), boost::make_ostream_joiner(std::cout, ','));
}
Reference
Header Synopsis
namespace boost {
namespace io {
template<class Delim, class Char = char,
class Traits = std::char_traits<Char> >
class ostream_joiner {
public:
typedef Char char_type;
typedef Traits traits_type;
typedef std::basic_ostream<Char, Traits> ostream_type;
typedef std::output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
ostream_joiner(ostream_type& output, const Delim& delim);
ostream_joiner(ostream_type& output, Delim&& delim);
template<class T>
ostream_joiner& operator=(const T& value);
ostream_joiner& operator*() noexcept;
ostream_joiner& operator++() noexcept;
ostream_joiner& operator++(int) noexcept;
};
template<class Char, class Traits, class Delim>
ostream_joiner<std::decay_t<Delim>, Char, Traits>
make_ostream_joiner(std::basic_ostream<Char, Traits>& output, Delim&& delim);
} // io
} // boost
Constructors
ostream_joiner(ostream_type& output, const Delim& delim);
- EFfects
-
Initializes the stored reference to the stream with
std::addressof(output)
and the stored delimiter withdelim
.
ostream_joiner(ostream_type& output, Delim&& delim);
- EFfects
-
Initializes the stored reference to the stream with
std::addressof(output)
and the stored delimiter withstd::move(delim)
.
Member functions
template<class T>
ostream_joiner& operator=(const T& value);
- Effects
-
If the is the first call to this member function, write the stored delimiter to the stored stream reference. Writes
value
to the stored stream reference. - Returns
-
*this
.
ostream_joiner& operator*() noexcept;
ostream_joiner& operator++() noexcept;
ostream_joiner& operator++(int) noexcept;
- Returns
-
*this
.
Free functions
template<class Char, class Traits, class Delim>
ostream_joiner<decay_t<Delim>, Char, Traits>
make_ostream_joiner(std::basic_ostream<Char, Traits>& output, Delim&& delim);
- Returns
-
ostream_joiner<std::decay_t<Delim>, Char, Traits>(output, std::forward<Delim>(delim))
.
Acknowledgments
Glen Fernandes implemented ostream_joiner
and make_ostream_joiner
.
Insert Formatted Output, <boost/io/ostream_put.hpp>
Description
The header <boost/io/ostream_put.hpp>
provides the function template
boost::io::ostream_put
for formatted output that satisfies the requirements
of [ostream.formatted.reqmts].
Example
The inserter for class template basic_string_view
could be implemented as
follows:
template<class charT, class traits>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const basic_string_view<charT, traits>& str)
{
return boost::io::ostream_put(os, str.data(), str.size());
}
Reference
Header Synopsis
namespace boost {
namespace io {
template<class charT, class traits>
std::basic_ostream<charT, traits>&
ostream_put(std::basic_ostream<charT, traits>& os,
const charT* data, std::size_t size);
} // io
} // boost
Free functions
template<class charT, class traits>
std::basic_ostream<charT, traits>&
ostream_put(std::basic_ostream<charT, traits>& os,
const charT* data, std::size_t size);
- Effects
-
Behaves like a formatted inserter (as described in [ostream.formatted.reqmts]) of
os
. Creates a character sequenceseq
of size characters starting atdata
, each widened usingos.widen()
([basic.ios.members]). Determines padding forseq
as described in [ostream.formatted.reqmts]. Insertsseq
intoos
. Callswidth(0)
. - Returns
-
os
.
Acknowledgments
Glen Fernandes updated the implementation of the basic_string_ref
and
basic_string_view
stream insertion operators to write directly to the
basic_streambuf
and refactored that functionality into this common utility.
Copyright and License
-
Copyright 2002 Daryle Walker
-
Copyright 2002, 2006, 2007, 2009, 2010 Beman Dawes
-
Copyright 2019 Glen Joseph Fernandes
Distributed under the Boost Software License, Version 1.0.