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