TeeStreambuf.hpp

00001 /*------------------------------------------------------------------------*/
00002 /*                 Copyright 2010 Sandia Corporation.                     */
00003 /*  Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive   */
00004 /*  license for use of this work by or on behalf of the U.S. Government.  */
00005 /*  Export of this program may require a license from the                 */
00006 /*  United States Government.                                             */
00007 /*------------------------------------------------------------------------*/
00008 
00009 #ifndef STK_UTIL_UTIL_TEESTREAMBUF_HPP
00010 #define STK_UTIL_UTIL_TEESTREAMBUF_HPP
00011 
00012 #include <string>
00013 #include <streambuf>
00014 #include <ostream>
00015 #include <set>
00016 #include <map>
00017 
00018 namespace stk {
00019 
00027 template<class Ch, class Tr = std::char_traits<Ch> >
00028 class basic_tee_streambuf : public std::basic_streambuf<Ch, Tr>
00029 {
00030   typedef std::set<std::ostream *> StreamSet;
00031   typedef std::map<std::ostream *, int> StreamErrorMap;
00032   
00033 public:
00038   basic_tee_streambuf()
00039   {}
00040 
00046   explicit basic_tee_streambuf(std::basic_ostream<Ch, Tr> *os) {
00047     add(os);
00048   }
00049 
00054   virtual ~basic_tee_streambuf()
00055   {}
00056 
00062   int eof() {
00063     return std::basic_streambuf<Ch, Tr>::traits_type::eof();
00064   }
00065 
00072   void add(std::ostream *os) {
00073     m_destinations.insert(os);
00074   }
00075 
00083   void remove(std::ostream *os) {
00084     m_destinations.erase(os);
00085   }
00086 
00091   void clear() {
00092     m_destinations.clear();
00093   }
00094 
00095 private:
00101   virtual int sync() {
00102     if (m_destinations.empty())
00103       return 1;
00104 
00105     StreamErrorMap return_code;
00106 
00107     for (StreamSet::const_iterator it = m_destinations.begin(); it != m_destinations.end(); ++it) {
00108       int ret = (*it)->rdbuf()->pubsync();
00109       return_code[*it] = ret;
00110     }
00111 
00112     // Remove streambufs with errors
00113     for (StreamSet::iterator it = m_destinations.begin(); it != m_destinations.end(); ++it)
00114       if (return_code[*it] == eof())
00115         m_destinations.erase(it);
00116 
00117     if (m_destinations.empty())
00118       return 1;
00119 
00120     return 1;
00121   }
00122 
00131   virtual typename std::basic_streambuf<Ch, Tr>::int_type overflow(const int c) {
00132     if (m_destinations.empty())
00133       return 1;
00134 
00135     StreamErrorMap return_code;
00136 
00137     for (StreamSet::const_iterator it = m_destinations.begin(); it != m_destinations.end(); ++it) {
00138       int ret = (*it)->rdbuf()->sputc(c);
00139       return_code[*it] = ret;
00140     }
00141 
00142     // Remove streambufs with errors
00143     for (StreamSet::iterator it = m_destinations.begin(); it != m_destinations.end(); ++it) 
00144       if (return_code[*it] == eof())
00145         m_destinations.erase(it);
00146 
00147     if (m_destinations.empty())
00148       return 1;
00149 
00150     return 1;
00151   }
00152 
00162   virtual std::streamsize xsputn(char const *buffer, std::streamsize n) {
00163     if (m_destinations.empty())
00164       return n;
00165 
00166     StreamErrorMap return_code;
00167     
00168     for (StreamSet::const_iterator it = m_destinations.begin(); it != m_destinations.end(); ++it) {
00169       std::ostream *os = (*it);
00170       int ret = os->rdbuf()->sputn(buffer,n);
00171       return_code[*it] = ret;
00172     }
00173 
00174     // Remove ostreams with errors
00175     for (StreamSet::iterator it = m_destinations.begin(); it != m_destinations.end(); ++it) {
00176       if (return_code[*it] < 0) {
00177         m_destinations.erase(it);
00178       }
00179     }
00180 
00181     if (m_destinations.empty())
00182       return n;
00183 
00184     return n;
00185   }
00186 
00187 private:
00188   StreamSet             m_destinations;    
00189 };
00190 
00191 typedef stk::basic_tee_streambuf<char> tee_streambuf;
00192 
00193 } // namespace stk
00194 
00195 #endif // STK_UTIL_UTIL_TEESTREAMBUF_HPP
Generated on Wed Apr 13 10:05:49 2011 for Sierra Toolkit by  doxygen 1.6.3