From 61b0f5d301a20d7a951d12f63caae9161dd1970f Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 27 Oct 2004 14:09:24 +0000 Subject: [PATCH] Added IndexBlock inner class to osgDB::Archive --- include/osgDB/Archive | 68 +++++++++++++- src/osgDB/Archive.cpp | 202 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 265 insertions(+), 5 deletions(-) diff --git a/include/osgDB/Archive b/include/osgDB/Archive index a6fb864ae..18446435f 100644 --- a/include/osgDB/Archive +++ b/include/osgDB/Archive @@ -17,6 +17,7 @@ #include #include +#include namespace osgDB { @@ -67,14 +68,75 @@ class OSGDB_EXPORT Archive : public ReaderWriter protected: - typedef std::istream::pos_type pos_type; - - typedef std::map FileNamePositionMap; + typedef std::istream::pos_type pos_type; + 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; } + + + void read(std::istream& in); + + bool getFileReferences(FileNamePositionMap& indexMap); + + + inline bool requiresWrite() const { return _requiresWrite; } + + void write(std::ostream& out); + + inline bool spaceAvailable(pos_type position, const std::string& filename) const + { + unsigned requiredSize = sizeof(position)+sizeof(unsigned int)+filename.size(); + return (_offsetOfNextAvailableSpace + requiredSize)<_blockSize; + } + + bool addFileReference(pos_type position, 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; + unsigned char* _data; + }; + + + + typedef std::list< osg::ref_ptr > IndexBlockList; + + void readIndexBlocks(); + + void writeIndexBlocks(); + + bool addFileReference(pos_type position, const std::string& fileName); + + static float s_currentSupportedVersion; + float _version; Status _status; std::ifstream _input; std::ofstream _output; + IndexBlockList _indexBlockList; FileNamePositionMap _indexMap; diff --git a/src/osgDB/Archive.cpp b/src/osgDB/Archive.cpp index fa6caf36c..8b0e45d7e 100644 --- a/src/osgDB/Archive.cpp +++ b/src/osgDB/Archive.cpp @@ -19,6 +19,129 @@ using namespace osgDB; +float Archive::s_currentSupportedVersion = 0.0; + +Archive::IndexBlock::IndexBlock(unsigned int blockSize): + _requiresWrite(false), + _filePosition(0), + _blockSize(0), + _offsetOfNextAvailableSpace(0), + _data(0) +{ + allocateData(blockSize); +} + +Archive::IndexBlock::~IndexBlock() +{ + delete [] _data; +} + +void Archive::IndexBlock::allocateData(unsigned int blockSize) +{ + _data = (blockSize!=0) ? new unsigned char[blockSize] : 0; + if (_data) + { + _blockSize = blockSize; + + // initialize the array + unsigned char* end = _data + _blockSize; + for(unsigned char* ptr=_data; ptr < end; ++ptr) *ptr = 0; + } + else + { + _blockSize = 0; + } +} + +void Archive::IndexBlock::read(std::istream& in) +{ + _filePosition = in.tellg(); + in.read(reinterpret_cast(&_blockSize), sizeof(_blockSize)); + in.read(reinterpret_cast(&_filePositionNextIndexBlock), sizeof(_filePositionNextIndexBlock)); + in.read(reinterpret_cast(&_offsetOfNextAvailableSpace), sizeof(_offsetOfNextAvailableSpace)); + + allocateData(_blockSize); + if (_data) + { + in.read(reinterpret_cast(_data),_blockSize); + } + else + { + osg::notify(osg::NOTICE)<<"Allocation Problem in Archive::IndexBlock::read(std::istream& in)"<(ptr)); + ptr += sizeof(pos_type); + + unsigned int filename_size = *(reinterpret_cast(ptr)); + ptr += sizeof(unsigned int); + + std::string filename(ptr, ptr+filename_size); + + ptr += filename_size; + } +} + +void Archive::IndexBlock::write(std::ostream& out) +{ + if (_filePosition==pos_type(0)) + { + _filePosition = out.tellp(); + } + else + { + out.seekp(_filePosition); + } + + out.write(reinterpret_cast(&_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::NOTICE)<<"Archive::IndexBlock::write()"<(ptr)) = position; + ptr += sizeof(pos_type); + + *(reinterpret_cast(ptr)) = filename.size(); + ptr += sizeof(unsigned int); + + for(unsigned int i=0;i(&s_currentSupportedVersion),sizeof(float)); + + IndexBlock *indexBlock = new IndexBlock(indexBlockSize); + if (indexBlock) + { + indexBlock->write(_output); + _indexBlockList.push_back(indexBlock); + } } void Archive::open(const std::string& filename, Status status) @@ -51,7 +183,20 @@ void Archive::open(const std::string& filename, Status status) void Archive::close() { _input.close(); - _output.close(); + + if (_status==WRITE) + { + for(IndexBlockList::iterator itr=_indexBlockList.begin(); + itr!=_indexBlockList.end(); + ++itr) + { + if ((*itr)->requiresWrite()) + { + (*itr)->write(_output); + } + } + _output.close(); + } } @@ -60,6 +205,52 @@ bool Archive::fileExists(const std::string& filename) const return (_indexMap.count(filename)!=0); } +bool Archive::addFileReference(pos_type position, const std::string& fileName) +{ + if (_status==READ) + { + osg::notify(osg::NOTICE)<<"Archive::getPositionForNewEntry("< indexBlock = _indexBlockList.empty() ? 0 : _indexBlockList.back(); + osg::ref_ptr previousBlock = indexBlock; + if (indexBlock.valid()) + { + blockSize = indexBlock->getBlockSize(); + if (!(indexBlock->spaceAvailable(position, 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, fileName); + } + return false; +} + + ReaderWriter::ReadResult Archive::readObject(const std::string& fileName,const Options* options) { if (_status!=READ) @@ -109,7 +300,14 @@ ReaderWriter::WriteResult Archive::writeObject(const osg::Object& obj,const std: } osg::notify(osg::NOTICE)<<"Archive::writeObject(obj, "<writeObject(obj, _output, options); + + pos_type position = _output.tellp(); + + WriteResult result = rw->writeObject(obj, _output, options); + + if (result.success()) addFileReference(position, fileName); + + return result; } ReaderWriter::WriteResult Archive::writeImage(const osg::Image& /*image*/,const std::string& fileName,const Options* options)