Added IndexBlock inner class to osgDB::Archive

This commit is contained in:
Robert Osfield
2004-10-27 14:09:24 +00:00
parent 2d4f7d7be0
commit 61b0f5d301
2 changed files with 265 additions and 5 deletions

View File

@@ -17,6 +17,7 @@
#include <osgDB/ReaderWriter>
#include <fstream>
#include <list>
namespace osgDB {
@@ -67,14 +68,75 @@ class OSGDB_EXPORT Archive : public ReaderWriter
protected:
typedef std::istream::pos_type pos_type;
typedef std::map<std::string, pos_type> FileNamePositionMap;
typedef std::istream::pos_type pos_type;
typedef std::map<std::string, pos_type> 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<IndexBlock> > 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;

View File

@@ -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)