OpenMesh: OpenMesh/Core/System/mostream.hh Source File

| OpenMesh

mostream.hh
1 /* ========================================================================= *
2 * *
3 * OpenMesh *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openmesh.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenMesh. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 * ========================================================================= */
41
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $Date$ *
46 * *
47 \*===========================================================================*/
48
49 //=============================================================================
50 //
51 // multiplex streams & ultilities
52 //
53 //=============================================================================
54
55 #ifndef OPENMESH_MOSTREAM_HH
56 #define OPENMESH_MOSTREAM_HH
57
58
59 //== INCLUDES =================================================================
60
61 #include <OpenMesh/Core/System/config.h>
62 #include <ostream>
63 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
64 # include <streambuf.h>
65 #else
66 # include <streambuf>
67 #endif
68 #include <vector>
69 #include <map>
70 #include <string>
71 #include <algorithm>
72
73 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ )
74 #include <mutex>
75 #endif
76
77
78 //== NAMESPACES ===============================================================
79
80 namespace OpenMesh {
81 #ifndef DOXY_IGNORE_THIS
82
83
84 //== CLASS DEFINITION =========================================================
85
86
87 class basic_multiplex_target
88 {
89 public:
90 virtual ~basic_multiplex_target() {}
91 virtual void operator<<(const std::string& _s) = 0;
92 };
93
94
95 template <class T>
96 class multiplex_target : public basic_multiplex_target
97 {
98 public:
99 explicit multiplex_target(T& _t) : target_(_t) {}
100 virtual void operator<<(const std::string& _s) { target_ << _s; }
101 private:
102 T& target_;
103 };
104
105
106
107 //== CLASS DEFINITION =========================================================
108
109
110 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
111 # define STREAMBUF streambuf
112 # define INT_TYPE int
113 # define TRAITS_TYPE
114 #else
115 # define STREAMBUF std::basic_streambuf<char>
116 #endif
117
118 class multiplex_streambuf : public STREAMBUF
119 {
120 public:
121
122 typedef STREAMBUF base_type;
123 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
124 typedef int int_type;
125 struct traits_type
126 {
127 static int_type eof() { return -1; }
128 static char to_char_type(int_type c) { return char(c); }
129 };
130 #else
131 typedef base_type::int_type int_type;
132 typedef base_type::traits_type traits_type;
133 #endif
134
135 // Constructor
136 multiplex_streambuf() : enabled_(true) { buffer_.reserve(100); }
137
138 // Destructor
139 ~multiplex_streambuf()
140 {
141 tmap_iter t_it(target_map_.begin()), t_end(target_map_.end());
142 for (; t_it!=t_end; ++t_it)
143 delete t_it->second;
144 }
145
146
147 // buffer enable/disable
148 bool is_enabled() const { return enabled_; }
149 void enable() { enabled_ = true; }
150 void disable() { enabled_ = false; }
151
152
153 // construct multiplex_target<T> and add it to targets
154 template <class T> bool connect(T& _target)
155 {
156 void* key = (void*) &_target;
157
158 if (target_map_.find(key) != target_map_.end())
159 return false;
160
161 target_type* mtarget = new multiplex_target<T>(_target);
162 target_map_[key] = mtarget;
163
164 __connect(mtarget);
165 return true;
166 }
167
168
169 // disconnect target from multiplexer
170 template <class T> bool disconnect(T& _target)
171 {
172 void* key = (void*) &_target;
173 tmap_iter t_it = target_map_.find(key);
174
175 if (t_it != target_map_.end())
176 {
177 __disconnect(t_it->second);
178 target_map_.erase(t_it);
179 return true;
180 }
181
182 return false;
183 }
184
185
186 protected:
187
188 // output what's in buffer_
189 virtual int sync()
190 {
191 // If working on multiple threads, we need to serialize the output correctly (requires c++11 headers)
192 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ )
193 std::lock_guard<std::mutex> lck (serializer_);
194 #endif
195
196 if (!buffer_.empty())
197 {
198 if (enabled_) multiplex();
199 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
200 buffer_ = ""; // member clear() not available!
201 #else
202 buffer_.clear();
203 #endif
204 }
205 return base_type::sync();
206 }
207
208
209 // take on char and add it to buffer_
210 // if '\n' is encountered, trigger a sync()
211 virtual
212 int_type overflow(int_type _c = multiplex_streambuf::traits_type::eof())
213 {
214 char c = traits_type::to_char_type(_c);
215
216 // If working on multiple threads, we need to serialize the output correctly (requires c++11 headers)
217 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ )
218 {
219 std::lock_guard<std::mutex> lck (serializer_);
220 buffer_.push_back(c);
221 }
222 #else
223 buffer_.push_back(c);
224 #endif
225
226 if (c == '\n') sync();
227 return 0;
228 }
229
230
231 private:
232
233 typedef basic_multiplex_target target_type;
234 typedef std::vector<target_type*> target_list;
235 typedef target_list::iterator tlist_iter;
236 typedef std::map<void*, target_type*> target_map;
237 typedef target_map::iterator tmap_iter;
238
239
240 // add _target to list of multiplex targets
241 void __connect(target_type* _target) { targets_.push_back(_target); }
242
243
244 // remove _target from list of multiplex targets
245 void __disconnect(target_type* _target) {
246 targets_.erase(std::find(targets_.begin(), targets_.end(), _target));
247 }
248
249
250 // multiplex output of buffer_ to all targets
251 void multiplex()
252 {
253 tlist_iter t_it(targets_.begin()), t_end(targets_.end());
254 for (; t_it!=t_end; ++t_it)
255 **t_it << buffer_;
256 }
257
258
259 private:
260
261 target_list targets_;
262 target_map target_map_;
263 std::string buffer_;
264 bool enabled_;
265
266 // If working on multiple threads, we need to serialize the output correctly (requires c++11 headers)
267 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ )
268 std::mutex serializer_;
269 #endif
270
271 };
272
273 #undef STREAMBUF
274
275
276 //== CLASS DEFINITION =========================================================
277
278
288 class mostream : public std::ostream
289 {
290 public:
291
293 explicit mostream() : std::ostream(NULL) { init(&streambuffer_); }
294
295
297 template <class T> bool connect(T& _target)
298 {
299 return streambuffer_.connect(_target);
300 }
301
302
304 template <class T> bool disconnect(T& _target)
305 {
306 return streambuffer_.disconnect(_target);
307 }
308
309
311 bool is_enabled() const { return streambuffer_.is_enabled(); }
312
314 void enable() { streambuffer_.enable(); }
315
317 void disable() { streambuffer_.disable(); }
318
319
320 private:
321 multiplex_streambuf streambuffer_;
322 };
323
324
325 //=============================================================================
326 #endif
327 } // namespace OpenMesh
328 //=============================================================================
329 #endif // OPENMESH_MOSTREAM_HH defined
330 //=============================================================================
OpenMesh::operator<<
auto operator<<(std::ostream &os, const VectorT< Scalar, DIM > &_vec) -> typename std::enable_if< sizeof(decltype(os<< _vec[0])) >=0
output a vector by printing its space-separated compontens
OpenMesh
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:64
std
STL namespace.