~ubuntu-branches/ubuntu/trusty/openscenegraph/trusty

« back to all changes in this revision

Viewing changes to OpenSceneGraph/src/osgPlugins/osga/OSGA_Archive.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cyril Brulebois
  • Date: 2008-07-29 04:34:38 UTC
  • mfrom: (1.1.6 upstream) (2.1.3 lenny)
  • Revision ID: james.westby@ubuntu.com-20080729043438-no1h9h0dpsrlzp1y
* Non-maintainer upload.
* No longer try to detect (using /proc/cpuinfo when available) how many
  CPUs are available, fixing the FTBFS (due to -j0) on various platforms
  (Closes: #477353). The right way to do it is to support parallel=n in
  DEB_BUILD_OPTIONS (see Debian Policy §4.9.1), and adequate support has
  been implemented.
* Add patch to fix FTBFS due to the build system now refusing to handle
  whitespaces (Policy CMP0004 say the logs), thanks to Andreas Putzo who
  provided it (Closes: #482239):
   - debian/patches/fix-cmp0004-build-failure.dpatch
* Remove myself from Uploaders, as requested a while ago, done by Luk in
  his 2.2.0-2.1 NMU, which was never acknowledged.

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
 
9
9
using namespace osgDB;
10
10
 
 
11
/*
 
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 )
 
15
and 
 
16
    OSGA_Archive::pos_type (64 bit file position index)
 
17
 
 
18
Purpose:
 
19
    To allow using OSGA files larger than 4GiB in Windows.
 
20
 
 
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.
 
23
 
 
24
    std::streampos can be implicitly cast from/to std::streamoff as 
 
25
    std::streampos class defines appropriate constructor and cast operator.
 
26
 
 
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.
 
30
 
 
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).
 
33
 
 
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.
 
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
    be easily extended to other 32bit systems supporting 64bit files, provided
 
46
    their std::streampos implementations are similar.
 
47
 
 
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
 
51
*/
 
52
 
 
53
/* 
 
54
    Recognize Dinkumware std C++ lib implementation. Its used by Microsoft, 
 
55
    but method is more generic - should work in all Dinkumware environments.
 
56
 
 
57
    Complex condition below was taken from 
 
58
        http://boost.org/boost/iostreams/positioning.hpp
 
59
 
 
60
    Great thanks to J.Tukanis and G. Sylvester-Bradley for figuring it out.
 
61
*/
 
62
#if ((defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)) && \
 
63
     !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) \
 
64
     && !defined(__QNX__)
 
65
 
 
66
inline std::streampos STREAM_POS( const OSGA_Archive::pos_type pos )
 
67
 
68
    return std::streampos( std::mbstate_t(), pos );
 
69
}
 
70
 
 
71
inline OSGA_Archive::pos_type ARCHIVE_POS( const std::streampos & pos )
 
72
 
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();
 
77
#endif
 
78
    std::streamoff offset = pos.operator std::streamoff( ) - _FPOSOFF( position );
 
79
 
 
80
    return OSGA_Archive::pos_type( position + offset );
 
81
}
 
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 )
 
85
 
86
    return std::streampos( pos );
 
87
}
 
88
 
 
89
inline OSGA_Archive::pos_type ARCHIVE_POS( const std::streampos & pos )
 
90
 
91
    return OSGA_Archive::pos_type( pos );
 
92
}
 
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;
13
97
 
49
133
    if (!in) return 0;
50
134
 
51
135
    osg::ref_ptr<IndexBlock> indexBlock = new IndexBlock;
52
 
    indexBlock->_filePosition = in.tellg();
 
136
    indexBlock->_filePosition = ARCHIVE_POS( in.tellg() );
53
137
    in.read(reinterpret_cast<char*>(&indexBlock->_blockSize), sizeof(indexBlock->_blockSize));
54
138
    in.read(reinterpret_cast<char*>(&indexBlock->_filePositionNextIndexBlock), sizeof(indexBlock->_filePositionNextIndexBlock));
55
139
    in.read(reinterpret_cast<char*>(&indexBlock->_offsetOfNextAvailableSpace), sizeof(indexBlock-> _offsetOfNextAvailableSpace));
150
234
        
151
235
        std::string filename(ptr, ptr+filename_size);
152
236
        
153
 
        // record this entry into the FileNamePositionMap
154
 
        indexMap[filename] = PositionSizePair(position,size);
 
237
        // record this entry into the FileNamePositionMap. 
 
238
        // Requests for files will be in unix style even on Win32 so need unix style keys in map.
 
239
        indexMap[osgDB::convertFileNameToUnixStyle(filename)] = PositionSizePair(position,size);
155
240
        
156
241
        ptr += filename_size;
157
242
        
162
247
 
163
248
void OSGA_Archive::IndexBlock::write(std::ostream& out)
164
249
{
 
250
    pos_type currentPos = ARCHIVE_POS( out.tellp() );
 
251
 
165
252
    if (_filePosition==pos_type(0))
166
253
    {
167
254
        osg::notify(osg::INFO)<<"OSGA_Archive::IndexBlock::write() setting _filePosition"<<std::endl;
168
 
        _filePosition = out.tellp();
 
255
        _filePosition = currentPos;
169
256
    }
170
257
    else
171
258
    {
172
 
         out.seekp(_filePosition);
 
259
         out.seekp( STREAM_POS( _filePosition ) );
173
260
    }
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;
175
262
 
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));
179
266
 
180
267
    out.write(reinterpret_cast<char*>(_data),_blockSize);
 
268
 
 
269
    if( _filePosition < currentPos ) // move file ptr to the end of file 
 
