123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
- <html>
- <head>
- <title>I/O Stream-State Saver Library</title>
- </head>
- <body text="black" bgcolor="white" link="blue" vlink="purple" alink="red">
- <h1><img src="../../../boost.png" alt="boost.png (6897 bytes)"
- align="middle" width="277" height="86">Header <<cite><a
- href="../../../boost/io/ios_state.hpp">boost/io/ios_state.hpp</a></cite>
- ></h1>
- <p>The header <cite><a
- href="../../../boost/io/ios_state.hpp">boost/io/ios_state.hpp</a></cite>
- covers saving the stream state of objects in the C++ IOStreams
- system.</p>
- <h2><a name="contents">Contents</a></h2>
- <ol>
- <li><a href="#contents">Contents</a></li>
- <li><a href="#rationale">Rationale</a></li>
- <li><a href="#header">Header Synopsis</a></li>
- <li><a href="#base_savers">Savers for Basic Standard Attributes</a></li>
- <li><a href="#adv_savers">Savers for Advanced Standard Attributes</a></li>
- <li><a href="#user_savers">Savers for User-Defined Attributes</a></li>
- <li><a href="#combo_savers">Savers for Combined Attributes</a></li>
- <li><a href="#example">Example</a></li>
- <li><a href="#refer">References</a></li>
- <li><a href="#credits">Credits</a>
- <ul>
- <li><a href="#contributors">Contributors</a></li>
- <li><a href="#history">History</a></li>
- </ul></li>
- </ol>
- <h2><a name="rationale">Rationale</a></h2>
- <p>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.</p>
- <p>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.</p>
- <blockquote><pre>#include <ostream>
- #include <ios>
- void hex_my_byte( std::ostream &os, char byte )
- {
- os << std::hex << static_cast<unsigned>(byte);
- }
- </pre></blockquote>
- <p>The <var>os</var> stream will retain its new hexadecimal printing
- mode after the call to <code>hex_my_byte</code>. 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.</p>
- <p>See the <a href="#example">example</a> below for better code, using
- saver classes.</p>
- <h2><a name="header">Header Synopsis</a></h2>
- <blockquote><pre>#include <iosfwd> <i>// for std::char_traits (declaration)</i>
- namespace boost
- {
- namespace io
- {
- class ios_flags_saver;
- class ios_precision_saver;
- class ios_width_saver;
- class ios_base_all_saver;
- template < typename Ch, class Tr = ::std::char_traits<Ch> >
- class basic_ios_iostate_saver;
- template < typename Ch, class Tr = ::std::char_traits<Ch> >
- class basic_ios_exception_saver;
- template < typename Ch, class Tr = ::std::char_traits<Ch> >
- class basic_ios_tie_saver;
- template < typename Ch, class Tr = ::std::char_traits<Ch> >
- class basic_ios_rdbuf_saver;
- template < typename Ch, class Tr = ::std::char_traits<Ch> >
- class basic_ios_fill_saver;
- template < typename Ch, class Tr = ::std::char_traits<Ch> >
- class basic_ios_locale_saver;
- template < typename 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;
- }
- }
- </pre></blockquote>
- <h2><a name="base_savers">Savers for Basic Standard Attributes</a></h2>
- <p>The basic saver classes have this format:</p>
- <blockquote><pre>class <var>saver_class</var>
- {
- typedef std::ios_base state_type;
- typedef <i>implementation_defined</i> aspect_type;
- explicit saver_class( state_type &s );
- saver_class( state_type &s, <var>aspect_type</var> const &new_value );
- ~saver_class();
- void restore();
- };
- </pre></blockquote>
- <p>The <var>state_type</var> is the IOStreams base class
- <code>std::ios_base</code>. 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 <var>aspect_type</var> value given. The destructor restores the
- stream's attribute to the saved value. The restoration can be activated
- early (and often) with the <code>restore</code> member function.</p>
- <table border="1" align="center">
- <caption>Basic IOStreams State Saver Classes</caption>
- <tr>
- <th>Class</th>
- <th>Saved Attribute</th>
- <th>Attribute Type</th>
- <th>Reading Method</th>
- <th>Writing Method</th>
- </tr>
- <tr>
- <td><code>boost::io::ios_flags_saver</code></td>
- <td>Format control flags</td>
- <td><code>std::ios_base::fmtflags</code></td>
- <td><code>flags</code></td>
- <td><code>flags</code></td>
- </tr>
- <tr>
- <td><code>boost::io::ios_precision_saver</code></td>
- <td>Number of digits to print after decimal point</td>
- <td><code>std::streamsize</code></td>
- <td><code>precision</code></td>
- <td><code>precision</code></td>
- </tr>
- <tr>
- <td><code>boost::io::ios_width_saver</code></td>
- <td>Minimum field width for printing objects</td>
- <td><code>std::streamsize</code></td>
- <td><code>width</code></td>
- <td><code>width</code></td>
- </tr>
- </table>
- <h2><a name="adv_savers">Savers for Advanced Standard Attributes</a></h2>
- <p>The saver class templates have this format:</p>
- <blockquote><pre>template < typename Ch, class Tr >
- class <var>saver_class</var>
- {
- typedef std::basic_ios<Ch, Tr> state_type;
- typedef <i>implementation_defined</i> aspect_type;
- explicit saver_class( state_type &s );
- saver_class( state_type &s, <var>aspect_type</var> const &new_value );
- ~saver_class();
- void restore();
- };
- </pre></blockquote>
- <p>The <var>state_type</var> is a version of the IOStreams base class
- template <code>std::basic_ios<Ch, Tr></code>, where
- <code>Ch</code> is a character type and <code>Tr</code> 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
- <var>aspect_type</var> value given. The destructor restores the stream's
- attribute to the saved value. The restoration can be activated
- early (and often) with the <code>restore</code> member function.</p>
- <table border="1" align="center">
- <caption>Advanced IOStreams State Saver Class Templates</caption>
- <tr>
- <th>Class Template</th>
- <th>Saved Attribute</th>
- <th>Attribute Type</th>
- <th>Reading Method</th>
- <th>Writing Method</th>
- </tr>
- <tr>
- <td><code>boost::io::basic_ios_iostate_saver<Ch, Tr></code></td>
- <td>Failure state of the stream <a href="#Note1">[1]</a>, <a href="#Note2">[2]</a></td>
- <td><code>std::ios_base::iostate</code></td>
- <td><code>rdstate</code></td>
- <td><code>clear</code></td>
- </tr>
- <tr>
- <td><code>boost::io::basic_ios_exception_saver<Ch, Tr></code></td>
- <td>Which failure states trigger an exception <a href="#Note1">[1]</a></td>
- <td><code>std::ios_base::iostate</code></td>
- <td><code>exceptions</code></td>
- <td><code>exceptions</code></td>
- </tr>
- <tr>
- <td><code>boost::io::basic_ios_tie_saver<Ch, Tr></code></td>
- <td>Output stream synchronized with the stream</td>
- <td><code>std::basic_ostream<Ch, Tr> *</code></td>
- <td><code>tie</code></td>
- <td><code>tie</code></td>
- </tr>
- <tr>
- <td><code>boost::io::basic_ios_rdbuf_saver<Ch, Tr></code></td>
- <td>Stream buffer associated with the stream <a href="#Note2">[2]</a></td>
- <td><code>std::basic_streambuf<Ch, Tr> *</code></td>
- <td><code>rdbuf</code></td>
- <td><code>rdbuf</code></td>
- </tr>
- <tr>
- <td><code>boost::io::basic_ios_fill_saver<Ch, Tr></code></td>
- <td>Character used to pad oversized field widths</td>
- <td><code>Ch</code></td>
- <td><code>fill</code></td>
- <td><code>fill</code></td>
- </tr>
- <tr>
- <td><code>boost::io::basic_ios_locale_saver<Ch, Tr></code></td>
- <td>Locale information associated with the stream <a href="#Note3">[3]</a></td>
- <td><code>std::locale</code></td>
- <td><code>getloc</code> (from <code>std::ios_base</code>)</td>
- <td><code>imbue</code> (from <code>std::basic_ios<Ch, Tr></code>)</td>
- </tr>
- </table>
- <h3>Notes</h3>
- <ol>
- <li>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 <a name="Note1">constructor or destructor of these class
- templates may throw</a>.</li>
- <li>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 <a name="Note2">constructor or destructor of these class
- templates may throw</a>.</li>
- <li>The <a name="Note3">saver for the locale uses the
- <code>std::basic_ios<Ch, Tr></code> class to extract their
- information</a>, although it could have used the functionality
- in <code>std::ios_base</code>. The problem is that the versions
- of the needed member functions in <code>ios_base</code> are not
- polymorphically related to the ones in <code>basic_ios</code>.
- 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
- <code>basic_ios</code>.</li>
- </ol>
- <h2><a name="user_savers">Savers for User-Defined Attributes</a></h2>
- <p>The saver classes for user-defined formatting information have this
- format:</p>
- <blockquote><pre>#include <iosfwd> <i>// for std::ios_base (declaration)</i>
- class <var>saver_class</var>
- {
- typedef std::ios_base state_type;
- typedef int index_type;
- typedef <i>implementation_defined</i> aspect_type;
- explicit saver_class( state_type &s, index_type i );
- saver_class( state_type &s, index_type i, <var>aspect_type</var> const &new_value );
- ~saver_class();
- void restore();
- };
- </pre></blockquote>
- <p>The index <var>i</var> differentiates between specific user-defined
- formatting attributes. The index can only be determined at run-time
- (most likely with the class-static <code>std::ios_base::xalloc</code>
- member function).</p>
- <p>The <var>state_type</var> is the base class of the IOStreams system,
- <code>std::ios_base</code>. 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 index 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 third argument to change the stream's
- attribute to the new <var>aspect_type</var> value given. The destructor
- restores the stream's attribute to the saved value. The restoration can
- be activated early (and often) with the <code>restore</code> member
- function.</p>
- <table border="1" align="center">
- <caption>IOStream User-Defined State Saver Classes</caption>
- <tr>
- <th>Class</th>
- <th>Saved Attribute</th>
- <th>Attribute Type</th>
- <th>Reference Method</th>
- </tr>
- <tr>
- <td><code>boost::io::ios_iword_saver</code></td>
- <td>Numeric user-defined format flag</td>
- <td><code>long</code></td>
- <td><code>iword</code></td>
- </tr>
- <tr>
- <td><code>boost::io::ios_pword_saver</code></td>
- <td>Pointer user-defined format flag</td>
- <td><code>void *</code></td>
- <td><code>pword</code></td>
- </tr>
- </table>
- <h2><a name="combo_savers">Savers for Combined Attributes</a></h2>
- <p>There are three class (templates) for combined attribute savers. The
- <code>boost:io::ios_base_all_saver</code> 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
- <code>boost::io::basic_ios_all_saver</code> 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
- <code>boost::io::ios_all_word_saver</code> 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 <code>restore</code> member function.</p>
- <h2><a name="example">Example</a></h2>
- <p>The code used in the <a href="#rationale">rationale</a> 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 & forth, without surrounding each
- change within a separate block, the <code>restore</code> member function
- can be called between each trial.</p>
- <blockquote><pre>#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()
- {
- using std::cout;
- using std::cerr;
- //...
- {
- boost::io::ios_all_saver ias( cout );
- new_hex_my_byte( cout, 'A' );
- }
- //...
- {
- boost::io::ios_all_saver ias( cerr );
- new_hex_my_byte( cerr, 'b' );
- ias.restore();
- new_hex_my_byte( cerr, 'C' );
- }
- //...
- }
- </pre></blockquote>
- <h2><a name="refer">References</a></h2>
- <ul>
- <li>The I/O state saver library header itself: <cite><a
- href="../../../boost/io/ios_state.hpp">boost/io/ios_state.hpp</a></cite></li>
- <li>Some test/example code: <cite><a
- href="../test/ios_state_test.cpp">ios_state_test.cpp</a></cite></li>
- </ul>
- <h2><a name="credits">Credits</a></h2>
- <h3><a name="contributors">Contributors</a></h3>
- <dl>
- <dt><a href="http://www.boost.org/people/daryle_walker.html">Daryle Walker</a>
- <dd>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 <cite><a
- href="../test/ios_state_test.cpp">ios_state_test.cpp</a></cite>.
- </dl>
- <h3><a name="history">History</a></h3>
- <dl>
- <dt>28 Feb 2005, Daryle Walker
- <dd>Added the <code>restore</code> member functions, based on suggestions
- by Gennadiy Rozental and Rob Stewart
- <dt>13 Mar 2002, Daryle Walker
- <dd>Initial version
- </dl>
- <hr>
- <p>Revised: 28 February 2005</p>
- <p>Copyright 2002, 2005 Daryle Walker. Use, modification, and distribution
- are subject to the Boost Software License, Version 1.0. (See accompanying
- file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or a copy at
- <<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>>.)</p>
- </body>
- </html>
|