- Timestamp:
- 03/21/12 18:36:20 (14 months ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
OpenSceneGraph/trunk/src/osgPlugins/osga/OSGA_Archive.cpp
r12642 r13041 11 11 /* 12 12 Functions to convert between 13 std::streampos ( typedef'ed as iostream::pos_type 13 std::streampos ( typedef'ed as iostream::pos_type 14 14 used as seekp,seekg argument and tellp,tellg return value ) 15 and 15 and 16 16 OSGA_Archive::pos_type (64 bit file position index) 17 17 … … 22 22 and is returned as result from iostream tellp and tellg methods. 23 23 24 std::streampos can be implicitly cast from/to std::streamoff as 24 std::streampos can be implicitly cast from/to std::streamoff as 25 25 std::streampos class defines appropriate constructor and cast operator. 26 26 27 Since std::streamoff is usually defined as simple int, 27 Since std::streamoff is usually defined as simple int, 28 28 it is possible to call seekp( ), seekg( ) with int argument and 29 29 assign tellp(), tellg() result to int type. 30 30 31 But this implicit methods fail when std::streamoff is 32 bit and 31 But this implicit methods fail when std::streamoff is 32 bit and 32 32 std::streampos actually points past 32 bit addressable range (2 GiB). 33 33 34 34 Even if std::streamoff is 32 bit and incapable of representing 64 bit file 35 35 positions, original std::streampos may be prefectly able to handle them. 36 37 But, when such situation occurs more elaborate conversion methods from/to 38 std::streampos are needed. Functions below employ such methods. 39 40 I made this fix for use with 32 bit Windows OSG. Acutally this 41 solution is not dependent on OS but standard C++ library. 42 Microsoft SDKs always use some version of Dinkumware libs. 43 44 Practically this tweak is made for Dinkumware C++ libs. I hope it can 36 37 But, when such situation occurs more elaborate conversion methods from/to 38 std::streampos are needed. Functions below employ such methods. 39 40 I made this fix for use with 32 bit Windows OSG. Acutally this 41 solution is not dependent on OS but standard C++ library. 42 Microsoft SDKs always use some version of Dinkumware libs. 43 44 Practically this tweak is made for Dinkumware C++ libs. I hope it can 45 45 be easily extended to other 32bit systems supporting 64bit files, provided 46 46 their std::streampos implementations are similar. 47 47 48 48 I based my solution on a small portion of boost iostreams code. 49 For additional reference look at: 49 For additional reference look at: 50 50 http://boost.org/boost/iostreams/positioning.hpp 51 51 */ 52 52 53 /* 54 Recognize Dinkumware std C++ lib implementation. Its used by Microsoft, 53 /* 54 Recognize Dinkumware std C++ lib implementation. Its used by Microsoft, 55 55 but method is more generic - should work in all Dinkumware environments. 56 56 57 Complex condition below was taken from 57 Complex condition below was taken from 58 58 http://boost.org/boost/iostreams/positioning.hpp 59 59 … … 65 65 66 66 inline std::streampos STREAM_POS( const OSGA_Archive::pos_type pos ) 67 { 67 { 68 68 return std::streampos( std::mbstate_t(), pos ); 69 69 } 70 70 71 71 inline OSGA_Archive::pos_type ARCHIVE_POS( const std::streampos & pos ) 72 { 72 { 73 73 #if defined(_CPPLIB_VER)//newer Dinkumware(eg: one included with VC++ 2003,2005) 74 74 fpos_t position = pos.seekpos(); … … 80 80 return OSGA_Archive::pos_type( position + offset ); 81 81 } 82 #else // non Dinkumware std C++ lib implementations 82 #else // non Dinkumware std C++ lib implementations 83 83 // do the old school streampos <-> streamoff casts 84 84 inline std::streampos STREAM_POS( const OSGA_Archive::pos_type pos ) 85 { 85 { 86 86 return std::streampos( pos ); 87 87 } 88 88 89 89 inline OSGA_Archive::pos_type ARCHIVE_POS( const std::streampos & pos ) 90 { 90 { 91 91 return OSGA_Archive::pos_type( pos ); 92 92 } 93 #endif // Dinkumware std C++ lib 93 #endif // Dinkumware std C++ lib 94 94 //////////////////////////////////////////////////////////////////////////////// 95 95 float OSGA_Archive::s_currentSupportedVersion = 0.0; … … 118 118 { 119 119 _blockSize = blockSize; 120 120 121 121 // initialize the array 122 122 char* end = _data + _blockSize; … … 138 138 in.read(reinterpret_cast<char*>(&indexBlock->_filePositionNextIndexBlock), sizeof(indexBlock->_filePositionNextIndexBlock)); 139 139 in.read(reinterpret_cast<char*>(&indexBlock->_offsetOfNextAvailableSpace), sizeof(indexBlock-> _offsetOfNextAvailableSpace)); 140 140 141 141 if (doEndianSwap) 142 142 { … … 161 161 while (ptr<end_ptr) 162 162 { 163 osg::swapBytes(ptr,sizeof(pos_type)); 163 osg::swapBytes(ptr,sizeof(pos_type)); 164 164 ptr += sizeof(pos_type); 165 165 166 osg::swapBytes(ptr,sizeof(size_type)); 166 osg::swapBytes(ptr,sizeof(size_type)); 167 167 ptr += sizeof(size_type); 168 168 169 osg::swapBytes(ptr,sizeof(unsigned int)); 169 osg::swapBytes(ptr,sizeof(unsigned int)); 170 170 unsigned int filename_size; // = *(reinterpret_cast<unsigned int*>(ptr)); 171 171 _read(ptr, filename_size); … … 185 185 186 186 OSG_INFO<<"Read index block"<<std::endl; 187 187 188 188 return indexBlock.release(); 189 189 190 190 } 191 191 … … 214 214 { 215 215 if (!_data || _offsetOfNextAvailableSpace==0) return false; 216 216 217 217 bool valuesAdded = false; 218 218 219 219 char* ptr = _data; 220 220 char* end_ptr = _data + _offsetOfNextAvailableSpace; 221 221 while (ptr<end_ptr) 222 222 { 223 pos_type position; // = *(reinterpret_cast<pos_type*>(ptr)); 223 pos_type position; // = *(reinterpret_cast<pos_type*>(ptr)); 224 224 _read(ptr, position); 225 225 ptr += sizeof(pos_type); 226 227 size_type size; // = *(reinterpret_cast<size_type*>(ptr)); 226 227 size_type size; // = *(reinterpret_cast<size_type*>(ptr)); 228 228 _read(ptr, size); 229 229 ptr += sizeof(size_type); … … 232 232 _read(ptr, filename_size); 233 233 ptr += sizeof(unsigned int); 234 234 235 235 std::string filename(ptr, ptr+filename_size); 236 237 // record this entry into the FileNamePositionMap. 236 237 // record this entry into the FileNamePositionMap. 238 238 // Requests for files will be in unix style even on Win32 so need unix style keys in map. 239 239 indexMap[osgDB::convertFileNameToUnixStyle(filename)] = PositionSizePair(position,size); 240 240 241 241 ptr += filename_size; 242 242 243 243 valuesAdded = true; 244 244 } … … 267 267 out.write(reinterpret_cast<char*>(_data),_blockSize); 268 268 269 if( _filePosition < currentPos ) // move file ptr to the end of file 269 if( _filePosition < currentPos ) // move file ptr to the end of file 270 270 out.seekp( STREAM_POS( currentPos ) ); 271 271 272 272 OSG_INFO<<"OSGA_Archive::IndexBlock::write() end"<<std::endl; 273 273 } … … 279 279 { 280 280 char* ptr = _data+_offsetOfNextAvailableSpace; 281 282 //*(reinterpret_cast<pos_type*>(ptr)) = position; 281 282 //*(reinterpret_cast<pos_type*>(ptr)) = position; 283 283 _write(ptr, position); 284 284 ptr += sizeof(pos_type); 285 286 //*(reinterpret_cast<size_type*>(ptr)) = size; 285 286 //*(reinterpret_cast<size_type*>(ptr)) = size; 287 287 _write(ptr, size); 288 288 ptr += sizeof(size_type); 289 289 290 290 //*(reinterpret_cast<unsigned int*>(ptr)) = filename.size(); 291 291 _write(ptr, static_cast<unsigned int>(filename.size())); 292 292 ptr += sizeof(unsigned int); 293 293 294 294 for(unsigned int i=0;i<filename.size();++i, ++ptr) 295 295 { 296 296 *ptr = filename[i]; 297 297 } 298 298 299 299 _offsetOfNextAvailableSpace = ptr-_data; 300 300 301 301 _requiresWrite = true; 302 302 303 303 OSG_INFO<<"OSGA_Archive::IndexBlock::addFileReference("<<(unsigned int)position<<", "<<filename<<")"<<std::endl; 304 304 305 305 return true; 306 306 } … … 346 346 pos_type file_size( 0 ); 347 347 _input.seekg( 0, std::ios_base::end ); 348 file_size = ARCHIVE_POS( _input.tellg() ); 348 file_size = ARCHIVE_POS( _input.tellg() ); 349 349 if( _input.is_open() && file_size <= 0 ) 350 { // compute end of file postition manually ... 350 { // compute end of file postition manually ... 351 351 // seekp( 0, ios::end ), tellp( ) fails in 32 bit windows with files > 4 GiB 352 size_t BlockHeaderSize = 353 sizeof( unsigned int /*_blockSize*/ ) + 352 size_t BlockHeaderSize = 353 sizeof( unsigned int /*_blockSize*/ ) + 354 354 sizeof( pos_type /*_filePositionNextIndexBlock*/ ) + 355 355 sizeof( unsigned int /*_offsetOfNextAvailableSpace*/ ); 356 356 357 357 for(IndexBlockList::iterator itr=_indexBlockList.begin(); 358 358 itr!=_indexBlockList.end(); … … 378 378 OSG_INFO<<"File position after open = "<<ARCHIVE_POS( _output.tellp() )<<" is_open "<<_output.is_open()<<std::endl; 379 379 380 // place write position at end of file. 380 // place write position at end of file. 381 381 _output.seekp( STREAM_POS( file_size ) ); 382 382 … … 408 408 return true; 409 409 } 410 410 411 411 } 412 412 } … … 431 431 432 432 bool validArchive = (identifier[0]=='o' && identifier[1]=='s' && identifier[2]=='g' && identifier[3]=='a'); 433 if (validArchive) 433 if (validArchive) 434 434 { 435 435 … … 458 458 459 459 // now need to build the filename map. 460 _indexMap.clear(); 460 _indexMap.clear(); 461 461 462 462 if (!_indexBlockList.empty()) … … 491 491 492 492 _input.close(); 493 493 494 494 if (_status==WRITE) 495 495 { … … 557 557 return false; 558 558 } 559 559 560 560 if (!_output) 561 561 { … … 563 563 return false; 564 564 } 565 566 565 566 567 567 // if the masterFileName isn't set yet use this fileName 568 568 if (_masterFileName.empty()) _masterFileName = fileName; … … 583 583 } 584 584 585 // if not one available create a new block. 585 // if not one available create a new block. 586 586 if (!indexBlock) 587 587 { 588 588 if (previousBlock.valid()) previousBlock->setPositionNextIndexBlock( ARCHIVE_POS( _output.tellp() ) ); 589 589 590 590 indexBlock = new IndexBlock(blockSize); 591 591 indexBlock->write(_output); 592 592 _indexBlockList.push_back(indexBlock.get()); 593 593 } 594 594 595 595 if (indexBlock.valid()) 596 596 { … … 605 605 { 606 606 public: 607 607 608 608 proxy_streambuf(std::streambuf* streambuf, unsigned int numChars): 609 609 _streambuf(streambuf), … … 611 611 setg(&oneChar, (&oneChar)+1, (&oneChar)+1); 612 612 } 613 613 614 614 /// Destructor deallocates no buffer space. 615 615 virtual ~proxy_streambuf() {} … … 619 619 protected: 620 620 621 unsigned int _numChars; 621 unsigned int _numChars; 622 622 char_type oneChar; 623 623 624 624 virtual int_type underflow() 625 625 { 626 626 if ( gptr() == &oneChar ) return traits_type::to_int_type(oneChar); 627 628 if ( _numChars==0 ) return traits_type::eof(); 627 628 if ( _numChars==0 ) return traits_type::eof(); 629 629 --_numChars; 630 630 631 631 int_type next_value = _streambuf->sbumpc(); 632 632 633 633 if ( !traits_type::eq_int_type(next_value,traits_type::eof()) ) 634 634 { … … 636 636 oneChar = traits_type::to_char_type(next_value); 637 637 } 638 638 639 639 return next_value; 640 640 } … … 644 644 { 645 645 ReadObjectFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {} 646 virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input) const { return rw.readObject(input, _options); } 646 virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input) const { return rw.readObject(input, _options); } 647 647 }; 648 648 … … 650 650 { 651 651 ReadImageFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {} 652 virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input)const { return rw.readImage(input, _options); } 652 virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input)const { return rw.readImage(input, _options); } 653 653 }; 654 654 … … 656 656 { 657 657 ReadHeightFieldFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {} 658 virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input) const { return rw.readHeightField(input, _options); } 658 virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input) const { return rw.readHeightField(input, _options); } 659 659 }; 660 660 … … 675 675 SERIALIZER(); 676 676 677 if (_status!=READ) 677 if (_status!=READ) 678 678 { 679 679 OSG_INFO<<"OSGA_Archive::readObject(obj, "<<readFunctor._filename<<") failed, archive opened as write only."<<std::endl; 680 680 return ReadResult(ReadResult::FILE_NOT_HANDLED); 681 681 } 682 682 683 683 FileNamePositionMap::const_iterator itr = _indexMap.find(readFunctor._filename); 684 684 if (itr==_indexMap.end()) … … 687 687 return ReadResult(ReadResult::FILE_NOT_FOUND); 688 688 } 689 689 690 690 ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(getLowerCaseFileExtension(readFunctor._filename)); 691 691 if (!rw) … … 694 694 return ReadResult(ReadResult::FILE_NOT_HANDLED); 695 695 } 696 696 697 697 OSG_INFO<<"OSGA_Archive::readObject(obj, "<<readFunctor._filename<<")"<<std::endl; 698 698 699 699 _input.seekg( STREAM_POS( itr->second.first ) ); 700 700 … … 707 707 708 708 ins.rdbuf(mystreambuf._streambuf); 709 709 710 710 return result; 711 711 } … … 743 743 _object(object) {} 744 744 const osg::Object& _object; 745 746 virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeObject(_object, output, _options); } 745 746 virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeObject(_object, output, _options); } 747 747 }; 748 748 … … 754 754 const osg::Image& _object; 755 755 756 virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeImage(_object, output, _options); } 756 virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeImage(_object, output, _options); } 757 757 }; 758 758 … … 764 764 const osg::HeightField& _object; 765 765 766 virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeHeightField(_object, output, _options); } 766 virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeHeightField(_object, output, _options); } 767 767 }; 768 768 … … 791 791 SERIALIZER(); 792 792 793 if (_status!=WRITE) 793 if (_status!=WRITE) 794 794 { 795 795 OSG_INFO<<"OSGA_Archive::write(obj, "<<writeFunctor._filename<<") failed, archive opened as read only."<<std::endl; … … 803 803 return WriteResult(WriteResult::FILE_NOT_HANDLED); 804 804 } 805 805 806 806 OSG_INFO<<"OSGA_Archive::write(obj, "<<writeFunctor._filename<<")"<<std::endl; 807 807 808 808 pos_type position = ARCHIVE_POS( _output.tellp() ); 809 809 810 810 WriteResult result = writeFunctor.doWrite(*rw,_output); 811 811 812 812 pos_type final_position = ARCHIVE_POS( _output.tellp() ); 813 813 size_type size = size_type( final_position-position ); 814 814 815 815 if (result.success()) addFileReference(position, size, writeFunctor._filename); 816 816 817 817 return result; 818 818 }
