- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# Core/System/mostream.hh

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