OpenMesh
SR_binary_spec.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 //
47 // Helper Functions for binary reading / writing
48 //
49 //=============================================================================
50 
51 #ifndef OPENMESH_SR_BINARY_SPEC_HH
52 #define OPENMESH_SR_BINARY_SPEC_HH
53 
54 //== INCLUDES =================================================================
55 
56 #include <OpenMesh/Core/System/config.h>
57 // -------------------- STL
58 #include <iterator>
59 #include <string>
60 #if defined(OM_CC_GCC) && (OM_CC_VERSION < 30000)
62 #else
63 # include <limits>
64 #endif
65 #include <vector>
66 #include <stdexcept> // logic_error
67 #include <numeric> // accumulate
68 // -------------------- OpenMesh
69 #include <OpenMesh/Core/Geometry/VectorT.hh>
70 #include <OpenMesh/Core/Mesh/Status.hh>
71 #include <OpenMesh/Core/IO/SR_types.hh>
72 #include <OpenMesh/Core/IO/SR_rbo.hh>
73 #include <OpenMesh/Core/IO/SR_binary.hh>
74 
75 
76 #include <OpenMesh/Core/Utils/typename.hh>
77 
78 #include <iostream>
79 
80 //== NAMESPACES ===============================================================
81 
82 namespace OpenMesh {
83 namespace IO {
84 
85 
86 //=============================================================================
87 
88 #ifndef DOXY_IGNORE_THIS
89 
90 //-----------------------------------------------------------------------------
91 // struct binary, helper for storing/restoring
92 
93 #define SIMPLE_BINARY( T ) \
94  template <> struct binary< T > { \
95  typedef T value_type; \
96  static const bool is_streamable = true; \
97  static size_t size_of(const value_type&) { return sizeof(value_type); } \
98  static size_t size_of(void) { return sizeof(value_type); } \
99  static std::string type_identifier(void) { return #T; } \
100  static size_t store( std::ostream& _os, const value_type& _val, \
101  bool _swap=false) { \
102  value_type tmp = _val; \
103  if (_swap) reverse_byte_order(tmp); \
104  _os.write( (const char*)&tmp, sizeof(value_type) ); \
105  return _os.good() ? sizeof(value_type) : 0; \
106  } \
107  \
108  static size_t restore( std::istream& _is, value_type& _val, \
109  bool _swap=false) { \
110  _is.read( (char*)&_val, sizeof(value_type) ); \
111  if (_swap) reverse_byte_order(_val); \
112  return _is.good() ? sizeof(value_type) : 0; \
113  } \
114  }
115 
116 SIMPLE_BINARY(bool);
117 //SIMPLE_BINARY(int);
118 
119 // Why is this needed? Should not be used as not 32 bit compatible
120 //SIMPLE_BINARY(unsigned long);
121 SIMPLE_BINARY(float);
122 SIMPLE_BINARY(double);
123 SIMPLE_BINARY(long double);
124 SIMPLE_BINARY(char);
125 
126 SIMPLE_BINARY(int8_t);
127 SIMPLE_BINARY(int16_t);
128 SIMPLE_BINARY(int32_t);
129 //SIMPLE_BINARY(int64_t); // TODO: This does not work. Find out why.
130 SIMPLE_BINARY(uint8_t);
131 SIMPLE_BINARY(uint16_t);
132 SIMPLE_BINARY(uint32_t);
133 SIMPLE_BINARY(uint64_t);
134 
135 //handles
136 SIMPLE_BINARY(FaceHandle);
137 SIMPLE_BINARY(EdgeHandle);
138 SIMPLE_BINARY(HalfedgeHandle);
139 SIMPLE_BINARY(VertexHandle);
140 SIMPLE_BINARY(MeshHandle);
141 
142 #undef SIMPLE_BINARY
143 
144 // For unsigned long which is of size 64 bit on 64 bit
145 // architectures: convert into 32 bit unsigned integer value
146 // in order to stay compatible between 32/64 bit architectures.
147 // This allows cross reading BUT forbids storing unsigned longs
148 // as data type since higher order word (4 bytes) will be truncated.
149 // Does not work in case the data type that is to be stored
150 // exceeds the value range of unsigned int in size, which is improbable...
151 
152 #define SIMPLE_BINARY( T ) \
153  template <> struct binary< T > { \
154  typedef T value_type; \
155  static const bool is_streamable = true; \
156  static size_t size_of(const value_type&) { return sizeof(value_type); } \
157  static size_t size_of(void) { return sizeof(value_type); } \
158  static std::string type_identifier(void) { return #T; } \
159  static size_t store( std::ostream& _os, const value_type& _val, \
160  bool _swap=false) { \
161  value_type tmp = _val; \
162  if (_swap) reverse_byte_order(tmp); \
163  /* Convert unsigned long to unsigned int for compatibility reasons */ \
164  unsigned int t1 = static_cast<unsigned int>(tmp); \
165  _os.write( (const char*)&t1, sizeof(unsigned int) ); \
166  return _os.good() ? sizeof(unsigned int) : 0; \
167  } \
168  \
169  static size_t restore( std::istream& _is, value_type& _val, \
170  bool _swap=false) { \
171  unsigned int t1; \
172  _is.read( (char*)&t1, sizeof(unsigned int) ); \
173  _val = t1; \
174  if (_swap) reverse_byte_order(_val); \
175  return _is.good() ? sizeof(unsigned int) : 0; \
176  } \
177  }
178 
179 SIMPLE_BINARY(unsigned long);
180 
181 #undef SIMPLE_BINARY
182 
183 #define VECTORT_BINARY( T ) \
184  template <> struct binary< T > { \
185  typedef T value_type; \
186  static const bool is_streamable = true; \
187  static size_t size_of(void) { return sizeof(value_type); } \
188  static size_t size_of(const value_type&) { return size_of(); } \
189  static std::string type_identifier(void) { return #T; } \
190  static size_t store( std::ostream& _os, const value_type& _val, \
191  bool _swap=false) { \
192  value_type tmp = _val; \
193  size_t i, b = size_of(_val), N = value_type::size_; \
194  if (_swap) \
195  for (i=0; i<N; ++i) \
196  reverse_byte_order( tmp[i] ); \
197  _os.write( (const char*)&tmp[0], b ); \
198  return _os.good() ? b : 0; \
199  } \
200  \
201  static size_t restore( std::istream& _is, value_type& _val, \
202  bool _swap=false) { \
203  size_t i, N=value_type::size_; \
204  size_t b = N * sizeof(value_type::value_type); \
205  _is.read( (char*)&_val[0], b ); \
206  if (_swap) for (i=0; i<N; ++i) \
207  reverse_byte_order( _val[i] ); \
208  return _is.good() ? b : 0; \
209  } \
210  }
211 
212 #define VECTORTS_BINARY( N ) \
213  VECTORT_BINARY( Vec##N##c ); \
214  VECTORT_BINARY( Vec##N##uc ); \
215  VECTORT_BINARY( Vec##N##s ); \
216  VECTORT_BINARY( Vec##N##us ); \
217  VECTORT_BINARY( Vec##N##i ); \
218  VECTORT_BINARY( Vec##N##ui ); \
219  VECTORT_BINARY( Vec##N##f ); \
220  VECTORT_BINARY( Vec##N##d );
221 
222 VECTORTS_BINARY( 1 )
223 VECTORTS_BINARY( 2 )
224 VECTORTS_BINARY( 3 )
225 VECTORTS_BINARY( 4 )
226 VECTORTS_BINARY( 5 )
227 VECTORTS_BINARY( 6 )
228 
229 #undef VECTORTS_BINARY
230 #undef VECTORT_BINARY
231 
232 template <> struct binary< std::string > {
233  typedef std::string value_type;
234  typedef uint16_t length_t;
235 
236  static const bool is_streamable = true;
237 
238  static size_t size_of() { return UnknownSize; }
239  static size_t size_of(const value_type &_v)
240  { return sizeof(length_t) + _v.size(); }
241  static std::string type_identifier(void) { return "std::string"; }
242  static
243  size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
244  {
245 #if defined(OM_CC_GCC) && (OM_CC_VERSION < 30000)
246  if (_v.size() < Utils::NumLimitsT<length_t>::max() )
247 #else
248  if (_v.size() < std::numeric_limits<length_t>::max() )
249 #endif
250  {
251  length_t len = length_t(_v.size());
252 
253  size_t bytes = binary<length_t>::store( _os, len, _swap );
254  _os.write( _v.data(), len );
255  return _os.good() ? len+bytes : 0;
256  }
257  throw std::runtime_error("Cannot store string longer than 64Kb");
258  }
259 
260  static
261  size_t restore(std::istream& _is, value_type& _val, bool _swap=false)
262  {
263  length_t len;
264  size_t bytes = binary<length_t>::restore( _is, len, _swap );
265  _val.resize(len);
266  _is.read( const_cast<char*>(_val.data()), len );
267 
268  return _is.good() ? (len+bytes) : 0;
269  }
270 };
271 
272 template <> struct binary<OpenMesh::Attributes::StatusInfo>
273 {
274  typedef OpenMesh::Attributes::StatusInfo value_type;
275  typedef value_type::value_type status_t;
276 
277  static const bool is_streamable = true;
278 
279  static size_t size_of() { return sizeof(status_t); }
280  static size_t size_of(const value_type&) { return size_of(); }
281 
282  static std::string type_identifier(void) { return "StatusInfo";}
283  static size_t n_bytes(size_t _n_elem)
284  { return _n_elem*sizeof(status_t); }
285 
286  static
287  size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
288  {
289  status_t v=_v.bits();
290  return binary<status_t>::store(_os, v, _swap);
291  }
292 
293  static
294  size_t restore( std::istream& _os, value_type& _v, bool _swap=false)
295  {
296  status_t v;
297  size_t b = binary<status_t>::restore(_os, v, _swap);
298  _v.set_bits(v);
299  return b;
300  }
301 };
302 
303 
304 //-----------------------------------------------------------------------------
305 // std::vector<T> specializations for struct binary<>
306 
307 template <typename T>
308 struct FunctorStore {
309  FunctorStore( std::ostream& _os, bool _swap) : os_(_os), swap_(_swap) { }
310  size_t operator () ( size_t _v1, const T& _s2 )
311  { return _v1+binary<T>::store(os_, _s2, swap_ ); }
312 
313  std::ostream& os_;
314  bool swap_;
315 };
316 
317 
318 template <typename T>
319 struct FunctorRestore {
320  FunctorRestore( std::istream& _is, bool _swap) : is_(_is), swap_(_swap) { }
321  size_t operator () ( size_t _v1, T& _s2 )
322  { return _v1+binary<T>::restore(is_, _s2, swap_ ); }
323  std::istream& is_;
324  bool swap_;
325 };
326 
327 template <typename T>
328 struct binary< std::vector< T >, typename std::enable_if<std::is_default_constructible<T>::value>::type > {
329  typedef std::vector< T > value_type;
330  typedef typename value_type::value_type elem_type;
331 
332  static const bool is_streamable = binary<T>::is_streamable;
333  static size_t size_of(bool _store_size = true)
334  { return IO::UnknownSize; }
335 
336  static size_t size_of(const value_type& _v, bool _store_size = true)
337  {
338  if(binary<T>::size_of() != IO::UnknownSize)
339  {
340  unsigned int N = static_cast<unsigned int>(_v.size());
341  auto res = binary<T>::size_of()*_v.size() + (_store_size? sizeof(decltype(N)) : 0);
342  return res;
343  }
344  else
345  {
346  size_t size = 0;
347  for(auto v : _v)
348  size += binary<T>::size_of(v);
349  if(_store_size)
351 
352  return size;
353  }
354  }
355 
356  static std::string type_identifier(void) { return "std::vector<" + binary<T>::type_identifier() + ">"; }
357  static
358  size_t store(std::ostream& _os, const value_type& _v, bool _swap=false, bool _store_size = true) {
359  size_t bytes=0;
360  if(_store_size)
361  {
362  unsigned int N = static_cast<unsigned int>(_v.size());
363  bytes += binary<unsigned int>::store( _os, N, _swap );
364  }
365  if (_swap)
366  bytes += std::accumulate( _v.begin(), _v.end(), static_cast<size_t>(0),
367  FunctorStore<elem_type>(_os,_swap) );
368  else
369  {
370  auto elem_size = binary<elem_type>::size_of();
371  if (elem_size != IO::UnknownSize && elem_size == sizeof(elem_type))
372  {
373  // size of all elements is known, equal, and densely packed in vector.
374  // Just store vector data
375  auto bytes_of_vec = size_of(_v, false);
376  bytes += bytes_of_vec;
377  if (_v.size() > 0)
378  _os.write( reinterpret_cast<const char*>(&_v[0]), bytes_of_vec);
379  }
380  else
381  {
382  // store individual elements
383  for (const auto& v : _v)
384  bytes += binary<elem_type>::store(_os, v, _swap);
385  }
386  }
387  return _os.good() ? bytes : 0;
388  }
389 
390  static size_t restore(std::istream& _is, value_type& _v, bool _swap=false, bool _restore_size = true) {
391 
392  size_t bytes=0;
393 
394  if(_restore_size)
395  {
396  unsigned int size_of_vec;
397  bytes += binary<unsigned int>::restore(_is, size_of_vec, _swap);
398  _v.resize(size_of_vec);
399  }
400 
401  if ( _swap)
402  bytes += std::accumulate( _v.begin(), _v.end(), size_t(0),
403  FunctorRestore<elem_type>(_is, _swap) );
404  else
405  {
406  auto elem_size = binary<elem_type>::size_of();
407  if (elem_size != IO::UnknownSize && elem_size == sizeof(elem_type))
408  {
409  // size of all elements is known, equal, and densely packed in vector.
410  // Just restore vector data
411  auto bytes_of_vec = size_of(_v, false);
412  bytes += bytes_of_vec;
413  if (_v.size() > 0)
414  _is.read( reinterpret_cast<char*>(&_v[0]), bytes_of_vec );
415  }
416  else
417  {
418  // restore individual elements
419  for (auto& v : _v)
420  bytes += binary<elem_type>::restore(_is, v, _swap);
421  }
422  }
423  return _is.good() ? bytes : 0;
424  }
425 };
426 
427 #include <OpenMesh/Core/IO/SR_binary_vector_of_bool.inl>
428 
429 // ----------------------------------------------------------------------------
430 
431 #endif // DOXY_IGNORE_THIS
432 
433 //=============================================================================
434 } // namespace IO
435 } // namespace OpenMesh
436 //=============================================================================
437 #endif // OPENMESH_SR_BINARY_SPEC_HH defined
438 //=============================================================================
439 
Temporary solution until std::numeric_limits is standard.
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
signed char int8_t
Binary read a short from _is and perform byte swapping if _swap is true.
Definition: SR_types.hh:80
short int16_t
Binary read a short from _is and perform byte swapping if _swap is true.
Definition: SR_types.hh:81
unsigned long long uint64_t
Binary read a short from _is and perform byte swapping if _swap is true.
Definition: SR_types.hh:89
unsigned int uint32_t
Binary read a short from _is and perform byte swapping if _swap is true.
Definition: SR_types.hh:85
unsigned short uint16_t
Binary read a short from _is and perform byte swapping if _swap is true.
Definition: SR_types.hh:81
int int32_t
Binary read a short from _is and perform byte swapping if _swap is true.
Definition: SR_types.hh:85
unsigned char uint8_t
Binary read a short from _is and perform byte swapping if _swap is true.
Definition: SR_types.hh:80
static size_t restore(std::istream &, value_type &, bool=false, bool=true)
Restore a value of T and return the number of bytes read.
Definition: SR_binary.hh:126
static const bool is_streamable
Can we store T? Set this to true in your specialization.
Definition: SR_binary.hh:106
static size_t store(std::ostream &, const value_type &, bool=false, bool=true)
Store a value of T and return the number of bytes written.
Definition: SR_binary.hh:118
static std::string type_identifier(void)
A string that identifies the type of T.
Definition: SR_binary.hh:114
static size_t size_of(void)
What's the size of T? If it depends on the actual value (e.g. for vectors) return UnknownSize.
Definition: SR_binary.hh:109
Add status information to a base class.
Definition: Status.hh:95
static Scalar max()
Return the maximum absolte value a scalar type can store.
Definition: NumLimitsT.hh:97

Project OpenMesh, ©  Visual Computing Institute, RWTH Aachen. Documentation generated using doxygen .