yat/utility/StreamRedirect.h

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