270
        out.seekp( STREAM_POS( currentPos ) );
181
271
    
182
272
    osg::notify(osg::INFO)<<"OSGA_Archive::IndexBlock::write() end"<<std::endl;
183
273
}
251
341
    {
252
342
        if (status==WRITE && open(filename,READ))
253
343
        {
 
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*/ );
 
354
          
 
355
                for(IndexBlockList::iterator itr=_indexBlockList.begin();
 
356
                    itr!=_indexBlockList.end();
 
357
                    ++itr)
 
358
                {
 
359
                    pos_type end = (*itr)->getPosition() + BlockHeaderSize + (*itr)->getBlockSize();
 
360
                    if( file_size < end ) file_size = end;
 
361
                }
 
362
 
 
363
                for(FileNamePositionMap::iterator mitr=_indexMap.begin();
 
364
                    mitr!=_indexMap.end();
 
365
                    ++mitr)
 
366
                {
 
367
                    pos_type end = mitr->second.first + mitr->second.second;
 
368
                    if( file_size < end ) file_size = end;
 
369
                }
 
370
            }
254
371
            _input.close();
255
372
            _status = WRITE;
256
373
 
257
374
            _output.open(filename.c_str(), std::ios_base::binary | std::ios_base::in | std::ios_base::out);
258
 
            
259
 
            osg::notify(osg::INFO)<<"File position after open = "<<(int)_output.tellp()<<" is_open "<<_output.is_open()<<std::endl;
260
 
 
261
 
            // place write position at end of file.
262
 
            _output.seekp(0, std::ios::end);
263
 
 
264
 
            osg::notify(osg::INFO)<<"File position after seekp = "<<(int)_output.tellp()<<std::endl;
 
375
 
 
376
            osg::notify(osg::INFO)<<"File position after open = "<<ARCHIVE_POS( _output.tellp() )<<" is_open "<<_output.is_open()<<std::endl;
 
377
 
 
378
            // place write position at end of file. 
 
379
            _output.seekp( STREAM_POS( file_size ) );
 
380
 
 
381
            osg::notify(osg::INFO)<<"File position after seekp = "<<ARCHIVE_POS( _output.tellp() )<<std::endl;
265
382
 
266
383
            osg::notify(osg::INFO)<<"OSGA_Archive::open("<<filename<<") open for writing"<<std::endl;
267
384
 
284
401
                _indexBlockList.push_back(indexBlock);
285
402
            }
286
403
 
287
 
            osg::notify(osg::INFO)<<"File position after write = "<<(int)_output.tellp()<<std::endl;
288
 
 
289
 
            // place write position at end of file.
290
 
            _output.seekp(0,std::ios::end);
291
 
 
292
 
            osg::notify(osg::INFO)<<"File position after seekp = "<<(int)_output.tellp()<<std::endl;
 
404
            osg::notify(osg::INFO)<<"File position after write = "<<ARCHIVE_POS( _output.tellp() )<<std::endl;
293
405
 
294
406
            return true;
295
407
        }
337
449
                _indexBlockList.push_back(indexBlock);
338
450
                if (indexBlock->getPositionNextIndexBlock()==pos_type(0)) break;
339
451
 
340
 
                input.seekg(indexBlock->getPositionNextIndexBlock());
 
452
                input.seekg( STREAM_POS( indexBlock->getPositionNextIndexBlock() ) );
341
453
            }
342
454
 
343
455
            // now need to build the filename map.
464
576
    // if not one available create a new block.    
465
577
    if (!indexBlock)
466
578
    {
467
 
        if (previousBlock.valid()) previousBlock->setPositionNextIndexBlock(_output.tellp());
 
579
        if (previousBlock.valid()) previousBlock->setPositionNextIndexBlock( ARCHIVE_POS( _output.tellp() ) );
468
580
    
469
581
        indexBlock = new IndexBlock(blockSize);
470
582
        indexBlock->write(_output);
549
661
 
550
662
    if (_status!=READ) 
551
663
    {
552
 
        osg::notify(osg::INFO)<<"OSGA_Archive::readObject(obj, "<<readFunctor._filename<<") failed, archive opened as read only."<<std::endl;
 
664
        osg::notify(osg::INFO)<<"OSGA_Archive::readObject(obj, "<<readFunctor._filename<<") failed, archive opened as write only."<<std::endl;
553
665
        return ReadResult(ReadResult::FILE_NOT_HANDLED);
554
666
    }
555
667
    
563
675
    ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(getLowerCaseFileExtension(readFunctor._filename));
564
676
    if (!rw)
565
677
    {
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);
568
680
    }
569
681
    
570
682
    osg::notify(osg::INFO)<<"OSGA_Archive::readObject(obj, "<<readFunctor._filename<<")"<<std::endl;
571
683
    
572
 
    _input.seekg(itr->second.first);
 
684
    _input.seekg( STREAM_POS( itr->second.first ) );
573
685
 
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);
663
775
    
664
776
    osg::notify(osg::INFO)<<"OSGA_Archive::write(obj, "<<writeFunctor._filename<<")"<<std::endl;
665
777
    
666
 
    // place write position at end of file.
667
 
    _output.seekp(0,std::ios::end);
668
 
    
669
 
    pos_type position = _output.tellp();
 
778
    pos_type position = ARCHIVE_POS( _output.tellp() );
670
779
    
671
780
    WriteResult result = writeFunctor.doWrite(*rw,_output);
672
781
    
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 );
675
784
 
676
785
    if (result.success()) addFileReference(position, size, writeFunctor._filename);
677
786