|
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_classic { 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_classic::basic_tee_streambuf<char> tee_streambuf; 00194 00195 } // namespace stk_classic 00196 00197 #endif // STK_UTIL_UTIL_TEESTREAMBUF_HPP