|
Sierra Toolkit Version of the Day
|
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