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

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

added constructor that creates and internal ifstream. refs #521.

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