885 lines
16 KiB
C++
885 lines
16 KiB
C++
#pragma warning( push ,1)
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <QMessageBox>
|
|
#include <QFile>
|
|
|
|
#include "ObjectArchive.h"
|
|
#pragma warning( pop )
|
|
|
|
#define Q_ASSERT_IS_LOAD() assert( IsLoading() && m_pDevice );
|
|
#define Q_ASSERT_IS_STORING() assert( IsStoring() && m_pDevice );
|
|
|
|
int g_nSerializeErrorMsgBoxMaxCount = 0;
|
|
void trimspace(char *p)
|
|
{
|
|
if (p == NULL || strlen(p) == 0)
|
|
return;
|
|
|
|
while (p[strlen(p)-1] == '\n')
|
|
{
|
|
p[strlen(p)-1] = '\0';
|
|
if (strlen(p) == 0)
|
|
return;
|
|
}
|
|
}
|
|
|
|
QByteArray* CObjectArchive::GetByteArray()
|
|
{
|
|
if( m_pDevice )
|
|
{
|
|
QBuffer *pBuffer = dynamic_cast<QBuffer *>( m_pDevice );
|
|
if( pBuffer )
|
|
{
|
|
return &(pBuffer->buffer());
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
CObjectArchive::CObjectArchive( QByteArray& byteArray,EGmArchiveMode eMode )
|
|
{
|
|
// new buffer
|
|
QBuffer *pBuffer = new QBuffer();
|
|
pBuffer->setBuffer( &byteArray );
|
|
pBuffer->open( eMode ==eStore ? QIODevice::WriteOnly: QIODevice::ReadOnly );
|
|
|
|
// set device
|
|
setDevice( pBuffer );
|
|
m_pDevice = pBuffer;
|
|
|
|
// set mode
|
|
m_eMode = eMode;
|
|
m_bQFileOpenedByMe = true;
|
|
|
|
// have opened
|
|
m_bOpened = true;
|
|
|
|
InitArchivePosData();
|
|
}
|
|
|
|
CObjectArchive::CObjectArchive( QString sFile, EGmArchiveMode eMode,qint64 nWriteOffSet )
|
|
{
|
|
filename=sFile;
|
|
QFile *pFile=new QFile;
|
|
pFile->setFileName(sFile);
|
|
m_bOpened = true;
|
|
if(eMode == eLoad)
|
|
{
|
|
if(!pFile->open(QIODevice::ReadOnly))
|
|
{
|
|
m_bOpened=false;
|
|
}
|
|
}
|
|
else if(eMode == eStore)
|
|
{
|
|
QIODevice::OpenMode mode =QIODevice::Truncate;
|
|
if( nWriteOffSet == 0 )
|
|
{
|
|
mode =QIODevice::Truncate;
|
|
}else if( nWriteOffSet<0 )
|
|
{
|
|
mode =QIODevice::Append;
|
|
}else
|
|
{
|
|
// extend file size
|
|
if(QFile::exists( sFile ) )
|
|
{
|
|
QFile file( sFile);
|
|
if( file.open( QIODevice::ReadWrite ) )
|
|
{
|
|
bool bFileSizeOK = ( file.size() >= (nWriteOffSet-1) );
|
|
assert( bFileSizeOK );
|
|
if( !bFileSizeOK )
|
|
{
|
|
file.resize( nWriteOffSet -1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
mode = static_cast<QIODevice::OpenMode > ( mode | QIODevice::WriteOnly );
|
|
if(!pFile->open(mode) )
|
|
{
|
|
m_bOpened=false;
|
|
}
|
|
}
|
|
|
|
setDevice(pFile);
|
|
m_pDevice = pFile;
|
|
m_eMode = eMode;
|
|
m_bQFileOpenedByMe=true;
|
|
|
|
InitArchivePosData();
|
|
}
|
|
|
|
bool CObjectArchive::IsOpened()
|
|
{
|
|
return m_bOpened;
|
|
}
|
|
|
|
void CObjectArchive::Attatch(QIODevice *pDevice,EGmArchiveMode eMode )
|
|
{
|
|
Close();
|
|
QDataStream::setDevice( pDevice );
|
|
m_pDevice = pDevice;
|
|
m_eMode = eMode;
|
|
m_bQFileOpenedByMe=false;
|
|
InitArchivePosData();
|
|
}
|
|
|
|
CObjectArchive::~CObjectArchive()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
bool CObjectArchive::IsLoading()
|
|
{
|
|
return (m_eMode==eLoad);
|
|
}
|
|
|
|
bool CObjectArchive::IsStoring()
|
|
{
|
|
return (m_eMode==eStore);
|
|
}
|
|
|
|
QIODevice* CObjectArchive::GetDevice()
|
|
{
|
|
return m_pDevice;
|
|
}
|
|
|
|
void CObjectArchive::Read(void* lpBuf, unsigned int nMax)
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
char * pBuf= NULL;
|
|
QDataStream::readBytes (pBuf, nMax);
|
|
|
|
if(pBuf!=NULL)
|
|
{
|
|
memcpy(lpBuf, pBuf, nMax);
|
|
delete [] pBuf;
|
|
}
|
|
}
|
|
|
|
void CObjectArchive::Write(const void* lpBuf, unsigned int nMax)
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
QDataStream::writeBytes((char*)lpBuf, nMax);
|
|
}
|
|
|
|
void CObjectArchive::Close()
|
|
{
|
|
if(m_pDevice == NULL) return;
|
|
filename="";
|
|
assert( IsWriteDataOK() );
|
|
if(m_bQFileOpenedByMe)
|
|
{
|
|
m_pDevice->close();
|
|
delete m_pDevice;
|
|
}
|
|
|
|
m_pDevice = NULL;
|
|
}
|
|
|
|
char * CObjectArchive::ReadString(char * lpsz, unsigned int nMax)
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
// if nMax is negative (such a large number doesn't make sense given today's
|
|
// 2gb address space), then assume it to mean "keep the newline".
|
|
int nStop = (int)nMax < 0 ? -(int)nMax : (int)nMax;
|
|
|
|
unsigned char ch = 'a';
|
|
int nRead = 0;
|
|
|
|
try
|
|
{
|
|
|
|
while (nRead < nStop)
|
|
{
|
|
if(nRead == m_currLength) throw ch;
|
|
*this >> ch;
|
|
// stop and end-of-line (trailing '\n' is ignored)
|
|
if (ch == '\n')
|
|
{
|
|
// store the newline when called with negative nMax
|
|
if ((int)nMax != nStop)
|
|
lpsz[nRead++] = ch;
|
|
break;
|
|
}
|
|
lpsz[nRead++] = ch;
|
|
// if((m_pDevice->atEnd()))
|
|
// {
|
|
// qDebug("End of file!");
|
|
// throw ch;
|
|
// }
|
|
}
|
|
}
|
|
catch(unsigned char e)
|
|
{
|
|
e;
|
|
}
|
|
|
|
|
|
lpsz[nRead] = '\0';
|
|
return lpsz;
|
|
}
|
|
|
|
//CObjectArchive & CObjectArchive::operator>> ( QString & s )
|
|
//{
|
|
// return *this ::>> s;
|
|
//}
|
|
|
|
int CObjectArchive::ReadString(QString& rString)
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
// empty string without deallocating
|
|
const int nMaxSize = 128;
|
|
// char * lpsz = (char *)rString.data();
|
|
char * lpsz = new char[nMaxSize];
|
|
memset(lpsz, 0, nMaxSize);
|
|
char * lpszResult;
|
|
char *tmp = lpsz;
|
|
int nLen = 0;
|
|
int memSize = nMaxSize;
|
|
for (;;)
|
|
{
|
|
// memset(lpsz, 0, nLen);
|
|
lpszResult = ReadString(lpsz, (unsigned int)-nMaxSize); // store the newline
|
|
|
|
// if string is read completely or EOF
|
|
if (lpszResult == NULL ||
|
|
(nLen = ( int )strlen(lpsz)) < nMaxSize ||
|
|
lpsz[nLen-1] == '\n')
|
|
{
|
|
break;
|
|
}
|
|
|
|
lpsz += nLen;
|
|
m_currLength -= nLen;
|
|
memSize += nLen;
|
|
tmp =(char *) realloc(tmp , memSize );
|
|
memset(lpsz, 0, nLen);
|
|
}
|
|
|
|
// remove '\n' from end of string if present
|
|
|
|
trimspace(tmp);
|
|
lpszResult = tmp;
|
|
rString = QString(lpszResult);
|
|
// delete []tmp;
|
|
return lpszResult != NULL;
|
|
}
|
|
|
|
void CObjectArchive::WriteString(char * lpsz)
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
QString str = lpsz;
|
|
*this<<str;
|
|
}
|
|
|
|
void CObjectArchive::WriteCount(unsigned long dwCount)
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
*this<<dwCount;
|
|
}
|
|
|
|
unsigned long CObjectArchive::ReadCount()
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
unsigned long dwCount;
|
|
*this >> dwCount;
|
|
return dwCount;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::PushArchive(QString& strFilePathName)
|
|
{
|
|
if(IsStoring())
|
|
{
|
|
*this<<strFilePathName;
|
|
}
|
|
else
|
|
{
|
|
*this>>strFilePathName;
|
|
}
|
|
CObjectArchive* pArchive2=new CObjectArchive(strFilePathName,m_eMode);
|
|
return pArchive2->IsOpened()?*pArchive2:*this;
|
|
}
|
|
|
|
void CObjectArchive::PopArchive(CObjectArchive& archive2)
|
|
{
|
|
if(&archive2 == this)return;
|
|
|
|
archive2.Close();
|
|
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator<<(int i)
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
*(QDataStream*)this <<i;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator<<(bool b )
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
*(QDataStream*)this <<b;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator<<(unsigned int u)
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
*(QDataStream*)this <<u;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator<<(short w)
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
*(QDataStream*)this <<w;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator<<(char ch)
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
*(QDataStream*)this <<(qint8)ch;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator<<(unsigned char by)
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
*(QDataStream*)this <<by;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator<<(unsigned short w)
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
*(QDataStream*)this <<w;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator<<(long l)
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
*(QDataStream*)this <<(qint64)l;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator<<(unsigned long dw)
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
*(QDataStream*)this <<(quint64)dw;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator<<(float f)
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
*(QDataStream*)this <<f;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator<<(double d)
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
*(QDataStream*)this <<d;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator<<(qint64 n)
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
*(QDataStream*)this <<n;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator<<(const QString & s )
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
*(QDataStream*)this <<s;
|
|
return *this;
|
|
}
|
|
|
|
// extraction operations
|
|
CObjectArchive& CObjectArchive::operator>>(int& i)
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
*(QDataStream*)this >>i;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator>>(bool & b )
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
*(QDataStream*)this >>b;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator>>( unsigned int & u )
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
*(QDataStream*)this >>u;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator>>(short& w)
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
*(QDataStream*)this >>w;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator>>(char& ch)
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
qint8 tch;
|
|
*(QDataStream*)this >>tch;
|
|
ch =(char)tch;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator>>(unsigned char& by)
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
*(QDataStream*)this >>by;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator>>(unsigned short& w)
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
*(QDataStream*)this >>w;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator>>(unsigned long & dw)
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
quint64 ul;
|
|
*(QDataStream*)this >>ul;//(quint64&)dw;
|
|
dw = (unsigned long)ul;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator>>(qint64 &n)
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
*(QDataStream*)this >>n;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator>>(float& f)
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
*(QDataStream*)this >>f;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator>>(double& d)
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
*(QDataStream*)this >>d;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator>>(long& l)
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
qint64 qltmp;
|
|
*(QDataStream*)this >>qltmp;
|
|
l = (long)qltmp;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator>>( QString & s )
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
*(QDataStream*)this >>s;
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator>>( QAction *pAction )
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
bool bChecked ;
|
|
*(QDataStream*)this >> bChecked;
|
|
if( pAction )
|
|
{
|
|
pAction->setChecked( bChecked );
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator<<( QAction *pAction )
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
bool bChecked = true;
|
|
if( pAction )
|
|
{
|
|
bChecked = pAction->isChecked();
|
|
}
|
|
|
|
*(QDataStream*)this << bChecked ;
|
|
return *this;
|
|
}
|
|
|
|
void CObjectArchive::ReadBlock ( unsigned short &blockcid ,unsigned int &datasize )
|
|
{
|
|
( *this ) >> blockcid; //read block Id
|
|
( *this ) >> datasize; //read block data size
|
|
}
|
|
|
|
void CObjectArchive::ReadObject( unsigned short& nBlockNumber,unsigned short &ver )
|
|
{
|
|
( *this ) >> ver ; // read version
|
|
( *this ) >> nBlockNumber; // read block number
|
|
}
|
|
|
|
void CObjectArchive::BeginWriteBlock( unsigned short id , const void *pThis )
|
|
{
|
|
#ifndef NDEBUG
|
|
m_nBlockNumber++ ; // block number
|
|
#endif
|
|
|
|
/**
|
|
* set current object
|
|
*/
|
|
SetActiveObject( pThis );
|
|
|
|
/**
|
|
* assert this block is not same to previousely block id
|
|
*/
|
|
Q_ASSERTBlockID( id,false );
|
|
#ifndef NDEBUG
|
|
m_pCurObjectPos->m_setBlockId.insert( id );
|
|
#endif
|
|
|
|
/**
|
|
* write block id
|
|
*/
|
|
( *this )<< id ;
|
|
|
|
/**
|
|
* record "block size" postion to "m_pCurObjectPos->m_uCurrentBlockSizePos"
|
|
*/
|
|
GetCurPos( m_pCurObjectPos->m_uCurrentBlockSizePos );
|
|
|
|
/**
|
|
* write block data size
|
|
*/
|
|
unsigned int nSize = 0 ;
|
|
( *this )<< nSize ;
|
|
|
|
/**
|
|
* record "block data" postion to "m_pCurObjectPos->m_uCurrentBlockDataPos"
|
|
*/
|
|
GetCurPos( m_pCurObjectPos->m_uCurrentBlockDataPos );
|
|
|
|
/**
|
|
* accumulate the block Number
|
|
*/
|
|
++( m_pCurObjectPos->m_nBlockNumInObject );
|
|
|
|
}
|
|
|
|
void CObjectArchive::EndWriteBlock( unsigned short id , const void *pThis )
|
|
{
|
|
|
|
id;
|
|
#ifndef NDEBUG
|
|
m_nBlockNumber-- ; // block number
|
|
#endif
|
|
|
|
/**
|
|
* set current object
|
|
*/
|
|
SetActiveObject( pThis ) ;
|
|
|
|
/**
|
|
* assert the block id have already exist
|
|
*/
|
|
Q_ASSERTBlockID( id,true );
|
|
|
|
/**
|
|
* calculate block data size
|
|
*/
|
|
unsigned int nSize = 0;
|
|
{
|
|
qint64 uSizeNow ;
|
|
GetCurPos( uSizeNow );
|
|
nSize = ( unsigned int )( uSizeNow - m_pCurObjectPos->m_uCurrentBlockDataPos );
|
|
}
|
|
|
|
/**
|
|
* write block data size
|
|
*/
|
|
WriteSize( m_pCurObjectPos->m_uCurrentBlockSizePos, &nSize, NULL );
|
|
|
|
}
|
|
|
|
void CObjectArchive::BeginWriteObject( const void *pThis,unsigned short ver )
|
|
{
|
|
#ifndef NDEBUG
|
|
m_nPackNumber++ ; // block nuber
|
|
#endif
|
|
|
|
( *this ) << ver; //write version
|
|
|
|
/**
|
|
* insert the object and set current object
|
|
*/
|
|
m_mapObjectPos[ pThis ] = CObjectArchivePos();
|
|
SetActiveObject( pThis );
|
|
|
|
/**
|
|
* record "block number" pos to m_pCurObjectPos->m_uBlockNumPos
|
|
*/
|
|
GetCurPos( m_pCurObjectPos->m_uBlockNumPos );
|
|
|
|
/**
|
|
* temporary write block number ,later,EndWriteObject will correct the value
|
|
*/
|
|
m_pCurObjectPos->m_nBlockNumInObject = 0;
|
|
( *this )<< m_pCurObjectPos->m_nBlockNumInObject;
|
|
}
|
|
|
|
void CObjectArchive::EndWriteObject( const void *pThis )
|
|
{
|
|
#ifndef NDEBUG
|
|
m_nPackNumber-- ; // block number
|
|
#endif
|
|
/**
|
|
* set active Object
|
|
*/
|
|
SetActiveObject( pThis );
|
|
|
|
/**
|
|
* write block number
|
|
*/
|
|
WriteSize( m_pCurObjectPos->m_uBlockNumPos, NULL ,&m_pCurObjectPos->m_nBlockNumInObject );
|
|
|
|
/**
|
|
* erase the object
|
|
*/
|
|
std::map< const void *,CObjectArchivePos >::iterator it = m_mapObjectPos.find( pThis );
|
|
m_mapObjectPos.erase( it );
|
|
|
|
/**
|
|
* invalidate current object
|
|
*/
|
|
m_pCurObjectPos = NULL;
|
|
}
|
|
|
|
void CObjectArchive::SeekPos( int Pos ,SEEKFROM from )
|
|
{
|
|
/**
|
|
* calculate the really position accord with form
|
|
*/
|
|
if( from == SEEKFROM_CUR )
|
|
{
|
|
Pos = ( int )( m_pDevice->pos() + Pos );
|
|
}
|
|
|
|
/**
|
|
* seek to pos
|
|
*/
|
|
m_pDevice->seek( Pos );
|
|
|
|
}
|
|
|
|
void CObjectArchive::SetActiveObject( const void *pThis )
|
|
{
|
|
/**
|
|
* find the "pThis " object in map
|
|
*/
|
|
std::map< const void * ,CObjectArchivePos >::iterator it = m_mapObjectPos.find( pThis );
|
|
m_pCurObjectPos = ( it != m_mapObjectPos.end() ? &it->second : NULL );
|
|
|
|
assert( m_pCurObjectPos != NULL );
|
|
}
|
|
|
|
|
|
inline void CObjectArchive::GetCurPos( qint64 &pos )
|
|
{
|
|
pos = m_pDevice->pos();
|
|
};
|
|
|
|
inline void CObjectArchive::WriteSize ( const qint64 &pos , const unsigned int *pDwordSize,unsigned short *pShortSize )
|
|
{
|
|
assert( ( pDwordSize || pShortSize ) && !( pDwordSize && pShortSize ) );
|
|
/**
|
|
* record the current Position
|
|
*/
|
|
qint64 uSizeNow ;
|
|
GetCurPos( uSizeNow );
|
|
|
|
/**
|
|
* seek to Position
|
|
*/
|
|
m_pDevice->seek( pos);
|
|
|
|
/**
|
|
* write data size
|
|
*/
|
|
if( pDwordSize )
|
|
{
|
|
( *this ) << *pDwordSize;
|
|
}else if( pShortSize )
|
|
{
|
|
( *this ) << *pShortSize;
|
|
}
|
|
|
|
/**
|
|
* restore previously Position
|
|
*/
|
|
m_pDevice->seek( uSizeNow );
|
|
};
|
|
|
|
|
|
#ifndef NDEBUG
|
|
inline void CObjectArchive::Q_ASSERTBlockID( unsigned short id ,bool bHave)
|
|
{
|
|
/**
|
|
* when debug ,Assert the block is is alread existence
|
|
*/
|
|
bool bHaveThis = m_pCurObjectPos && ( m_pCurObjectPos->m_setBlockId.find( id ) != m_pCurObjectPos->m_setBlockId.end() );
|
|
assert( bHave ? bHaveThis : !bHaveThis );
|
|
|
|
};
|
|
#else
|
|
inline void CObjectArchive::Q_ASSERTBlockID( unsigned short id,bool bHave )
|
|
{
|
|
/**
|
|
* when release , do nothing
|
|
*/
|
|
id;
|
|
bHave;
|
|
};
|
|
#endif
|
|
|
|
|
|
bool CObjectArchive::IsWriteDataOK( )
|
|
{
|
|
#ifndef NDEBUG
|
|
/**
|
|
* aftern Archive data, if "m_nBlockNumber ==0 && m_nPackNumber ==0 ",
|
|
* then ,"begin object " match "end object ","beginBlock" match "endBlokc",otherwise , some Coding errors occur
|
|
*/
|
|
return m_nBlockNumber ==0 && m_nPackNumber ==0 ;
|
|
#else
|
|
return true; //when release , do nothing
|
|
#endif
|
|
}
|
|
|
|
void CObjectArchive::InitArchivePosData()
|
|
{
|
|
#ifndef NDEBUG
|
|
m_nBlockNumber = 0 ;
|
|
m_nPackNumber = 0 ;
|
|
#endif
|
|
m_pCurObjectPos = NULL;
|
|
m_nObjectID = 0;
|
|
|
|
// set Qt Datastream version
|
|
setVersion(QDataStream::Qt_4_3);
|
|
}
|
|
|
|
void CObjectArchive::SkipObject()
|
|
{
|
|
/**
|
|
* read version and block number
|
|
*/
|
|
unsigned short nBlockSize = 0;
|
|
unsigned short ver = 1;
|
|
ReadObject( nBlockSize,ver );
|
|
/**
|
|
* loop all block
|
|
*/
|
|
for( int i = 0;i < nBlockSize ; ++i )
|
|
{
|
|
/**
|
|
* read block id and block data size
|
|
*/
|
|
unsigned short id = 0 ;
|
|
unsigned int size = 0 ;
|
|
ReadBlock( id,size ) ;
|
|
|
|
/**
|
|
* skip the block data
|
|
*/
|
|
m_pDevice->seek( m_pDevice->pos()+ size );
|
|
}
|
|
}
|
|
|
|
|
|
bool CObjectArchive::WriteEmptyObject( )
|
|
{
|
|
/**
|
|
* write version( 1 ) and block Nubmer ( 0 )
|
|
* thus ,when lower version software read higher file,will cause read nothing
|
|
*/
|
|
void *p = (void *)CreateNewObjectID();
|
|
BeginWriteObject( p,1 );
|
|
EndWriteObject( p );
|
|
return true;
|
|
}
|
|
|
|
bool CObjectArchive::ReadEmptyObject( )
|
|
{
|
|
/**
|
|
* skip read the object
|
|
*/
|
|
this->SkipObject();
|
|
return true;
|
|
}
|
|
|
|
qint64 CObjectArchive::CreateNewObjectID()
|
|
{
|
|
++m_nObjectID;
|
|
return m_nObjectID;
|
|
}
|
|
|
|
void CObjectArchive::RollbackWriteObject( int nObjectBeginPos )
|
|
{
|
|
/**
|
|
* seek to the object's first pos ,then write a emtpy object
|
|
*/
|
|
m_pDevice->seek( nObjectBeginPos );
|
|
WriteEmptyObject();
|
|
}
|
|
|
|
void CObjectArchive::RollbackReadObject( int nObjectBeginPos )
|
|
{
|
|
/**
|
|
* seek to the object's first pos ,then skip the object
|
|
*/
|
|
m_pDevice->seek(nObjectBeginPos);
|
|
SkipObject();
|
|
}
|
|
|
|
|
|
CObjectArchive& CObjectArchive::operator<<( QUuid id )
|
|
{
|
|
Q_ASSERT_IS_STORING();
|
|
*(QDataStream*)this << id.toString();
|
|
return *this;
|
|
}
|
|
|
|
CObjectArchive& CObjectArchive::operator>>(QUuid &id )
|
|
{
|
|
Q_ASSERT_IS_LOAD();
|
|
|
|
QString strID;
|
|
*(QDataStream*)this >> strID;
|
|
|
|
id = strID;
|
|
|
|
return *this;
|
|
}
|