Line data Source code
1 : // Copyright (c) 2005-2023 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/snapdev
4 : // contact@m2osw.com
5 : //
6 : // This program is free software: you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation, either version 3 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License
17 : // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 : #pragma once
19 :
20 : /** \file
21 : * \brief Save stream flags.
22 : *
23 : * When writing to a stream, you may change the flags with functions such
24 : * as `std::hex` or `std::setw()`. This class helps you save the current
25 : * state in order to be able to restore it later.
26 : *
27 : * Another way to avoid changing the flags of a stream is to use an
28 : * `std::stringstream`, do all the necessary write in that stream and
29 : * then copy the result to the other stream. This is not always possible
30 : * and this is when this class comes in handy.
31 : */
32 :
33 : // C++
34 : //
35 : #include <sstream>
36 :
37 :
38 :
39 : namespace snapdev
40 : {
41 :
42 :
43 : /** \class safe_stream
44 : * \brief A class used to safely handle stream flags, width, and precision.
45 : *
46 : * Create an object of this type on your stack, and the flags, width,
47 : * and precision of your standard streams will be safe-guarded.
48 : *
49 : * See the constructor for an example.
50 : *
51 : * \note
52 : * Although you may use this class within another class, it is not likely
53 : * to work well. It is really meant to be used on the stack only.
54 : */
55 : template<typename CharT, typename Traits>
56 : class safe_stream
57 : {
58 : public:
59 : /** \brief Save the current format of a stream.
60 : *
61 : * This function saves the various format data of a stream. This
62 : * includes the flags, precision, and width as well as the user
63 : * defined format data.
64 : *
65 : * The destructor automatically restores the flags. The
66 : * restore() function can also be called early, although that
67 : * eventually breaks the RAII feature since restore only
68 : * restores the flags once. Further calls to the restore()
69 : * function do nothing.
70 : *
71 : * To use:
72 : *
73 : * \code
74 : * {
75 : * as2js::safe_stream stream_flags(std::cout);
76 : * ...
77 : * // this call changes the flags to write numbers in hexadecimal
78 : * std::cout << std::hex << 123 << ...;
79 : * ...
80 : * } // here all flags, width, precision get restored automatically
81 : * \endcode
82 : *
83 : * \param[in] s The stream of which flags are to be saved.
84 : */
85 2 : safe_stream(std::basic_ios<CharT, Traits> & s)
86 2 : : f_stream(&s)
87 : //, f_flags(s.flags())
88 : //, f_precision(s.precision())
89 : //, f_width(s.width())
90 : {
91 2 : f_copyfmt.copyfmt(*f_stream);
92 2 : }
93 :
94 :
95 : /** \brief Restore the flags, width, and precision of a stream.
96 : *
97 : * The destructor automatically restores the stream flags, width,
98 : * and precision when called. Putting such an object on the stack
99 : * is the safest way to make sure that your function does not leak
100 : * the stream flags, width, and precision.
101 : *
102 : * This function calls the restore() function. Note that restore()
103 : * has no effect when called more than once.
104 : */
105 2 : ~safe_stream()
106 : {
107 2 : restore();
108 2 : }
109 :
110 :
111 : /** \brief The restore function copies the flags, width, and precision
112 : * back in the stream.
113 : *
114 : * This function restores the flags, width, and precision of the stream
115 : * as they were when the object was passed to the constructor of this
116 : * object.
117 : *
118 : * The function can be called any number of time, however, it only
119 : * restores the flags, width, and precision the first time it is called.
120 : *
121 : * In most cases, you want to let your safe_stream object
122 : * destructor call this restore() function automatically, although
123 : * you may need to restore the format early once in a while.
124 : */
125 2 : void restore()
126 : {
127 2 : if(f_stream != nullptr)
128 : {
129 2 : f_stream->copyfmt(f_copyfmt);
130 : }
131 2 : }
132 :
133 :
134 : /** \brief Copying these objects is not allowed.
135 : *
136 : * This object cannot be duplicated.
137 : */
138 : safe_stream(safe_stream const & rhs) = delete;
139 :
140 :
141 : /** \brief Copying these objects is not allowed.
142 : *
143 : * This object cannot be duplicated.
144 : */
145 : safe_stream & operator = (safe_stream const & rhs) = delete;
146 :
147 :
148 : private:
149 : /** \brief Stream being made safe.
150 : *
151 : * This points to the stream for which this class saves and
152 : * restores the state.
153 : *
154 : * We use a bare pointer because we want to be able to set it to
155 : * a nullptr once it was restored. We can only restore once. After
156 : * that, you are on your own.
157 : */
158 : std::basic_ios<CharT, Traits> * f_stream = nullptr;
159 :
160 : /** \brief This other stream is used to save the state.
161 : *
162 : * Any stream will do, I use the stringstream because it works.
163 : * If there is a simpler \em thing I can use, let me know!
164 : */
165 : std::basic_stringstream<CharT, Traits> f_copyfmt = std::basic_stringstream<CharT, Traits>();
166 : };
167 :
168 :
169 :
170 : } // namespace snapdev
171 : // vim: ts=4 sw=4 et
|