2016-09-19 08:41:21 +00:00
# ifndef __SERIALIZER_H
# define __SERIALIZER_H
# include <stdint.h>
2016-09-19 17:14:30 +00:00
# include <type_traits>
2016-09-19 08:41:21 +00:00
# include "tarray.h"
# include "r_defs.h"
2016-09-20 21:13:12 +00:00
# include "resourcefiles/file_zip.h"
2016-09-19 08:41:21 +00:00
2016-09-20 23:18:29 +00:00
struct ticcmd_t ;
struct usercmd_t ;
2016-09-19 08:41:21 +00:00
struct FWriter ;
struct FReader ;
extern TArray < sector_t > loadsectors ;
extern TArray < line_t > loadlines ;
extern TArray < side_t > loadsides ;
2016-09-22 22:45:41 +00:00
inline bool nullcmp ( const void * buffer , size_t length )
{
const char * p = ( const char * ) buffer ;
for ( ; length > 0 ; length - - )
{
if ( * p + + ! = 0 ) return false ;
}
return true ;
}
2016-09-19 08:41:21 +00:00
2016-09-20 16:27:47 +00:00
struct NumericValue
{
enum EType
{
NM_invalid ,
NM_signed ,
NM_unsigned ,
NM_float
} type ;
union
{
int64_t signedval ;
uint64_t unsignedval ;
double floatval ;
} ;
bool operator ! = ( const NumericValue & other )
{
return type ! = other . type | | signedval ! = other . signedval ;
}
} ;
2016-09-19 08:41:21 +00:00
class FSerializer
{
public :
FWriter * w = nullptr ;
FReader * r = nullptr ;
int ArraySize ( ) ;
2016-09-20 16:27:47 +00:00
void WriteKey ( const char * key ) ;
2016-09-22 22:45:41 +00:00
void WriteObjects ( ) ;
2016-09-19 08:41:21 +00:00
public :
2016-09-19 11:36:58 +00:00
~ FSerializer ( )
{
Close ( ) ;
}
2016-09-21 19:57:24 +00:00
bool OpenWriter ( bool pretty = true ) ;
2016-09-22 22:45:41 +00:00
bool OpenReader ( const char * buffer , size_t length ) ;
bool OpenReader ( FCompressedBuffer * input ) ;
2016-09-19 08:41:21 +00:00
void Close ( ) ;
2016-09-23 07:38:55 +00:00
void ReadObjects ( ) ;
2016-09-20 16:27:47 +00:00
bool BeginObject ( const char * name , bool randomaccess = false ) ;
2016-09-22 22:45:41 +00:00
void EndObject ( bool endwarning = false ) ;
2016-09-19 08:41:21 +00:00
bool BeginArray ( const char * name ) ;
void EndArray ( ) ;
2016-09-20 07:11:13 +00:00
unsigned GetSize ( const char * group ) ;
2016-09-20 16:27:47 +00:00
const char * GetKey ( ) ;
2016-09-19 08:41:21 +00:00
const char * GetOutput ( unsigned * len = nullptr ) ;
2016-09-20 21:13:12 +00:00
FCompressedBuffer GetCompressedOutput ( ) ;
2016-09-22 22:45:41 +00:00
FSerializer & Discard ( const char * key ) ;
2016-09-19 08:41:21 +00:00
FSerializer & Args ( const char * key , int * args , int * defargs , int special ) ;
FSerializer & Terrain ( const char * key , int & terrain , int * def = nullptr ) ;
2016-09-19 10:53:42 +00:00
FSerializer & Sprite ( const char * key , int32_t & spritenum , int32_t * def ) ;
2016-09-19 22:41:22 +00:00
FSerializer & StringPtr ( const char * key , const char * & charptr ) ; // This only retrieves the address but creates no permanent copy of the string unlike the regular char* serializer.
2016-09-21 10:19:13 +00:00
FSerializer & AddString ( const char * key , const char * charptr ) ;
2016-09-19 22:41:22 +00:00
FSerializer & ScriptNum ( const char * key , int & num ) ;
2016-09-19 08:41:21 +00:00
bool isReading ( ) const
{
return r ! = nullptr ;
}
bool isWriting ( ) const
{
return w ! = nullptr ;
}
bool canSkip ( ) const ;
template < class T >
FSerializer & operator ( ) ( const char * key , T & obj )
{
return Serialize ( * this , key , obj , ( T * ) nullptr ) ;
}
template < class T >
FSerializer & operator ( ) ( const char * key , T & obj , T & def )
{
return Serialize ( * this , key , obj , & def ) ;
}
template < class T >
FSerializer & Array ( const char * key , T * obj , int count , bool fullcompare = false )
{
2016-09-22 22:45:41 +00:00
if ( fullcompare & & isWriting ( ) & & nullcmp ( obj , count * sizeof ( T ) ) )
2016-09-19 08:41:21 +00:00
{
return * this ;
}
if ( BeginArray ( key ) )
{
2016-09-22 09:51:29 +00:00
if ( isReading ( ) )
{
int max = ArraySize ( ) ;
if ( max < count ) count = max ;
}
2016-09-19 08:41:21 +00:00
for ( int i = 0 ; i < count ; i + + )
{
Serialize ( * this , nullptr , obj [ i ] , ( T * ) nullptr ) ;
}
EndArray ( ) ;
}
return * this ;
}
template < class T >
FSerializer & Array ( const char * key , T * obj , T * def , int count , bool fullcompare = false )
{
if ( fullcompare & & isWriting ( ) & & def ! = nullptr & & ! memcmp ( obj , def , count * sizeof ( T ) ) )
{
return * this ;
}
if ( BeginArray ( key ) )
{
2016-09-22 09:53:09 +00:00
if ( isReading ( ) )
{
int max = ArraySize ( ) ;
if ( max < count ) count = max ;
}
2016-09-19 08:41:21 +00:00
for ( int i = 0 ; i < count ; i + + )
{
Serialize ( * this , nullptr , obj [ i ] , def ? & def [ i ] : nullptr ) ;
}
EndArray ( ) ;
}
return * this ;
}
2016-09-19 17:14:30 +00:00
template < class T >
FSerializer & Enum ( const char * key , T & obj )
{
auto val = ( std : : underlying_type < T > : : type ) obj ;
Serialize ( * this , key , val , nullptr ) ;
obj = ( T ) val ;
return * this ;
}
2016-09-19 08:41:21 +00:00
} ;
FSerializer & Serialize ( FSerializer & arc , const char * key , bool & value , bool * defval ) ;
FSerializer & Serialize ( FSerializer & arc , const char * key , int64_t & value , int64_t * defval ) ;
FSerializer & Serialize ( FSerializer & arc , const char * key , uint64_t & value , uint64_t * defval ) ;
FSerializer & Serialize ( FSerializer & arc , const char * key , int32_t & value , int32_t * defval ) ;
FSerializer & Serialize ( FSerializer & arc , const char * key , uint32_t & value , uint32_t * defval ) ;
FSerializer & Serialize ( FSerializer & arc , const char * key , int8_t & value , int8_t * defval ) ;
FSerializer & Serialize ( FSerializer & arc , const char * key , uint8_t & value , uint8_t * defval ) ;
FSerializer & Serialize ( FSerializer & arc , const char * key , int16_t & value , int16_t * defval ) ;
FSerializer & Serialize ( FSerializer & arc , const char * key , uint16_t & value , uint16_t * defval ) ;
FSerializer & Serialize ( FSerializer & arc , const char * key , double & value , double * defval ) ;
FSerializer & Serialize ( FSerializer & arc , const char * key , float & value , float * defval ) ;
FSerializer & Serialize ( FSerializer & arc , const char * key , FTextureID & value , FTextureID * defval ) ;
2016-09-20 16:27:47 +00:00
FSerializer & Serialize ( FSerializer & arc , const char * key , DObject * & value , DObject * * /*defval*/ , bool * retcode = nullptr ) ;
2016-09-19 08:41:21 +00:00
FSerializer & Serialize ( FSerializer & arc , const char * key , FName & value , FName * defval ) ;
FSerializer & Serialize ( FSerializer & arc , const char * key , FSoundID & sid , FSoundID * def ) ;
2016-09-19 22:41:22 +00:00
FSerializer & Serialize ( FSerializer & arc , const char * key , FString & sid , FString * def ) ;
2016-09-20 16:27:47 +00:00
FSerializer & Serialize ( FSerializer & arc , const char * key , NumericValue & sid , NumericValue * def ) ;
2016-09-20 23:18:29 +00:00
FSerializer & Serialize ( FSerializer & arc , const char * key , ticcmd_t & sid , ticcmd_t * def ) ;
FSerializer & Serialize ( FSerializer & arc , const char * key , usercmd_t & cmd , usercmd_t * def ) ;
2016-09-19 08:41:21 +00:00
template < class T >
FSerializer & Serialize ( FSerializer & arc , const char * key , T * & value , T * * )
{
DObject * v = static_cast < DObject * > ( value ) ;
Serialize ( arc , key , v , nullptr ) ;
value = static_cast < T * > ( v ) ;
return arc ;
}
template < class T >
FSerializer & Serialize ( FSerializer & arc , const char * key , TObjPtr < T > & value , TObjPtr < T > * )
{
Serialize ( arc , key , value . o , nullptr ) ;
return arc ;
}
template < class T , class TT >
FSerializer & Serialize ( FSerializer & arc , const char * key , TArray < T , TT > & value , TArray < T , TT > * )
{
if ( arc . isWriting ( ) )
{
if ( value . Size ( ) = = 0 ) return arc ; // do not save empty arrays
}
bool res = arc . BeginArray ( key ) ;
if ( arc . isReading ( ) )
{
if ( ! res )
{
value . Clear ( ) ;
return arc ;
}
value . Resize ( arc . ArraySize ( ) ) ;
}
for ( unsigned i = 0 ; i < value . Size ( ) ; i + + )
{
Serialize ( arc , nullptr , value [ i ] , ( T * ) nullptr ) ;
}
arc . EndArray ( ) ;
return arc ;
}
2016-09-19 17:14:30 +00:00
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , FPolyObj * & value , FPolyObj * * defval ) ;
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , sector_t * & value , sector_t * * defval ) ;
2016-09-20 21:13:12 +00:00
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , const FPolyObj * & value , const FPolyObj * * defval ) ;
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , const sector_t * & value , const sector_t * * defval ) ;
2016-09-19 17:14:30 +00:00
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , player_t * & value , player_t * * defval ) ;
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , line_t * & value , line_t * * defval ) ;
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , side_t * & value , side_t * * defval ) ;
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , vertex_t * & value , vertex_t * * defval ) ;
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , FDynamicColormap * & cm , FDynamicColormap * * def ) ;
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , PClassActor * & clst , PClassActor * * def ) ;
2016-09-20 16:27:47 +00:00
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , PClass * & clst , PClass * * def ) ;
2016-09-19 17:14:30 +00:00
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , FStrifeDialogueNode * & node , FStrifeDialogueNode * * def ) ;
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , FString * & pstr , FString * * def ) ;
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , FDoorAnimation * & pstr , FDoorAnimation * * def ) ;
2016-09-19 22:41:22 +00:00
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , char * & pstr , char * * def ) ;
2016-09-20 11:21:41 +00:00
template < > FSerializer & Serialize ( FSerializer & arc , const char * key , FFont * & font , FFont * * def ) ;
2016-09-19 17:14:30 +00:00
2016-09-20 23:18:29 +00:00
template < > inline FSerializer & Serialize ( FSerializer & arc , const char * key , PClassPlayerPawn * & clst , PClassPlayerPawn * * def )
{
return Serialize ( arc , key , ( PClassActor * & ) clst , ( PClassActor * * ) def ) ;
}
2016-09-20 21:13:12 +00:00
2016-09-20 16:27:47 +00:00
FSerializer & Serialize ( FSerializer & arc , const char * key , FState * & state , FState * * def , bool * retcode ) ;
template < > inline FSerializer & Serialize ( FSerializer & arc , const char * key , FState * & state , FState * * def )
{
return Serialize ( arc , key , state , def , nullptr ) ;
}
2016-09-19 17:14:30 +00:00
2016-09-19 08:41:21 +00:00
inline FSerializer & Serialize ( FSerializer & arc , const char * key , DVector3 & p , DVector3 * def )
{
return arc . Array < double > ( key , & p [ 0 ] , def ? & ( * def ) [ 0 ] : nullptr , 3 , true ) ;
}
inline FSerializer & Serialize ( FSerializer & arc , const char * key , DRotator & p , DRotator * def )
{
return arc . Array < DAngle > ( key , & p [ 0 ] , def ? & ( * def ) [ 0 ] : nullptr , 3 , true ) ;
}
inline FSerializer & Serialize ( FSerializer & arc , const char * key , DVector2 & p , DVector2 * def )
{
return arc . Array < double > ( key , & p [ 0 ] , def ? & ( * def ) [ 0 ] : nullptr , 2 , true ) ;
}
inline FSerializer & Serialize ( FSerializer & arc , const char * key , DAngle & p , DAngle * def )
{
return Serialize ( arc , key , p . Degrees , def ? & def - > Degrees : nullptr ) ;
}
inline FSerializer & Serialize ( FSerializer & arc , const char * key , PalEntry & pe , PalEntry * def )
{
return Serialize ( arc , key , pe . d , def ? & def - > d : nullptr ) ;
}
inline FSerializer & Serialize ( FSerializer & arc , const char * key , FRenderStyle & style , FRenderStyle * def )
{
2016-09-20 21:13:12 +00:00
return arc . Array ( key , & style . BlendOp , def ? & def - > BlendOp : nullptr , 4 ) ;
2016-09-19 08:41:21 +00:00
}
template < class T , class TT >
FSerializer & Serialize ( FSerializer & arc , const char * key , TFlags < T , TT > & flags , TFlags < T , TT > * def )
{
return Serialize ( arc , key , flags . Value , def ? & def - > Value : nullptr ) ;
}
# endif