Moved the .osga implementation into the src/osgPlugins/osga plugin and made
osgDB::Archive a pure virtual base class.
This commit is contained in:
@@ -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"
|
||||
|
||||
|
||||
@@ -113,40 +113,38 @@ int main( int argc, char **argv )
|
||||
return 1;
|
||||
}
|
||||
|
||||
osgDB::Archive archive;
|
||||
osg::ref_ptr<osgDB::Archive> archive;
|
||||
|
||||
if (insert)
|
||||
{
|
||||
osgDB::Archive archive;
|
||||
archive.open(archiveFilename, osgDB::Archive::WRITE);
|
||||
archive = osgDB::openArchive(archiveFilename, osgDB::Archive::WRITE);
|
||||
|
||||
std::cout<<"Going through files"<<files.size()<<std::endl;
|
||||
|
||||
for (FileNameList::iterator itr=files.begin();
|
||||
itr!=files.end();
|
||||
++itr)
|
||||
if (archive.valid())
|
||||
{
|
||||
std::cout<<" Tring to read"<<*itr<<std::endl;
|
||||
osg::ref_ptr<osg::Object> obj = osgDB::readObjectFile(*itr);
|
||||
if (obj.valid())
|
||||
for (FileNameList::iterator itr=files.begin();
|
||||
itr!=files.end();
|
||||
++itr)
|
||||
{
|
||||
std::cout<<" Have read"<<*itr<<std::endl;
|
||||
archive.writeObject(*obj, *itr);
|
||||
osg::ref_ptr<osg::Object> 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<osg::Object> obj = result.getObject();
|
||||
std::cout<<"readObejct time = "<<osg::Timer::instance()->delta_m(start,osg::Timer::instance()->tick())<<std::endl;
|
||||
if (obj.valid())
|
||||
@@ -157,11 +155,11 @@ int main( int argc, char **argv )
|
||||
}
|
||||
}
|
||||
|
||||
if (list)
|
||||
if (list && archive.valid())
|
||||
{
|
||||
std::cout<<"List of files in archive:"<<std::endl;
|
||||
osgDB::Archive::FileNameList fileNames;
|
||||
if (archive.getFileNames(fileNames))
|
||||
if (archive->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<<std::endl;
|
||||
std::cout<<"Master file "<<archive.getMasterFileName()<<std::endl;
|
||||
std::cout<<"Master file "<<archive->getMasterFileName()<<std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
namespace osgDB {
|
||||
|
||||
|
||||
/** Base class for implementing database Archives. */
|
||||
/** Base class for implementing database Archives. See src/osgPlugins/osga for an example of a concrete implementation. */
|
||||
class OSGDB_EXPORT Archive : public ReaderWriter
|
||||
{
|
||||
public:
|
||||
@@ -37,168 +37,33 @@ class OSGDB_EXPORT Archive : public ReaderWriter
|
||||
virtual bool acceptsExtension(const std::string& /*extension*/) { return true; }
|
||||
|
||||
/** open the archive.*/
|
||||
virtual bool open(const std::string& filename, ArchiveStatus status, unsigned int indexBlockSizeHint=4096);
|
||||
virtual bool open(const std::string& filename, ArchiveStatus status, unsigned int indexBlockSizeHint=4096) = 0;
|
||||
|
||||
/** close the archive.*/
|
||||
virtual void close();
|
||||
virtual void close() = 0;
|
||||
|
||||
/** return true if file exists in archive.*/
|
||||
virtual bool fileExists(const std::string& filename) const;
|
||||
virtual bool fileExists(const std::string& filename) const = 0;
|
||||
|
||||
/** Get the file name which represents the master file recorded in the Archive.*/
|
||||
virtual std::string getMasterFileName() const;
|
||||
virtual std::string getMasterFileName() const = 0;
|
||||
|
||||
typedef std::vector<std::string> 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<pos_type, size_type> PositionSizePair;
|
||||
typedef std::map<std::string, PositionSizePair> 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<IndexBlock> > 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;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -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> indexBlock = new IndexBlock;
|
||||
indexBlock->_filePosition = in.tellg();
|
||||
in.read(reinterpret_cast<char*>(&indexBlock->_blockSize), sizeof(indexBlock->_blockSize));
|
||||
in.read(reinterpret_cast<char*>(&indexBlock->_filePositionNextIndexBlock), sizeof(indexBlock->_filePositionNextIndexBlock));
|
||||
in.read(reinterpret_cast<char*>(&indexBlock->_offsetOfNextAvailableSpace), sizeof(indexBlock-> _offsetOfNextAvailableSpace));
|
||||
|
||||
if (doEndianSwap)
|
||||
{
|
||||
osg::swapBytes(reinterpret_cast<char*>(&indexBlock->_blockSize), sizeof(indexBlock->_blockSize));
|
||||
osg::swapBytes(reinterpret_cast<char*>(&indexBlock->_filePositionNextIndexBlock), sizeof(indexBlock->_filePositionNextIndexBlock));
|
||||
osg::swapBytes(reinterpret_cast<char*>(&indexBlock->_offsetOfNextAvailableSpace), sizeof(indexBlock-> _offsetOfNextAvailableSpace));
|
||||
}
|
||||
|
||||
osg::notify(osg::NOTICE)<<"indexBlock->_blockSize="<<indexBlock->_blockSize<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<"indexBlock->_filePositionNextIndexBlock="<<indexBlock->_filePositionNextIndexBlock<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<"indexBlock->_offsetOfNextAvailableSpace="<<indexBlock->_offsetOfNextAvailableSpace<<std::endl;
|
||||
|
||||
indexBlock->allocateData(indexBlock->_blockSize);
|
||||
if (indexBlock->_data)
|
||||
{
|
||||
in.read(reinterpret_cast<char*>(indexBlock->_data),indexBlock->_blockSize);
|
||||
|
||||
if (doEndianSwap)
|
||||
{
|
||||
char* ptr = indexBlock->_data;
|
||||
char* end_ptr = indexBlock->_data + indexBlock->_offsetOfNextAvailableSpace;
|
||||
while (ptr<end_ptr)
|
||||
{
|
||||
osg::swapBytes(ptr,sizeof(pos_type));
|
||||
ptr += sizeof(pos_type);
|
||||
|
||||
osg::swapBytes(ptr,sizeof(size_type));
|
||||
ptr += sizeof(size_type);
|
||||
|
||||
osg::swapBytes(ptr,sizeof(unsigned int));
|
||||
unsigned int filename_size = *(reinterpret_cast<unsigned int*>(ptr));
|
||||
ptr += sizeof(unsigned int);
|
||||
ptr += filename_size;
|
||||
|
||||
osg::notify(osg::NOTICE)<<"filename size="<<filename_size<<std::endl;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Allocation Problem in Archive::IndexBlock::read(std::istream& in)"<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO)<<"Read index block"<<std::endl;
|
||||
|
||||
return indexBlock.release();
|
||||
|
||||
}
|
||||
|
||||
std::string Archive::IndexBlock::getFirstFileName() const
|
||||
{
|
||||
char* ptr = _data;
|
||||
char* end_ptr = _data + _offsetOfNextAvailableSpace;
|
||||
if (ptr<end_ptr)
|
||||
{
|
||||
ptr += sizeof(pos_type);
|
||||
ptr += sizeof(size_type);
|
||||
|
||||
unsigned int filename_size = *(reinterpret_cast<unsigned int*>(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<end_ptr)
|
||||
{
|
||||
pos_type position = *(reinterpret_cast<pos_type*>(ptr));
|
||||
ptr += sizeof(pos_type);
|
||||
|
||||
size_type size = *(reinterpret_cast<size_type*>(ptr));
|
||||
ptr += sizeof(size_type);
|
||||
|
||||
unsigned int filename_size = *(reinterpret_cast<unsigned int*>(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"<<std::endl;
|
||||
_filePosition = out.tellp();
|
||||
}
|
||||
else
|
||||
{
|
||||
out.seekp(_filePosition);
|
||||
}
|
||||
osg::notify(osg::INFO)<<"Archive::IndexBlock::write() to _filePosition"<<out.tellp()<<std::endl;
|
||||
|
||||
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::INFO)<<"Archive::IndexBlock::write() end"<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
bool Archive::IndexBlock::addFileReference(pos_type position, size_type size, const std::string& filename)
|
||||
{
|
||||
if (spaceAvailable(position, size, filename))
|
||||
{
|
||||
char* ptr = _data+_offsetOfNextAvailableSpace;
|
||||
|
||||
*(reinterpret_cast<pos_type*>(ptr)) = position;
|
||||
ptr += sizeof(pos_type);
|
||||
|
||||
*(reinterpret_cast<size_type*>(ptr)) = size;
|
||||
ptr += sizeof(size_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];
|
||||
}
|
||||
|
||||
_offsetOfNextAvailableSpace = ptr-_data;
|
||||
|
||||
_requiresWrite = true;
|
||||
|
||||
osg::notify(osg::INFO)<<"Archive::IndexBlock::addFileReference("<<(unsigned int)position<<", "<<filename<<")"<<std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Archive::IndexBlock::setPositionNextIndexBlock(pos_type position)
|
||||
{
|
||||
_filePositionNextIndexBlock = position;
|
||||
_requiresWrite = true;
|
||||
}
|
||||
|
||||
Archive::Archive()
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Don't forget endian...."<<std::endl;
|
||||
}
|
||||
|
||||
Archive::~Archive()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
bool Archive::open(const std::string& filename, ArchiveStatus status, unsigned int indexBlockSize)
|
||||
{
|
||||
if (status==READ)
|
||||
{
|
||||
_status = status;
|
||||
_input.open(filename.c_str(), std::ios_base::binary | std::ios_base::in);
|
||||
|
||||
if (_input)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"trying Archive::open("<<filename<<")"<<std::endl;
|
||||
|
||||
char identifier[4];
|
||||
_input.read(identifier,4);
|
||||
|
||||
bool validArchive = (identifier[0]=='o' && identifier[1]=='s' && identifier[2]=='g' && identifier[3]=='a');
|
||||
if (validArchive)
|
||||
{
|
||||
|
||||
unsigned int endianTestWord=0;
|
||||
_input.read(reinterpret_cast<char*>(&endianTestWord),4);
|
||||
bool doEndianSwap = (endianTestWord!=ENDIAN_TEST_NUMBER);
|
||||
|
||||
_input.read(reinterpret_cast<char*>(&_version),sizeof(_version));
|
||||
if (doEndianSwap)
|
||||
{
|
||||
osg::swapBytes(reinterpret_cast<char*>(&_version),sizeof(_version));
|
||||
}
|
||||
|
||||
osg::notify(osg::NOTICE)<<"Archive::open() doEndianSwap="<<doEndianSwap<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<"Archive::open() Version="<<_version<<std::endl;
|
||||
|
||||
IndexBlock *indexBlock = 0;
|
||||
|
||||
while ( (indexBlock=Archive::IndexBlock::read(_input, doEndianSwap)) != 0)
|
||||
{
|
||||
_indexBlockList.push_back(indexBlock);
|
||||
if (indexBlock->getPositionNextIndexBlock()==pos_type(0)) break;
|
||||
|
||||
_input.seekg(indexBlock->getPositionNextIndexBlock());
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO)<<"Archive::open("<<filename<<") succeeded"<<std::endl;
|
||||
|
||||
// now need to build the filename map.
|
||||
_indexMap.clear();
|
||||
|
||||
if (!_indexBlockList.empty())
|
||||
{
|
||||
_masterFileName = _indexBlockList.front()->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)<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO)<<"Archive::open("<<filename<<") failed"<<std::endl;
|
||||
|
||||
_input.close();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (status==WRITE && open(filename,READ))
|
||||
{
|
||||
_input.close();
|
||||
_status = WRITE;
|
||||
|
||||
_output.open(filename.c_str(), std::ios_base::binary | std::ios_base::in | std::ios_base::out);
|
||||
|
||||
osg::notify(osg::INFO)<<"File position after open = "<<(int)_output.tellp()<<" is_open "<<_output.is_open()<<std::endl;
|
||||
|
||||
// place write position at end of file.
|
||||
_output.seekp(0, std::ios::end);
|
||||
|
||||
osg::notify(osg::INFO)<<"File position after seekp = "<<(int)_output.tellp()<<std::endl;
|
||||
|
||||
osg::notify(osg::INFO)<<"Archive::open("<<filename<<") open for writing"<<std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
else // no file opened or using create so resort to creating the archive.
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Archive::open("<<filename<<"), archive being created."<<std::endl;
|
||||
|
||||
_status = WRITE;
|
||||
_output.open(filename.c_str(), std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
|
||||
_output<<"osga";
|
||||
_output.write(reinterpret_cast<const char*>(&ENDIAN_TEST_NUMBER),4);
|
||||
_output.write(reinterpret_cast<char*>(&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()<<std::endl;
|
||||
|
||||
// place write position at end of file.
|
||||
_output.seekp(0,std::ios::end);
|
||||
|
||||
osg::notify(osg::INFO)<<"File position after seekp = "<<(int)_output.tellp()<<std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Archive::close()
|
||||
{
|
||||
_input.close();
|
||||
|
||||
if (_status==WRITE)
|
||||
{
|
||||
writeIndexBlocks();
|
||||
_output.close();
|
||||
}
|
||||
}
|
||||
|
||||
std::string Archive::getMasterFileName() const
|
||||
{
|
||||
return _masterFileName;
|
||||
}
|
||||
|
||||
bool Archive::getFileNames(FileNameList& fileNameList) const
|
||||
{
|
||||
fileNameList.clear();
|
||||
fileNameList.reserve(_indexMap.size());
|
||||
for(FileNamePositionMap::const_iterator itr=_indexMap.begin();
|
||||
itr!=_indexMap.end();
|
||||
++itr)
|
||||
{
|
||||
fileNameList.push_back(itr->first);
|
||||
}
|
||||
return !fileNameList.empty();
|
||||
}
|
||||
|
||||
|
||||
void Archive::writeIndexBlocks()
|
||||
{
|
||||
if (_status==WRITE)
|
||||
{
|
||||
for(IndexBlockList::iterator itr=_indexBlockList.begin();
|
||||
itr!=_indexBlockList.end();
|
||||
++itr)
|
||||
{
|
||||
if ((*itr)->requiresWrite())
|
||||
{
|
||||
(*itr)->write(_output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Archive::fileExists(const std::string& filename) const
|
||||
{
|
||||
return (_indexMap.count(filename)!=0);
|
||||
}
|
||||
|
||||
bool Archive::addFileReference(pos_type position, size_type size, const std::string& fileName)
|
||||
{
|
||||
if (_status==READ)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Archive::getPositionForNewEntry("<<fileName<<") failed, archive opened as read only."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_output)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Archive::getPositionForNewEntry("<<fileName<<") failed, _output set up."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// if the masterFileName isn't set yet use this fileName
|
||||
if (_masterFileName.empty()) _masterFileName = fileName;
|
||||
|
||||
|
||||
// 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, size, fileName)))
|
||||
{
|
||||
previousBlock = indexBlock;
|
||||
indexBlock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// if not one available create a new block.
|
||||
if (!indexBlock)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Creating new block"<<std::endl;
|
||||
|
||||
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 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, "<<readFunctor._filename<<") failed, archive opened as read only."<<std::endl;
|
||||
return ReadResult(ReadResult::FILE_NOT_HANDLED);
|
||||
}
|
||||
|
||||
FileNamePositionMap::const_iterator itr = _indexMap.find(readFunctor._filename);
|
||||
if (itr==_indexMap.end())
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Archive::readObject(obj, "<<readFunctor._filename<<") failed, file not found in archive"<<std::endl;
|
||||
return ReadResult(ReadResult::FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(getLowerCaseFileExtension(readFunctor._filename));
|
||||
if (!rw)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Archive::readObject(obj, "<<readFunctor._filename<<") failed to find appropriate plugin to write file."<<std::endl;
|
||||
return ReadResult(ReadResult::FILE_NOT_HANDLED);
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO)<<"Archive::readObject(obj, "<<readFunctor._filename<<")"<<std::endl;
|
||||
|
||||
_input.seekg(itr->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, "<<writeFunctor._filename<<") failed, archive opened as read only."<<std::endl;
|
||||
return WriteResult(WriteResult::FILE_NOT_HANDLED);
|
||||
}
|
||||
|
||||
ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(getLowerCaseFileExtension(writeFunctor._filename));
|
||||
if (!rw)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Archive::write(obj, "<<writeFunctor._filename<<") failed to find appropriate plugin to write file."<<std::endl;
|
||||
return WriteResult(WriteResult::FILE_NOT_HANDLED);
|
||||
}
|
||||
|
||||
osg::notify(osg::NOTICE)<<"Archive::write(obj, "<<writeFunctor._filename<<")"<<std::endl;
|
||||
|
||||
// place write position at end of file.
|
||||
_output.seekp(0,std::ios::end);
|
||||
|
||||
pos_type position = _output.tellp();
|
||||
|
||||
WriteResult result = writeFunctor.doWrite(*rw,_output);
|
||||
|
||||
pos_type final_position = _output.tellp();
|
||||
size_type size = size_type(final_position-position);
|
||||
|
||||
if (result.success()) addFileReference(position, size, writeFunctor._filename);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
ReaderWriter::WriteResult Archive::writeObject(const osg::Object& obj,const std::string& fileName,const Options* options)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Archive::writeObject(obj, "<<fileName<<")"<<std::endl;
|
||||
return write(WriteObjectFunctor(obj, fileName, options));
|
||||
}
|
||||
|
||||
ReaderWriter::WriteResult Archive::writeImage(const osg::Image& image,const std::string& fileName,const Options* options)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Archive::writeImage(obj, "<<fileName<<")"<<std::endl;
|
||||
return write(WriteImageFunctor(image, fileName, options));
|
||||
}
|
||||
|
||||
ReaderWriter::WriteResult Archive::writeHeightField(const osg::HeightField& heightField,const std::string& fileName,const Options* options)
|
||||
{
|
||||
return write(WriteHeightFieldFunctor(heightField, fileName, options));
|
||||
}
|
||||
|
||||
ReaderWriter::WriteResult Archive::writeNode(const osg::Node& node,const std::string& fileName,const Options* options)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Archive::writeNode(obj, "<<fileName<<")"<<std::endl;
|
||||
return write(WriteNodeFunctor(node, fileName, options));
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
OSGA_Archive.cpp\
|
||||
ReaderWriterOSGA.cpp\
|
||||
|
||||
|
||||
|
||||
682
src/osgPlugins/osga/OSGA_Archive.cpp
Normal file
682
src/osgPlugins/osga/OSGA_Archive.cpp
Normal file
@@ -0,0 +1,682 @@
|
||||
#include <osg/Notify>
|
||||
#include <osg/Endian>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/FileNameUtils>
|
||||
|
||||
#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> indexBlock = new IndexBlock;
|
||||
indexBlock->_filePosition = in.tellg();
|
||||
in.read(reinterpret_cast<char*>(&indexBlock->_blockSize), sizeof(indexBlock->_blockSize));
|
||||
in.read(reinterpret_cast<char*>(&indexBlock->_filePositionNextIndexBlock), sizeof(indexBlock->_filePositionNextIndexBlock));
|
||||
in.read(reinterpret_cast<char*>(&indexBlock->_offsetOfNextAvailableSpace), sizeof(indexBlock-> _offsetOfNextAvailableSpace));
|
||||
|
||||
if (doEndianSwap)
|
||||
{
|
||||
osg::swapBytes(reinterpret_cast<char*>(&indexBlock->_blockSize), sizeof(indexBlock->_blockSize));
|
||||
osg::swapBytes(reinterpret_cast<char*>(&indexBlock->_filePositionNextIndexBlock), sizeof(indexBlock->_filePositionNextIndexBlock));
|
||||
osg::swapBytes(reinterpret_cast<char*>(&indexBlock->_offsetOfNextAvailableSpace), sizeof(indexBlock-> _offsetOfNextAvailableSpace));
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO)<<"indexBlock->_blockSize="<<indexBlock->_blockSize<<std::endl;
|
||||
osg::notify(osg::INFO)<<"indexBlock->_filePositionNextIndexBlock="<<indexBlock->_filePositionNextIndexBlock<<std::endl;
|
||||
osg::notify(osg::INFO)<<"indexBlock->_offsetOfNextAvailableSpace="<<indexBlock->_offsetOfNextAvailableSpace<<std::endl;
|
||||
|
||||
indexBlock->allocateData(indexBlock->_blockSize);
|
||||
if (indexBlock->_data)
|
||||
{
|
||||
in.read(reinterpret_cast<char*>(indexBlock->_data),indexBlock->_blockSize);
|
||||
|
||||
if (doEndianSwap)
|
||||
{
|
||||
char* ptr = indexBlock->_data;
|
||||
char* end_ptr = indexBlock->_data + indexBlock->_offsetOfNextAvailableSpace;
|
||||
while (ptr<end_ptr)
|
||||
{
|
||||
osg::swapBytes(ptr,sizeof(pos_type));
|
||||
ptr += sizeof(pos_type);
|
||||
|
||||
osg::swapBytes(ptr,sizeof(size_type));
|
||||
ptr += sizeof(size_type);
|
||||
|
||||
osg::swapBytes(ptr,sizeof(unsigned int));
|
||||
unsigned int filename_size = *(reinterpret_cast<unsigned int*>(ptr));
|
||||
ptr += sizeof(unsigned int);
|
||||
ptr += filename_size;
|
||||
|
||||
osg::notify(osg::INFO)<<"filename size="<<filename_size<<std::endl;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::INFO)<<"Allocation Problem in OSGA_Archive::IndexBlock::read(std::istream& in)"<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO)<<"Read index block"<<std::endl;
|
||||
|
||||
return indexBlock.release();
|
||||
|
||||
}
|
||||
|
||||
std::string OSGA_Archive::IndexBlock::getFirstFileName() const
|
||||
{
|
||||
char* ptr = _data;
|
||||
char* end_ptr = _data + _offsetOfNextAvailableSpace;
|
||||
if (ptr<end_ptr)
|
||||
{
|
||||
ptr += sizeof(pos_type);
|
||||
ptr += sizeof(size_type);
|
||||
|
||||
unsigned int filename_size = *(reinterpret_cast<unsigned int*>(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<end_ptr)
|
||||
{
|
||||
pos_type position = *(reinterpret_cast<pos_type*>(ptr));
|
||||
ptr += sizeof(pos_type);
|
||||
|
||||
size_type size = *(reinterpret_cast<size_type*>(ptr));
|
||||
ptr += sizeof(size_type);
|
||||
|
||||
unsigned int filename_size = *(reinterpret_cast<unsigned int*>(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"<<std::endl;
|
||||
_filePosition = out.tellp();
|
||||
}
|
||||
else
|
||||
{
|
||||
out.seekp(_filePosition);
|
||||
}
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::IndexBlock::write() to _filePosition"<<out.tellp()<<std::endl;
|
||||
|
||||
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::INFO)<<"OSGA_Archive::IndexBlock::write() end"<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
bool OSGA_Archive::IndexBlock::addFileReference(pos_type position, size_type size, const std::string& filename)
|
||||
{
|
||||
if (spaceAvailable(position, size, filename))
|
||||
{
|
||||
char* ptr = _data+_offsetOfNextAvailableSpace;
|
||||
|
||||
*(reinterpret_cast<pos_type*>(ptr)) = position;
|
||||
ptr += sizeof(pos_type);
|
||||
|
||||
*(reinterpret_cast<size_type*>(ptr)) = size;
|
||||
ptr += sizeof(size_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];
|
||||
}
|
||||
|
||||
_offsetOfNextAvailableSpace = ptr-_data;
|
||||
|
||||
_requiresWrite = true;
|
||||
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::IndexBlock::addFileReference("<<(unsigned int)position<<", "<<filename<<")"<<std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void OSGA_Archive::IndexBlock::setPositionNextIndexBlock(pos_type position)
|
||||
{
|
||||
_filePositionNextIndexBlock = position;
|
||||
_requiresWrite = true;
|
||||
}
|
||||
|
||||
OSGA_Archive::OSGA_Archive()
|
||||
{
|
||||
}
|
||||
|
||||
OSGA_Archive::~OSGA_Archive()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
bool OSGA_Archive::open(const std::string& filename, ArchiveStatus status, unsigned int indexBlockSize)
|
||||
{
|
||||
if (status==READ)
|
||||
{
|
||||
_status = status;
|
||||
_input.open(filename.c_str(), std::ios_base::binary | std::ios_base::in);
|
||||
|
||||
if (_input)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"trying OSGA_Archive::open("<<filename<<")"<<std::endl;
|
||||
|
||||
char identifier[4];
|
||||
_input.read(identifier,4);
|
||||
|
||||
bool validArchive = (identifier[0]=='o' && identifier[1]=='s' && identifier[2]=='g' && identifier[3]=='a');
|
||||
if (validArchive)
|
||||
{
|
||||
|
||||
unsigned int endianTestWord=0;
|
||||
_input.read(reinterpret_cast<char*>(&endianTestWord),4);
|
||||
bool doEndianSwap = (endianTestWord!=ENDIAN_TEST_NUMBER);
|
||||
|
||||
_input.read(reinterpret_cast<char*>(&_version),sizeof(_version));
|
||||
if (doEndianSwap)
|
||||
{
|
||||
osg::swapBytes(reinterpret_cast<char*>(&_version),sizeof(_version));
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::open() doEndianSwap="<<doEndianSwap<<std::endl;
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::open() Version="<<_version<<std::endl;
|
||||
|
||||
IndexBlock *indexBlock = 0;
|
||||
|
||||
while ( (indexBlock=OSGA_Archive::IndexBlock::read(_input, doEndianSwap)) != 0)
|
||||
{
|
||||
_indexBlockList.push_back(indexBlock);
|
||||
if (indexBlock->getPositionNextIndexBlock()==pos_type(0)) break;
|
||||
|
||||
_input.seekg(indexBlock->getPositionNextIndexBlock());
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::open("<<filename<<") succeeded"<<std::endl;
|
||||
|
||||
// now need to build the filename map.
|
||||
_indexMap.clear();
|
||||
|
||||
if (!_indexBlockList.empty())
|
||||
{
|
||||
_masterFileName = _indexBlockList.front()->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)<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::open("<<filename<<") failed"<<std::endl;
|
||||
|
||||
_input.close();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (status==WRITE && open(filename,READ))
|
||||
{
|
||||
_input.close();
|
||||
_status = WRITE;
|
||||
|
||||
_output.open(filename.c_str(), std::ios_base::binary | std::ios_base::in | std::ios_base::out);
|
||||
|
||||
osg::notify(osg::INFO)<<"File position after open = "<<(int)_output.tellp()<<" is_open "<<_output.is_open()<<std::endl;
|
||||
|
||||
// place write position at end of file.
|
||||
_output.seekp(0, std::ios::end);
|
||||
|
||||
osg::notify(osg::INFO)<<"File position after seekp = "<<(int)_output.tellp()<<std::endl;
|
||||
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::open("<<filename<<") open for writing"<<std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
else // no file opened or using create so resort to creating the archive.
|
||||
{
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::open("<<filename<<"), archive being created."<<std::endl;
|
||||
|
||||
_status = WRITE;
|
||||
_output.open(filename.c_str(), std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
|
||||
_output<<"osga";
|
||||
_output.write(reinterpret_cast<const char*>(&ENDIAN_TEST_NUMBER),4);
|
||||
_output.write(reinterpret_cast<char*>(&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()<<std::endl;
|
||||
|
||||
// place write position at end of file.
|
||||
_output.seekp(0,std::ios::end);
|
||||
|
||||
osg::notify(osg::INFO)<<"File position after seekp = "<<(int)_output.tellp()<<std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void OSGA_Archive::close()
|
||||
{
|
||||
_input.close();
|
||||
|
||||
if (_status==WRITE)
|
||||
{
|
||||
writeIndexBlocks();
|
||||
_output.close();
|
||||
}
|
||||
}
|
||||
|
||||
std::string OSGA_Archive::getMasterFileName() const
|
||||
{
|
||||
return _masterFileName;
|
||||
}
|
||||
|
||||
bool OSGA_Archive::getFileNames(FileNameList& fileNameList) const
|
||||
{
|
||||
fileNameList.clear();
|
||||
fileNameList.reserve(_indexMap.size());
|
||||
for(FileNamePositionMap::const_iterator itr=_indexMap.begin();
|
||||
itr!=_indexMap.end();
|
||||
++itr)
|
||||
{
|
||||
fileNameList.push_back(itr->first);
|
||||
}
|
||||
return !fileNameList.empty();
|
||||
}
|
||||
|
||||
|
||||
void OSGA_Archive::writeIndexBlocks()
|
||||
{
|
||||
if (_status==WRITE)
|
||||
{
|
||||
for(IndexBlockList::iterator itr=_indexBlockList.begin();
|
||||
itr!=_indexBlockList.end();
|
||||
++itr)
|
||||
{
|
||||
if ((*itr)->requiresWrite())
|
||||
{
|
||||
(*itr)->write(_output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool OSGA_Archive::fileExists(const std::string& filename) const
|
||||
{
|
||||
return (_indexMap.count(filename)!=0);
|
||||
}
|
||||
|
||||
bool OSGA_Archive::addFileReference(pos_type position, size_type size, const std::string& fileName)
|
||||
{
|
||||
if (_status==READ)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::getPositionForNewEntry("<<fileName<<") failed, archive opened as read only."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_output)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::getPositionForNewEntry("<<fileName<<") failed, _output set up."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// if the masterFileName isn't set yet use this fileName
|
||||
if (_masterFileName.empty()) _masterFileName = fileName;
|
||||
|
||||
|
||||
// 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, 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, "<<readFunctor._filename<<") failed, archive opened as read only."<<std::endl;
|
||||
return ReadResult(ReadResult::FILE_NOT_HANDLED);
|
||||
}
|
||||
|
||||
FileNamePositionMap::const_iterator itr = _indexMap.find(readFunctor._filename);
|
||||
if (itr==_indexMap.end())
|
||||
{
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::readObject(obj, "<<readFunctor._filename<<") failed, file not found in archive"<<std::endl;
|
||||
return ReadResult(ReadResult::FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(getLowerCaseFileExtension(readFunctor._filename));
|
||||
if (!rw)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::readObject(obj, "<<readFunctor._filename<<") failed to find appropriate plugin to write file."<<std::endl;
|
||||
return ReadResult(ReadResult::FILE_NOT_HANDLED);
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::readObject(obj, "<<readFunctor._filename<<")"<<std::endl;
|
||||
|
||||
_input.seekg(itr->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, "<<writeFunctor._filename<<") failed, archive opened as read only."<<std::endl;
|
||||
return WriteResult(WriteResult::FILE_NOT_HANDLED);
|
||||
}
|
||||
|
||||
ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(getLowerCaseFileExtension(writeFunctor._filename));
|
||||
if (!rw)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::write(obj, "<<writeFunctor._filename<<") failed to find appropriate plugin to write file."<<std::endl;
|
||||
return WriteResult(WriteResult::FILE_NOT_HANDLED);
|
||||
}
|
||||
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::write(obj, "<<writeFunctor._filename<<")"<<std::endl;
|
||||
|
||||
// place write position at end of file.
|
||||
_output.seekp(0,std::ios::end);
|
||||
|
||||
pos_type position = _output.tellp();
|
||||
|
||||
WriteResult result = writeFunctor.doWrite(*rw,_output);
|
||||
|
||||
pos_type final_position = _output.tellp();
|
||||
size_type size = size_type(final_position-position);
|
||||
|
||||
if (result.success()) addFileReference(position, size, writeFunctor._filename);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
ReaderWriter::WriteResult OSGA_Archive::writeObject(const osg::Object& obj,const std::string& fileName,const Options* options)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::writeObject(obj, "<<fileName<<")"<<std::endl;
|
||||
return write(WriteObjectFunctor(obj, fileName, options));
|
||||
}
|
||||
|
||||
ReaderWriter::WriteResult OSGA_Archive::writeImage(const osg::Image& image,const std::string& fileName,const Options* options)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::writeImage(obj, "<<fileName<<")"<<std::endl;
|
||||
return write(WriteImageFunctor(image, fileName, options));
|
||||
}
|
||||
|
||||
ReaderWriter::WriteResult OSGA_Archive::writeHeightField(const osg::HeightField& heightField,const std::string& fileName,const Options* options)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::writeHeightField(obj, "<<fileName<<")"<<std::endl;
|
||||
return write(WriteHeightFieldFunctor(heightField, fileName, options));
|
||||
}
|
||||
|
||||
ReaderWriter::WriteResult OSGA_Archive::writeNode(const osg::Node& node,const std::string& fileName,const Options* options)
|
||||
{
|
||||
osg::notify(osg::INFO)<<"OSGA_Archive::writeNode(obj, "<<fileName<<")"<<std::endl;
|
||||
return write(WriteNodeFunctor(node, fileName, options));
|
||||
}
|
||||
|
||||
185
src/osgPlugins/osga/OSGA_Archive.h
Normal file
185
src/osgPlugins/osga/OSGA_Archive.h
Normal file
@@ -0,0 +1,185 @@
|
||||
#include <osg/Notify>
|
||||
#include <osgDB/Archive>
|
||||
#include <osgDB/FileNameUtils>
|
||||
|
||||
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<std::string> 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<pos_type, size_type> PositionSizePair;
|
||||
typedef std::map<std::string, PositionSizePair> 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<IndexBlock> > 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;
|
||||
|
||||
|
||||
};
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
#include <osgDB/FileUtils>
|
||||
#include <osgDB/FileNameUtils>
|
||||
#include <osgDB/Archive>
|
||||
|
||||
#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<osgDB::Archive> archive = new osgDB::Archive;
|
||||
osg::ref_ptr<OSGA_Archive> archive = new OSGA_Archive;
|
||||
if (!archive->open(fileName, status, indexBlockSize))
|
||||
{
|
||||
return ReadResult(ReadResult::FILE_NOT_HANDLED);
|
||||
|
||||
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user