⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 osga_archive.cpp

📁 最新osg包
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include <osg/Notify>#include <osg/Endian>#include <osgDB/Registry>#include <osgDB/FileNameUtils>#include "OSGA_Archive.h"using namespace osgDB;/*Functions to convert between    std::streampos ( typedef'ed as iostream::pos_type               used as seekp,seekg argument and tellp,tellg return value )and     OSGA_Archive::pos_type (64 bit file position index)Purpose:    To allow using OSGA files larger than 4GiB in Windows.    std::streampos is used as argument to iostreams seekp and seekg methods    and is returned as result from iostream tellp and tellg methods.    std::streampos can be implicitly cast from/to std::streamoff as     std::streampos class defines appropriate constructor and cast operator.    Since std::streamoff is usually defined as simple int,     it is possible to call seekp( ), seekg( ) with int argument and    assign tellp(), tellg() result to int type.    But this implicit methods fail when std::streamoff is 32 bit and     std::streampos actually points past 32 bit addressable range (2 GiB).    Even if std::streamoff is 32 bit and incapable of representing 64 bit file    positions, original std::streampos may be prefectly able to handle them.       But, when such situation occurs more elaborate conversion methods from/to       std::streampos are needed. Functions below employ such methods.         I made this fix for use with 32 bit Windows OSG. Acutally this     solution is not dependent on OS but standard C++ library.     Microsoft SDKs always use some version of Dinkumware libs.     Practically this tweak is made for Dinkumware C++ libs. I hope it can     be easily extended to other 32bit systems supporting 64bit files, provided    their std::streampos implementations are similar.    I based my solution on a small portion of boost iostreams code.    For additional reference look at:         http://boost.org/boost/iostreams/positioning.hpp*//*     Recognize Dinkumware std C++ lib implementation. Its used by Microsoft,     but method is more generic - should work in all Dinkumware environments.    Complex condition below was taken from         http://boost.org/boost/iostreams/positioning.hpp    Great thanks to J.Tukanis and G. Sylvester-Bradley for figuring it out.*/#if ((defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)) && \     !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) \     && !defined(__QNX__)inline std::streampos STREAM_POS( const OSGA_Archive::pos_type pos ){     return std::streampos( std::mbstate_t(), pos );}inline OSGA_Archive::pos_type ARCHIVE_POS( const std::streampos & pos ){ #if defined(_CPPLIB_VER)//newer Dinkumware(eg: one included with VC++ 2003,2005)    fpos_t position = pos.seekpos();#else // older Dinkumware (eg: one included in Win Server 2003 Platform SDK )    fpos_t position = pos.get_fpos_t();#endif    std::streamoff offset = pos.operator std::streamoff( ) - _FPOSOFF( position );    return OSGA_Archive::pos_type( position + offset );}#else // non Dinkumware std C++ lib implementations // do the old school streampos <-> streamoff castsinline std::streampos STREAM_POS( const OSGA_Archive::pos_type pos ){     return std::streampos( pos );}inline OSGA_Archive::pos_type ARCHIVE_POS( const std::streampos & pos ){     return OSGA_Archive::pos_type( pos );}#endif // Dinkumware std C++ lib ////////////////////////////////////////////////////////////////////////////////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 = ARCHIVE_POS( 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));                _read(ptr, filename_size);                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));        _read(ptr, filename_size);        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));         _read(ptr, position);        ptr += sizeof(pos_type);                size_type size; // = *(reinterpret_cast<size_type*>(ptr));         _read(ptr, size);        ptr += sizeof(size_type);        unsigned int filename_size; // = *(reinterpret_cast<unsigned int*>(ptr));        _read(ptr, filename_size);        ptr += sizeof(unsigned int);                std::string filename(ptr, ptr+filename_size);                // record this entry into the FileNamePositionMap.         // Requests for files will be in unix style even on Win32 so need unix style keys in map.        indexMap[osgDB::convertFileNameToUnixStyle(filename)] = PositionSizePair(position,size);                ptr += filename_size;                valuesAdded = true;    }    return valuesAdded;}void OSGA_Archive::IndexBlock::write(std::ostream& out){    pos_type currentPos = ARCHIVE_POS( out.tellp() );    if (_filePosition==pos_type(0))    {        osg::notify(osg::INFO)<<"OSGA_Archive::IndexBlock::write() setting _filePosition"<<std::endl;        _filePosition = currentPos;    }    else    {         out.seekp( STREAM_POS( _filePosition ) );    }    osg::notify(osg::INFO)<<"OSGA_Archive::IndexBlock::write() to _filePosition"<< ARCHIVE_POS( 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);    if( _filePosition < currentPos ) // move file ptr to the end of file         out.seekp( STREAM_POS( currentPos ) );        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;         _write(ptr, position);        ptr += sizeof(pos_type);                //*(reinterpret_cast<size_type*>(ptr)) = size;         _write(ptr, size);        ptr += sizeof(size_type);                //*(reinterpret_cast<unsigned int*>(ptr)) = filename.size();        _write(ptr, static_cast<unsigned int>(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){    SERIALIZER();    if (status==READ)    {        _status = status;        _input.open(filename.c_str(), std::ios_base::binary | std::ios_base::in);        return _open(_input);    }    else    {        if (status==WRITE && open(filename,READ))        {            pos_type file_size( 0 );            _input.seekg( 0, std::ios_base::end );            file_size = ARCHIVE_POS( _input.tellg() );             if( _input.is_open() && file_size <= 0 )            {   // compute end of file postition manually ...                 // seekp( 0, ios::end ), tellp( ) fails in 32 bit windows with files > 4 GiB                size_t BlockHeaderSize =                     sizeof( unsigned int /*_blockSize*/ ) +                     sizeof( pos_type /*_filePositionNextIndexBlock*/ ) +                    sizeof( unsigned int /*_offsetOfNextAvailableSpace*/ );                          for(IndexBlockList::iterator itr=_indexBlockList.begin();                    itr!=_indexBlockList.end();                    ++itr)                {                    pos_type end = (*itr)->getPosition() + BlockHeaderSize + (*itr)->getBlockSize();                    if( file_size < end ) file_size = end;                }                for(FileNamePositionMap::iterator mitr=_indexMap.begin();                    mitr!=_indexMap.end();                    ++mitr)                {                    pos_type end = mitr->second.first + mitr->second.second;                    if( file_size < end ) file_size = end;                }            }            _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 = "<<ARCHIVE_POS( _output.tellp() )<<" is_open "<<_output.is_open()<<std::endl;            // place write position at end of file.             _output.seekp( STREAM_POS( file_size ) );            osg::notify(osg::INFO)<<"File position after seekp = "<<ARCHIVE_POS( _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 = "<<ARCHIVE_POS( _output.tellp() )<<std::endl;            return true;        }        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -