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

| OpenMesh

mostream.hh
1 /* ========================================================================= *
2 * *
3 * OpenMesh *
4 * Copyright (c) 2001-2022, 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 //=============================================================================
45 //
46 // multiplex streams & ultilities
47 //
48 //=============================================================================
49
50 #ifndef OPENMESH_MOSTREAM_HH
51 #define OPENMESH_MOSTREAM_HH
52
53
54 //== INCLUDES =================================================================
55
56 #include <OpenMesh/Core/System/config.h>
57 #include <ostream>
58 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
59 # include <streambuf.h>
60 #else
61 # include <streambuf>
62 #endif
63 #include <vector>
64 #include <map>
65 #include <string>
66 #include <algorithm>
67
68 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ )
69 #include <mutex>
70 #endif
71
72
73 //== NAMESPACES ===============================================================
74
75 namespace OpenMesh {
76 #ifndef DOXY_IGNORE_THIS
77
78
79 //== CLASS DEFINITION =========================================================
80
81
82 class basic_multiplex_target
83 {
84 public:
85 virtual ~basic_multiplex_target() {}
86 virtual void operator<<(const std::string& _s) = 0;
87 };
88
89
90 template <class T>
91 class multiplex_target : public basic_multiplex_target
92 {
93 public:
94 explicit multiplex_target(T& _t) : target_(_t) {}
95 virtual void operator<<(const std::string& _s) override { target_ << _s; }
96 private:
97 T& target_;
98 };
99
100
101
102 //== CLASS DEFINITION =========================================================
103
104
105 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
106 # define STREAMBUF streambuf
107 # define INT_TYPE int
108 # define TRAITS_TYPE
109 #else
110 # define STREAMBUF std::basic_streambuf<char>
111 #endif
112
113 class multiplex_streambuf : public STREAMBUF
114 {
115 public:
116
117 typedef STREAMBUF base_type;
118 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
119 typedef int int_type;
120 struct traits_type
121 {
122 static int_type eof() { return -1; }
123 static char to_char_type(int_type c) { return char(c); }
124 };
125 #else
126 typedef base_type::int_type int_type;
127 typedef base_type::traits_type traits_type;
128 #endif
129
130 // Constructor
131 multiplex_streambuf() : enabled_(true) { buffer_.reserve(100); }
132
133 // Destructor
134 ~multiplex_streambuf()
135 {
136 tmap_iter t_it(target_map_.begin()), t_end(target_map_.end());
137 for (; t_it!=t_end; ++t_it)
138 delete t_it->second;
139 }
140
141
142 // buffer enable/disable
143 bool is_enabled() const { return enabled_; }
144 void enable() { enabled_ = true; }
145 void disable() { enabled_ = false; }
146
147
148 // construct multiplex_target<T> and add it to targets
149 template <class T> bool connect(T& _target)
150 {
151 void* key = (void*) &_target;
152
153 if (target_map_.find(key) != target_map_.end())
154 return false;
155
156 target_type* mtarget = new multiplex_target<T>(_target);
157 target_map_[key] = mtarget;
158
159 __connect(mtarget);
160 return true;
161 }
162
163
164 // disconnect target from multiplexer
165 template <class T> bool disconnect(T& _target)
166 {
167 void* key = (void*) &_target;
168 tmap_iter t_it = target_map_.find(key);
169
170 if (t_it != target_map_.end())
171 {
172 __disconnect(t_it->second);
173 target_map_.erase(t_it);
174 return true;
175 }
176
177 return false;
178 }
179
180
181 protected:
182
183 // output what's in buffer_
184 virtual int sync()
185 {
186 // If working on multiple threads, we need to serialize the output correctly (requires c++11 headers)
187 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ )
188 std::lock_guard<std::mutex> lck (serializer_);
189 #endif
190
191 if (!buffer_.empty())
192 {
193 if (enabled_) multiplex();
194 #if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
195 buffer_ = ""; // member clear() not available!
196 #else
197 buffer_.clear();
198 #endif
199 }
200 return base_type::sync();
201 }
202
203
204 // take on char and add it to buffer_
205 // if '\n' is encountered, trigger a sync()
206 virtual
207 int_type overflow(int_type _c = multiplex_streambuf::traits_type::eof())
208 {
209 char c = traits_type::to_char_type(_c);
210
211 // If working on multiple threads, we need to serialize the output correctly (requires c++11 headers)
212 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ )
213 {
214 std::lock_guard<std::mutex> lck (serializer_);
215 buffer_.push_back(c);
216 }
217 #else
218 buffer_.push_back(c);
219 #endif
220
221 if (c == '\n') sync();
222 return 0;
223 }
224
225
226 private:
227
228 typedef basic_multiplex_target target_type;
229 typedef std::vector<target_type*> target_list;
230 typedef target_list::iterator tlist_iter;
231 typedef std::map<void*, target_type*> target_map;
232 typedef target_map::iterator tmap_iter;
233
234
235 // add _target to list of multiplex targets
236 void __connect(target_type* _target) { targets_.push_back(_target); }
237
238
239 // remove _target from list of multiplex targets
240 void __disconnect(target_type* _target) {
241 targets_.erase(std::find(targets_.begin(), targets_.end(), _target));
242 }
243
244
245 // multiplex output of buffer_ to all targets
246 void multiplex()
247 {
248 tlist_iter t_it(targets_.begin()), t_end(targets_.end());
249 for (; t_it!=t_end; ++t_it)
250 **t_it << buffer_;
251 }
252
253
254 private:
255
256 target_list targets_;
257 target_map target_map_;
258 std::string buffer_;
259 bool enabled_;
260
261 // If working on multiple threads, we need to serialize the output correctly (requires c++11 headers)
262 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ )
263 std::mutex serializer_;
264 #endif
265
266 };
267
268 #undef STREAMBUF
269
270
271 //== CLASS DEFINITION =========================================================
272
273
283 class mostream : public std::ostream
284 {
285 public:
286
288 explicit mostream() : std::ostream(nullptr) { init(&streambuffer_); }
289
290
292 template <class T> bool connect(T& _target)
293 {
294 return streambuffer_.connect(_target);
295 }
296
297
299 template <class T> bool disconnect(T& _target)
300 {
301 return streambuffer_.disconnect(_target);
302 }
303
304
306 bool is_enabled() const { return streambuffer_.is_enabled(); }
307
309 void enable() { streambuffer_.enable(); }
310
312 void disable() { streambuffer_.disable(); }
313
314
315 private:
316 multiplex_streambuf streambuffer_;
317 };
318
319
320 //=============================================================================
321 #endif
322 } // namespace OpenMesh
323 //=============================================================================
324 #endif // OPENMESH_MOSTREAM_HH defined
325 //=============================================================================
OpenMesh
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
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