forked from 0ad/0ad
Updated serialization framework with support for arbitrary object types
This was SVN commit r122.
This commit is contained in:
parent
0e658da83d
commit
6026b76adc
@ -2,6 +2,7 @@
|
||||
#define _AllNetMessages_H
|
||||
|
||||
#include "types.h"
|
||||
#include "CStr.h"
|
||||
|
||||
enum NetMessageType
|
||||
{
|
||||
@ -40,11 +41,13 @@ enum NetMessageType
|
||||
START_NMTS()
|
||||
|
||||
START_NMT_CLASS(AlohaMessage, NMT_Aloha)
|
||||
NMT_FIELD_INT(m_AlohaCode, uint, 4)
|
||||
// NMT_FIELD_INT(m_AlohaCode, u64, 8)
|
||||
NMT_FIELD(CStr, m_AlohaCode)
|
||||
END_NMT_CLASS()
|
||||
|
||||
START_NMT_CLASS(SayonaraMessage, NMT_Sayonara)
|
||||
NMT_FIELD_INT(m_SayonaraCode, uint, 4)
|
||||
// NMT_FIELD_INT(m_SayonaraCode, u64, 8)
|
||||
NMT_FIELD(CStr, m_SayonaraCode)
|
||||
END_NMT_CLASS()
|
||||
|
||||
END_NMTS()
|
||||
|
@ -9,6 +9,7 @@
|
||||
#undef END_NMTS
|
||||
#undef START_NMT_CLASS
|
||||
#undef NMT_FIELD_INT
|
||||
#undef NMT_FIELD
|
||||
#undef END_NMT_CLASS
|
||||
|
||||
#else
|
||||
@ -23,17 +24,45 @@
|
||||
#define START_NMTS()
|
||||
#define END_NMTS()
|
||||
|
||||
/**
|
||||
* Start the definition of a network message type.
|
||||
*
|
||||
* @param _nm The name of the class
|
||||
* @param _tp The NetMessageType associated with the class. IT is *not* safe to
|
||||
* have several classes with the same value of _tp in the same executable
|
||||
*/
|
||||
#define START_NMT_CLASS(_nm, _tp) \
|
||||
CNetMessage *Deserialize##_nm(u8 *, uint); \
|
||||
CNetMessage *Deserialize##_nm(const u8 *, uint); \
|
||||
struct _nm: public CNetMessage \
|
||||
{ \
|
||||
_nm(): CNetMessage(_tp) {} \
|
||||
virtual uint GetSerializedLength() const; \
|
||||
virtual void Serialize(u8 *buffer) const;
|
||||
|
||||
/**
|
||||
* Add an integer field to the message type.
|
||||
*
|
||||
* @param _nm The name of the field
|
||||
* @param _hosttp The local type of the field (the data type used in the field
|
||||
* definition)
|
||||
* @param _netsz The number of bytes that should be serialized. If the variable
|
||||
* has a value larger than the maximum value of the specified network size,
|
||||
* higher order bytes will be discarded.
|
||||
*/
|
||||
#define NMT_FIELD_INT(_nm, _hosttp, _netsz) \
|
||||
_hosttp _nm;
|
||||
|
||||
/**
|
||||
* Add a generic field to the message type. The data type must be a class
|
||||
* implementing the ISerializable interface
|
||||
*
|
||||
* @param _tp The local data type of the field
|
||||
* @param _nm The name of the field
|
||||
* @see ISerializable
|
||||
*/
|
||||
#define NMT_FIELD(_tp, _nm) \
|
||||
_tp _nm;
|
||||
|
||||
#define END_NMT_CLASS() };
|
||||
|
||||
#include "NMTCreator.h"
|
||||
@ -53,6 +82,9 @@ uint _nm::GetSerializedLength() const \
|
||||
#define NMT_FIELD_INT(_nm, _hosttp, _netsz) \
|
||||
ret += _netsz;
|
||||
|
||||
#define NMT_FIELD(_tp, _nm) \
|
||||
ret += _nm.GetSerializedLength();
|
||||
|
||||
#define END_NMT_CLASS() \
|
||||
return ret; \
|
||||
};
|
||||
@ -67,11 +99,14 @@ uint _nm::GetSerializedLength() const \
|
||||
#define START_NMT_CLASS(_nm, _tp) \
|
||||
void _nm::Serialize(u8 *buffer) const \
|
||||
{ \
|
||||
printf("In " #_nm "::Serialize()\n"); \
|
||||
/*printf("In " #_nm "::Serialize()\n");*/ \
|
||||
u8 *pos=buffer; \
|
||||
|
||||
#define NMT_FIELD_INT(_nm, _hosttp, _netsz) \
|
||||
pos=SerializeInt<_hosttp, _netsz>(pos, _nm); \
|
||||
Serialize_int_##_netsz(pos, _nm); \
|
||||
|
||||
#define NMT_FIELD(_tp, _nm) \
|
||||
pos=_nm.Serialize(pos);
|
||||
|
||||
#define END_NMT_CLASS() }
|
||||
|
||||
@ -82,17 +117,23 @@ void _nm::Serialize(u8 *buffer) const \
|
||||
#define START_NMTS()
|
||||
#define END_NMTS()
|
||||
|
||||
#define BAIL_DESERIALIZER STMT( delete ret; return NULL; )
|
||||
|
||||
#define START_NMT_CLASS(_nm, _tp) \
|
||||
CNetMessage *Deserialize##_nm(u8 *buffer, uint length) \
|
||||
CNetMessage *Deserialize##_nm(const u8 *buffer, uint length) \
|
||||
{ \
|
||||
printf("In Deserialize" #_nm "\n"); \
|
||||
/*printf("In Deserialize" #_nm "\n"); */\
|
||||
_nm *ret=new _nm(); \
|
||||
u8 *pos=buffer; \
|
||||
u8 *end=buffer+length; \
|
||||
const u8 *pos=buffer; \
|
||||
const u8 *end=buffer+length; \
|
||||
|
||||
#define NMT_FIELD_INT(_nm, _hosttp, _netsz) \
|
||||
ret->_nm=DeserializeInt<_hosttp, _netsz>(&pos); \
|
||||
printf("\t" #_nm " == 0x%x\n", ret->_nm);
|
||||
if (pos+_netsz >= end) BAIL_DESERIALIZER; \
|
||||
Deserialize_int_##_netsz(pos, (ret->_nm)); \
|
||||
/*printf("\t" #_nm " == 0x%x\n", ret->_nm);*/
|
||||
|
||||
#define NMT_FIELD(_tp, _nm) \
|
||||
if ((pos=ret->_nm.Deserialize(pos, end)) == NULL) BAIL_DESERIALIZER;
|
||||
|
||||
#define END_NMT_CLASS() \
|
||||
return ret; \
|
||||
@ -100,6 +141,8 @@ CNetMessage *Deserialize##_nm(u8 *buffer, uint length) \
|
||||
|
||||
#include "NMTCreator.h"
|
||||
|
||||
#undef BAIL_DESERIALIZER
|
||||
|
||||
/*************************************************************************/
|
||||
// Pass 5, Deserializer Registration
|
||||
#define START_NMTS() SNetMessageDeserializerRegistration g_DeserializerRegistrations[] = {
|
||||
@ -110,6 +153,8 @@ CNetMessage *Deserialize##_nm(u8 *buffer, uint length) \
|
||||
|
||||
#define NMT_FIELD_INT(_nm, _hosttp, _netsz)
|
||||
|
||||
#define NMT_FIELD(_tp, _nm)
|
||||
|
||||
#define END_NMT_CLASS()
|
||||
|
||||
#include "NMTCreator.h"
|
||||
|
@ -14,21 +14,36 @@ protected:
|
||||
inline CNetMessage(NetMessageType type):
|
||||
m_Type(type)
|
||||
{}
|
||||
public:
|
||||
inline CNetMessage(): m_Type(NMT_NONE)
|
||||
{}
|
||||
|
||||
public:
|
||||
inline NetMessageType GetType() const
|
||||
{ return m_Type; }
|
||||
|
||||
/**
|
||||
* @returns The length of the message when serialized.
|
||||
*/
|
||||
virtual uint GetSerializedLength() const;
|
||||
/**
|
||||
* Serialize the message into the buffer. The buffer will have the size
|
||||
* returned from the last call to GetSerializedLength()
|
||||
*/
|
||||
virtual void Serialize(u8 *buffer) const;
|
||||
|
||||
/**
|
||||
* Deserialize a net message, using the globally registered deserializers.
|
||||
*
|
||||
* @param type The NetMessageType of the message
|
||||
* @param buffer A pointer to the buffer holding the message data
|
||||
* @param length The length of the message data
|
||||
*
|
||||
* @returns a pointer to a newly created CNetMessage subclass, or NULL if
|
||||
* there was an error in data format.
|
||||
*/
|
||||
static CNetMessage *DeserializeMessage(NetMessageType type, u8 *buffer, uint length);
|
||||
};
|
||||
|
||||
class CNetMessage;
|
||||
typedef CNetMessage * (*NetMessageDeserializer) (u8 *buffer, uint length);
|
||||
typedef CNetMessage * (*NetMessageDeserializer) (const u8 *buffer, uint length);
|
||||
|
||||
struct SNetMessageDeserializerRegistration
|
||||
{
|
||||
|
@ -2,29 +2,94 @@
|
||||
#define _Serialization_H
|
||||
|
||||
#include "types.h"
|
||||
#include "misc.h"
|
||||
|
||||
template <typename _T, int netsize>
|
||||
inline u8 *SerializeInt(u8 *pos, _T val)
|
||||
{
|
||||
for (int i=0;i<netsize;i++)
|
||||
{
|
||||
*(pos++)=val&0xff;
|
||||
val >>= 8;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
#define Serialize_int_1(_pos, _val) \
|
||||
STMT( *((_pos)++) = _val&0xff; )
|
||||
|
||||
template <typename _T, int netsize>
|
||||
inline _T DeserializeInt(u8 **pos)
|
||||
#define Serialize_int_2(_pos, _val) STMT(\
|
||||
Serialize_int_1(_pos, _val>>8); \
|
||||
Serialize_int_1(_pos, _val); \
|
||||
)
|
||||
|
||||
#define Serialize_int_3(_pos, _val) STMT(\
|
||||
Serialize_int_1(_pos, _val>>16); \
|
||||
Serialize_int_2(_pos, _val); \
|
||||
)
|
||||
|
||||
#define Serialize_int_4(_pos, _val) STMT(\
|
||||
Serialize_int_1(_pos, _val>>24); \
|
||||
Serialize_int_3(_pos, _val); \
|
||||
)
|
||||
|
||||
#define Serialize_int_8(_pos, _val) STMT(\
|
||||
Serialize_int_4(_pos, _val>>32); \
|
||||
Serialize_int_4(_pos, _val); \
|
||||
)
|
||||
|
||||
#define Deserialize_int_1(_pos, _val) STMT(\
|
||||
(_val) -= (_val) & 0xff; \
|
||||
(_val) += *((_pos)++); )
|
||||
|
||||
#define Deserialize_int_2(_pos, _val) STMT(\
|
||||
Deserialize_int_1(_pos, _val); \
|
||||
_val <<= 8; \
|
||||
Deserialize_int_1(_pos, _val); )
|
||||
|
||||
#define Deserialize_int_3(_pos, _val) STMT(\
|
||||
Deserialize_int_2(_pos, _val); \
|
||||
_val <<= 8; \
|
||||
Deserialize_int_1(_pos, _val); )
|
||||
|
||||
#define Deserialize_int_4(_pos, _val) STMT(\
|
||||
Deserialize_int_3(_pos, _val); \
|
||||
_val <<= 8; \
|
||||
Deserialize_int_1(_pos, _val); )
|
||||
|
||||
#define Deserialize_int_8(_pos, _val) STMT(\
|
||||
Deserialize_int_4(_pos, _val); \
|
||||
_val <<= 8; \
|
||||
Deserialize_int_4(_pos, _val); )
|
||||
|
||||
/*#define Serialize_CStr(_pos, _str) STMT( \
|
||||
uint len=_str.Length(); \
|
||||
Serialize_int_4(_pos, len); \
|
||||
memcpy(_pos, _str, len+1); _pos += len+1; )
|
||||
|
||||
#define Deserialize_CStr(_pos, _str) STMT( \
|
||||
uint len; Deserialize_int_4(_pos, len); \
|
||||
_str=CStr((char *)_pos); _pos += len+1; )*/
|
||||
|
||||
/**
|
||||
* An interface for serializable objects. For a serializable object to be usable
|
||||
* as a network message field, it must have a constructor without arguments.
|
||||
*/
|
||||
class ISerializable
|
||||
{
|
||||
_T val=0;
|
||||
uint i=netsize;
|
||||
while (i--)
|
||||
{
|
||||
val = (val << 8) + (*pos)[i];
|
||||
}
|
||||
(*pos) += netsize;
|
||||
return val;
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* Return the length of the serialized form of this object
|
||||
*/
|
||||
virtual uint GetSerializedLength() const = 0;
|
||||
/**
|
||||
* Serialize the object into the passed buffer.
|
||||
*
|
||||
* @return a pointer to the location in the buffer right after the
|
||||
* serialized object
|
||||
*/
|
||||
virtual u8 *Serialize(u8 *buffer) const = 0;
|
||||
/**
|
||||
* Deserialize the object (i.e. read in data from the buffer and initialize
|
||||
* the object's fields). Note that it is up to the deserializer to detect
|
||||
* errors in data format.
|
||||
*
|
||||
* @param buffer A pointer pointing to the start of the serialized data.
|
||||
* @param end A pointer to the end of the message.
|
||||
*
|
||||
* @returns a pointer to the location in the buffer right after the
|
||||
* serialized object, or NULL if there was a data format error
|
||||
*/
|
||||
virtual const u8 *Deserialize(const u8 *buffer, const u8 *end) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user