diff --git a/VisualStudio/osgPlugins/osga/osga.dsp b/VisualStudio/osgPlugins/osga/osga.dsp index b4a2bd84a..b1d37ee04 100644 --- a/VisualStudio/osgPlugins/osga/osga.dsp +++ b/VisualStudio/osgPlugins/osga/osga.dsp @@ -96,12 +96,20 @@ LINK32=link.exe # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File +SOURCE=..\..\..\src\osgPlugins\osga\OSGA_Archive.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\src\osgPlugins\osga\ReaderWriterOSGA.cpp # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\src\osgPlugins\osga\OSGA_Archive.h +# End Source File # End Group # Begin Group "Resource Files" diff --git a/examples/osgarchive/osgarchive.cpp b/examples/osgarchive/osgarchive.cpp index 687e3da2a..8830ed881 100644 --- a/examples/osgarchive/osgarchive.cpp +++ b/examples/osgarchive/osgarchive.cpp @@ -113,40 +113,38 @@ int main( int argc, char **argv ) return 1; } - osgDB::Archive archive; + osg::ref_ptr archive; if (insert) { - osgDB::Archive archive; - archive.open(archiveFilename, osgDB::Archive::WRITE); + archive = osgDB::openArchive(archiveFilename, osgDB::Archive::WRITE); - std::cout<<"Going through files"< obj = osgDB::readObjectFile(*itr); - if (obj.valid()) + for (FileNameList::iterator itr=files.begin(); + itr!=files.end(); + ++itr) { - std::cout<<" Have read"<<*itr< obj = osgDB::readObjectFile(*itr); + if (obj.valid()) + { + archive->writeObject(*obj, *itr); + } } } } else { - archive.open(archiveFilename,osgDB::Archive::READ); + archive = osgDB::openArchive(archiveFilename, osgDB::Archive::READ); - if (extract) + if (extract && archive.valid()) { for (FileNameList::iterator itr=files.begin(); itr!=files.end(); ++itr) { osg::Timer_t start = osg::Timer::instance()->tick(); - osgDB::ReaderWriter::ReadResult result = archive.readObject(*itr); + osgDB::ReaderWriter::ReadResult result = archive->readObject(*itr); osg::ref_ptr obj = result.getObject(); std::cout<<"readObejct time = "<delta_m(start,osg::Timer::instance()->tick())<getFileNames(fileNames)) { for(osgDB::Archive::FileNameList::const_iterator itr=fileNames.begin(); itr!=fileNames.end(); @@ -172,7 +170,7 @@ int main( int argc, char **argv ) } std::cout<getMasterFileName()< FileNameList; /** Get the full list of file names available in the archive.*/ - virtual bool getFileNames(FileNameList& fileNameList) const; + virtual bool getFileNames(FileNameList& fileNameList) const = 0; - /** Read an osg::Object of specified file name from the Archive.*/ - virtual ReadResult readObject(const std::string& fileName,const Options* options=NULL); + virtual ReadResult readObject(const std::string& /*fileName*/,const Options* =NULL) = 0; + virtual ReadResult readImage(const std::string& /*fileName*/,const Options* =NULL) = 0; + virtual ReadResult readHeightField(const std::string& /*fileName*/,const Options* =NULL) = 0; + virtual ReadResult readNode(const std::string& /*fileName*/,const Options* =NULL) = 0; - /** Read an osg::Image of specified file name from the Archive.*/ - virtual ReadResult readImage(const std::string& fileName,const Options* options=NULL); - - /** Read an osg::HeightField of specified file name from the Archive.*/ - virtual ReadResult readHeightField(const std::string& fileName,const Options* options=NULL); - - /** Read an osg::Node of specified file name from the Archive.*/ - virtual ReadResult readNode(const std::string& fileName,const Options* options=NULL); - - /** Write an osg::Object with specified file name to the Archive.*/ - virtual WriteResult writeObject(const osg::Object& obj,const std::string& fileName,const Options* options=NULL); - - /** Write an osg::Image with specified file name to the Archive.*/ - virtual WriteResult writeImage(const osg::Image& image,const std::string& fileName,const Options* options=NULL); - - /** Write an osg::HeightField with specified file name to the Archive.*/ - virtual WriteResult writeHeightField(const osg::HeightField& heightField,const std::string& fileName,const Options* options=NULL); - - /** Write an osg::Node with specified file name to the Archive.*/ - virtual WriteResult writeNode(const osg::Node& node,const std::string& fileName,const Options* options=NULL); - - - protected: - - #if defined(_MSC_VER) - typedef __int64 pos_type; - typedef __int64 size_type; - #else - typedef unsigned long long pos_type; - typedef unsigned long long size_type; - #endif - - typedef std::pair PositionSizePair; - typedef std::map FileNamePositionMap; - - class IndexBlock : public osg::Referenced - { - public: - IndexBlock(unsigned int blockSize=0); - - inline pos_type getPosition() const { return _filePosition; } - - inline unsigned int getBlockSize() const { return _blockSize; } - - - void setPositionNextIndexBlock(pos_type position); - - inline pos_type getPositionNextIndexBlock() const { return _filePositionNextIndexBlock; } - - - static IndexBlock* read(std::istream& in, bool doEndianSwap); - - std::string getFirstFileName() const; - - bool getFileReferences(FileNamePositionMap& indexMap) const; - - - inline bool requiresWrite() const { return _requiresWrite; } - - void write(std::ostream& out); - - inline bool spaceAvailable(pos_type, size_type, const std::string& filename) const - { - unsigned requiredSize = sizeof(pos_type)+sizeof(size_type)+sizeof(unsigned int)+filename.size(); - return (_offsetOfNextAvailableSpace + requiredSize)<_blockSize; - } - - bool addFileReference(pos_type position, size_type size, const std::string& filename); - - - - protected: - - void allocateData(unsigned int blockSize); - - virtual ~IndexBlock(); - bool _requiresWrite; - pos_type _filePosition; - - unsigned int _blockSize; - pos_type _filePositionNextIndexBlock; - unsigned int _offsetOfNextAvailableSpace; - char* _data; - }; - - /** Functor used in internal implementations.*/ - struct ReadFunctor - { - ReadFunctor(const std::string& filename, const ReaderWriter::Options* options): - _filename(filename), - _options(options) {} - - virtual ~ReadFunctor() {} - virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input) const = 0; - - std::string _filename; - const ReaderWriter::Options* _options; - }; - - struct ReadObjectFunctor; - struct ReadImageFunctor; - struct ReadHeightFieldFunctor; - struct ReadNodeFunctor; - - /** Functor used in internal implementations.*/ - struct WriteFunctor - { - WriteFunctor(const std::string& filename, const ReaderWriter::Options* options): - _filename(filename), - _options(options) {} - - virtual ~WriteFunctor() {} - virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const = 0; - - std::string _filename; - const ReaderWriter::Options* _options; - }; - - struct WriteObjectFunctor; - struct WriteImageFunctor; - struct WriteHeightFieldFunctor; - struct WriteNodeFunctor; - - - ReaderWriter::ReadResult read(const ReadFunctor& readFunctor); - ReaderWriter::WriteResult write(const WriteFunctor& writeFunctor); - - typedef std::list< osg::ref_ptr > IndexBlockList; - - void writeIndexBlocks(); - - bool addFileReference(pos_type position, size_type size, const std::string& fileName); - - static float s_currentSupportedVersion; - float _version; - ArchiveStatus _status; - std::ifstream _input; - std::fstream _output; - - std::string _masterFileName; - IndexBlockList _indexBlockList; - FileNamePositionMap _indexMap; + virtual WriteResult writeObject(const osg::Object& /*obj*/,const std::string& /*fileName*/,const Options* =NULL) = 0; + virtual WriteResult writeImage(const osg::Image& /*image*/,const std::string& /*fileName*/,const Options* =NULL) = 0; + virtual WriteResult writeHeightField(const osg::HeightField& /*heightField*/,const std::string& /*fileName*/,const Options* =NULL) = 0; + virtual WriteResult writeNode(const osg::Node& /*node*/,const std::string& /*fileName*/,const Options* =NULL) = 0; + }; diff --git a/src/osgDB/Archive.cpp b/src/osgDB/Archive.cpp index 4828e59a3..e5d9fe305 100644 --- a/src/osgDB/Archive.cpp +++ b/src/osgDB/Archive.cpp @@ -22,9 +22,6 @@ using namespace osgDB; -float Archive::s_currentSupportedVersion = 0.0; -const unsigned int ENDIAN_TEST_NUMBER = 0x00000001; - osgDB::Archive* osgDB::openArchive(const std::string& filename, Archive::ArchiveStatus status, unsigned int indexBlockSizeHint) { return openArchive(filename, status, indexBlockSizeHint, Registry::instance()->getUseObjectCacheHint()); @@ -36,673 +33,11 @@ osgDB::Archive* osgDB::openArchive(const std::string& filename, Archive::Archive return result.takeArchive(); } -Archive::IndexBlock::IndexBlock(unsigned int blockSize): - _requiresWrite(false), - _filePosition(0), - _blockSize(0), - _filePositionNextIndexBlock(0), - _offsetOfNextAvailableSpace(0), - _data(0) -{ - allocateData(blockSize); -} - -Archive::IndexBlock::~IndexBlock() -{ - delete [] _data; -} - -void Archive::IndexBlock::allocateData(unsigned int blockSize) -{ - _data = (blockSize!=0) ? new char[blockSize] : 0; - if (_data) - { - _blockSize = blockSize; - - // initialize the array - char* end = _data + _blockSize; - for(char* ptr=_data; ptr < end; ++ptr) *ptr = 0; - } - else - { - _blockSize = 0; - } -} - -Archive::IndexBlock* Archive::IndexBlock::read(std::istream& in, bool doEndianSwap) -{ - if (!in) return 0; - - osg::ref_ptr indexBlock = new IndexBlock; - indexBlock->_filePosition = in.tellg(); - in.read(reinterpret_cast(&indexBlock->_blockSize), sizeof(indexBlock->_blockSize)); - in.read(reinterpret_cast(&indexBlock->_filePositionNextIndexBlock), sizeof(indexBlock->_filePositionNextIndexBlock)); - in.read(reinterpret_cast(&indexBlock->_offsetOfNextAvailableSpace), sizeof(indexBlock-> _offsetOfNextAvailableSpace)); - - if (doEndianSwap) - { - osg::swapBytes(reinterpret_cast(&indexBlock->_blockSize), sizeof(indexBlock->_blockSize)); - osg::swapBytes(reinterpret_cast(&indexBlock->_filePositionNextIndexBlock), sizeof(indexBlock->_filePositionNextIndexBlock)); - osg::swapBytes(reinterpret_cast(&indexBlock->_offsetOfNextAvailableSpace), sizeof(indexBlock-> _offsetOfNextAvailableSpace)); - } - - osg::notify(osg::NOTICE)<<"indexBlock->_blockSize="<_blockSize<_filePositionNextIndexBlock="<_filePositionNextIndexBlock<_offsetOfNextAvailableSpace="<_offsetOfNextAvailableSpace<allocateData(indexBlock->_blockSize); - if (indexBlock->_data) - { - in.read(reinterpret_cast(indexBlock->_data),indexBlock->_blockSize); - - if (doEndianSwap) - { - char* ptr = indexBlock->_data; - char* end_ptr = indexBlock->_data + indexBlock->_offsetOfNextAvailableSpace; - while (ptr(ptr)); - ptr += sizeof(unsigned int); - ptr += filename_size; - - osg::notify(osg::NOTICE)<<"filename size="<(ptr)); - ptr += sizeof(unsigned int); - - return std::string(ptr, ptr+filename_size); - } - else - { - return std::string(); - } -} - -bool Archive::IndexBlock::getFileReferences(FileNamePositionMap& indexMap) const -{ - if (!_data || _offsetOfNextAvailableSpace==0) return false; - - bool valuesAdded = false; - - char* ptr = _data; - char* end_ptr = _data + _offsetOfNextAvailableSpace; - while (ptr(ptr)); - ptr += sizeof(pos_type); - - size_type size = *(reinterpret_cast(ptr)); - ptr += sizeof(size_type); - - unsigned int filename_size = *(reinterpret_cast(ptr)); - ptr += sizeof(unsigned int); - - std::string filename(ptr, ptr+filename_size); - - // record this entry into the FileNamePositionMap - indexMap[filename] = PositionSizePair(position,size); - - ptr += filename_size; - - valuesAdded = true; - } - return valuesAdded; -} - -void Archive::IndexBlock::write(std::ostream& out) -{ - if (_filePosition==pos_type(0)) - { - osg::notify(osg::INFO)<<"Archive::IndexBlock::write() setting _filePosition"<(&_blockSize), sizeof(_blockSize)); - out.write(reinterpret_cast(&_filePositionNextIndexBlock), sizeof(_filePositionNextIndexBlock)); - out.write(reinterpret_cast(&_offsetOfNextAvailableSpace), sizeof(_offsetOfNextAvailableSpace)); - - out.write(reinterpret_cast(_data),_blockSize); - - osg::notify(osg::INFO)<<"Archive::IndexBlock::write() end"<(ptr)) = position; - ptr += sizeof(pos_type); - - *(reinterpret_cast(ptr)) = size; - ptr += sizeof(size_type); - - *(reinterpret_cast(ptr)) = filename.size(); - ptr += sizeof(unsigned int); - - for(unsigned int i=0;i(&endianTestWord),4); - bool doEndianSwap = (endianTestWord!=ENDIAN_TEST_NUMBER); - - _input.read(reinterpret_cast(&_version),sizeof(_version)); - if (doEndianSwap) - { - osg::swapBytes(reinterpret_cast(&_version),sizeof(_version)); - } - - osg::notify(osg::NOTICE)<<"Archive::open() doEndianSwap="<getFirstFileName(); - } - - for(IndexBlockList::iterator itr=_indexBlockList.begin(); - itr!=_indexBlockList.end(); - ++itr) - { - (*itr)->getFileReferences(_indexMap); - } - - for(FileNamePositionMap::iterator mitr=_indexMap.begin(); - mitr!=_indexMap.end(); - ++mitr) - { - osg::notify(osg::INFO)<<" filename "<<(mitr->first)<<" pos="<<(int)((mitr->second).first)<<" size="<<(int)((mitr->second).second)<(&ENDIAN_TEST_NUMBER),4); - _output.write(reinterpret_cast(&s_currentSupportedVersion),sizeof(float)); - - IndexBlock *indexBlock = new IndexBlock(indexBlockSize); - if (indexBlock) - { - indexBlock->write(_output); - _indexBlockList.push_back(indexBlock); - } - - osg::notify(osg::INFO)<<"File position after write = "<<(int)_output.tellp()< indexBlock = _indexBlockList.empty() ? 0 : _indexBlockList.back(); - osg::ref_ptr previousBlock = indexBlock; - if (indexBlock.valid()) - { - blockSize = indexBlock->getBlockSize(); - if (!(indexBlock->spaceAvailable(position, size, fileName))) - { - previousBlock = indexBlock; - indexBlock = 0; - } - } - - // if not one available create a new block. - if (!indexBlock) - { - osg::notify(osg::NOTICE)<<"Creating new block"<setPositionNextIndexBlock(_output.tellp()); - - indexBlock = new IndexBlock(blockSize); - indexBlock->write(_output); - _indexBlockList.push_back(indexBlock.get()); - } - - if (indexBlock.valid()) - { - return indexBlock->addFileReference(position, size, fileName); - } - return false; -} - - - -class proxy_streambuf : public std::streambuf -{ - public: - - proxy_streambuf(std::streambuf* streambuf, unsigned int numChars): - _streambuf(streambuf), - _numChars(numChars), - value_peeked(false), - peek_value(0) {} - - /// Destructor deallocates no buffer space. - virtual ~proxy_streambuf() {} - - std::streambuf* _streambuf; - unsigned int _numChars; - - bool value_peeked; - int_type peek_value; - - protected: - - virtual int_type uflow () - { - if (_numChars==0) return -1; - - --_numChars; - - int_type val = value_peeked ? peek_value : _streambuf->sbumpc(); - value_peeked = false; - - return val; - } - - virtual int_type - underflow() - { - if (value_peeked) return peek_value; - - value_peeked = true; - peek_value = _streambuf->sbumpc(); - return peek_value; - } -}; - -struct Archive::ReadObjectFunctor : public Archive::ReadFunctor -{ - ReadObjectFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {} - virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input) const { return rw.readObject(input, _options); } -}; - -struct Archive::ReadImageFunctor : public Archive::ReadFunctor -{ - ReadImageFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {} - virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input)const { return rw.readImage(input, _options); } -}; - -struct Archive::ReadHeightFieldFunctor : public Archive::ReadFunctor -{ - ReadHeightFieldFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {} - virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input) const { return rw.readHeightField(input, _options); } -}; - -struct Archive::ReadNodeFunctor : public Archive::ReadFunctor -{ - ReadNodeFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {} - virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input) const { return rw.readNode(input, _options); } -}; - -ReaderWriter::ReadResult Archive::read(const ReadFunctor& readFunctor) -{ - if (_status!=READ) - { - osg::notify(osg::INFO)<<"Archive::readObject(obj, "<getReaderWriterForExtension(getLowerCaseFileExtension(readFunctor._filename)); - if (!rw) - { - osg::notify(osg::INFO)<<"Archive::readObject(obj, "<second.first); - - // set up proxy stream buffer to proide the faked ending. - std::istream& ins = _input; - proxy_streambuf mystreambuf(ins.rdbuf(),itr->second.second); - ins.rdbuf(&mystreambuf); - - ReaderWriter::ReadResult result = readFunctor.doRead(*rw, _input); - - ins.rdbuf(mystreambuf._streambuf); - - return result; -} - -ReaderWriter::ReadResult Archive::readObject(const std::string& fileName,const Options* options) -{ - return read(ReadObjectFunctor(fileName, options)); -} - -ReaderWriter::ReadResult Archive::readImage(const std::string& fileName,const Options* options) -{ - return read(ReadImageFunctor(fileName, options)); -} - -ReaderWriter::ReadResult Archive::readHeightField(const std::string& fileName,const Options* options) -{ - return read(ReadHeightFieldFunctor(fileName, options)); -} - -ReaderWriter::ReadResult Archive::readNode(const std::string& fileName,const Options* options) -{ - return read(ReadNodeFunctor(fileName, options)); -} - - -struct Archive::WriteObjectFunctor : public Archive::WriteFunctor -{ - WriteObjectFunctor(const osg::Object& object, const std::string& filename, const ReaderWriter::Options* options): - WriteFunctor(filename,options), - _object(object) {} - const osg::Object& _object; - - virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeObject(_object, output, _options); } -}; - -struct Archive::WriteImageFunctor : public Archive::WriteFunctor -{ - WriteImageFunctor(const osg::Image& object, const std::string& filename, const ReaderWriter::Options* options): - WriteFunctor(filename,options), - _object(object) {} - const osg::Image& _object; - - virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output)const { return rw.writeImage(_object, output, _options); } -}; - -struct Archive::WriteHeightFieldFunctor : public Archive::WriteFunctor -{ - WriteHeightFieldFunctor(const osg::HeightField& object, const std::string& filename, const ReaderWriter::Options* options): - WriteFunctor(filename,options), - _object(object) {} - const osg::HeightField& _object; - - virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeHeightField(_object, output, _options); } -}; - -struct Archive::WriteNodeFunctor : public Archive::WriteFunctor -{ - WriteNodeFunctor(const osg::Node& object, const std::string& filename, const ReaderWriter::Options* options): - WriteFunctor(filename,options), - _object(object) {} - const osg::Node& _object; - - virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeNode(_object, output, _options); } -}; - -ReaderWriter::WriteResult Archive::write(const WriteFunctor& writeFunctor) -{ - if (_status!=WRITE) - { - osg::notify(osg::NOTICE)<<"Archive::write(obj, "<getReaderWriterForExtension(getLowerCaseFileExtension(writeFunctor._filename)); - if (!rw) - { - osg::notify(osg::NOTICE)<<"Archive::write(obj, "< +#include + +#include +#include + +#include "OSGA_Archive.h" + +using namespace osgDB; + +float OSGA_Archive::s_currentSupportedVersion = 0.0; +const unsigned int ENDIAN_TEST_NUMBER = 0x00000001; + +OSGA_Archive::IndexBlock::IndexBlock(unsigned int blockSize): + _requiresWrite(false), + _filePosition(0), + _blockSize(0), + _filePositionNextIndexBlock(0), + _offsetOfNextAvailableSpace(0), + _data(0) +{ + allocateData(blockSize); +} + +OSGA_Archive::IndexBlock::~IndexBlock() +{ + delete [] _data; +} + +void OSGA_Archive::IndexBlock::allocateData(unsigned int blockSize) +{ + _data = (blockSize!=0) ? new char[blockSize] : 0; + if (_data) + { + _blockSize = blockSize; + + // initialize the array + char* end = _data + _blockSize; + for(char* ptr=_data; ptr < end; ++ptr) *ptr = 0; + } + else + { + _blockSize = 0; + } +} + +OSGA_Archive::IndexBlock* OSGA_Archive::IndexBlock::read(std::istream& in, bool doEndianSwap) +{ + if (!in) return 0; + + osg::ref_ptr indexBlock = new IndexBlock; + indexBlock->_filePosition = in.tellg(); + in.read(reinterpret_cast(&indexBlock->_blockSize), sizeof(indexBlock->_blockSize)); + in.read(reinterpret_cast(&indexBlock->_filePositionNextIndexBlock), sizeof(indexBlock->_filePositionNextIndexBlock)); + in.read(reinterpret_cast(&indexBlock->_offsetOfNextAvailableSpace), sizeof(indexBlock-> _offsetOfNextAvailableSpace)); + + if (doEndianSwap) + { + osg::swapBytes(reinterpret_cast(&indexBlock->_blockSize), sizeof(indexBlock->_blockSize)); + osg::swapBytes(reinterpret_cast(&indexBlock->_filePositionNextIndexBlock), sizeof(indexBlock->_filePositionNextIndexBlock)); + osg::swapBytes(reinterpret_cast(&indexBlock->_offsetOfNextAvailableSpace), sizeof(indexBlock-> _offsetOfNextAvailableSpace)); + } + + osg::notify(osg::INFO)<<"indexBlock->_blockSize="<_blockSize<_filePositionNextIndexBlock="<_filePositionNextIndexBlock<_offsetOfNextAvailableSpace="<_offsetOfNextAvailableSpace<allocateData(indexBlock->_blockSize); + if (indexBlock->_data) + { + in.read(reinterpret_cast(indexBlock->_data),indexBlock->_blockSize); + + if (doEndianSwap) + { + char* ptr = indexBlock->_data; + char* end_ptr = indexBlock->_data + indexBlock->_offsetOfNextAvailableSpace; + while (ptr(ptr)); + ptr += sizeof(unsigned int); + ptr += filename_size; + + osg::notify(osg::INFO)<<"filename size="<(ptr)); + ptr += sizeof(unsigned int); + + return std::string(ptr, ptr+filename_size); + } + else + { + return std::string(); + } +} + +bool OSGA_Archive::IndexBlock::getFileReferences(FileNamePositionMap& indexMap) const +{ + if (!_data || _offsetOfNextAvailableSpace==0) return false; + + bool valuesAdded = false; + + char* ptr = _data; + char* end_ptr = _data + _offsetOfNextAvailableSpace; + while (ptr(ptr)); + ptr += sizeof(pos_type); + + size_type size = *(reinterpret_cast(ptr)); + ptr += sizeof(size_type); + + unsigned int filename_size = *(reinterpret_cast(ptr)); + ptr += sizeof(unsigned int); + + std::string filename(ptr, ptr+filename_size); + + // record this entry into the FileNamePositionMap + indexMap[filename] = PositionSizePair(position,size); + + ptr += filename_size; + + valuesAdded = true; + } + return valuesAdded; +} + +void OSGA_Archive::IndexBlock::write(std::ostream& out) +{ + if (_filePosition==pos_type(0)) + { + osg::notify(osg::INFO)<<"OSGA_Archive::IndexBlock::write() setting _filePosition"<(&_blockSize), sizeof(_blockSize)); + out.write(reinterpret_cast(&_filePositionNextIndexBlock), sizeof(_filePositionNextIndexBlock)); + out.write(reinterpret_cast(&_offsetOfNextAvailableSpace), sizeof(_offsetOfNextAvailableSpace)); + + out.write(reinterpret_cast(_data),_blockSize); + + osg::notify(osg::INFO)<<"OSGA_Archive::IndexBlock::write() end"<(ptr)) = position; + ptr += sizeof(pos_type); + + *(reinterpret_cast(ptr)) = size; + ptr += sizeof(size_type); + + *(reinterpret_cast(ptr)) = filename.size(); + ptr += sizeof(unsigned int); + + for(unsigned int i=0;i(&endianTestWord),4); + bool doEndianSwap = (endianTestWord!=ENDIAN_TEST_NUMBER); + + _input.read(reinterpret_cast(&_version),sizeof(_version)); + if (doEndianSwap) + { + osg::swapBytes(reinterpret_cast(&_version),sizeof(_version)); + } + + osg::notify(osg::INFO)<<"OSGA_Archive::open() doEndianSwap="<getFirstFileName(); + } + + for(IndexBlockList::iterator itr=_indexBlockList.begin(); + itr!=_indexBlockList.end(); + ++itr) + { + (*itr)->getFileReferences(_indexMap); + } + + for(FileNamePositionMap::iterator mitr=_indexMap.begin(); + mitr!=_indexMap.end(); + ++mitr) + { + osg::notify(osg::INFO)<<" filename "<<(mitr->first)<<" pos="<<(int)((mitr->second).first)<<" size="<<(int)((mitr->second).second)<(&ENDIAN_TEST_NUMBER),4); + _output.write(reinterpret_cast(&s_currentSupportedVersion),sizeof(float)); + + IndexBlock *indexBlock = new IndexBlock(indexBlockSize); + if (indexBlock) + { + indexBlock->write(_output); + _indexBlockList.push_back(indexBlock); + } + + osg::notify(osg::INFO)<<"File position after write = "<<(int)_output.tellp()< indexBlock = _indexBlockList.empty() ? 0 : _indexBlockList.back(); + osg::ref_ptr previousBlock = indexBlock; + if (indexBlock.valid()) + { + blockSize = indexBlock->getBlockSize(); + if (!(indexBlock->spaceAvailable(position, size, fileName))) + { + previousBlock = indexBlock; + indexBlock = 0; + } + } + + // if not one available create a new block. + if (!indexBlock) + { + if (previousBlock.valid()) previousBlock->setPositionNextIndexBlock(_output.tellp()); + + indexBlock = new IndexBlock(blockSize); + indexBlock->write(_output); + _indexBlockList.push_back(indexBlock.get()); + } + + if (indexBlock.valid()) + { + return indexBlock->addFileReference(position, size, fileName); + } + return false; +} + + + +class proxy_streambuf : public std::streambuf +{ + public: + + proxy_streambuf(std::streambuf* streambuf, unsigned int numChars): + _streambuf(streambuf), + _numChars(numChars), + value_peeked(false), + peek_value(0) {} + + /// Destructor deallocates no buffer space. + virtual ~proxy_streambuf() {} + + std::streambuf* _streambuf; + unsigned int _numChars; + + bool value_peeked; + int_type peek_value; + + protected: + + virtual int_type uflow () + { + if (_numChars==0) return -1; + + --_numChars; + + int_type val = value_peeked ? peek_value : _streambuf->sbumpc(); + value_peeked = false; + + return val; + } + + virtual int_type + underflow() + { + if (value_peeked) return peek_value; + + value_peeked = true; + peek_value = _streambuf->sbumpc(); + return peek_value; + } +}; + +struct OSGA_Archive::ReadObjectFunctor : public OSGA_Archive::ReadFunctor +{ + ReadObjectFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {} + virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input) const { return rw.readObject(input, _options); } +}; + +struct OSGA_Archive::ReadImageFunctor : public OSGA_Archive::ReadFunctor +{ + ReadImageFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {} + virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input)const { return rw.readImage(input, _options); } +}; + +struct OSGA_Archive::ReadHeightFieldFunctor : public OSGA_Archive::ReadFunctor +{ + ReadHeightFieldFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {} + virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input) const { return rw.readHeightField(input, _options); } +}; + +struct OSGA_Archive::ReadNodeFunctor : public OSGA_Archive::ReadFunctor +{ + ReadNodeFunctor(const std::string& filename, const ReaderWriter::Options* options):ReadFunctor(filename,options) {} + virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input) const { return rw.readNode(input, _options); } +}; + +ReaderWriter::ReadResult OSGA_Archive::read(const ReadFunctor& readFunctor) +{ + if (_status!=READ) + { + osg::notify(osg::INFO)<<"OSGA_Archive::readObject(obj, "<getReaderWriterForExtension(getLowerCaseFileExtension(readFunctor._filename)); + if (!rw) + { + osg::notify(osg::INFO)<<"OSGA_Archive::readObject(obj, "<second.first); + + // set up proxy stream buffer to proide the faked ending. + std::istream& ins = _input; + proxy_streambuf mystreambuf(ins.rdbuf(),itr->second.second); + ins.rdbuf(&mystreambuf); + + ReaderWriter::ReadResult result = readFunctor.doRead(*rw, _input); + + ins.rdbuf(mystreambuf._streambuf); + + return result; +} + +ReaderWriter::ReadResult OSGA_Archive::readObject(const std::string& fileName,const Options* options) +{ + return read(ReadObjectFunctor(fileName, options)); +} + +ReaderWriter::ReadResult OSGA_Archive::readImage(const std::string& fileName,const Options* options) +{ + return read(ReadImageFunctor(fileName, options)); +} + +ReaderWriter::ReadResult OSGA_Archive::readHeightField(const std::string& fileName,const Options* options) +{ + return read(ReadHeightFieldFunctor(fileName, options)); +} + +ReaderWriter::ReadResult OSGA_Archive::readNode(const std::string& fileName,const Options* options) +{ + return read(ReadNodeFunctor(fileName, options)); +} + + +struct OSGA_Archive::WriteObjectFunctor : public OSGA_Archive::WriteFunctor +{ + WriteObjectFunctor(const osg::Object& object, const std::string& filename, const ReaderWriter::Options* options): + WriteFunctor(filename,options), + _object(object) {} + const osg::Object& _object; + + virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeObject(_object, output, _options); } +}; + +struct OSGA_Archive::WriteImageFunctor : public OSGA_Archive::WriteFunctor +{ + WriteImageFunctor(const osg::Image& object, const std::string& filename, const ReaderWriter::Options* options): + WriteFunctor(filename,options), + _object(object) {} + const osg::Image& _object; + + virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output)const { return rw.writeImage(_object, output, _options); } +}; + +struct OSGA_Archive::WriteHeightFieldFunctor : public OSGA_Archive::WriteFunctor +{ + WriteHeightFieldFunctor(const osg::HeightField& object, const std::string& filename, const ReaderWriter::Options* options): + WriteFunctor(filename,options), + _object(object) {} + const osg::HeightField& _object; + + virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeHeightField(_object, output, _options); } +}; + +struct OSGA_Archive::WriteNodeFunctor : public OSGA_Archive::WriteFunctor +{ + WriteNodeFunctor(const osg::Node& object, const std::string& filename, const ReaderWriter::Options* options): + WriteFunctor(filename,options), + _object(object) {} + const osg::Node& _object; + + virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const { return rw.writeNode(_object, output, _options); } +}; + +ReaderWriter::WriteResult OSGA_Archive::write(const WriteFunctor& writeFunctor) +{ + if (_status!=WRITE) + { + osg::notify(osg::INFO)<<"OSGA_Archive::write(obj, "<getReaderWriterForExtension(getLowerCaseFileExtension(writeFunctor._filename)); + if (!rw) + { + osg::notify(osg::INFO)<<"OSGA_Archive::write(obj, "< +#include +#include + +class OSGA_Archive : public osgDB::Archive +{ + public: + OSGA_Archive(); + virtual ~OSGA_Archive(); + + virtual const char* libraryName() const { return "osga"; } + + virtual const char* className() const { return "Archive"; } + + virtual bool acceptsExtension(const std::string& extension) + { + return osgDB::equalCaseInsensitive(extension,"osga"); + } + + /** open the archive.*/ + virtual bool open(const std::string& filename, ArchiveStatus status, unsigned int indexBlockSizeHint=4096); + + /** close the archive.*/ + virtual void close(); + + /** return true if file exists in archive.*/ + virtual bool fileExists(const std::string& filename) const; + + /** Get the file name which represents the master file recorded in the Archive.*/ + virtual std::string getMasterFileName() const; + + typedef std::vector FileNameList; + + /** Get the full list of file names available in the archive.*/ + virtual bool getFileNames(FileNameList& fileNameList) const; + + + /** Read an osg::Object of specified file name from the Archive.*/ + virtual ReadResult readObject(const std::string& fileName,const Options* options=NULL); + + /** Read an osg::Image of specified file name from the Archive.*/ + virtual ReadResult readImage(const std::string& fileName,const Options* options=NULL); + + /** Read an osg::HeightField of specified file name from the Archive.*/ + virtual ReadResult readHeightField(const std::string& fileName,const Options* options=NULL); + + /** Read an osg::Node of specified file name from the Archive.*/ + virtual ReadResult readNode(const std::string& fileName,const Options* options=NULL); + + /** Write an osg::Object with specified file name to the Archive.*/ + virtual WriteResult writeObject(const osg::Object& obj,const std::string& fileName,const Options* options=NULL); + + /** Write an osg::Image with specified file name to the Archive.*/ + virtual WriteResult writeImage(const osg::Image& image,const std::string& fileName,const Options* options=NULL); + + /** Write an osg::HeightField with specified file name to the Archive.*/ + virtual WriteResult writeHeightField(const osg::HeightField& heightField,const std::string& fileName,const Options* options=NULL); + + /** Write an osg::Node with specified file name to the Archive.*/ + virtual WriteResult writeNode(const osg::Node& node,const std::string& fileName,const Options* options=NULL); + + + protected: + + #if defined(_MSC_VER) + typedef __int64 pos_type; + typedef __int64 size_type; + #else + typedef unsigned long long pos_type; + typedef unsigned long long size_type; + #endif + + typedef std::pair PositionSizePair; + typedef std::map FileNamePositionMap; + + class IndexBlock : public osg::Referenced + { + public: + IndexBlock(unsigned int blockSize=0); + + inline pos_type getPosition() const { return _filePosition; } + + inline unsigned int getBlockSize() const { return _blockSize; } + + + void setPositionNextIndexBlock(pos_type position); + + inline pos_type getPositionNextIndexBlock() const { return _filePositionNextIndexBlock; } + + + static IndexBlock* read(std::istream& in, bool doEndianSwap); + + std::string getFirstFileName() const; + + bool getFileReferences(FileNamePositionMap& indexMap) const; + + + inline bool requiresWrite() const { return _requiresWrite; } + + void write(std::ostream& out); + + inline bool spaceAvailable(pos_type, size_type, const std::string& filename) const + { + unsigned requiredSize = sizeof(pos_type)+sizeof(size_type)+sizeof(unsigned int)+filename.size(); + return (_offsetOfNextAvailableSpace + requiredSize)<_blockSize; + } + + bool addFileReference(pos_type position, size_type size, const std::string& filename); + + + + protected: + + void allocateData(unsigned int blockSize); + + virtual ~IndexBlock(); + bool _requiresWrite; + pos_type _filePosition; + + unsigned int _blockSize; + pos_type _filePositionNextIndexBlock; + unsigned int _offsetOfNextAvailableSpace; + char* _data; + }; + + /** Functor used in internal implementations.*/ + struct ReadFunctor + { + ReadFunctor(const std::string& filename, const ReaderWriter::Options* options): + _filename(filename), + _options(options) {} + + virtual ~ReadFunctor() {} + virtual ReaderWriter::ReadResult doRead(ReaderWriter& rw, std::istream& input) const = 0; + + std::string _filename; + const ReaderWriter::Options* _options; + }; + + struct ReadObjectFunctor; + struct ReadImageFunctor; + struct ReadHeightFieldFunctor; + struct ReadNodeFunctor; + + /** Functor used in internal implementations.*/ + struct WriteFunctor + { + WriteFunctor(const std::string& filename, const ReaderWriter::Options* options): + _filename(filename), + _options(options) {} + + virtual ~WriteFunctor() {} + virtual ReaderWriter::WriteResult doWrite(ReaderWriter& rw, std::ostream& output) const = 0; + + std::string _filename; + const ReaderWriter::Options* _options; + }; + + struct WriteObjectFunctor; + struct WriteImageFunctor; + struct WriteHeightFieldFunctor; + struct WriteNodeFunctor; + + + ReaderWriter::ReadResult read(const ReadFunctor& readFunctor); + ReaderWriter::WriteResult write(const WriteFunctor& writeFunctor); + + typedef std::list< osg::ref_ptr > IndexBlockList; + + void writeIndexBlocks(); + + bool addFileReference(pos_type position, size_type size, const std::string& fileName); + + static float s_currentSupportedVersion; + float _version; + ArchiveStatus _status; + std::ifstream _input; + std::fstream _output; + + std::string _masterFileName; + IndexBlockList _indexBlockList; + FileNamePositionMap _indexMap; + + +}; diff --git a/src/osgPlugins/osga/ReaderWriterOSGA.cpp b/src/osgPlugins/osga/ReaderWriterOSGA.cpp index 3b61aed67..a9b928519 100644 --- a/src/osgPlugins/osga/ReaderWriterOSGA.cpp +++ b/src/osgPlugins/osga/ReaderWriterOSGA.cpp @@ -2,7 +2,9 @@ #include #include -#include + +#include "OSGA_Archive.h" + class ReaderWriterOSGA : public osgDB::ReaderWriter { @@ -23,7 +25,7 @@ public: std::string fileName = osgDB::findDataFile( file ); if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; - osg::ref_ptr archive = new osgDB::Archive; + osg::ref_ptr archive = new OSGA_Archive; if (!archive->open(fileName, status, indexBlockSize)) { return ReadResult(ReadResult::FILE_NOT_HANDLED); diff --git a/src/osgTerrain/DataSet.cpp b/src/osgTerrain/DataSet.cpp index d6eb4c1d5..5e1cdcb71 100644 --- a/src/osgTerrain/DataSet.cpp +++ b/src/osgTerrain/DataSet.cpp @@ -3895,8 +3895,8 @@ void DataSet::_buildDestination(bool writeToDisk) if (!_archive && !_archiveName.empty()) { - _archive = new osgDB::Archive; - _archive->open(_archiveName, osgDB::Archive::CREATE); + unsigned int indexBlockSizeHint=4096; + _archive = openArchive(_archiveName, osgDB::Archive::CREATE, indexBlockSizeHint); } if (_destinationGraph.valid())