9
9
using namespace osgDB;
12
Functions to convert between
13
std::streampos ( typedef'ed as iostream::pos_type
14
used as seekp,seekg argument and tellp,tellg return value )
16
OSGA_Archive::pos_type (64 bit file position index)
19
To allow using OSGA files larger than 4GiB in Windows.
21
std::streampos is used as argument to iostreams seekp and seekg methods
22
and is returned as result from iostream tellp and tellg methods.
24
std::streampos can be implicitly cast from/to std::streamoff as
25
std::streampos class defines appropriate constructor and cast operator.
27
Since std::streamoff is usually defined as simple int,
28
it is possible to call seekp( ), seekg( ) with int argument and
29
assign tellp(), tellg() result to int type.
31
But this implicit methods fail when std::streamoff is 32 bit and
32
std::streampos actually points past 32 bit addressable range (2 GiB).
34
Even if std::streamoff is 32 bit and incapable of representing 64 bit file
35
positions, original std::streampos may be prefectly able to handle them.
37
But, when such situation occurs more elaborate conversion methods from/to
38
std::streampos are needed. Functions below employ such methods.
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.
44
Practically this tweak is made for Dinkumware C++ libs. I hope it can
45
be easily extended to other 32bit systems supporting 64bit files, provided
46
their std::streampos implementations are similar.
48
I based my solution on a small portion of boost iostreams code.
49
For additional reference look at:
50
http://boost.org/boost/iostreams/positioning.hpp
54
Recognize Dinkumware std C++ lib implementation. Its used by Microsoft,
55
but method is more generic - should work in all Dinkumware environments.
57
Complex condition below was taken from
58
http://boost.org/boost/iostreams/positioning.hpp
60
Great thanks to J.Tukanis and G. Sylvester-Bradley for figuring it out.
62
#if ((defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)) && \
63
!defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) \
66
inline std::streampos STREAM_POS( const OSGA_Archive::pos_type pos )
68
return std::streampos( std::mbstate_t(), pos );
71
inline OSGA_Archive::pos_type ARCHIVE_POS( const std::streampos & pos )
73
#if defined(_CPPLIB_VER)//newer Dinkumware(eg: one included with VC++ 2003,2005)
74
fpos_t position = pos.seekpos();
75
#else // older Dinkumware (eg: one included in Win Server 2003 Platform SDK )
76
fpos_t position = pos.get_fpos_t();
78
std::streamoff offset = pos.operator std::streamoff( ) - _FPOSOFF( position );
80
return OSGA_Archive::pos_type( position + offset );
82
#else // non Dinkumware std C++ lib implementations
83
// do the old school streampos <-> streamoff casts
84
inline std::streampos STREAM_POS( const OSGA_Archive::pos_type pos )
86
return std::streampos( pos );
89
inline OSGA_Archive::pos_type ARCHIVE_POS( const std::streampos & pos )
91
return OSGA_Archive::pos_type( pos );
93
#endif // Dinkumware std C++ lib
94
////////////////////////////////////////////////////////////////////////////////
11
95
float OSGA_Archive::s_currentSupportedVersion = 0.0;
12
96
const unsigned int ENDIAN_TEST_NUMBER = 0x00000001;
163
248
void OSGA_Archive::IndexBlock::write(std::ostream& out)
250
pos_type currentPos = ARCHIVE_POS( out.tellp() );
165
252
if (_filePosition==pos_type(0))
167
254
osg::notify(osg::INFO)<<"OSGA_Archive::IndexBlock::write() setting _filePosition"<<std::endl;
168
_filePosition = out.tellp();
255
_filePosition = currentPos;
172
out.seekp(_filePosition);
259
out.seekp( STREAM_POS( _filePosition ) );
174
osg::notify(osg::INFO)<<"OSGA_Archive::IndexBlock::write() to _filePosition"<<out.tellp()<<std::endl;
261
osg::notify(osg::INFO)<<"OSGA_Archive::IndexBlock::write() to _filePosition"<< ARCHIVE_POS( out.tellp() )<<std::endl;
176
263
out.write(reinterpret_cast<char*>(&_blockSize), sizeof(_blockSize));
177
264
out.write(reinterpret_cast<char*>(&_filePositionNextIndexBlock), sizeof(_filePositionNextIndexBlock));
178
265
out.write(reinterpret_cast<char*>(&_offsetOfNextAvailableSpace), sizeof(_offsetOfNextAvailableSpace));
180
267
out.write(reinterpret_cast<char*>(_data),_blockSize);
269
if( _filePosition < currentPos ) // move file ptr to the end of file
270
out.seekp( STREAM_POS( currentPos ) );
182
272
osg::notify(osg::INFO)<<"OSGA_Archive::IndexBlock::write() end"<<std::endl;
252
342
if (status==WRITE && open(filename,READ))
344
pos_type file_size( 0 );
345
_input.seekg( 0, std::ios_base::end );
346
file_size = ARCHIVE_POS( _input.tellg() );
347
if( _input.is_open() && file_size <= 0 )
348
{ // compute end of file postition manually ...
349
// seekp( 0, ios::end ), tellp( ) fails in 32 bit windows with files > 4 GiB
350
size_t BlockHeaderSize =
351
sizeof( unsigned int /*_blockSize*/ ) +
352
sizeof( pos_type /*_filePositionNextIndexBlock*/ ) +
353
sizeof( unsigned int /*_offsetOfNextAvailableSpace*/ );
355
for(IndexBlockList::iterator itr=_indexBlockList.begin();
356
itr!=_indexBlockList.end();
359
pos_type end = (*itr)->getPosition() + BlockHeaderSize + (*itr)->getBlockSize();
360
if( file_size < end ) file_size = end;
363
for(FileNamePositionMap::iterator mitr=_indexMap.begin();
364
mitr!=_indexMap.end();
367
pos_type end = mitr->second.first + mitr->second.second;
368
if( file_size < end ) file_size = end;
257
374
_output.open(filename.c_str(), std::ios_base::binary | std::ios_base::in | std::ios_base::out);
259
osg::notify(osg::INFO)<<"File position after open = "<<(int)_output.tellp()<<" is_open "<<_output.is_open()<<std::endl;
261
// place write position at end of file.
262
_output.seekp(0, std::ios::end);
264
osg::notify(osg::INFO)<<"File position after seekp = "<<(int)_output.tellp()<<std::endl;
376
osg::notify(osg::INFO)<<"File position after open = "<<ARCHIVE_POS( _output.tellp() )<<" is_open "<<_output.is_open()<<std::endl;
378
// place write position at end of file.
379
_output.seekp( STREAM_POS( file_size ) );
381
osg::notify(osg::INFO)<<"File position after seekp = "<<ARCHIVE_POS( _output.tellp() )<<std::endl;
266
383
osg::notify(osg::INFO)<<"OSGA_Archive::open("<<filename<<") open for writing"<<std::endl;
563
675
ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(getLowerCaseFileExtension(readFunctor._filename));
566
osg::notify(osg::INFO)<<"OSGA_Archive::readObject(obj, "<<readFunctor._filename<<") failed to find appropriate plugin to write file."<<std::endl;
678
osg::notify(osg::INFO)<<"OSGA_Archive::readObject(obj, "<<readFunctor._filename<<") failed to find appropriate plugin to read file."<<std::endl;
567
679
return ReadResult(ReadResult::FILE_NOT_HANDLED);
570
682
osg::notify(osg::INFO)<<"OSGA_Archive::readObject(obj, "<<readFunctor._filename<<")"<<std::endl;
572
_input.seekg(itr->second.first);
684
_input.seekg( STREAM_POS( itr->second.first ) );
574
// set up proxy stream buffer to proide the faked ending.
686
// set up proxy stream buffer to provide the faked ending.
575
687
std::istream& ins = _input;
576
688
proxy_streambuf mystreambuf(ins.rdbuf(),itr->second.second);
577
689
ins.rdbuf(&mystreambuf);
664
776
osg::notify(osg::INFO)<<"OSGA_Archive::write(obj, "<<writeFunctor._filename<<")"<<std::endl;
666
// place write position at end of file.
667
_output.seekp(0,std::ios::end);
669
pos_type position = _output.tellp();
778
pos_type position = ARCHIVE_POS( _output.tellp() );
671
780
WriteResult result = writeFunctor.doWrite(*rw,_output);
673
pos_type final_position = _output.tellp();
674
size_type size = size_type(final_position-position);
782
pos_type final_position = ARCHIVE_POS( _output.tellp() );
783
size_type size = size_type( final_position-position );
676
785
if (result.success()) addFileReference(position, size, writeFunctor._filename);