Sierra Toolkit Version of the Day
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       if ((*it)->rdbuf() != this) {
00109         int ret = (*it)->rdbuf()->pubsync();
00110         return_code[*it] = ret;
00111       }
00112     }
00113 
00114     // Remove streambufs with errors
00115     for (StreamSet::iterator it = m_destinations.begin(); it != m_destinations.end(); ++it)
00116       if (return_code[*it] == eof())
00117         m_destinations.erase(it);
00118 
00119     if (m_destinations.empty())
00120       return 1;
00121 
00122     return 1;
00123   }
00124 
00133   virtual typename std::basic_streambuf<Ch, Tr>::int_type overflow(const int c) {
00134     if (m_destinations.empty())
00135       return 1;
00136 
00137     StreamErrorMap return_code;
00138 
00139     for (StreamSet::const_iterator it = m_destinations.begin(); it != m_destinations.end(); ++it) {
00140       int ret = (*it)->rdbuf()->sputc(c);
00141       return_code[*it] = ret;
00142     }
00143 
00144     // Remove streambufs with errors
00145     for (StreamSet::iterator it = m_destinations.begin(); it != m_destinations.end(); ++it) 
00146       if (return_code[*it] == eof())
00147         m_destinations.erase(it);
00148 
00149     if (m_destinations.empty())
00150       return 1;
00151 
00152     return 1;
00153   }
00154 
00164   virtual std::streamsize xsputn(char const *buffer, std::streamsize n) {
00165     if (m_destinations.empty())
00166       return n;
00167 
00168     StreamErrorMap return_code;
00169     
00170     for (StreamSet::const_iterator it = m_destinations.begin(); it != m_destinations.end(); ++it) {
00171       std::ostream *os = (*it);
00172       int ret = os->rdbuf()->sputn(buffer,n);
00173       return_code[*it] = ret;
00174     }
00175 
00176     // Remove ostreams with errors
00177     for (StreamSet::iterator it = m_destinations.begin(); it != m_destinations.end(); ++it) {
00178       if (return_code[*it] < 0) {
00179         m_destinations.erase(it);
00180       }
00181     }
00182 
00183     if (m_destinations.empty())
00184       return n;
00185 
00186     return n;
00187   }
00188 
00189 private:
00190   StreamSet             m_destinations;    
00191 };
00192 
00193 typedef stk::basic_tee_streambuf<char> tee_streambuf;
00194 
00195 } // namespace stk
00196 
00197 #endif // STK_UTIL_UTIL_TEESTREAMBUF_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines