📄 archive.cpp
字号:
)
{
int index;
pointer_fixup_t *fixup;
ReadData( ARC_ObjectPointer, &index, sizeof( index ) );
// Check for a NULL pointer
assert( ptr );
if ( !ptr )
{
FileError( "NULL pointer in ReadObjectPointer." );
}
//
// see if the variable was NULL
//
if ( index == ARCHIVE_NULL_POINTER )
{
*ptr = NULL;
}
else
{
// init the pointer with NULL until we can fix it
*ptr = NULL;
fixup = new pointer_fixup_t;
fixup->ptr = ( void ** )ptr;
fixup->index = index;
fixup->type = pointer_fixup_normal;
fixupList.AddObject( fixup );
}
}
void Archiver::ReadSafePointer
(
SafePtrBase * ptr
)
{
int index;
pointer_fixup_t *fixup;
ReadData( ARC_SafePointer, &index, sizeof( &index ) );
// Check for a NULL pointer
assert( ptr );
if ( !ptr )
{
FileError( "NULL pointer in ReadSafePointer." );
}
//
// see if the variable was NULL
//
if ( index == ARCHIVE_NULL_POINTER )
{
ptr->InitSafePtr( NULL );
}
else
{
// init the pointer with NULL until we can fix it
ptr->InitSafePtr( NULL );
// Add new fixup
fixup = new pointer_fixup_t;
fixup->ptr = ( void ** )ptr;
fixup->index = index;
fixup->type = pointer_fixup_safe;
fixupList.AddObject( fixup );
}
}
Event Archiver::ReadEvent
(
void
)
{
Event ev;
CheckRead();
CheckType( ARC_Event );
if ( !fileerror )
{
ev.Unarchive( *this );
}
return ev;
}
void Archiver::ReadEvent
(
Event * ev
)
{
CheckRead();
CheckType( ARC_Event );
if ( !fileerror )
{
ev->Unarchive( *this );
}
}
void Archiver::ReadRaw
(
void *data,
size_t size
)
{
ReadData( ARC_Raw, data, size );
}
str Archiver::ReadString
(
void
)
{
size_t s;
char *data;
str string;
CheckRead();
CheckType( ARC_String );
if ( !fileerror )
{
s = ReadSize();
if ( !fileerror )
{
data = new char[ s + 1 ];
if ( s )
{
readfile.Read( data, s );
}
data[ s ] = 0;
string = data;
delete [] data;
}
}
return string;
}
void Archiver::ReadString
(
str * string
)
{
*string = ReadString();
}
Class *Archiver::ReadObject
(
void
)
{
ClassDef *cls;
Class *obj;
str classname;
long objstart;
long endpos;
int index;
size_t size;
qboolean isent;
int type;
CheckRead();
type = ReadType();
if ( ( type != ARC_Object ) && ( type != ARC_Entity ) )
{
FileError( "Expecting %s or %s", typenames[ ARC_Object ], typenames[ ARC_Entity ] );
}
size = ReadSize();
classname = ReadString();
cls = getClass( classname.c_str() );
if ( !cls )
{
FileError( "Invalid class %s.", classname.c_str() );
}
isent = checkInheritance( &Entity::ClassInfo, cls );
if ( type == ARC_Entity )
{
if ( !isent )
{
FileError( "Non-Entity class object '%s' saved as an Entity based object.", classname.c_str() );
}
game.force_entnum = true;
game.spawn_entnum = ReadInteger();
}
else if ( isent )
{
FileError( "Entity class object '%s' saved as non-Entity based object.", classname.c_str() );
}
index = ReadInteger();
objstart = readfile.Pos();
obj = ( Class * )cls->newInstance();
if ( !obj )
{
FileError( "Failed to on new instance of class %s.", classname.c_str() );
}
else
{
obj->Unarchive( *this );
}
if ( isent )
{
game.force_entnum = false;
}
if ( !fileerror )
{
endpos = readfile.Pos();
if ( ( endpos - objstart ) > size )
{
FileError( "Object read past end of object's data" );
}
else if ( ( endpos - objstart ) < size )
{
FileError( "Object didn't read entire data from file" );
}
}
//
// register this pointer with our list
//
classpointerList.AddObjectAt( index, obj );
return obj;
}
Class *Archiver::ReadObject
(
Class *obj
)
{
ClassDef *cls;
str classname;
long objstart;
long endpos;
int index;
size_t size;
int type;
qboolean isent;
CheckRead();
type = ReadType();
if ( ( type != ARC_Object ) && ( type != ARC_Entity ) )
{
FileError( "Expecting %s or %s", typenames[ ARC_Object ], typenames[ ARC_Entity ] );
}
size = ReadSize();
classname = ReadString();
cls = getClass( classname.c_str() );
if ( !cls )
{
FileError( "Invalid class %s.", classname.c_str() );
}
if ( obj->classinfo() != cls )
{
FileError( "Archive has a '%s' object, but was expecting a '%s' object.", classname.c_str(), obj->getClassname() );
}
isent = obj->isSubclassOf( Entity );
if ( type == ARC_Entity )
{
if ( !isent )
{
FileError( "Non-Entity class object '%s' saved as an Entity based object.", classname.c_str() );
}
( ( Entity * )obj )->SetEntNum( ReadInteger() );
}
else if ( isent )
{
FileError( "Entity class object '%s' saved as non-Entity based object.", classname.c_str() );
}
index = ReadInteger();
objstart = readfile.Pos();
obj->Unarchive( *this );
if ( !fileerror )
{
endpos = readfile.Pos();
if ( ( endpos - objstart ) > size )
{
FileError( "Object read past end of object's data" );
}
else if ( ( endpos - objstart ) < size )
{
FileError( "Object didn't read entire data from file" );
}
}
//
// register this pointer with our list
//
classpointerList.AddObjectAt( index, obj );
return obj;
}
/****************************************************************************************
File Write functions
*****************************************************************************************/
void Archiver::Create
(
const char *name
)
{
assert( name );
if ( !name )
{
gi.error( "NULL pointer for filename in Archiver::Create.\n" );
}
fileerror = false;
archivemode = ARCHIVE_WRITE;
filename = name;
gi.CreatePath( filename.c_str() );
file = fopen( filename.c_str(), "wb" );
if ( !file )
{
FileError( "Couldn't open file." );
}
WriteUnsigned( ArchiveHeader );
WriteUnsigned( ArchiveVersion );
WriteString( str( ArchiveInfo ) );
numclassespos = ftell( file );
WriteInteger( 0 );
}
inline void Archiver::CheckWrite
(
void
)
{
assert( archivemode == ARCHIVE_WRITE );
if ( !fileerror && ( archivemode != ARCHIVE_WRITE ) )
{
FileError( "File write during a read operation." );
}
}
inline void Archiver::WriteType
(
int type
)
{
fwrite( &type, sizeof( type ), 1, file );
}
inline void Archiver::WriteSize
(
size_t size
)
{
fwrite( &size, sizeof( size ), 1, file );
}
inline void Archiver::WriteData
(
int type,
const void *data,
size_t size
)
{
CheckWrite();
WriteType( type );
WriteSize( size );
if ( !fileerror && size )
{
fwrite( data, size, 1, file );
}
}
#define WRITE( func, type ) \
void Archiver::Write##func \
( \
type v \
) \
\
{ \
WriteData( ARC_##func, &v, sizeof( type ) ); \
}
WRITE( Vector, Vector & );
WRITE( Quat, Quat & );
WRITE( Integer, int );
WRITE( Unsigned, unsigned );
WRITE( Byte, byte );
WRITE( Char, char );
WRITE( Short, short );
WRITE( UnsignedShort, unsigned short );
WRITE( Float, float );
WRITE( Double, double );
WRITE( Boolean, qboolean );
void Archiver::WriteRaw
(
const void *data,
size_t size
)
{
WriteData( ARC_Raw, data, size );
}
void Archiver::WriteString
(
str &string
)
{
WriteData( ARC_String, string.c_str(), string.length() );
}
void Archiver::WriteObject
(
Class *obj
)
{
str classname;
long sizepos;
long objstart;
long endpos;
int index;
size_t size;
qboolean isent;
assert( obj );
if ( !obj )
{
FileError( "NULL object in WriteObject" );
}
isent = obj->isSubclassOf( Entity );
CheckWrite();
if ( isent )
{
WriteType( ARC_Entity );
}
else
{
WriteType( ARC_Object );
}
sizepos = ftell( file );
size = 0;
WriteSize( size );
classname = obj->getClassname();
WriteString( classname );
if ( isent )
{
// Write out the entity number
WriteInteger( ( ( Entity * )obj )->entnum );
}
// write out pointer index for this class pointer
index = classpointerList.AddUniqueObject( obj );
WriteInteger( index );
if ( !fileerror )
{
objstart = ftell( file );
obj->Archive( *this );
}
if ( !fileerror )
{
endpos = ftell( file );
size = endpos - objstart;
fseek( file, sizepos, SEEK_SET );
WriteSize( size );
if ( !fileerror )
{
fseek( file, endpos, SEEK_SET );
}
}
}
void Archiver::WriteObjectPointer
(
Class * ptr
)
{
int index;
if ( ptr )
{
index = classpointerList.AddUniqueObject( ptr );
}
else
{
index = ARCHIVE_NULL_POINTER;
}
WriteData( ARC_ObjectPointer, &index, sizeof( index ) );
}
void Archiver::WriteSafePointer
(
Class * ptr
)
{
int index;
if ( ptr )
{
index = classpointerList.AddUniqueObject( ptr );
}
else
{
index = ARCHIVE_NULL_POINTER;
}
WriteData( ARC_SafePointer, &index, sizeof( index ) );
}
void Archiver::WriteEvent
(
Event &ev
)
{
CheckWrite();
WriteType( ARC_Event );
//FIXME!!!! Make this handle null events
if ( &ev == NULL )
{
NullEvent.Archive( *this );
}
else
{
ev.Archive( *this );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -