OpenMesh
|
00001 /*===========================================================================*\ 00002 * * 00003 * OpenMesh * 00004 * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * 00005 * www.openmesh.org * 00006 * * 00007 *---------------------------------------------------------------------------* 00008 * This file is part of OpenMesh. * 00009 * * 00010 * OpenMesh is free software: you can redistribute it and/or modify * 00011 * it under the terms of the GNU Lesser General Public License as * 00012 * published by the Free Software Foundation, either version 3 of * 00013 * the License, or (at your option) any later version with the * 00014 * following exceptions: * 00015 * * 00016 * If other files instantiate templates or use macros * 00017 * or inline functions from this file, or you compile this file and * 00018 * link it with other files to produce an executable, this file does * 00019 * not by itself cause the resulting executable to be covered by the * 00020 * GNU Lesser General Public License. This exception does not however * 00021 * invalidate any other reasons why the executable file might be * 00022 * covered by the GNU Lesser General Public License. * 00023 * * 00024 * OpenMesh is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU Lesser General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU LesserGeneral Public * 00030 * License along with OpenMesh. If not, * 00031 * see <http://www.gnu.org/licenses/>. * 00032 * * 00033 \*===========================================================================*/ 00034 00035 /*===========================================================================*\ 00036 * * 00037 * $Revision: 362 $ * 00038 * $Date: 2011-01-26 10:21:12 +0100 (Mi, 26 Jan 2011) $ * 00039 * * 00040 \*===========================================================================*/ 00041 00042 //============================================================================= 00043 // 00044 // multiplex streams & ultilities 00045 // 00046 //============================================================================= 00047 00048 #ifndef OPENMESH_MOSTREAM_HH 00049 #define OPENMESH_MOSTREAM_HH 00050 00051 00052 //== INCLUDES ================================================================= 00053 00054 #include <OpenMesh/Core/System/config.h> 00055 #include <iostream> 00056 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000 00057 # include <streambuf.h> 00058 #else 00059 # include <streambuf> 00060 #endif 00061 #include <vector> 00062 #include <map> 00063 #include <string> 00064 #include <algorithm> 00065 00066 00067 //== NAMESPACES =============================================================== 00068 00069 namespace OpenMesh { 00070 #ifndef DOXY_IGNORE_THIS 00071 00072 00073 //== CLASS DEFINITION ========================================================= 00074 00075 00076 class basic_multiplex_target 00077 { 00078 public: 00079 virtual ~basic_multiplex_target() {} 00080 virtual void operator<<(const std::string& _s) = 0; 00081 }; 00082 00083 00084 template <class T> 00085 class multiplex_target : public basic_multiplex_target 00086 { 00087 public: 00088 multiplex_target(T& _t) : target_(_t) {} 00089 virtual void operator<<(const std::string& _s) { target_ << _s; } 00090 private: 00091 T& target_; 00092 }; 00093 00094 00095 00096 //== CLASS DEFINITION ========================================================= 00097 00098 00099 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000 00100 # define STREAMBUF streambuf 00101 # define INT_TYPE int 00102 # define TRAITS_TYPE 00103 #else 00104 # define STREAMBUF std::basic_streambuf<char> 00105 #endif 00106 00107 class multiplex_streambuf : public STREAMBUF 00108 { 00109 public: 00110 00111 typedef STREAMBUF base_type; 00112 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000 00113 typedef int int_type; 00114 struct traits_type 00115 { 00116 static int_type eof() { return -1; } 00117 static char to_char_type(int_type c) { return char(c); } 00118 }; 00119 #else 00120 typedef base_type::int_type int_type; 00121 typedef base_type::traits_type traits_type; 00122 #endif 00123 00124 // Constructor 00125 multiplex_streambuf() : enabled_(true) { buffer_.reserve(100); } 00126 00127 // Destructor 00128 ~multiplex_streambuf() 00129 { 00130 tmap_iter t_it(target_map_.begin()), t_end(target_map_.end()); 00131 for (; t_it!=t_end; ++t_it) 00132 delete t_it->second; 00133 } 00134 00135 00136 // buffer enable/disable 00137 bool is_enabled() const { return enabled_; } 00138 void enable() { enabled_ = true; } 00139 void disable() { enabled_ = false; } 00140 00141 00142 // construct multiplex_target<T> and add it to targets 00143 template <class T> bool connect(T& _target) 00144 { 00145 void* key = (void*) &_target; 00146 00147 if (target_map_.find(key) != target_map_.end()) 00148 return false; 00149 00150 target_type* mtarget = new multiplex_target<T>(_target); 00151 target_map_[key] = mtarget; 00152 00153 __connect(mtarget); 00154 return true; 00155 } 00156 00157 00158 // disconnect target from multiplexer 00159 template <class T> bool disconnect(T& _target) 00160 { 00161 void* key = (void*) &_target; 00162 tmap_iter t_it = target_map_.find(key); 00163 00164 if (t_it != target_map_.end()) 00165 { 00166 __disconnect(t_it->second); 00167 target_map_.erase(t_it); 00168 return true; 00169 } 00170 00171 return false; 00172 } 00173 00174 00175 protected: 00176 00177 // output what's in buffer_ 00178 virtual int sync() 00179 { 00180 if (!buffer_.empty()) 00181 { 00182 if (enabled_) multiplex(); 00183 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000 00184 buffer_ = ""; // member clear() not available! 00185 #else 00186 buffer_.clear(); 00187 #endif 00188 } 00189 return base_type::sync(); 00190 } 00191 00192 00193 // take on char and add it to buffer_ 00194 // if '\n' is encountered, trigger a sync() 00195 virtual 00196 int_type overflow(int_type _c = multiplex_streambuf::traits_type::eof()) 00197 { 00198 char c = traits_type::to_char_type(_c); 00199 buffer_.push_back(c); 00200 if (c == '\n') sync(); 00201 return 0; 00202 } 00203 00204 00205 private: 00206 00207 typedef basic_multiplex_target target_type; 00208 typedef std::vector<target_type*> target_list; 00209 typedef target_list::iterator tlist_iter; 00210 typedef std::map<void*, target_type*> target_map; 00211 typedef target_map::iterator tmap_iter; 00212 00213 00214 // add _target to list of multiplex targets 00215 void __connect(target_type* _target) { targets_.push_back(_target); } 00216 00217 00218 // remove _target from list of multiplex targets 00219 void __disconnect(target_type* _target) { 00220 targets_.erase(std::find(targets_.begin(), targets_.end(), _target)); 00221 } 00222 00223 00224 // multiplex output of buffer_ to all targets 00225 void multiplex() 00226 { 00227 tlist_iter t_it(targets_.begin()), t_end(targets_.end()); 00228 for (; t_it!=t_end; ++t_it) 00229 **t_it << buffer_; 00230 } 00231 00232 00233 private: 00234 00235 target_list targets_; 00236 target_map target_map_; 00237 std::string buffer_; 00238 bool enabled_; 00239 }; 00240 00241 #undef STREAMBUF 00242 00243 00244 //== CLASS DEFINITION ========================================================= 00245 00246 00256 class mostream : public std::ostream 00257 { 00258 public: 00259 00261 explicit mostream() : std::ostream(NULL) { init(&streambuffer_); } 00262 00263 00265 template <class T> bool connect(T& _target) 00266 { 00267 return streambuffer_.connect(_target); 00268 } 00269 00270 00272 template <class T> bool disconnect(T& _target) 00273 { 00274 return streambuffer_.disconnect(_target); 00275 } 00276 00277 00279 bool is_enabled() const { return streambuffer_.is_enabled(); } 00280 00282 void enable() { streambuffer_.enable(); } 00283 00285 void disable() { streambuffer_.disable(); } 00286 00287 00288 private: 00289 multiplex_streambuf streambuffer_; 00290 }; 00291 00292 00293 //============================================================================= 00294 #endif 00295 } // namespace OpenMesh 00296 //============================================================================= 00297 #endif // OPENMESH_MOSTREAM_HH defined 00298 //=============================================================================