OpenMesh
OpenMesh/Core/System/mostream.hh
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 //=============================================================================