Added IndexBlock inner class to osgDB::Archive
This commit is contained in:
@@ -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<char*>(&_blockSize), sizeof(_blockSize));
|
||||
in.read(reinterpret_cast<char*>(&_filePositionNextIndexBlock), sizeof(_filePositionNextIndexBlock));
|
||||
in.read(reinterpret_cast<char*>(&_offsetOfNextAvailableSpace), sizeof(_offsetOfNextAvailableSpace));
|
||||
|
||||
allocateData(_blockSize);
|
||||
if (_data)
|
||||
{
|
||||
in.read(reinterpret_cast<char*>(_data),_blockSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Allocation Problem in Archive::IndexBlock::read(std::istream& in)"<<std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Archive::IndexBlock::getFileReferences(FileNamePositionMap& indexMap)
|
||||
{
|
||||
if (!_data || _offsetOfNextAvailableSpace==0) return false;
|
||||
unsigned char* ptr = _data;
|
||||
unsigned char* end_ptr = _data + _offsetOfNextAvailableSpace;
|
||||
while (ptr<end_ptr)
|
||||
{
|
||||
pos_type position = *(reinterpret_cast<pos_type*>(ptr));
|
||||
ptr += sizeof(pos_type);
|
||||
|
||||
unsigned int filename_size = *(reinterpret_cast<unsigned int*>(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<char*>(&_blockSize), sizeof(_blockSize));
|
||||
out.write(reinterpret_cast<char*>(&_filePositionNextIndexBlock), sizeof(_filePositionNextIndexBlock));
|
||||
out.write(reinterpret_cast<char*>(&_offsetOfNextAvailableSpace), sizeof(_offsetOfNextAvailableSpace));
|
||||
|
||||
out.write(reinterpret_cast<char*>(_data),_blockSize);
|
||||
|
||||
osg::notify(osg::NOTICE)<<"Archive::IndexBlock::write()"<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
bool Archive::IndexBlock::addFileReference(pos_type position, const std::string& filename)
|
||||
{
|
||||
if (spaceAvailable(position, filename))
|
||||
{
|
||||
unsigned char* ptr = _data+_offsetOfNextAvailableSpace;
|
||||
|
||||
*(reinterpret_cast<pos_type*>(ptr)) = position;
|
||||
ptr += sizeof(pos_type);
|
||||
|
||||
*(reinterpret_cast<unsigned int*>(ptr)) = filename.size();
|
||||
ptr += sizeof(unsigned int);
|
||||
|
||||
for(unsigned int i=0;i<filename.size();++i, ++ptr)
|
||||
{
|
||||
*ptr = filename[i];
|
||||
}
|
||||
|
||||
_requiresWrite = true;
|
||||
|
||||
osg::notify(osg::NOTICE)<<"Archive::IndexBlock::addFileReference("<<(unsigned int)position<<", "<<filename<<")"<<std::endl;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Archive::IndexBlock::setPositionNextIndexBlock(pos_type position)
|
||||
{
|
||||
_filePositionNextIndexBlock = position;
|
||||
_requiresWrite = true;
|
||||
}
|
||||
|
||||
Archive::Archive()
|
||||
{
|
||||
}
|
||||
@@ -32,6 +155,15 @@ void Archive::create(const std::string& filename, unsigned int indexBlockSize)
|
||||
{
|
||||
_status = WRITE;
|
||||
_output.open(filename.c_str());
|
||||
_output<<"osga";
|
||||
_output.write(reinterpret_cast<char*>(&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("<<fileName<<") failed, archive opened as read only."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_output)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Archive::getPositionForNewEntry("<<fileName<<") failed, _output set up."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// get an IndexBlock with space available if possible
|
||||
unsigned int blockSize = 4096;
|
||||
osg::ref_ptr<IndexBlock> indexBlock = _indexBlockList.empty() ? 0 : _indexBlockList.back();
|
||||
osg::ref_ptr<IndexBlock> 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, "<<fileName<<")"<<std::endl;
|
||||
return rw->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)
|
||||
|
||||
Reference in New Issue
Block a user