source: trunk/yat/utility/StreamRedirect.h @ 2050

Last change on this file since 2050 was 2050, checked in by Peter, 12 years ago

refs #521. added constructor taking ostream and string. It does not take char* (as ofstream does) because I don't see the point with that. Needed to split member variable ios_ into a ostream* and istream* because the two cases need separate treatment (ostream needs to be flushed in destructor).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.6 KB
Line 
1#ifndef _theplu_yat_utility_stream_readirect_
2#define _theplu_yat_utility_stream_readirect_
3
4// $Id: StreamRedirect.h 2050 2009-09-06 01:54:05Z peter $
5
6/*
7  Copyright (C) 2009 Peter Johansson
8
9  This file is part of the yat library, http://dev.thep.lu.se/yat
10
11  The yat library is free software; you can redistribute it and/or
12  modify it under the terms of the GNU General Public License as
13  published by the Free Software Foundation; either version 3 of the
14  License, or (at your option) any later version.
15
16  The yat library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20
21  You should have received a copy of the GNU General Public License
22  along with yat. If not, see <http://www.gnu.org/licenses/>.
23*/
24
25#include "yat_assert.h"
26
27#include <fstream>
28#include <istream>
29#include <ostream>
30#include <streambuf>
31#include <string>
32
33namespace theplu {
34namespace yat {
35namespace utility {
36
37  /**
38     \brief Redirect a stream to another stream.
39
40     
41
42     \note It is important that an instance of this class is
43     deallocated before the stream it holds (see
44     BasicStreamRedirect::~BasicStreamRedirect).
45
46     \see StreamRedirect and wStreamRedirect
47
48     \since New in yat 0.6
49   */
50  template<class charT, class traits = std::char_traits<charT> >
51  class BasicStreamRedirect
52  {
53  public:
54    /**
55       Constructor for ostream
56
57       \a is1 is redirected to get its input from the buffer of \a is2
58       (rather than its own buffer). A reference to \a is1 and its
59       buffer is stored, so \a is1 can be restored in the destructor.
60
61       If \a active is false, the class does nothing.
62     */
63    BasicStreamRedirect(std::basic_istream<charT, traits>& is1, 
64                        std::basic_istream<charT, traits>& is2,
65                        bool active=true);
66   
67    /**
68       Constructor for ostream
69
70       \a os1 is redirected to send its output to the buffer of \a os2
71       (rather than its own buffer). A reference to \a os1 and its
72       buffer is stored, so \a os1 can be restored in the destructor.
73
74       If \a active is false, the class does nothing.
75    */
76    BasicStreamRedirect(std::basic_ostream<charT, traits>& os1, 
77                        std::basic_ostream<charT, traits>& os2,
78                        bool active=true);
79   
80    /**
81       Constructor for ostream
82
83       \a os1 is redirected to send its output to the buffer of \a os2
84       (rather than its own buffer). A reference to \a os1 and its
85       buffer is stored, so \a os1 can be restored in the destructor.
86
87       If \a active is false, the class does nothing.
88    */
89    BasicStreamRedirect(std::basic_ostream<charT, traits>& os1, 
90                        const std::string& file, bool active=true);
91   
92    /**
93       \brief Destructor - resets the redirect
94
95       The stream (first argument in constructor) is restored to use
96       its original buffer.
97
98       \note It is important that the stream held is not deallocated
99       before this object is destroyed. 1) The behavior of this
100       destructor is undefined. 2) The stream destroys the streambuf
101       in its destructor, so if the stream is destroyed before it is
102       restored, the streambuf will likely be deallocated twice. In
103       addition, the original streambuf of the stream will not be
104       closed and deallocated; hence a memory and resource leak.
105    */
106    ~BasicStreamRedirect(void);
107   
108  private:
109    // no copying
110    BasicStreamRedirect(const BasicStreamRedirect&);
111    BasicStreamRedirect& operator=(const BasicStreamRedirect&);
112   
113    void init(std::basic_ios<charT, traits>& ios1, 
114              std::basic_ios<charT, traits>& ios2);
115   
116    std::basic_streambuf<charT, traits>* buf_;
117    std::basic_ifstream<charT, traits>* ifs_;
118    std::basic_istream<charT, traits>* is_;
119    std::basic_ofstream<charT, traits>* ofs_;
120    std::basic_ostream<charT, traits>* os_;
121  };
122 
123  /**
124     \since New in yat 0.6
125  */
126  typedef BasicStreamRedirect<char> StreamRedirect;
127 
128  /**
129     \since New in yat 0.6
130  */
131  typedef BasicStreamRedirect<wchar_t> wStreamRedirect;
132 
133 
134  // template implementations
135 
136  template<class charT, class traits>
137  BasicStreamRedirect<charT, traits>::
138  BasicStreamRedirect(std::basic_istream<charT, traits>& is1, 
139                      std::basic_istream<charT, traits>& is2, bool active)
140    : buf_(NULL), ifs_(NULL), is_(NULL), ofs_(NULL), os_(NULL) 
141  {
142    if (active) {
143      is_ = &is1;
144      init(is1, is2);
145    }
146  }
147 
148 
149  template<class charT, class traits>
150  BasicStreamRedirect<charT, traits>::
151  BasicStreamRedirect(std::basic_ostream<charT, traits>& os1, 
152                      std::basic_ostream<charT, traits>& os2, bool active)
153    : buf_(NULL), ifs_(NULL), is_(NULL), ofs_(NULL), os_(NULL) 
154  {
155    if (active) {
156      os_ = &os1;
157      init(os1, os2);
158    }
159  }
160 
161 
162  template<class charT, class traits>
163  BasicStreamRedirect<charT, traits>::
164  BasicStreamRedirect(std::basic_ostream<charT, traits>& os1, 
165                      const std::string& file, bool active)
166    : buf_(NULL), ifs_(NULL), is_(NULL), ofs_(NULL), os_(NULL) 
167  {
168    if (active) {
169      ofs_ = new std::basic_ofstream<charT, traits>(file.c_str());
170      os_ = &os1;
171      init(os1, *ofs_);
172    }
173  }
174 
175 
176  template<class charT, class traits>
177  BasicStreamRedirect<charT, traits>::
178  ~BasicStreamRedirect(void)
179  {
180    YAT_ASSERT(os_==NULL || is_==NULL);
181
182    // only restore stream if active is true
183    if (os_) {
184      std::flush(*os_);
185      os_->rdbuf(buf_);
186    }
187    else if (is_) {
188      is_->rdbuf(buf_);
189    }
190    delete ifs_;
191    delete ofs_;
192  }
193 
194 
195  template<class charT, class traits>
196  void 
197  BasicStreamRedirect<charT, traits>::init(std::basic_ios<charT, traits>& s1, 
198                                           std::basic_ios<charT, traits>& s2)
199  {
200    // save the buffer
201    buf_ = s1.rdbuf();
202    // redirect os1 to os2
203    s1.rdbuf(s2.rdbuf());
204  }
205 
206}}} // of namespace utility, yat, and theplu
207
208#endif
Note: See TracBrowser for help on using the repository browser.