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

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

the conclusion that the stream needed to flushed was nonsense, so I changed back to having and ios* as member variable. refs #521

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.2 KB
Line 
1#ifndef _theplu_yat_utility_stream_readirect_
2#define _theplu_yat_utility_stream_readirect_
3
4// $Id: StreamRedirect.h 2051 2009-09-06 16:47:19Z 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       If \a active is false, the class does nothing.
84    */
85    BasicStreamRedirect(std::basic_ostream<charT, traits>& os1, 
86                        const std::string& file, bool active=true);
87   
88    /**
89       \brief Destructor - resets the redirect
90
91       The stream (first argument in constructor) is restored to use
92       its original buffer.
93
94       \note It is important that the stream held is not deallocated
95       before this object is destroyed. 1) The behavior of this
96       destructor is undefined. 2) The stream destroys the streambuf
97       in its destructor, so if the stream is destroyed before it is
98       restored, the streambuf will likely be deallocated twice. In
99       addition, the original streambuf of the stream will not be
100       closed and deallocated; hence a memory and resource leak.
101    */
102    ~BasicStreamRedirect(void);
103   
104  private:
105    // no copying
106    BasicStreamRedirect(const BasicStreamRedirect&);
107    BasicStreamRedirect& operator=(const BasicStreamRedirect&);
108   
109    void init(std::basic_ios<charT, traits>& ios1, 
110              std::basic_ios<charT, traits>& ios2,
111              bool active);
112   
113    std::basic_streambuf<charT, traits>* buf_;
114    std::basic_ifstream<charT, traits>* ifs_;
115    std::basic_ios<charT, traits>* ios_;
116    std::basic_ofstream<charT, traits>* ofs_;
117  };
118 
119  /**
120     \since New in yat 0.6
121  */
122  typedef BasicStreamRedirect<char> StreamRedirect;
123 
124  /**
125     \since New in yat 0.6
126  */
127  typedef BasicStreamRedirect<wchar_t> wStreamRedirect;
128 
129 
130  // template implementations
131 
132  template<class charT, class traits>
133  BasicStreamRedirect<charT, traits>::
134  BasicStreamRedirect(std::basic_istream<charT, traits>& is1, 
135                      std::basic_istream<charT, traits>& is2, bool active)
136    : buf_(NULL), ifs_(NULL), ios_(NULL), ofs_(NULL)
137  {
138    init(is1, is2, active);
139  }
140 
141 
142  template<class charT, class traits>
143  BasicStreamRedirect<charT, traits>::
144  BasicStreamRedirect(std::basic_ostream<charT, traits>& os1, 
145                      std::basic_ostream<charT, traits>& os2, bool active)
146    : buf_(NULL), ifs_(NULL), ios_(NULL), ofs_(NULL)
147  {
148    init(os1, os2, active);
149  }
150 
151 
152  template<class charT, class traits>
153  BasicStreamRedirect<charT, traits>::
154  BasicStreamRedirect(std::basic_ostream<charT, traits>& os1, 
155                      const std::string& file, bool active)
156    : buf_(NULL), ifs_(NULL), ios_(NULL), ofs_(NULL)
157  {
158    if (active) {
159      ofs_ = new std::basic_ofstream<charT, traits>(file.c_str());
160      init(os1, *ofs_, active);
161    }
162  }
163 
164 
165  template<class charT, class traits>
166  BasicStreamRedirect<charT, traits>::
167  ~BasicStreamRedirect(void)
168  {
169    // only restore stream if active is true
170    if (ios_) {
171      ios_->rdbuf(buf_);
172    }
173    delete ifs_;
174    delete ofs_;
175  }
176 
177 
178  template<class charT, class traits>
179  void 
180  BasicStreamRedirect<charT, traits>::init(std::basic_ios<charT, traits>& s1, 
181                                           std::basic_ios<charT, traits>& s2,
182                                           bool active)
183  {
184    if (active) {
185      ios_ = &s1;
186      // save the buffer
187      buf_ = s1.rdbuf();
188      // redirect os1 to os2
189      s1.rdbuf(s2.rdbuf());
190    }
191  }
192 
193}}} // of namespace utility, yat, and theplu
194
195#endif
Note: See TracBrowser for help on using the repository browser.