OpenMesh

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

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mostream.hh
1 /*===========================================================================*\
2 * *
3 * OpenMesh *
4 * Copyright (C) 2001-2012 by Computer Graphics Group, RWTH Aachen *
5 * www.openmesh.org *
6 * *
7 *---------------------------------------------------------------------------*
8 * This file is part of OpenMesh. *
9 * *
10 * OpenMesh is free software: you can redistribute it and/or modify *
11 * it under the terms of the GNU Lesser General Public License as *
12 * published by the Free Software Foundation, either version 3 of *
13 * the License, or (at your option) any later version with the *
14 * following exceptions: *
15 * *
16 * If other files instantiate templates or use macros *
17 * or inline functions from this file, or you compile this file and *
18 * link it with other files to produce an executable, this file does *
19 * not by itself cause the resulting executable to be covered by the *
20 * GNU Lesser General Public License. This exception does not however *
21 * invalidate any other reasons why the executable file might be *
22 * covered by the GNU Lesser General Public License. *
23 * *
24 * OpenMesh is distributed in the hope that it will be useful, *
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
27 * GNU Lesser General Public License for more details. *
28 * *
29 * You should have received a copy of the GNU LesserGeneral Public *
30 * License along with OpenMesh. If not, *
31 * see <http://www.gnu.org/licenses/>. *
32 * *
33 \*===========================================================================*/
34
35 /*===========================================================================*\
36 * *
37 * $Revision: 736 $ *
38 * $Date: 2012-10-08 09:30:49 +0200 (Mo, 08. Okt 2012) $ *
39 * *
40 \*===========================================================================*/
41
42 //=============================================================================
43 //
44 // multiplex streams & ultilities
45 //
46 //=============================================================================
47
48 #ifndef OPENMESH_MOSTREAM_HH
49 #define OPENMESH_MOSTREAM_HH
50
51
52 //== INCLUDES =================================================================
53
54 #include <OpenMesh/Core/System/config.h>
55 #include <iostream>
56 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
57 # include <streambuf.h>
58 #else
59 # include <streambuf>
60 #endif
61 #include <vector>
62 #include <map>
63 #include <string>
64 #include <algorithm>
65
66
67 //== NAMESPACES ===============================================================
68
69 namespace OpenMesh {
70 #ifndef DOXY_IGNORE_THIS
71
72
73 //== CLASS DEFINITION =========================================================
74
75
76 class basic_multiplex_target
77 {
78 public:
79 virtual ~basic_multiplex_target() {}
80 virtual void operator<<(const std::string& _s) = 0;
81 };
82
83
84 template <class T>
85 class multiplex_target : public basic_multiplex_target
86 {
87 public:
88 multiplex_target(T& _t) : target_(_t) {}
89 virtual void operator<<(const std::string& _s) { target_ << _s; }
90 private:
91 T& target_;
92 };
93
94
95
96 //== CLASS DEFINITION =========================================================
97
98
99 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
100 # define STREAMBUF streambuf
101 # define INT_TYPE int
102 # define TRAITS_TYPE
103 #else
104 # define STREAMBUF std::basic_streambuf<char>
105 #endif
106
107 class multiplex_streambuf : public STREAMBUF
108 {
109 public:
110
111 typedef STREAMBUF base_type;
112 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
113 typedef int int_type;
114 struct traits_type
115 {
116 static int_type eof() { return -1; }
117 static char to_char_type(int_type c) { return char(c); }
118 };
119 #else
120 typedef base_type::int_type int_type;
121 typedef base_type::traits_type traits_type;
122 #endif
123
124 // Constructor
125 multiplex_streambuf() : enabled_(true) { buffer_.reserve(100); }
126
127 // Destructor
128 ~multiplex_streambuf()
129 {
130 tmap_iter t_it(target_map_.begin()), t_end(target_map_.end());
131 for (; t_it!=t_end; ++t_it)
132 delete t_it->second;
133 }
134
135
136 // buffer enable/disable
137 bool is_enabled() const { return enabled_; }
138 void enable() { enabled_ = true; }
139 void disable() { enabled_ = false; }
140
141
142 // construct multiplex_target<T> and add it to targets
143 template <class T> bool connect(T& _target)
144 {
145 void* key = (void*) &_target;
146
147 if (target_map_.find(key) != target_map_.end())
148 return false;
149
150 target_type* mtarget = new multiplex_target<T>(_target);
151 target_map_[key] = mtarget;
152
153 __connect(mtarget);
154 return true;
155 }
156
157
158 // disconnect target from multiplexer
159 template <class T> bool disconnect(T& _target)
160 {
161 void* key = (void*) &_target;
162 tmap_iter t_it = target_map_.find(key);
163
164 if (t_it != target_map_.end())
165 {
166 __disconnect(t_it->second);
167 target_map_.erase(t_it);
168 return true;
169 }
170
171 return false;
172 }
173
174
175 protected:
176
177 // output what's in buffer_
178 virtual int sync()
179 {
180 if (!buffer_.empty())
181 {
182 if (enabled_) multiplex();
183 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
184 buffer_ = ""; // member clear() not available!
185 #else
186 buffer_.clear();
187 #endif
188 }
189 return base_type::sync();
190 }
191
192
193 // take on char and add it to buffer_
194 // if '\n' is encountered, trigger a sync()
195 virtual
196 int_type overflow(int_type _c = multiplex_streambuf::traits_type::eof())
197 {
198 char c = traits_type::to_char_type(_c);
199 buffer_.push_back(c);
200 if (c == '\n') sync();
201 return 0;
202 }
203
204
205 private:
206
207 typedef basic_multiplex_target target_type;
208 typedef std::vector<target_type*> target_list;
209 typedef target_list::iterator tlist_iter;
210 typedef std::map<void*, target_type*> target_map;
211 typedef target_map::iterator tmap_iter;
212
213
214 // add _target to list of multiplex targets
215 void __connect(target_type* _target) { targets_.push_back(_target); }
216
217
218 // remove _target from list of multiplex targets
219 void __disconnect(target_type* _target) {
220 targets_.erase(std::find(targets_.begin(), targets_.end(), _target));
221 }
222
223
224 // multiplex output of buffer_ to all targets
225 void multiplex()
226 {
227 tlist_iter t_it(targets_.begin()), t_end(targets_.end());
228 for (; t_it!=t_end; ++t_it)
229 **t_it << buffer_;
230 }
231
232
233 private:
234
235 target_list targets_;
236 target_map target_map_;
237 std::string buffer_;
238 bool enabled_;
239 };
240
241 #undef STREAMBUF
242
243
244 //== CLASS DEFINITION =========================================================
245
246
256 class mostream : public std::ostream
257 {
258 public:
259
261 explicit mostream() : std::ostream(NULL) { init(&streambuffer_); }
262
263
265 template <class T> bool connect(T& _target)
266 {
267 return streambuffer_.connect(_target);
268 }
269
270
272 template <class T> bool disconnect(T& _target)
273 {
274 return streambuffer_.disconnect(_target);
275 }
276
277
279 bool is_enabled() const { return streambuffer_.is_enabled(); }
280
282 void enable() { streambuffer_.enable(); }
283
285 void disable() { streambuffer_.disable(); }
286
287
288 private:
289 multiplex_streambuf streambuffer_;
290 };
291
292
293 //=============================================================================
294 #endif
295 } // namespace OpenMesh
296 //=============================================================================
297 #endif // OPENMESH_MOSTREAM_HH defined
298 //=============================================================================