- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# Core/IO/OMFormat.hh

    00001 /*===========================================================================*\
    00002  *                                                                           *
    00003  *                               OpenMesh                                    *
    00004  *      Copyright (C) 2001-2005 by Computer Graphics Group, RWTH Aachen      *
    00005  *                           www.openmesh.org                                *
    00006  *                                                                           *
    00007  *---------------------------------------------------------------------------*
    00008  *                                                                           *
    00009  *                                License                                    *
    00010  *                                                                           *
    00011  *  This library is free software; you can redistribute it and/or modify it  *
    00012  *  under the terms of the GNU Library General Public License as published   *
    00013  *  by the Free Software Foundation, version 2.                              *
    00014  *                                                                           *
    00015  *  This library is distributed in the hope that it will be useful, but      *
    00016  *  WITHOUT ANY WARRANTY; without even the implied warranty of               *
    00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU        *
    00018  *  Library General Public License for more details.                         *
    00019  *                                                                           *
    00020  *  You should have received a copy of the GNU Library General Public        *
    00021  *  License along with this library; if not, write to the Free Software      *
    00022  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                *
    00023  *                                                                           *
    00024 \*===========================================================================*/
    00025
    00026
    00027 #ifndef OPENMESH_IO_OMFORMAT_HH
    00028 #define OPENMESH_IO_OMFORMAT_HH
    00029
    00030
    00031 //=== INCLUDES ================================================================
    00032
    00033 #include <OpenMesh/Core/System/config.hh>
    00034 #include <OpenMesh/Core/System/omstream.hh>
    00035 #include <OpenMesh/Core/IO/SR_store.hh>
    00036 #include <OpenMesh/Core/Utils/GenProg.hh>
    00037 #include <OpenMesh/Core/Utils/Endian.hh>
    00038 #include <OpenMesh/Core/Utils/vector_traits.hh>
    00039 // --------------------
    00040 #include <iostream>
    00041 #if defined(OM_CC_GCC) && (OM_GCC_VERSION < 30000)
    00042 #  include <OpenMesh/Tools/Utils/NumLimitsT.hh>
    00043 #  define OM_MISSING_HEADER_LIMITS 1
    00044 #else
    00045 #  include <limits>
    00046 #endif
    00047
    00048
    00049 //== NAMESPACES ==============================================================
    00050
    00051 #ifndef DOXY_IGNORE_THIS
    00052 namespace OpenMesh {
    00053 namespace IO   {
    00054 namespace OMFormat {
    00055
    00056
    00057 //=== IMPLEMENTATION ==========================================================
    00058
    00059
    00063
    00064 //-----------------------------------------------------------------------------
    00065
    00066   // <:Header>
    00067   // <:Comment>
    00068   // Chunk 0
    00069   //   <:ChunkHeader>
    00070   //   <:Comment>
    00071   //   data
    00072   // Chunk 1
    00073   //   <:ChunkHeader>
    00074   //   <:Comment>
    00075   //   data
    00076   // .
    00077   // .
    00078   // .
    00079   // Chunk N
    00080
    00081   typedef unsigned char      uchar;
    00082   typedef uint8_t            uint8;
    00083   typedef uint16_t           uint16;
    00084   typedef uint32_t           uint32;
    00085   typedef uint64_t           uint64;
    00086   typedef int8_t             int8;
    00087   typedef int16_t            int16;
    00088   typedef int32_t            int32;
    00089   typedef int64_t            int64;
    00090   typedef float32_t          float32;
    00091   typedef float64_t          float64;
    00092
    00093   struct Header
    00094   {
    00095     uchar  magic_[2]; // OM
    00096     uchar  mesh_;    // [T]riangles, [Q]uads, [P]olygonals
    00097     uint8  version_;
    00098     uint32 n_vertices_;
    00099     uint32 n_faces_;
    00100     uint32 n_edges_;
    00101
    00102     size_t store( std::ostream& _os, bool _swap ) const
    00103     {
    00104       _os.write( (char*)this, 4); // magic_, mesh_, version_
    00105       size_t bytes = 4;
    00106       bytes += binary<uint32_t>::store( _os, n_vertices_, _swap );
    00107       bytes += binary<uint32_t>::store( _os, n_faces_, _swap );
    00108       bytes += binary<uint32_t>::store( _os, n_edges_, _swap );
    00109       return bytes;
    00110     }
    00111
    00112     size_t restore( std::istream& _is, bool _swap )
    00113     {
    00114       if (_is.read( (char*)this, 4 ).eof())
    00115         return 0;
    00116
    00117       size_t bytes = 4;
    00118       bytes += binary<uint32_t>::restore( _is, n_vertices_, _swap );
    00119       bytes += binary<uint32_t>::restore( _is, n_faces_, _swap );
    00120       bytes += binary<uint32_t>::restore( _is, n_edges_, _swap );
    00121       return bytes;
    00122     }
    00123
    00124   };
    00125
    00126   struct Chunk
    00127   {
    00128     typedef size_t esize_t; // element size, used for custom properties
    00129
    00130     enum Type {
    00131       Type_Pos       = 0x00,
    00132       Type_Normal    = 0x01,
    00133       Type_Texcoord  = 0x02,
    00134       Type_Status    = 0x03,
    00135       Type_Color     = 0x04,
    00136       Type_Custom    = 0x06,
    00137       Type_Topology  = 0x07
    00138     };
    00139
    00140     enum Entity {
    00141       Entity_Vertex    = 0x00,
    00142       Entity_Mesh      = 0x01,
    00143       Entity_Face      = 0x02,
    00144       Entity_Edge      = 0x04,
    00145       Entity_Halfedge  = 0x06,
    00146     };
    00147
    00148     enum Dim {
    00149       Dim_1D = 0x00,
    00150       Dim_2D = 0x01,
    00151       Dim_3D = 0x02,
    00152       Dim_4D = 0x03,
    00153       Dim_5D = 0x04,
    00154       Dim_6D = 0x05,
    00155       Dim_7D = 0x06,
    00156       Dim_8D = 0x07
    00157     };
    00158
    00159     enum Integer_Size {
    00160       Integer_8   = 0x00, // 1 byte for (unsigned) char
    00161       Integer_16  = 0x01, // 2 bytes for short
    00162       Integer_32  = 0x02, // 4 bytes for long
    00163       Integer_64  = 0x03  // 8 bytes for long long
    00164     };
    00165
    00166     enum Float_Size {
    00167       Float_32  = 0x00, //  4 bytes for float
    00168       Float_64  = 0x01, //  8 bytes for double
    00169       Float_128 = 0x02  // 16 bytes for long double (an assumption!)
    00170     };
    00171
    00172     static const int SIZE_RESERVED = 1; //  1
    00173     static const int SIZE_NAME     = 1; //  2
    00174     static const int SIZE_ENTITY   = 3; //  5
    00175     static const int SIZE_TYPE     = 4; //  9
    00176
    00177     static const int SIZE_SIGNED   = 1; // 10
    00178     static const int SIZE_FLOAT    = 1; // 11
    00179     static const int SIZE_DIM      = 3; // 14
    00180     static const int SIZE_BITS     = 2; // 16
    00181
    00182     static const int OFF_RESERVED = 0;                          //  0
    00183     static const int OFF_NAME     = SIZE_RESERVED + OFF_RESERVED; //  2
    00184     static const int OFF_ENTITY   = SIZE_NAME     + OFF_NAME;   //  3
    00185     static const int OFF_TYPE     = SIZE_ENTITY   + OFF_ENTITY; //  5
    00186     static const int OFF_SIGNED   = SIZE_TYPE     + OFF_TYPE;   //  9
    00187     static const int OFF_FLOAT    = SIZE_SIGNED   + OFF_SIGNED; // 10
    00188     static const int OFF_DIM      = SIZE_FLOAT    + OFF_FLOAT;  // 11
    00189     static const int OFF_BITS     = SIZE_DIM      + OFF_DIM;    // 14
    00190
    00191     // !Attention! When changing the bit size, the operators
    00192     // << (uint16, Header) and << (Header, uint16) must be changed as well
    00193     //
    00194     // Entries signed_, float_, dim_, bits_ are not used when type_
    00195     // equals Type_Custom
    00196     //
    00197     struct Header // 16 bits long
    00198     {
    00199       unsigned reserved_: SIZE_RESERVED;
    00200       unsigned name_    : SIZE_NAME;   // 1 named property, 0 anonymous
    00201       unsigned entity_  : SIZE_ENTITY; // 0 vertex, 1 mesh, 2 edge,
    00202                                        // 4 halfedge, 6 face
    00203       unsigned type_    : SIZE_TYPE;   // 0 pos, 1 normal, 2 texcoord,
    00204                                        // 3 status, 4 color 6 custom 7 topology
    00205       unsigned signed_  : SIZE_SIGNED; // bool
    00206       unsigned float_   : SIZE_FLOAT;  // bool
    00207       unsigned dim_     : SIZE_DIM;    // 0 1D, 1 2D, 2 3D, .., 7 8D
    00208       unsigned bits_    : SIZE_BITS;   // {8, 16, 32, 64} | {32, 64, 128}
    00209                                        // (integer)         (float)
    00210       unsigned unused_  : 16; // fill up to 32 bits
    00211     }; // struct Header
    00212
    00213
    00214     class PropertyName : public std::string
    00215     {
    00216     public:
    00217
    00218       static const size_t size_max = 256;
    00219
    00220       PropertyName( ) { }
    00221
    00222       PropertyName( const std::string& _name ) { *this = _name; }
    00223
    00224       bool is_valid() const { return is_valid( size() ); }
    00225
    00226       static bool is_valid( size_t _s ) { return _s <= size_max; }
    00227
    00228       PropertyName& operator = ( const std::string& _rhs )
    00229       {
    00230         assert( is_valid( _rhs.size() ) );
    00231
    00232         if ( is_valid( _rhs.size() ) )
    00233           std::string::operator = ( _rhs );
    00234         else
    00235         {
    00236           omerr() << "Warning! Property name too long. Will be shortened!\n";
    00237           this->std::string::operator = ( _rhs.substr(0, size_max) );
    00238         }
    00239
    00240         return *this;
    00241       }
    00242
    00243     };
    00244
    00245   }; // Chunk
    00246
    00247   // ------------------------------------------------------------ Helper
    00248
    00249   // -------------------- get size information
    00250
    00252   inline size_t header_size(void) { return sizeof(Header); }
    00253
    00254
    00256   inline size_t chunk_header_size( void ) { return sizeof(uint16); }
    00257
    00258
    00260   inline size_t scalar_size( const Chunk::Header& _hdr )
    00261   {
    00262     return _hdr.float_ ? (0x01 << _hdr.bits_) : (0x04 << _hdr.bits_);
    00263   }
    00264
    00265
    00267   inline size_t dimensions(const Chunk::Header& _chdr) { return _chdr.dim_+1; }
    00268
    00269
    00271   inline size_t vector_size( const Chunk::Header& _chdr )
    00272   {
    00273     return dimensions(_chdr)*scalar_size(_chdr);
    00274   }
    00275
    00276
    00278   inline size_t chunk_data_size( Header& _hdr,  Chunk::Header& _chunk_hdr )
    00279   {
    00280     size_t C     = 0;
    00281
    00282     switch( _chunk_hdr.entity_ )
    00283     {
    00284       case Chunk::Entity_Vertex:   C  = _hdr.n_vertices_; break;
    00285       case Chunk::Entity_Face:     C  = _hdr.n_faces_;    break;
    00286       case Chunk::Entity_Halfedge: C  = _hdr.n_edges_;    // no break!
    00287       case Chunk::Entity_Edge:     C += _hdr.n_edges_;    break;
    00288       case Chunk::Entity_Mesh:     C  = 1;                break;
    00289       default:
    00290         std::cerr << "Invalid value in _chunk_hdr.entity_\n";
    00291         assert( false );
    00292     }
    00293
    00294     return C * vector_size( _chunk_hdr );
    00295   }
    00296
    00297   inline size_t chunk_size( Header& _hdr, Chunk::Header& _chunk_hdr )
    00298   {
    00299     return chunk_header_size() + chunk_data_size( _hdr, _chunk_hdr );
    00300   }
    00301
    00302   // -------------------- convert from Chunk::Header to storage type
    00303
    00304   uint16& operator << (uint16& val, const Chunk::Header& hdr);
    00305   Chunk::Header& operator << (Chunk::Header& hdr, const uint16 val);
    00306
    00307
    00308   // -------------------- type information
    00309
    00310   template <typename T> bool is_float(const T&)
    00311   {
    00312 #if defined(OM_MISSING_HEADER_LIMITS)
    00313     return !Utils::NumLimitsT<T>::is_integer();
    00314 #else
    00315     return !std::numeric_limits<T>::is_integer;
    00316 #endif
    00317   }
    00318
    00319   template <typename T> bool is_integer(const T)
    00320   {
    00321 #if defined(OM_MISSING_HEADER_LIMITS)
    00322     return Utils::NumLimitsT<T>::is_integer();
    00323 #else
    00324     return std::numeric_limits<T>::is_integer;
    00325 #endif
    00326   }
    00327
    00328   template <typename T> bool is_signed(const T&)
    00329   {
    00330 #if defined(OM_MISSING_HEADER_LIMITS)
    00331     return Utils::NumLimitsT<T>::is_signed();
    00332 #else
    00333     return std::numeric_limits<T>::is_signed;
    00334 #endif
    00335   }
    00336
    00337   // -------------------- conversions (format type <- type/value)
    00338
    00339   template <typename VecType>
    00340   inline
    00341   Chunk::Dim dim( VecType )
    00342   {
    00343     assert( vector_traits< VecType >::size() < 9 );
    00344     return static_cast<Chunk::Dim>(vector_traits< VecType >::size() - 1);
    00345   }
    00346
    00347   template <>
    00348   inline
    00349   Chunk::Dim dim( const Chunk::Header& _hdr )
    00350   {
    00351     return static_cast<Chunk::Dim>( _hdr.dim_ );
    00352   }
    00353
    00354   // calc minimum (power-of-2) number of bits needed
    00355   Chunk::Integer_Size needed_bits( size_t s );
    00356
    00357
    00358   // Return the storage type (Chunk::Header::bits_)
    00359   template <typename T>
    00360   inline
    00361   unsigned int bits(const T& val)
    00362   {
    00363     return is_integer(val)
    00364       ? (static_cast<unsigned int>(integer_size(val)))
    00365       : (static_cast<unsigned int>(float_size(val)));
    00366   }
    00367
    00368   // Convert size of type to Integer_Size
    00369   template <typename T> Chunk::Integer_Size integer_size(const T& d)
    00370   {
    00371     assert( is_integer(d) );
    00372
    00373     switch( sizeof(T) )
    00374     {
    00375       case  1: return OMFormat::Chunk::Integer_8;
    00376       case  2: return OMFormat::Chunk::Integer_16;
    00377       case  4: return OMFormat::Chunk::Integer_32;
    00378       case  8: return OMFormat::Chunk::Integer_64;
    00379     }
    00380     return Chunk::Integer_Size(0);
    00381   }
    00382
    00383
    00384   // Convert size of type to FLoat_Size
    00385   template <typename T> Chunk::Float_Size float_size(const T& d)
    00386   {
    00387     assert( is_float(d) );
    00388
    00389     switch( sizeof(T) )
    00390     {
    00391       case  4: return OMFormat::Chunk::Float_32;
    00392       case  8: return OMFormat::Chunk::Float_64;
    00393       case 16: return OMFormat::Chunk::Float_128;
    00394     }
    00395     return Chunk::Float_Size(0);
    00396   }
    00397
    00398   // -------------------- create/read version
    00399
    00400   inline uint8 mk_version(const uint16 major, const uint16 minor)
    00401   { return (major & 0x07) << 5 | (minor & 0x1f); }
    00402
    00403
    00404   inline uint16 major_version(const uint8 version)
    00405   { return (version >> 5) & 0x07; }
    00406
    00407
    00408   inline uint16 minor_version(const uint8 version)
    00409   { return (version & 0x001f); }
    00410
    00411
    00412   // ---------------------------------------- convenience functions
    00413
    00414   const char *as_string(Chunk::Type t);
    00415   const char *as_string(Chunk::Entity e);
    00416   const char *as_string(Chunk::Dim d);
    00417   const char *as_string(Chunk::Integer_Size d);
    00418   const char *as_string(Chunk::Float_Size d);
    00419
    00420   std::ostream& operator << ( std::ostream& _os, const Header& _h );
    00421   std::ostream& operator << ( std::ostream& _os, const Chunk::Header& _c );
    00422
    00424 } // namespace OMFormat
    00425
    00426   // -------------------- (re-)store header
    00427
    00428   template <> inline
    00429   size_t store( std::ostream& _os, const OMFormat::Header& _hdr, bool _swap)
    00430   { return _hdr.store( _os, _swap ); }
    00431
    00432   template <> inline
    00433   size_t restore( std::istream& _is, OMFormat::Header& _hdr, bool _swap )
    00434   { return _hdr.restore( _is, _swap ); }
    00435
    00436
    00437   // -------------------- (re-)store chunk header
    00438
    00439   template <> inline
    00440   size_t
    00441   store( std::ostream& _os, const OMFormat::Chunk::Header& _hdr, bool _swap)
    00442   {
    00443     OMFormat::uint16 val; val << _hdr;
    00444     return binary<uint16_t>::store( _os, val, _swap );
    00445   }
    00446
    00447   template <> inline
    00448   size_t
    00449   restore( std::istream& _is, OMFormat::Chunk::Header& _hdr, bool _swap )
    00450   {
    00451     OMFormat::uint16 val;
    00452     size_t bytes = binary<uint16_t>::restore( _is, val, _swap );
    00453
    00454     _hdr << val;
    00455
    00456     return bytes;
    00457   }
    00458
    00459   // -------------------- (re-)store integer with wanted number of bits (bytes)
    00460
    00461   typedef GenProg::True  t_signed;
    00462   typedef GenProg::False t_unsigned;
    00463
    00464
    00465   // helper to store a an integer
    00466   template< typename T >
    00467   size_t
    00468   store( std::ostream& _os,
    00469          const T& _val,
    00470          OMFormat::Chunk::Integer_Size _b,
    00471          bool _swap,
    00472          t_signed);
    00473
    00474   // helper to store a an unsigned integer
    00475   template< typename T >
    00476   size_t
    00477   store( std::ostream& _os,
    00478          const T& _val,
    00479          OMFormat::Chunk::Integer_Size _b,
    00480          bool _swap,
    00481          t_unsigned);
    00482
    00484   template< typename T >
    00485   inline
    00486   size_t
    00487   store( std::ostream& _os,
    00488          const T& _val,
    00489          OMFormat::Chunk::Integer_Size _b,
    00490          bool _swap)
    00491   {
    00492     assert( OMFormat::is_integer( _val ) );
    00493
    00494     if ( OMFormat::is_signed( _val ) )
    00495       return store( _os, _val, _b, _swap, t_signed()   );
    00496     return   store( _os, _val, _b, _swap, t_unsigned() );
    00497   }
    00498
    00499
    00500
    00501   // helper to store a an integer
    00502   template< typename T > inline
    00503   size_t restore( std::istream& _is,
    00504                   T& _val,
    00505                   OMFormat::Chunk::Integer_Size _b,
    00506                   bool _swap,
    00507                   t_signed);
    00508
    00509   // helper to store a an unsigned integer
    00510   template< typename T > inline
    00511   size_t restore( std::istream& _is,
    00512                   T& _val,
    00513                   OMFormat::Chunk::Integer_Size _b,
    00514                   bool _swap,
    00515                   t_unsigned);
    00516
    00518   template< typename T >
    00519   inline
    00520   size_t
    00521   restore( std::istream& _is,
    00522            T& _val,
    00523            OMFormat::Chunk::Integer_Size _b,
    00524            bool _swap)
    00525   {
    00526     assert( OMFormat::is_integer( _val ) );
    00527
    00528     if ( OMFormat::is_signed( _val ) )
    00529       return restore( _is, _val, _b, _swap, t_signed() );
    00530     return restore( _is, _val, _b, _swap, t_unsigned() );
    00531   }
    00532
    00533
    00534   //
    00535   // ---------------------------------------- storing vectors
    00536
    00537   template <typename VecT> inline
    00538   size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<1>,
    00539                 bool _swap )
    00540   {
    00541     return store( _os, _vec[0], _swap );
    00542   }
    00543
    00544   template <typename VecT> inline
    00545   size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<2>,
    00546                 bool _swap )
    00547   {
    00548     size_t bytes =  store( _os, _vec[0], _swap );
    00549     bytes += store( _os, _vec[1], _swap );
    00550     return bytes;
    00551   }
    00552
    00553   template <typename VecT> inline
    00554   size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<3>,
    00555                 bool _swap )
    00556   {
    00557     size_t bytes =  store( _os, _vec[0], _swap );
    00558     bytes += store( _os, _vec[1], _swap );
    00559     bytes += store( _os, _vec[2], _swap );
    00560     return bytes;
    00561   }
    00562
    00563   template <typename VecT> inline
    00564   size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<4>,
    00565                 bool _swap )
    00566   {
    00567     size_t bytes =  store( _os, _vec[0], _swap );
    00568     bytes += store( _os, _vec[1], _swap );
    00569     bytes += store( _os, _vec[2], _swap );
    00570     bytes += store( _os, _vec[3], _swap );
    00571     return bytes;
    00572   }
    00573
    00575   template <typename VecT> inline
    00576   size_t vector_store( std::ostream& _os, const VecT& _vec, bool _swap )
    00577   {
    00578     return store( _os, _vec,
    00579                   GenProg::Int2Type< vector_traits<VecT>::size_ >(),
    00580                   _swap );
    00581   }
    00582
    00583   // ---------------------------------------- restoring vectors
    00584
    00585   template <typename VecT>
    00586   inline
    00587   size_t
    00588   restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<1>,
    00589            bool _swap )
    00590   {
    00591     return restore( _is, _vec[0], _swap );
    00592   }
    00593
    00594   template <typename VecT>
    00595   inline
    00596   size_t
    00597   restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<2>,
    00598          bool _swap )
    00599   {
    00600     size_t bytes =  restore( _is, _vec[0], _swap );
    00601     bytes += restore( _is, _vec[1], _swap );
    00602     return bytes;
    00603   }
    00604
    00605   template <typename VecT>
    00606   inline
    00607   size_t
    00608   restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<3>,
    00609          bool _swap )
    00610   {
    00611     typedef typename vector_traits<VecT>::value_type scalar_type;
    00612     size_t bytes;
    00613
    00614     bytes  = binary<scalar_type>::restore( _is, _vec[0], _swap );
    00615     bytes += binary<scalar_type>::restore( _is, _vec[1], _swap );
    00616     bytes += binary<scalar_type>::restore( _is, _vec[2], _swap );
    00617     return bytes;
    00618   }
    00619
    00620   template <typename VecT>
    00621   inline
    00622   size_t
    00623   restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<4>,
    00624            bool _swap )
    00625   {
    00626     typedef typename vector_traits<VecT>::value_type scalar_type;
    00627     size_t bytes;
    00628
    00629     bytes  = binary<scalar_type>::restore( _is, _vec[0], _swap );
    00630     bytes += binary<scalar_type>::restore( _is, _vec[1], _swap );
    00631     bytes += binary<scalar_type>::restore( _is, _vec[2], _swap );
    00632     bytes += binary<scalar_type>::restore( _is, _vec[3], _swap );
    00633     return bytes;
    00634   }
    00635
    00637   template <typename VecT>
    00638   inline
    00639   size_t
    00640   vector_restore( std::istream& _is, VecT& _vec, bool _swap )
    00641   {
    00642     return restore( _is, _vec,
    00643                     GenProg::Int2Type< vector_traits<VecT>::size_ >(),
    00644                     _swap );
    00645   }
    00646
    00647   // ---------------------------------------- storing property names
    00648
    00649   template <>
    00650   inline
    00651   size_t store( std::ostream& _os, const OMFormat::Chunk::PropertyName& _pn,
    00652                 bool _swap )
    00653   {
    00654     store( _os, _pn.size(), OMFormat::Chunk::Integer_8, _swap ); // 1 byte
    00655     if ( _pn.size() )
    00656       _os.write( _pn.c_str(), _pn.size() ); // size bytes
    00657     return _pn.size() + 1;
    00658   }
    00659
    00660   template <>
    00661   inline
    00662   size_t restore( std::istream& _is, OMFormat::Chunk::PropertyName& _pn,
    00663                   bool _swap )
    00664   {
    00665     size_t size;
    00666
    00667     restore( _is, size, OMFormat::Chunk::Integer_8, _swap); // 1 byte
    00668
    00669     assert( OMFormat::Chunk::PropertyName::is_valid( size ) );
    00670
    00671     if ( size > 0 )
    00672     {
    00673       char buf[256];
    00674       _is.read( buf, size ); // size bytes
    00675       buf[size] = '\0';
    00676       _pn.resize(size);
    00677       _pn = buf;
    00678     }
    00679     return size+1;
    00680   }
    00681
    00682 //=============================================================================
    00683 } // namespace IO
    00684 } // namespace OpenMesh
    00685 #endif
    00686 //=============================================================================
    00687 #if defined(OM_MISSING_HEADER_LIMITS)
    00688 #  undef OM_MISSING_HEADER_LIMITS
    00689 #endif
    00690 //=============================================================================
    00691 #if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_IO_OMFORMAT_CC)
    00692 #  define OPENMESH_IO_OMFORMAT_TEMPLATES
    00693 #  include "OMFormat.cc"
    00694 #endif
    00695 //=============================================================================
    00696 #endif
    00697 //=============================================================================