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.

Table 1. Basic IOStreams State Saver Classes
Class Saved Attribute Attribute Type Reading Method Writing Method

ios_flags_saver

Format control flags

std::ios_base::fmtflags

flags

flags

ios_precision_saver

Number of digits to print after decimal point

std::streamsize

precision

precision

ios_width_saver

Minimum field width for printing objects

std::streamsize

width

width

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.

Table 2. Advanced IOStreams State Saver Class Templates
Class Saved Attribute Attribute Type Reading Method Writing Method

basic_ios_iostate_saver<Ch, Tr>

Failure state of the stream [1], [2]

std::ios_base::iostate

rdstate

clear

basic_ios_exception_saver<Ch, Tr>

Which failure states trigger an exception [1]

std::ios_base::iostate

exceptions

exceptions

basic_ios_tie_saver<Ch, Tr>

Output stream synchronized with the stream

std::basic_ostream<Ch, Tr>*

tie

tie

basic_ios_rdbuf_saver<Ch, Tr>

Stream buffer associated with the stream [2]

std::basic_streambuf<Ch, Tr>*

rdbuf

rdbuf

basic_ios_fill_saver<Ch, Tr>

Character used to pad oversized field widths

Ch

fill

fill

basic_ios_locale_saver<Ch, Tr>

Locale information associated with the stream [3]

std::locale

getloc (from std::ios_base)

imbue (from std::basic_ios<Ch, Tr>)

Notes

  1. 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.

  2. 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.

  3. The saver for the locale uses the std::basic_ios<Ch, Tr> class to extract their information, although it could have used the functionality in std::ios_base. The problem is that the versions of the needed member functions in ios_base are not polymorphically related to the ones in basic_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 in basic_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 to escape or delim, as determined by operator==, first output escape.

  • delim

Remarks

string, escape, and delim have the type and value of the corresponding arguments of the call to the quoted function that constructed proxy.

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 by operator==, then:

    • Turn off the skipws flag.

    • string.clear()

    • Until an unescaped delim character is reached or is.not_good(), extract characters from os 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, and delim have the type and value of the corresponding arguments of the call to the quoted function that constructed proxy.

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 with delim.

ostream_joiner(ostream_type& output, Delim&& delim);
EFfects

Initializes the stored reference to the stream with std::addressof(output) and the stored delimiter with std::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 sequence seq of size characters starting at data, each widened using os.widen() ([basic.ios.members]). Determines padding for seq as described in [ostream.formatted.reqmts]. Inserts seq into os. Calls width(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.

Null Streams, <boost/io/nullstream.hpp>

Description

The header <boost/io/nullstream.hpp> provides the class template boost::io::basic_nullbuf which is a null stream buffer and class template boost::io::basic_onullstream which is a null stream.

Example

The following program passes a null stream to a function.

#include <boost/io/ostream_joiner.hpp>
#include <fstream>

void setup(std::ostream& log);

int main(int argc, char* argv[])
{
    if (argc == 2) {
        std::ofstream file(argv[1]);
        setup(file);
    } else {
        boost::io::onullstream none;
        setup(none);
    }
}

Reference

Header Synopsis

namespace boost {
namespace io {

template<class CharT, class Traits = std::char_traits<Char> >
class basic_nullbuf
    : public std::basic_streambuf<CharT, Traits> {
protected:
    typename Traits::int_type overflow(typename Traits::int_type c) override;

    std::streamsize xsputn(const CharT*, std::streamsize n) override;
};

template<class CharT, class Traits = std::char_traits<CharT> >
class basic_onullstream
    : public std::basic_ostream<CharT, Traits> {
public:
    basic_onullstream();
};

typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;

} // io
} // boost

Acknowledgments

Glen Fernandes implemented basic_nullbuf and basic_onullstream.

  • 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.