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 #ifndef OPENMESH_IO_OMFORMAT_HH
46 #define OPENMESH_IO_OMFORMAT_HH
47 
48 
49 //=== INCLUDES ================================================================
50 
51 #include <OpenMesh/Core/System/config.h>
52 #include <OpenMesh/Core/System/omstream.hh>
53 #include <OpenMesh/Core/IO/SR_store.hh>
54 #include <OpenMesh/Core/Utils/GenProg.hh>
55 #include <OpenMesh/Core/Utils/Endian.hh>
56 #include <OpenMesh/Core/Utils/vector_traits.hh>
57 // --------------------
58 #include <iostream>
59 #if defined(OM_CC_GCC) && (OM_GCC_VERSION < 30000)
60 #  include <OpenMesh/Tools/Utils/NumLimitsT.hh>
61 #  define OM_MISSING_HEADER_LIMITS 1
62 #else
63 #  include <limits>
64 #endif
65 
66 
67 //== NAMESPACES ==============================================================
68 
69 #ifndef DOXY_IGNORE_THIS
70 namespace OpenMesh {
71 namespace IO   {
72 namespace OMFormat {
73 
74 
75 //=== IMPLEMENTATION ==========================================================
76 
77 
78 /** \name Mesh Reading / Writing
79 */
80 //@{
81 
82 //-----------------------------------------------------------------------------
83 
84   // <:Header>
85   // <:Comment>
86   // Chunk 0
87   //   <:ChunkHeader>
88   //   <:Comment>
89   //   data
90   // Chunk 1
91   //   <:ChunkHeader>
92   //   <:Comment>
93   //   data
94   // .
95   // .
96   // .
97   // Chunk N
98 
99   //
100   // NOTICE!
101   //
102   // The usage of data types who differ in size
103   // on different pc architectures (32/64 bit) and/or
104   // operating systems, e.g. (unsigned) long, size_t,
105   // is not recommended because of inconsistencies
106   // in case of cross writing and reading.
107   //
108   // Basic types that are supported are:
109 
110 
111   typedef unsigned char      uchar;
112   typedef uint8_t            uint8;
113   typedef uint16_t           uint16;
114   typedef uint32_t           uint32;
115   typedef uint64_t           uint64;
116   typedef int8_t             int8;
117   typedef int16_t            int16;
118   typedef int32_t            int32;
119   typedef int64_t            int64;
120   typedef float32_t          float32;
121   typedef float64_t          float64;
122 
123   struct Header
124   {
125     uchar  magic_[2]; // OM
126     uchar  mesh_;    // [T]riangles, [Q]uads, [P]olygonals
127     uint8  version_;
128     uint32 n_vertices_;
129     uint32 n_faces_;
130     uint32 n_edges_;
131 
storeOpenMesh::IO::OMFormat::Header132     size_t store( std::ostream& _os, bool _swap ) const
133     {
134       _os.write( (char*)this, 4); // magic_, mesh_, version_
135       size_t bytes = 4;
136       bytes += binary<uint32_t>::store( _os, n_vertices_, _swap );
137       bytes += binary<uint32_t>::store( _os, n_faces_, _swap );
138       bytes += binary<uint32_t>::store( _os, n_edges_, _swap );
139       return bytes;
140     }
141 
restoreOpenMesh::IO::OMFormat::Header142     size_t restore( std::istream& _is, bool _swap )
143     {
144       if (_is.read( (char*)this, 4 ).eof())
145 	return 0;
146 
147       size_t bytes = 4;
148       bytes += binary<uint32_t>::restore( _is, n_vertices_, _swap );
149       bytes += binary<uint32_t>::restore( _is, n_faces_, _swap );
150       bytes += binary<uint32_t>::restore( _is, n_edges_, _swap );
151       return bytes;
152     }
153 
154   };
155 
156   struct Chunk
157   {
158     // Hardcoded this size to an uint32 to make the system 32/64 bit compatible.
159     // Needs further investigation!
160     typedef uint32 esize_t; // element size, used for custom properties
161 
162     enum Type {
163       Type_Pos       = 0x00,
164       Type_Normal    = 0x01,
165       Type_Texcoord  = 0x02,
166       Type_Status    = 0x03,
167       Type_Color     = 0x04,
168       Type_Custom    = 0x06,
169       Type_Topology  = 0x07
170     };
171 
172     enum Entity {
173       Entity_Vertex    = 0x00,
174       Entity_Mesh      = 0x01,
175       Entity_Face      = 0x02,
176       Entity_Edge      = 0x04,
177       Entity_Halfedge  = 0x06,
178       Entity_Sentinel  = 0x07
179     };
180 
181     enum Dim {
182       Dim_1D = 0x00,
183       Dim_2D = 0x01,
184       Dim_3D = 0x02,
185       Dim_4D = 0x03,
186       Dim_5D = 0x04,
187       Dim_6D = 0x05,
188       Dim_7D = 0x06,
189       Dim_8D = 0x07
190     };
191 
192     enum Integer_Size {
193       Integer_8   = 0x00, // 1 byte for (unsigned) char
194       Integer_16  = 0x01, // 2 bytes for short
195       Integer_32  = 0x02, // 4 bytes for long
196       Integer_64  = 0x03  // 8 bytes for long long
197     };
198 
199     enum Float_Size {
200       Float_32  = 0x00, //  4 bytes for float
201       Float_64  = 0x01, //  8 bytes for double
202       Float_128 = 0x02  // 16 bytes for long double (an assumption!)
203     };
204 
205     static const int SIZE_RESERVED = 1; //  1
206     static const int SIZE_NAME     = 1; //  2
207     static const int SIZE_ENTITY   = 3; //  5
208     static const int SIZE_TYPE     = 4; //  9
209 
210     static const int SIZE_SIGNED   = 1; // 10
211     static const int SIZE_FLOAT    = 1; // 11
212     static const int SIZE_DIM      = 3; // 14
213     static const int SIZE_BITS     = 2; // 16
214 
215     static const int OFF_RESERVED = 0;                          //  0
216     static const int OFF_NAME     = SIZE_RESERVED + OFF_RESERVED; //  2
217     static const int OFF_ENTITY   = SIZE_NAME     + OFF_NAME;   //  3
218     static const int OFF_TYPE     = SIZE_ENTITY   + OFF_ENTITY; //  5
219     static const int OFF_SIGNED   = SIZE_TYPE     + OFF_TYPE;   //  9
220     static const int OFF_FLOAT    = SIZE_SIGNED   + OFF_SIGNED; // 10
221     static const int OFF_DIM      = SIZE_FLOAT    + OFF_FLOAT;  // 11
222     static const int OFF_BITS     = SIZE_DIM      + OFF_DIM;    // 14
223 
224     // !Attention! When changing the bit size, the operators
225     // << (uint16, Header) and << (Header, uint16) must be changed as well
226     //
227     // Entries signed_, float_, dim_, bits_ are not used when type_
228     // equals Type_Custom
229     //
230     struct Header // 16 bits long
231     {
232       unsigned reserved_: SIZE_RESERVED;
233       unsigned name_    : SIZE_NAME;   // 1 named property, 0 anonymous
234       unsigned entity_  : SIZE_ENTITY; // 0 vertex, 1 mesh, 2 edge,
235                                        // 4 halfedge, 6 face
236       unsigned type_    : SIZE_TYPE;   // 0 pos, 1 normal, 2 texcoord,
237                                        // 3 status, 4 color 6 custom 7 topology
238       unsigned signed_  : SIZE_SIGNED; // bool
239       unsigned float_   : SIZE_FLOAT;  // bool
240       unsigned dim_     : SIZE_DIM;    // 0 1D, 1 2D, 2 3D, .., 7 8D
241       unsigned bits_    : SIZE_BITS;   // {8, 16, 32, 64} | {32, 64, 128}
242                                        // (integer)         (float)
243       unsigned unused_  : 16; // fill up to 32 bits
244     }; // struct Header
245 
246 
247     class PropertyName : public std::string
248     {
249     public:
250 
251       static const size_t size_max = 256;
252 
PropertyName()253       PropertyName( ) { }
254 
PropertyName(const std::string & _name)255       explicit PropertyName( const std::string& _name ) { *this = _name; }
256 
is_valid() const257       bool is_valid() const { return is_valid( size() ); }
258 
is_valid(size_t _s)259       static bool is_valid( size_t _s ) { return _s <= size_max; }
260 
operator =(const std::string & _rhs)261       PropertyName& operator = ( const std::string& _rhs )
262       {
263 	assert( is_valid( _rhs.size() ) );
264 
265 	if ( is_valid( _rhs.size() ) )
266 	  std::string::operator = ( _rhs );
267 	else
268 	{
269 	  omerr() << "Warning! Property name too long. Will be shortened!\n";
270 	  this->std::string::operator = ( _rhs.substr(0, size_max) );
271 	}
272 
273 	return *this;
274       }
275 
276     };
277 
278   }; // Chunk
279 
280   // ------------------------------------------------------------ Helper
281 
282   // -------------------- get size information
283 
284   /// Return size of header in bytes.
header_size(void)285   inline size_t header_size(void) { return sizeof(Header); }
286 
287 
288   /// Return size of chunk header in bytes.
chunk_header_size(void)289   inline size_t chunk_header_size( void ) { return sizeof(uint16); }
290 
291 
292   /// Return the size of a scaler in bytes.
scalar_size(const Chunk::Header & _hdr)293   inline size_t scalar_size( const Chunk::Header& _hdr )
294   {
295     return _hdr.float_ ? (0x01 << _hdr.bits_) : (0x04 << _hdr.bits_);
296   }
297 
298 
299   /// Return the dimension of the vector in a chunk
dimensions(const Chunk::Header & _chdr)300   inline size_t dimensions(const Chunk::Header& _chdr) { return _chdr.dim_+1; }
301 
302 
303   /// Return the size of a vector in bytes.
vector_size(const Chunk::Header & _chdr)304   inline size_t vector_size( const Chunk::Header& _chdr )
305   {
306     return dimensions(_chdr)*scalar_size(_chdr);
307   }
308 
309 
310   /// Return the size of chunk data in bytes
chunk_data_size(Header & _hdr,Chunk::Header & _chunk_hdr)311   inline size_t chunk_data_size( Header& _hdr,  Chunk::Header& _chunk_hdr )
312   {
313     size_t C;
314     switch( _chunk_hdr.entity_ )
315     {
316       case Chunk::Entity_Vertex:   C  = _hdr.n_vertices_; break;
317       case Chunk::Entity_Face:     C  = _hdr.n_faces_;    break;
318       case Chunk::Entity_Halfedge: C  = _hdr.n_edges_*2;  break;
319       case Chunk::Entity_Edge:     C  = _hdr.n_edges_;    break;
320       case Chunk::Entity_Mesh:     C  = 1;                break;
321       default:
322         C = 0;
323         std::cerr << "Invalid value in _chunk_hdr.entity_\n";
324         assert( false );
325         break;
326     }
327 
328     return C * vector_size( _chunk_hdr );
329   }
330 
chunk_size(Header & _hdr,Chunk::Header & _chunk_hdr)331   inline size_t chunk_size( Header& _hdr, Chunk::Header& _chunk_hdr )
332   {
333     return chunk_header_size() + chunk_data_size( _hdr, _chunk_hdr );
334   }
335 
336   // -------------------- convert from Chunk::Header to storage type
337 
338   uint16& operator << (uint16& val, const Chunk::Header& hdr);
339   Chunk::Header& operator << (Chunk::Header& hdr, const uint16 val);
340 
341 
342   // -------------------- type information
343 
is_float(const T &)344   template <typename T> bool is_float(const T&)
345   {
346 #if defined(OM_MISSING_HEADER_LIMITS)
347     return !Utils::NumLimitsT<T>::is_integer();
348 #else
349     return !std::numeric_limits<T>::is_integer;
350 #endif
351   }
352 
is_double(const T &)353   template <typename T> bool is_double(const T&)
354   {
355     return false;
356   }
357 
is_double(const double &)358   template <> inline bool is_double(const double&)
359   {
360     return true;
361   }
362 
is_integer(const T)363   template <typename T> bool is_integer(const T)
364   {
365 #if defined(OM_MISSING_HEADER_LIMITS)
366     return Utils::NumLimitsT<T>::is_integer();
367 #else
368     return std::numeric_limits<T>::is_integer;
369 #endif
370   }
371 
is_signed(const T &)372   template <typename T> bool is_signed(const T&)
373   {
374 #if defined(OM_MISSING_HEADER_LIMITS)
375     return Utils::NumLimitsT<T>::is_signed();
376 #else
377     return std::numeric_limits<T>::is_signed;
378 #endif
379   }
380 
381   // -------------------- conversions (format type <- type/value)
382 
383   template <typename VecType>
384   inline
dim(VecType)385   Chunk::Dim dim( VecType )
386   {
387     assert( vector_traits< VecType >::size() < 9 );
388     return static_cast<Chunk::Dim>(vector_traits< VecType >::size() - 1);
389   }
390 
391   template <typename VecType>
392   inline
dim(const Chunk::Header & _hdr)393   Chunk::Dim dim( const Chunk::Header& _hdr )
394   {
395     return static_cast<Chunk::Dim>( _hdr.dim_ );
396   }
397 
398   // calc minimum (power-of-2) number of bits needed
399   Chunk::Integer_Size needed_bits( size_t s );
400 
401   // Convert size of type to Integer_Size
402 #ifdef NDEBUG
integer_size(const T &)403   template <typename T> Chunk::Integer_Size integer_size(const T&)
404 #else
405   template <typename T> Chunk::Integer_Size integer_size(const T& d)
406 #endif
407   {
408 #ifndef NDEBUG
409     assert( is_integer(d) );
410 #endif
411 
412     switch( sizeof(T) )
413     {
414       case  1: return OMFormat::Chunk::Integer_8;
415       case  2: return OMFormat::Chunk::Integer_16;
416       case  4: return OMFormat::Chunk::Integer_32;
417       case  8: return OMFormat::Chunk::Integer_64;
418       default:
419         std::cerr << "Invalid value in integer_size\n";
420         assert( false );
421         break;
422     }
423     return Chunk::Integer_Size(0);
424   }
425 
426 
427   // Convert size of type to FLoat_Size
428 #ifdef NDEBUG
float_size(const T &)429   template <typename T> Chunk::Float_Size float_size(const T&)
430 #else
431   template <typename T> Chunk::Float_Size float_size(const T& d)
432 #endif
433   {
434 #ifndef NDEBUG
435     assert( is_float(d) );
436 #endif
437 
438     switch( sizeof(T) )
439     {
440       case  4: return OMFormat::Chunk::Float_32;
441       case  8: return OMFormat::Chunk::Float_64;
442       case 16: return OMFormat::Chunk::Float_128;
443       default:
444         std::cerr << "Invalid value in float_size\n";
445         assert( false );
446         break;
447     }
448     return Chunk::Float_Size(0);
449   }
450 
451   // Return the storage type (Chunk::Header::bits_)
452   template <typename T>
453   inline
bits(const T & val)454   unsigned int bits(const T& val)
455   {
456     return is_integer(val)
457       ? (static_cast<unsigned int>(integer_size(val)))
458       : (static_cast<unsigned int>(float_size(val)));
459   }
460 
461   // -------------------- create/read version
462 
mk_version(const uint16 major,const uint16 minor)463   inline uint8 mk_version(const uint16 major, const uint16 minor)
464   { return (major & 0x07) << 5 | (minor & 0x1f); }
465 
466 
major_version(const uint8 version)467   inline uint16 major_version(const uint8 version)
468   { return (version >> 5) & 0x07; }
469 
470 
minor_version(const uint8 version)471   inline uint16 minor_version(const uint8 version)
472   { return (version & 0x001f); }
473 
474 
475   // ---------------------------------------- convenience functions
476 
477   std::string as_string(uint8 version);
478 
479   const char *as_string(Chunk::Type t);
480   const char *as_string(Chunk::Entity e);
481   const char *as_string(Chunk::Dim d);
482   const char *as_string(Chunk::Integer_Size d);
483   const char *as_string(Chunk::Float_Size d);
484 
485   std::ostream& operator << ( std::ostream& _os, const Header& _h );
486   std::ostream& operator << ( std::ostream& _os, const Chunk::Header& _c );
487 
488 //@}
489 } // namespace OMFormat
490 
491   // -------------------- (re-)store header
492 
493   template <> inline
store(std::ostream & _os,const OMFormat::Header & _hdr,bool _swap)494   size_t store( std::ostream& _os, const OMFormat::Header& _hdr, bool _swap)
495   { return _hdr.store( _os, _swap ); }
496 
497   template <> inline
restore(std::istream & _is,OMFormat::Header & _hdr,bool _swap)498   size_t restore( std::istream& _is, OMFormat::Header& _hdr, bool _swap )
499   { return _hdr.restore( _is, _swap ); }
500 
501 
502   // -------------------- (re-)store chunk header
503 
504   template <> inline
505   size_t
store(std::ostream & _os,const OMFormat::Chunk::Header & _hdr,bool _swap)506   store( std::ostream& _os, const OMFormat::Chunk::Header& _hdr, bool _swap)
507   {
508     OMFormat::uint16 val; val << _hdr;
509     return binary<uint16_t>::store( _os, val, _swap );
510   }
511 
512   template <> inline
513   size_t
restore(std::istream & _is,OMFormat::Chunk::Header & _hdr,bool _swap)514   restore( std::istream& _is, OMFormat::Chunk::Header& _hdr, bool _swap )
515   {
516     OMFormat::uint16 val;
517     size_t bytes = binary<uint16_t>::restore( _is, val, _swap );
518 
519     _hdr << val;
520 
521     return bytes;
522   }
523 
524   // -------------------- (re-)store integer with wanted number of bits (bytes)
525 
526   typedef GenProg::TrueType  t_signed;
527   typedef GenProg::FalseType t_unsigned;
528 
529   // helper to store a an integer
530   template< typename T >
531   size_t
532   store( std::ostream& _os,
533 	 const T& _val,
534 	 OMFormat::Chunk::Integer_Size _b,
535 	 bool _swap,
536 	 t_signed);
537 
538   // helper to store a an unsigned integer
539   template< typename T >
540   size_t
541   store( std::ostream& _os,
542 	 const T& _val,
543 	 OMFormat::Chunk::Integer_Size _b,
544 	 bool _swap,
545 	 t_unsigned);
546 
547   /// Store an integer with a wanted number of bits
548   template< typename T >
549   inline
550   size_t
store(std::ostream & _os,const T & _val,OMFormat::Chunk::Integer_Size _b,bool _swap)551   store( std::ostream& _os,
552 	 const T& _val,
553 	 OMFormat::Chunk::Integer_Size _b,
554 	 bool _swap)
555   {
556     assert( OMFormat::is_integer( _val ) );
557 
558     if ( OMFormat::is_signed( _val ) )
559       return store( _os, _val, _b, _swap, t_signed()   );
560     return   store( _os, _val, _b, _swap, t_unsigned() );
561   }
562 
563   // helper to store a an integer
564   template< typename T > inline
565   size_t restore( std::istream& _is,
566 		  T& _val,
567 		  OMFormat::Chunk::Integer_Size _b,
568 		  bool _swap,
569 		  t_signed);
570 
571   // helper to store a an unsigned integer
572   template< typename T > inline
573   size_t restore( std::istream& _is,
574 		  T& _val,
575 		  OMFormat::Chunk::Integer_Size _b,
576 		  bool _swap,
577 		  t_unsigned);
578 
579   /// Restore an integer with a wanted number of bits
580   template< typename T >
581   inline
582   size_t
restore(std::istream & _is,T & _val,OMFormat::Chunk::Integer_Size _b,bool _swap)583   restore( std::istream& _is,
584 	   T& _val,
585 	   OMFormat::Chunk::Integer_Size _b,
586 	   bool _swap)
587   {
588     assert( OMFormat::is_integer( _val ) );
589 
590     if ( OMFormat::is_signed( _val ) )
591       return restore( _is, _val, _b, _swap, t_signed() );
592     return restore( _is, _val, _b, _swap, t_unsigned() );
593   }
594 
595 
596   //
597   // ---------------------------------------- storing vectors
598   template <typename VecT> inline
store(std::ostream & _os,const VecT & _vec,GenProg::Int2Type<2>,bool _swap)599   size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<2>,
600 		bool _swap )
601   {
602     size_t bytes =  store( _os, _vec[0], _swap );
603     bytes += store( _os, _vec[1], _swap );
604     return bytes;
605   }
606 
607   template <typename VecT> inline
store(std::ostream & _os,const VecT & _vec,GenProg::Int2Type<3>,bool _swap)608   size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<3>,
609 		bool _swap )
610   {
611     size_t bytes =  store( _os, _vec[0], _swap );
612     bytes += store( _os, _vec[1], _swap );
613     bytes += store( _os, _vec[2], _swap );
614     return bytes;
615   }
616 
617   template <typename VecT> inline
store(std::ostream & _os,const VecT & _vec,GenProg::Int2Type<4>,bool _swap)618   size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<4>,
619 		bool _swap )
620   {
621     size_t bytes =  store( _os, _vec[0], _swap );
622     bytes += store( _os, _vec[1], _swap );
623     bytes += store( _os, _vec[2], _swap );
624     bytes += store( _os, _vec[3], _swap );
625     return bytes;
626   }
627 
628   template <typename VecT> inline
store(std::ostream & _os,const VecT & _vec,GenProg::Int2Type<1>,bool _swap)629   size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<1>,
630 		bool _swap )
631   {
632     return store( _os, _vec[0], _swap );
633   }
634 
635   /// storing a vector type
636   template <typename VecT> inline
vector_store(std::ostream & _os,const VecT & _vec,bool _swap)637   size_t vector_store( std::ostream& _os, const VecT& _vec, bool _swap )
638   {
639     return store( _os, _vec,
640 		  GenProg::Int2Type< vector_traits<VecT>::size_ >(),
641 		  _swap );
642   }
643 
644   // ---------------------------------------- restoring vectors
645   template <typename VecT>
646   inline
647   size_t
restore(std::istream & _is,VecT & _vec,GenProg::Int2Type<2>,bool _swap)648   restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<2>,
649 	 bool _swap )
650   {
651     size_t bytes =  restore( _is, _vec[0], _swap );
652     bytes += restore( _is, _vec[1], _swap );
653     return bytes;
654   }
655 
656   template <typename VecT>
657   inline
658   size_t
restore(std::istream & _is,VecT & _vec,GenProg::Int2Type<3>,bool _swap)659   restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<3>,
660 	 bool _swap )
661   {
662     typedef typename vector_traits<VecT>::value_type scalar_type;
663     size_t bytes;
664 
665     bytes  = binary<scalar_type>::restore( _is, _vec[0], _swap );
666     bytes += binary<scalar_type>::restore( _is, _vec[1], _swap );
667     bytes += binary<scalar_type>::restore( _is, _vec[2], _swap );
668     return bytes;
669   }
670 
671   template <typename VecT>
672   inline
673   size_t
restore(std::istream & _is,VecT & _vec,GenProg::Int2Type<4>,bool _swap)674   restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<4>,
675 	   bool _swap )
676   {
677     typedef typename vector_traits<VecT>::value_type scalar_type;
678     size_t bytes;
679 
680     bytes  = binary<scalar_type>::restore( _is, _vec[0], _swap );
681     bytes += binary<scalar_type>::restore( _is, _vec[1], _swap );
682     bytes += binary<scalar_type>::restore( _is, _vec[2], _swap );
683     bytes += binary<scalar_type>::restore( _is, _vec[3], _swap );
684     return bytes;
685   }
686 
687   template <typename VecT>
688   inline
689   size_t
restore(std::istream & _is,VecT & _vec,GenProg::Int2Type<1>,bool _swap)690   restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<1>,
691 	 bool _swap )
692   {
693     return restore( _is, _vec[0], _swap );
694   }
695 
696   /// Restoring a vector type
697   template <typename VecT>
698   inline
699   size_t
vector_restore(std::istream & _is,VecT & _vec,bool _swap)700   vector_restore( std::istream& _is, VecT& _vec, bool _swap )
701   {
702     return restore( _is, _vec,
703 		    GenProg::Int2Type< vector_traits<VecT>::size_ >(),
704 		    _swap );
705   }
706 
707 
708   // ---------------------------------------- storing property names
709 
710   template <>
711   inline
store(std::ostream & _os,const OMFormat::Chunk::PropertyName & _pn,bool _swap)712   size_t store( std::ostream& _os, const OMFormat::Chunk::PropertyName& _pn,
713 		bool _swap )
714   {
715     store( _os, _pn.size(), OMFormat::Chunk::Integer_8, _swap ); // 1 byte
716     if ( _pn.size() )
717       _os.write( _pn.c_str(), _pn.size() ); // size bytes
718     return _pn.size() + 1;
719   }
720 
721   template <>
722   inline
restore(std::istream & _is,OMFormat::Chunk::PropertyName & _pn,bool _swap)723   size_t restore( std::istream& _is, OMFormat::Chunk::PropertyName& _pn,
724 		  bool _swap )
725   {
726     size_t size;
727 
728     restore( _is, size, OMFormat::Chunk::Integer_8, _swap); // 1 byte
729 
730     assert( OMFormat::Chunk::PropertyName::is_valid( size ) );
731 
732     if ( size > 0 )
733     {
734       char buf[256];
735       _is.read( buf, size ); // size bytes
736       buf[size] = '\0';
737       _pn.resize(size);
738       _pn = buf;
739     }
740     return size+1;
741   }
742 
743 //=============================================================================
744 } // namespace IO
745 } // namespace OpenMesh
746 #endif
747 //=============================================================================
748 #if defined(OM_MISSING_HEADER_LIMITS)
749 #  undef OM_MISSING_HEADER_LIMITS
750 #endif
751 //=============================================================================
752 #if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_IO_OMFORMAT_CC)
753 #  define OPENMESH_IO_OMFORMAT_TEMPLATES
754 #  include "OMFormatT_impl.hh"
755 #endif
756 //=============================================================================
757 #endif
758 //=============================================================================
759