root/OpenSceneGraph/trunk/src/osgPlugins/osga/OSGA_Archive.cpp @ 13041

Revision 13041, 28.2 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osg/Notify>
2#include <osg/Endian>
3
4#include <osgDB/Registry>
5#include <osgDB/FileNameUtils>
6
7#include "OSGA_Archive.h"
8
9using namespace osgDB;
10
11/*
12Functions to convert between
13    std::streampos ( typedef'ed as iostream::pos_type
14              used as seekp,seekg argument and tellp,tellg return value )
15and
16    OSGA_Archive::pos_type (64 bit file position index)
17
18Purpose:
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
66inline std::streampos STREAM_POS( const OSGA_Archive::pos_type pos )
67{
68    return std::streampos( std::mbstate_t(), pos );
69}
70
71inline 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
84inline std::streampos STREAM_POS( const OSGA_Archive::pos_type pos )
85{
86    return std::streampos( pos );
87}
88
89inline 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////////////////////////////////////////////////////////////////////////////////
95float OSGA_Archive::s_currentSupportedVersion = 0.0;
96const unsigned int ENDIAN_TEST_NUMBER = 0x00000001;
97
98OSGA_Archive::IndexBlock::IndexBlock(unsigned int blockSize):
99    _requiresWrite(false),
100    _filePosition(0),
101    _blockSize(0),
102    _filePositionNextIndexBlock(0),
103    _offsetOfNextAvailableSpace(0),
104    _data(0)
105{
106    allocateData(blockSize);
107}
108
109OSGA_Archive::IndexBlock::~IndexBlock()
110{
111    delete [] _data;
112}
113
114void OSGA_Archive::IndexBlock::allocateData(unsigned int blockSize)
115{
116    _data = (blockSize!=0) ? new char[blockSize]  : 0;
117    if (_data)
118    {
119        _blockSize = blockSize;
120
121        // initialize the array
122        char* end = _data + _blockSize;
123        for(char* ptr=_data; ptr < end; ++ptr) *ptr = 0;
124    }
125    else
126    {
127        _blockSize = 0;
128    }
129}
130
131OSGA_Archive::IndexBlock* OSGA_Archive::IndexBlock::read(std::istream& in, bool doEndianSwap)
132{
133    if (!in) return 0;
134
135    osg::ref_ptr<IndexBlock> indexBlock = new IndexBlock;
136    indexBlock->_filePosition = ARCHIVE_POS( in.tellg() );
137    in.read(reinterpret_cast<char*>(&indexBlock->_blockSize), sizeof(indexBlock->_blockSize));
138    in.read(reinterpret_cast<char*>(&indexBlock->_filePositionNextIndexBlock), sizeof(indexBlock->_filePositionNextIndexBlock));
139    in.read(reinterpret_cast<char*>(&indexBlock->_offsetOfNextAvailableSpace), sizeof(indexBlock-> _offsetOfNextAvailableSpace));
140
141    if (doEndianSwap)
142    {
143        osg::swapBytes(reinterpret_cast<char*>(&indexBlock->_blockSize), sizeof(indexBlock->_blockSize));
144        osg::swapBytes(reinterpret_cast<char*>(&indexBlock->_filePositionNextIndexBlock), sizeof(indexBlock->_filePositionNextIndexBlock));
145        osg::swapBytes(reinterpret_cast<char*>(&indexBlock->_offsetOfNextAvailableSpace), sizeof(indexBlock-> _offsetOfNextAvailableSpace));
146    }
147
148//    OSG_INFO<<"indexBlock->_blockSize="<<indexBlock->_blockSize<<std::endl;
149//    OSG_INFO<<"indexBlock->_filePositionNextIndexBlock="<<indexBlock->_filePositionNextIndexBlock<<std::endl;
150//    OSG_INFO<<"indexBlock->_offsetOfNextAvailableSpace="<<indexBlock->_offsetOfNextAvailableSpace<<std::endl;
151
152    indexBlock->allocateData(indexBlock->_blockSize);
153    if (indexBlock->_data)
154    {
155        in.read(reinterpret_cast<char*>(indexBlock->_data),indexBlock->_blockSize);
156
157        if (doEndianSwap)
158        {
159            char* ptr = indexBlock->_data;
160            char* end_ptr = indexBlock->_data + indexBlock->_offsetOfNextAvailableSpace;
161            while (ptr<end_ptr)
162            {
163                osg::swapBytes(ptr,sizeof(pos_type));
164                ptr += sizeof(pos_type);
165
166                osg::swapBytes(ptr,sizeof(size_type));
167                ptr += sizeof(size_type);
168
169                osg::swapBytes(ptr,sizeof(unsigned int));
170                unsigned int filename_size; // = *(reinterpret_cast<unsigned int*>(ptr));
171                _read(ptr, filename_size);
172                ptr += sizeof(unsigned int);
173                ptr += filename_size;
174
175                OSG_INFO<<"filename size="<<filename_size<<std::endl;
176
177            }
178        }
179    }
180    else
181    {
182        OSG_INFO<<"Allocation Problem in OSGA_Archive::IndexBlock::read(std::istream& in)"<<std::endl;
183        return 0;
184    }
185
186    OSG_INFO<<"Read index block"<<std::endl;
187
188    return indexBlock.release();
189
190}
191
192std::string OSGA_Archive::IndexBlock::getFirstFileName() const
193{
194    char* ptr = _data;
195    char* end_ptr = _data + _offsetOfNextAvailableSpace;
196    if (ptr<end_ptr)
197    {
198        ptr += sizeof(pos_type);
199        ptr += sizeof(size_type);
200
201        unsigned int filename_size; // = *(reinterpret_cast<unsigned int*>(ptr));
202        _read(ptr, filename_size);
203        ptr += sizeof(unsigned int);
204
205        return std::string(ptr, ptr+filename_size);
206    }
207    else
208    {
209        return std::string();
210    }
211}
212
213bool OSGA_Archive::IndexBlock::getFileReferences(FileNamePositionMap& indexMap) const
214{
215    if (!_data || _offsetOfNextAvailableSpace==0) return false;
216
217    bool valuesAdded = false;
218
219    char* ptr = _data;
220    char* end_ptr = _data + _offsetOfNextAvailableSpace;
221    while (ptr<end_ptr)
222    {
223        pos_type position; // = *(reinterpret_cast<pos_type*>(ptr));
224        _read(ptr, position);
225        ptr += sizeof(pos_type);
226
227        size_type size; // = *(reinterpret_cast<size_type*>(ptr));
228        _read(ptr, size);
229        ptr += sizeof(size_type);
230
231        unsigned int filename_size; // = *(reinterpret_cast<unsigned int*>(ptr));
232        _read(ptr, filename_size);
233        ptr += sizeof(unsigned int);
234
235        std::string filename(ptr, ptr+filename_size);
236
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);
240
241        ptr += filename_size;
242
243        valuesAdded = true;
244    }
245    return valuesAdded;
246}
247
248void OSGA_Archive::IndexBlock::write(std::ostream& out)
249{
250    pos_type currentPos = ARCHIVE_POS( out.tellp() );
251
252    if (_filePosition==pos_type(0))
253    {
254        OSG_INFO<<"OSGA_Archive::IndexBlock::write() setting _filePosition"<<std::endl;
255        _filePosition = currentPos;
256    }
257    else
258    {
259         out.seekp( STREAM_POS( _filePosition ) );
260    }
261    OSG_INFO<<"OSGA_Archive::IndexBlock::write() to _filePosition"<< ARCHIVE_POS( out.tellp() )<<std::endl;
262
263    out.write(reinterpret_cast<char*>(&_blockSize), sizeof(_blockSize));
264    out.write(reinterpret_cast<char*>(&_filePositionNextIndexBlock), sizeof(_filePositionNextIndexBlock));
265    out.write(reinterpret_cast<char*>(&_offsetOfNextAvailableSpace), sizeof(_offsetOfNextAvailableSpace));
266
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 ) );
271
272    OSG_INFO<<"OSGA_Archive::IndexBlock::write() end"<<std::endl;
273}
274
275
276bool OSGA_Archive::IndexBlock::addFileReference(pos_type position, size_type size, const std::string& filename)
277{
278    if (spaceAvailable(position, size, filename))
279    {
280        char* ptr = _data+_offsetOfNextAvailableSpace;
281
282        //*(reinterpret_cast<pos_type*>(ptr)) = position;
283        _write(ptr, position);
284        ptr += sizeof(pos_type);
285
286        //*(reinterpret_cast<size_type*>(ptr)) = size;
287        _write(ptr, size);
288        ptr += sizeof(size_type);
289
290        //*(reinterpret_cast<unsigned int*>(ptr)) = filename.size();
291        _write(ptr, static_cast<unsigned int>(filename.size()));
292        ptr += sizeof(unsigned int);
293
294        for(unsigned int i=0;i<filename.size();++i, ++ptr)
295        {
296            *ptr = filename[i];
297        }
298
299        _offsetOfNextAvailableSpace = ptr-_data;
300
301        _requiresWrite = true;
302
303        OSG_INFO<<"OSGA_Archive::IndexBlock::addFileReference("<<(unsigned int)position<<", "<<filename<<")"<<std::endl;
304
305        return true;
306    }
307    else
308    {
309        return false;
310    }
311}
312
313void OSGA_Archive::IndexBlock::setPositionNextIndexBlock(pos_type position)
314{
315    _filePositionNextIndexBlock = position;
316    _requiresWrite = true;
317}
318
319OSGA_Archive::OSGA_Archive()
320{
321}
322
323OSGA_Archive::~OSGA_Archive()
324{
325    close();
326}
327
328
329bool OSGA_Archive::open(const std::string& filename, ArchiveStatus status, unsigned int indexBlockSize)
330{
331    SERIALIZER();
332
333    _archiveFileName = filename;
334
335    if (status==READ)
336    {
337        _status = status;
338        _input.open(filename.c_str(), std::ios_base::binary | std::ios_base::in);
339
340        return _open(_input);
341    }
342    else
343    {
344        if (status==WRITE && open(filename,READ))
345        {
346            pos_type file_size( 0 );
347            _input.seekg( 0, std::ios_base::end );
348            file_size = ARCHIVE_POS( _input.tellg() );
349            if( _input.is_open() && file_size <= 0 )
350            {   // compute end of file postition manually ...
351                // seekp( 0, ios::end ), tellp( ) fails in 32 bit windows with files > 4 GiB
352                size_t BlockHeaderSize =
353                    sizeof( unsigned int /*_blockSize*/ ) +
354                    sizeof( pos_type /*_filePositionNextIndexBlock*/ ) +
355                    sizeof( unsigned int /*_offsetOfNextAvailableSpace*/ );
356
357                for(IndexBlockList::iterator itr=_indexBlockList.begin();
358                    itr!=_indexBlockList.end();
359                    ++itr)
360                {
361                    pos_type end = (*itr)->getPosition() + BlockHeaderSize + (*itr)->getBlockSize();
362                    if( file_size < end ) file_size = end;
363                }
364
365                for(FileNamePositionMap::iterator mitr=_indexMap.begin();
366                    mitr!=_indexMap.end();
367                    ++mitr)
368                {
369                    pos_type end = mitr->second.first + mitr->second.second;
370                    if( file_size < end ) file_size = end;
371                }
372            }
373            _input.close();
374            _status = WRITE;
375
376            _output.open(filename.c_str(), std::ios_base::binary | std::ios_base::in | std::ios_base::out);
377
378            OSG_INFO<<"File position after open = "<<ARCHIVE_POS( _output.tellp() )<<" is_open "<<_output.is_open()<<std::endl;
379
380            // place write position at end of file.
381            _output.seekp( STREAM_POS( file_size ) );
382
383            OSG_INFO<<"File position after seekp = "<<ARCHIVE_POS( _output.tellp() )<<std::endl;
384
385            OSG_INFO<<"OSGA_Archive::open("<<filename<<") open for writing"<<std::endl;
386
387            return true;
388        }
389        else // no file opened or using create so resort to creating the archive.
390        {
391            OSG_INFO<<"OSGA_Archive::open("<<filename<<"), archive being created."<<std::endl;
392
393            _status = WRITE;
394            _output.open(filename.c_str(), std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
395            _output<<"osga";
396            _output.write(reinterpret_cast<const char*>(&ENDIAN_TEST_NUMBER),4);
397            _output.write(reinterpret_cast<char*>(&s_currentSupportedVersion),sizeof(float));
398
399            IndexBlock *indexBlock = new IndexBlock(indexBlockSize);
400            if (indexBlock)
401            {
402                indexBlock->write(_output);
403                _indexBlockList.push_back(indexBlock);
404            }
405
406            OSG_INFO<<"File position after write = "<<ARCHIVE_POS( _output.tellp() )<<std::endl;
407
408            return true;
409        }
410
411    }
412}
413
414bool OSGA_Archive::open(std::istream& fin)
415{
416    SERIALIZER();
417
418    _archiveFileName = "";
419
420    OSG_NOTICE<<"OSGA_Archive::open"<<std::endl;
421    static_cast<std::istream&>(_input).rdbuf(fin.rdbuf());
422    return _open(_input);
423}
424
425bool OSGA_Archive::_open(std::istream& input)
426{
427    if (input)
428    {
429        char identifier[4];
430        input.read(identifier,4);
431
432        bool validArchive = (identifier[0]=='o' && identifier[1]=='s' && identifier[2]=='g' && identifier[3]=='a');
433        if (validArchive)
434        {
435
436            unsigned int endianTestWord=0;
437            input.read(reinterpret_cast<char*>(&endianTestWord),4);
438            bool doEndianSwap = (endianTestWord!=ENDIAN_TEST_NUMBER);
439
440            input.read(reinterpret_cast<char*>(&_version),sizeof(_version));
441            if (doEndianSwap)
442            {
443                osg::swapBytes(reinterpret_cast<char*>(&_version),sizeof(_version));
444            }
445
446            OSG_INFO<<"OSGA_Archive::open() doEndianSwap="<<doEndianSwap<<std::endl;
447            OSG_INFO<<"OSGA_Archive::open() Version="<<_version<<std::endl;
448
449            IndexBlock *indexBlock = 0;
450
451            while ( (indexBlock=OSGA_Archive::IndexBlock::read(input, doEndianSwap)) != 0)
452            {
453                _indexBlockList.push_back(indexBlock);
454                if (indexBlock->getPositionNextIndexBlock()==pos_type(0)) break;
455
456                input.seekg( STREAM_POS( indexBlock->getPositionNextIndexBlock() ) );
457            }
458
459            // now need to build the filename map.
460            _indexMap.clear();
461
462            if (!_indexBlockList.empty())
463            {
464                _masterFileName = _indexBlockList.front()->getFirstFileName();
465            }
466
467            for(IndexBlockList::iterator itr=_indexBlockList.begin();
468                itr!=_indexBlockList.end();
469                ++itr)
470            {
471                (*itr)->getFileReferences(_indexMap);
472            }
473
474            for(FileNamePositionMap::iterator mitr=_indexMap.begin();
475                mitr!=_indexMap.end();
476                ++mitr)
477            {
478                OSG_INFO<<"    filename "<<(mitr->first)<<" pos="<<(int)((mitr->second).first)<<" size="<<(int)((mitr->second).second)<<std::endl;
479            }
480
481
482            return true;
483        }
484    }
485    return false;
486}
487
488void OSGA_Archive::close()
489{
490    SERIALIZER();
491
492    _input.close();
493
494    if (_status==WRITE)
495    {
496        writeIndexBlocks();
497        _output.close();
498    }
499}
500
501std::string OSGA_Archive::getMasterFileName() const
502{
503    return _masterFileName;
504}
505
506osgDB::FileType OSGA_Archive::getFileType(const std::string& filename) const
507{
508    if (_indexMap.count(filename)!=0) return osgDB::REGULAR_FILE;
509    return osgDB::FILE_NOT_FOUND;
510}
511
512bool OSGA_Archive::getFileNames(FileNameList& fileNameList) const
513{
514    SERIALIZER();
515
516    fileNameList.clear();
517    fileNameList.reserve(_indexMap.size());
518    for(FileNamePositionMap::const_iterator itr=_indexMap.begin();
519        itr!=_indexMap.end();
520        ++itr)
521    {
522        fileNameList.push_back(itr->first);
523    }
524    return !fileNameList.empty();
525}
526
527void OSGA_Archive::writeIndexBlocks()
528{
529    SERIALIZER();
530
531    if (_status==WRITE)
532    {
533        for(IndexBlockList::iterator itr=_indexBlockList.begin();
534            itr!=_indexBlockList.end();
535            ++itr)
536        {
537            if ((*itr)->requiresWrite())
538            {
539                (*itr)->write(_output);
540            }
541        }
542    }
543}
544
545bool OSGA_Archive::fileExists(const std::string& filename) const
546{
547    return (_indexMap.count(filename)!=0);
548}
549
550bool OSGA_Archive::addFileReference(pos_type position, size_type size, const std::string& fileName)
551{
552    SERIALIZER();
553
554    if (_status==READ)
555    {
556        OSG_INFO<<"OSGA_Archive::getPositionForNewEntry("<<fileName<<") failed, archive opened as read only."<<std::endl;
557        return false;
558    }
559
560    if (!_output)
561    {
562        OSG_INFO<<"OSGA_Archive::getPositionForNewEntry("<<fileName<<") failed, _output set up."<<std::endl;
563        return false;
564    }
565
566
567    // if the masterFileName isn't set yet use this fileName
568    if (_masterFileName.empty()) _masterFileName = fileName;
569
570
571    // get an IndexBlock with space available if possible
572    unsigned int blockSize = 4096;
573    osg::ref_ptr<IndexBlock> indexBlock = _indexBlockList.empty() ? 0 : _indexBlockList.back().get();
574    osg::ref_ptr<IndexBlock> previousBlock = indexBlock;
575    if (indexBlock.valid())
576    {
577        blockSize = indexBlock->getBlockSize();
578        if (!(indexBlock->spaceAvailable(position, size, fileName)))
579        {
580            previousBlock = indexBlock;
581            indexBlock = 0;
582        }
583    }
584
585    // if not one available create a new block.
586    if (!indexBlock)
587    {
588        if (previousBlock.valid()) previousBlock->setPositionNextIndexBlock( ARCHIVE_POS( _output.tellp() ) );
589
590        indexBlock = new IndexBlock(blockSize);
591        indexBlock->write(_output);
592        _indexBlockList.push_back(indexBlock.get());
593    }
594
595    if (indexBlock.valid())
596    {
597        return indexBlock->addFileReference(position, size, fileName);
598    }
599    return false;
600}
601
602
603
604class proxy_streambuf : public std::streambuf
605{
606   public:
607
608      proxy_streambuf(std::streambuf* streambuf, unsigned int numChars):
609        _streambuf(streambuf),
610        _numChars(numChars) {
611            setg(&oneChar, (&oneChar)+1, (&oneChar)+1);
612    }
613
614      /// Destructor deallocates no buffer space.
615      virtual ~proxy_streambuf()  {}
616
617      std::streambuf* _streambuf;
618
619    protected:
620
621      unsigned int _numChars;
622      char_type oneChar;
623
624      virtual int_type underflow()
625      {
626     if ( gptr() == &oneChar ) return traits_type::to_int_type(oneChar);
627
628         if ( _numChars==0 ) return traits_type::eof();
629         --_numChars;
630
631           int_type next_value = _streambuf->sbumpc();
632
633         if ( !traits_type::eq_int_type(next_value,traits_type::eof()) )
634     {
635       setg(&oneChar, &oneChar, (&oneChar)+1);
636            oneChar = traits_type::to_char_type(next_value);
637     }
638
639         return next_value;
640      }
641};
642
643struct OSGA_Archive::ReadObjectFunctor : public OSGA_Archive::ReadFunctor
644{
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); }
647};
648
649struct OSGA_Archive::ReadImageFunctor : public OSGA_Archive::ReadFunctor
650{
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); }
653};
654
655struct OSGA_Archive::ReadHeightFieldFunctor : public OSGA_Archive::ReadFunctor
656{
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); }
659};
660
661struct OSGA_Archive::ReadNodeFunctor : public OSGA_Archive::ReadFunctor
662{
663    ReadNodeFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {}
664    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input) const { return rw.readNode(input, _options); }
665};
666
667struct OSGA_Archive::ReadShaderFunctor : public OSGA_Archive::ReadFunctor
668{
669    ReadShaderFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {}
670    virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input) const { return rw.readShader(input, _options); }
671};
672
673ReaderWriter::ReadResult OSGA_Archive::read(const ReadFunctor& readFunctor)
674{
675    SERIALIZER();
676
677    if (_status!=READ)
678    {
679        OSG_INFO<<"OSGA_Archive::readObject(obj, "<<readFunctor._filename<<") failed, archive opened as write only."<<std::endl;
680        return ReadResult(ReadResult::FILE_NOT_HANDLED);
681    }
682
683    FileNamePositionMap::const_iterator itr = _indexMap.find(readFunctor._filename);
684    if (itr==_indexMap.end())
685    {
686        OSG_INFO<<"OSGA_Archive::readObject(obj, "<<readFunctor._filename<<") failed, file not found in archive"<<std::endl;
687        return ReadResult(ReadResult::FILE_NOT_FOUND);
688    }
689
690    ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(getLowerCaseFileExtension(readFunctor._filename));
691    if (!rw)
692    {
693        OSG_INFO<<"OSGA_Archive::readObject(obj, "<<readFunctor._filename<<") failed to find appropriate plugin to read file."<<std::endl;
694        return ReadResult(ReadResult::FILE_NOT_HANDLED);
695    }
696
697    OSG_INFO<<"OSGA_Archive::readObject(obj, "<<readFunctor._filename<<")"<<std::endl;
698
699    _input.seekg( STREAM_POS( itr->second.first ) );
700
701    // set up proxy stream buffer to provide the faked ending.
702    std::istream& ins = _input;
703    proxy_streambuf mystreambuf(ins.rdbuf(),itr->second.second);
704    ins.rdbuf(&mystreambuf);
705
706    ReaderWriter::ReadResult result = readFunctor.doRead(*rw, _input);
707
708    ins.rdbuf(mystreambuf._streambuf);
709
710    return result;
711}
712
713ReaderWriter::ReadResult OSGA_Archive::readObject(const std::string& fileName,const Options* options) const
714{
715    return const_cast<OSGA_Archive*>(this)->read(ReadObjectFunctor(fileName, options));
716}
717
718ReaderWriter::ReadResult OSGA_Archive::readImage(const std::string& fileName,const Options* options) const
719{
720    return const_cast<OSGA_Archive*>(this)->read(ReadImageFunctor(fileName, options));
721}
722
723ReaderWriter::ReadResult OSGA_Archive::readHeightField(const std::string& fileName,const Options* options) const
724{
725    return const_cast<OSGA_Archive*>(this)->read(ReadHeightFieldFunctor(fileName, options));
726}
727
728ReaderWriter::ReadResult OSGA_Archive::readNode(const std::string& fileName,const Options* options) const
729{
730    return const_cast<OSGA_Archive*>(this)->read(ReadNodeFunctor(fileName, options));
731}
732
733ReaderWriter::ReadResult OSGA_Archive::readShader(const std::string& fileName,const Options* options) const
734{
735    return const_cast<OSGA_Archive*>(this)->read(ReadShaderFunctor(fileName, options));
736}
737
738
739struct OSGA_Archive::WriteObjectFunctor : public OSGA_Archive::WriteFunctor
740{
741    WriteObjectFunctor(const osg::Object& object, const std::string& filename, const ReaderWriter::Options* options):
742        WriteFunctor(filename,options),
743        _object(object) {}
744    const osg::Object& _object;
745
746    virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeObject(_object, output, _options); }
747};
748
749struct OSGA_Archive::WriteImageFunctor : public OSGA_Archive::WriteFunctor
750{
751    WriteImageFunctor(const osg::Image& object, const std::string& filename, const ReaderWriter::Options* options):
752        WriteFunctor(filename,options),
753        _object(object) {}
754    const osg::Image& _object;
755
756    virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeImage(_object, output, _options); }
757};
758
759struct OSGA_Archive::WriteHeightFieldFunctor : public OSGA_Archive::WriteFunctor
760{
761    WriteHeightFieldFunctor(const osg::HeightField& object, const std::string& filename, const ReaderWriter::Options* options):
762        WriteFunctor(filename,options),
763        _object(object) {}
764    const osg::HeightField& _object;
765
766    virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeHeightField(_object, output, _options); }
767};
768
769struct OSGA_Archive::WriteNodeFunctor : public OSGA_Archive::WriteFunctor
770{
771    WriteNodeFunctor(const osg::Node& object, const std::string& filename, const ReaderWriter::Options* options):
772        WriteFunctor(filename,options),
773        _object(object) {}
774    const osg::Node& _object;
775
776    virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeNode(_object, output, _options); }
777};
778
779struct OSGA_Archive::WriteShaderFunctor : public OSGA_Archive::WriteFunctor
780{
781    WriteShaderFunctor(const osg::Shader& object, const std::string& filename, const ReaderWriter::Options* options):
782        WriteFunctor(filename,options),
783        _object(object) {}
784    const osg::Shader& _object;
785
786    virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeShader(_object, output, _options); }
787};
788
789ReaderWriter::WriteResult OSGA_Archive::write(const WriteFunctor& writeFunctor)
790{
791    SERIALIZER();
792
793    if (_status!=WRITE)
794    {
795        OSG_INFO<<"OSGA_Archive::write(obj, "<<writeFunctor._filename<<") failed, archive opened as read only."<<std::endl;
796        return WriteResult(WriteResult::FILE_NOT_HANDLED);
797    }
798
799    ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(getLowerCaseFileExtension(writeFunctor._filename));
800    if (!rw)
801    {
802        OSG_INFO<<"OSGA_Archive::write(obj, "<<writeFunctor._filename<<") failed to find appropriate plugin to write file."<<std::endl;
803        return WriteResult(WriteResult::FILE_NOT_HANDLED);
804    }
805
806    OSG_INFO<<"OSGA_Archive::write(obj, "<<writeFunctor._filename<<")"<<std::endl;
807
808    pos_type position = ARCHIVE_POS( _output.tellp() );
809
810    WriteResult result = writeFunctor.doWrite(*rw,_output);
811
812    pos_type final_position = ARCHIVE_POS( _output.tellp() );
813    size_type size = size_type( final_position-position );
814
815    if (result.success()) addFileReference(position, size, writeFunctor._filename);
816
817    return result;
818}
819
820
821ReaderWriter::WriteResult OSGA_Archive::writeObject(const osg::Object& obj,const std::string& fileName,const Options* options) const
822{
823    OSG_INFO<<"OSGA_Archive::writeObject(obj, "<<fileName<<")"<<std::endl;
824    return const_cast<OSGA_Archive*>(this)->write(WriteObjectFunctor(obj, fileName, options));
825}
826
827ReaderWriter::WriteResult OSGA_Archive::writeImage(const osg::Image& image,const std::string& fileName,const Options* options) const
828{
829    OSG_INFO<<"OSGA_Archive::writeImage(obj, "<<fileName<<")"<<std::endl;
830    return const_cast<OSGA_Archive*>(this)->write(WriteImageFunctor(image, fileName, options));
831}
832
833ReaderWriter::WriteResult OSGA_Archive::writeHeightField(const osg::HeightField& heightField,const std::string& fileName,const Options* options) const
834{
835    OSG_INFO<<"OSGA_Archive::writeHeightField(obj, "<<fileName<<")"<<std::endl;
836    return const_cast<OSGA_Archive*>(this)->write(WriteHeightFieldFunctor(heightField, fileName, options));
837}
838
839ReaderWriter::WriteResult OSGA_Archive::writeNode(const osg::Node& node,const std::string& fileName,const Options* options) const
840{
841    OSG_INFO<<"OSGA_Archive::writeNode(obj, "<<fileName<<")"<<std::endl;
842    return const_cast<OSGA_Archive*>(this)->write(WriteNodeFunctor(node, fileName, options));
843}
844
845ReaderWriter::WriteResult OSGA_Archive::writeShader(const osg::Shader& shader,const std::string& fileName,const Options* options) const
846{
847    OSG_INFO<<"OSGA_Archive::writeShader(obj, "<<fileName<<")"<<std::endl;
848    return const_cast<OSGA_Archive*>(this)->write(WriteShaderFunctor(shader, fileName, options));
849}
Note: See TracBrowser for help on using the browser.