Developer Documentation
SR_binary_spec.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 
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 
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 //== NAMESPACES ===============================================================
76 
77 namespace OpenMesh {
78 namespace IO {
79 
80 
81 //=============================================================================
82 
83 #ifndef DOXY_IGNORE_THIS
84 
85 //-----------------------------------------------------------------------------
86 // struct binary, helper for storing/restoring
87 
88 #define SIMPLE_BINARY( T ) \
89  template <> struct binary< T > { \
90  typedef T value_type; \
91  static const bool is_streamable = true; \
92  static size_t size_of(const value_type&) { return sizeof(value_type); } \
93  static size_t size_of(void) { return sizeof(value_type); } \
94  static size_t store( std::ostream& _os, const value_type& _val, \
95  bool _swap=false) { \
96  value_type tmp = _val; \
97  if (_swap) reverse_byte_order(tmp); \
98  _os.write( (const char*)&tmp, sizeof(value_type) ); \
99  return _os.good() ? sizeof(value_type) : 0; \
100  } \
101  \
102  static size_t restore( std::istream& _is, value_type& _val, \
103  bool _swap=false) { \
104  _is.read( (char*)&_val, sizeof(value_type) ); \
105  if (_swap) reverse_byte_order(_val); \
106  return _is.good() ? sizeof(value_type) : 0; \
107  } \
108  }
109 
110 SIMPLE_BINARY(bool);
111 //SIMPLE_BINARY(int);
112 
113 // Why is this needed? Should not be used as not 32 bit compatible
114 //SIMPLE_BINARY(unsigned long);
115 SIMPLE_BINARY(float);
116 SIMPLE_BINARY(double);
117 SIMPLE_BINARY(long double);
118 SIMPLE_BINARY(char);
119 
120 SIMPLE_BINARY(int8_t);
121 SIMPLE_BINARY(int16_t);
122 SIMPLE_BINARY(int32_t);
123 SIMPLE_BINARY(int64_t);
124 SIMPLE_BINARY(uint8_t);
125 SIMPLE_BINARY(uint16_t);
126 SIMPLE_BINARY(uint32_t);
127 SIMPLE_BINARY(uint64_t);
128 
129 #undef SIMPLE_BINARY
130 
131 // For unsigned long which is of size 64 bit on 64 bit
132 // architectures: convert into 32 bit unsigned integer value
133 // in order to stay compatible between 32/64 bit architectures.
134 // This allows cross reading BUT forbids storing unsigned longs
135 // as data type since higher order word (4 bytes) will be truncated.
136 // Does not work in case the data type that is to be stored
137 // exceeds the value range of unsigned int in size, which is improbable...
138 
139 #define SIMPLE_BINARY( T ) \
140  template <> struct binary< T > { \
141  typedef T value_type; \
142  static const bool is_streamable = true; \
143  static size_t size_of(const value_type&) { return sizeof(value_type); } \
144  static size_t size_of(void) { return sizeof(value_type); } \
145  static size_t store( std::ostream& _os, const value_type& _val, \
146  bool _swap=false) { \
147  value_type tmp = _val; \
148  if (_swap) reverse_byte_order(tmp); \
149  /* Convert unsigned long to unsigned int for compatibility reasons */ \
150  unsigned int t1 = static_cast<unsigned int>(tmp); \
151  _os.write( (const char*)&t1, sizeof(unsigned int) ); \
152  return _os.good() ? sizeof(unsigned int) : 0; \
153  } \
154  \
155  static size_t restore( std::istream& _is, value_type& _val, \
156  bool _swap=false) { \
157  unsigned int t1; \
158  _is.read( (char*)&t1, sizeof(unsigned int) ); \
159  _val = t1; \
160  if (_swap) reverse_byte_order(_val); \
161  return _is.good() ? sizeof(unsigned int) : 0; \
162  } \
163  }
164 
165 SIMPLE_BINARY(unsigned long);
166 
167 #undef SIMPLE_BINARY
168 
169 #define VECTORT_BINARY( T ) \
170  template <> struct binary< T > { \
171  typedef T value_type; \
172  static const bool is_streamable = true; \
173  static size_t size_of(void) { return sizeof(value_type); } \
174  static size_t size_of(const value_type&) { return size_of(); } \
175  static size_t store( std::ostream& _os, const value_type& _val, \
176  bool _swap=false) { \
177  value_type tmp = _val; \
178  size_t i, b = size_of(_val), N = value_type::size_; \
179  if (_swap) for (i=0; i<N; ++i) \
180  reverse_byte_order( tmp[i] ); \
181  _os.write( (const char*)&tmp[0], b ); \
182  return _os.good() ? b : 0; \
183  } \
184  \
185  static size_t restore( std::istream& _is, value_type& _val, \
186  bool _swap=false) { \
187  size_t i, N=value_type::size_; \
188  size_t b = N * sizeof(value_type::value_type); \
189  _is.read( (char*)&_val[0], b ); \
190  if (_swap) for (i=0; i<N; ++i) \
191  reverse_byte_order( _val[i] ); \
192  return _is.good() ? b : 0; \
193  } \
194  }
195 
196 #define VECTORTS_BINARY( N ) \
197  VECTORT_BINARY( Vec##N##c ); \
198  VECTORT_BINARY( Vec##N##uc ); \
199  VECTORT_BINARY( Vec##N##s ); \
200  VECTORT_BINARY( Vec##N##us ); \
201  VECTORT_BINARY( Vec##N##i ); \
202  VECTORT_BINARY( Vec##N##ui ); \
203  VECTORT_BINARY( Vec##N##f ); \
204  VECTORT_BINARY( Vec##N##d );
205 
206 VECTORTS_BINARY( 1 )
207 VECTORTS_BINARY( 2 )
208 VECTORTS_BINARY( 3 )
209 VECTORTS_BINARY( 4 )
210 VECTORTS_BINARY( 6 )
211 
212 #undef VECTORTS_BINARY
213 #undef VECTORT_BINARY
214 
215 template <> struct binary< std::string > {
216  typedef std::string value_type;
217  typedef uint16_t length_t;
218 
219  static const bool is_streamable = true;
220 
221  static size_t size_of() { return UnknownSize; }
222  static size_t size_of(const value_type &_v)
223  { return sizeof(length_t) + _v.size(); }
224 
225  static
226  size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
227  {
228 #if defined(OM_CC_GCC) && (OM_CC_VERSION < 30000)
229  if (_v.size() < Utils::NumLimitsT<length_t>::max() )
230 #else
231  if (_v.size() < std::numeric_limits<length_t>::max() )
232 #endif
233  {
234  length_t len = length_t(_v.size());
235 
236  size_t bytes = binary<length_t>::store( _os, len, _swap );
237  _os.write( _v.data(), len );
238  return _os.good() ? len+bytes : 0;
239  }
240  throw std::runtime_error("Cannot store string longer than 64Kb");
241  }
242 
243  static
244  size_t restore(std::istream& _is, value_type& _val, bool _swap=false)
245  {
246  length_t len;
247  size_t bytes = binary<length_t>::restore( _is, len, _swap );
248  _val.resize(len);
249  _is.read( const_cast<char*>(_val.data()), len );
250 
251  return _is.good() ? (len+bytes) : 0;
252  }
253 };
254 
255 
256 template <> struct binary<OpenMesh::Attributes::StatusInfo>
257 {
258  typedef OpenMesh::Attributes::StatusInfo value_type;
259  typedef value_type::value_type status_t;
260 
261  static const bool is_streamable = true;
262 
263  static size_t size_of() { return sizeof(status_t); }
264  static size_t size_of(const value_type&) { return size_of(); }
265 
266  static size_t n_bytes(size_t _n_elem)
267  { return _n_elem*sizeof(status_t); }
268 
269  static
270  size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
271  {
272  status_t v=_v.bits();
273  return binary<status_t>::store(_os, v, _swap);
274  }
275 
276  static
277  size_t restore( std::istream& _os, value_type& _v, bool _swap=false)
278  {
279  status_t v;
280  size_t b = binary<status_t>::restore(_os, v, _swap);
281  _v.set_bits(v);
282  return b;
283  }
284 };
285 
286 
287 //-----------------------------------------------------------------------------
288 // std::vector<T> specializations for struct binary<>
289 
290 template <typename T>
291 struct FunctorStore {
292  FunctorStore( std::ostream& _os, bool _swap) : os_(_os), swap_(_swap) { }
293  size_t operator () ( size_t _v1, const T& _s2 )
294  { return _v1+binary<T>::store(os_, _s2, swap_ ); }
295 
296  std::ostream& os_;
297  bool swap_;
298 };
299 
300 
301 template <typename T>
302 struct FunctorRestore {
303  FunctorRestore( std::istream& _is, bool _swap) : is_(_is), swap_(_swap) { }
304  size_t operator () ( size_t _v1, T& _s2 )
305  { return _v1+binary<T>::restore(is_, _s2, swap_ ); }
306  std::istream& is_;
307  bool swap_;
308 };
309 
310 #include <OpenMesh/Core/IO/SR_binary_vector_of_fundamentals.inl>
311 #include <OpenMesh/Core/IO/SR_binary_vector_of_string.inl>
312 #include <OpenMesh/Core/IO/SR_binary_vector_of_bool.inl>
313 
314 // ----------------------------------------------------------------------------
315 
316 #endif // DOXY_IGNORE_THIS
317 
318 //=============================================================================
319 } // namespace IO
320 } // namespace OpenMesh
321 //=============================================================================
322 #endif // OPENMESH_SR_BINARY_SPEC_HH defined
323 //=============================================================================
324 
signed char int8_t
Definition: SR_types.hh:80
size_t size_of(const T &_v)
Definition: StoreRestore.hh:89
short int16_t
Definition: SR_types.hh:81
STL namespace.
unsigned long long uint64_t
Definition: SR_types.hh:89
static Scalar max()
Return the maximum absolte value a scalar type can store.
Definition: NumLimitsT.hh:97
unsigned short uint16_t
Definition: SR_types.hh:81
unsigned char uint8_t
Definition: SR_types.hh:80
unsigned int uint32_t
Definition: SR_types.hh:85
long long int64_t
Definition: SR_types.hh:89