Updated serialization framework with support for arbitrary object types

This was SVN commit r122.
This commit is contained in:
Simon Brenner 2003-11-30 16:36:43 +00:00
parent 0e658da83d
commit 6026b76adc
4 changed files with 164 additions and 36 deletions

View File

@ -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()

View File

@ -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"

View File

@ -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
{

View File

@ -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