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