1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
|
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Serialization.h"
#include <vector>
// If included from within the NMT Creation process, perform a pass
#ifdef CREATING_NMT
#include NMT_CREATE_HEADER_NAME
#undef START_NMTS
#undef END_NMTS
#undef START_NMT_CLASS
#undef START_NMT_CLASS_DERIVED
#undef NMT_FIELD_INT
#undef NMT_FIELD
#undef NMT_START_ARRAY
#undef NMT_END_ARRAY
#undef END_NMT_CLASS
#else
// If not within the creation process, and called with argument, perform the
// creation process with the header specified
#ifdef NMT_CREATE_HEADER_NAME
#ifndef ARRAY_STRUCT_PREFIX
#define ARRAY_STRUCT_PREFIX(_nm) S_##_nm
#endif
#define CREATING_NMT
#ifndef NMT_CREATOR_IMPLEMENT
/*************************************************************************/
// Pass 1, class definition
#define NMT_CREATOR_PASS_CLASSDEF
#define START_NMTS()
#define END_NMTS()
#define START_NMT_CLASS(_nm, _tp) \
START_NMT_CLASS_DERIVED(CNetMessage, _nm, _tp)
/**
* Start the definition of a network message type.
*
* @param _base The name of the base class of the message
* @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_DERIVED(_base, _nm, _tp) \
CNetMessage *Deserialize##_nm(const u8 *, size_t); \
class _nm: public _base \
{ \
protected: \
_nm(NetMessageType type): _base(type) {}\
\
/* This one is for subclasses that want to use the base class' string */ \
/* converters to get SubMessage { <parent fields>, ... } */ \
CStr ToStringRaw() const;\
public: \
_nm(): _base(_tp) {} \
virtual size_t GetSerializedLength() const; \
virtual u8 *Serialize(u8 *buffer) const; \
virtual const u8 *Deserialize(const u8 *pos, const u8 *end); \
virtual CStr ToString() const; \
inline operator CStr () const \
{ return ToString(); }
/**
* 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 NMT_START_ARRAY(_nm) \
struct ARRAY_STRUCT_PREFIX(_nm); \
std::vector <ARRAY_STRUCT_PREFIX(_nm)> _nm; \
struct ARRAY_STRUCT_PREFIX(_nm) {
#define NMT_END_ARRAY() \
};
#define END_NMT_CLASS() };
#include "NMTCreator.h"
#undef NMT_CREATOR_PASS_CLASSDEF
#else // NMT_CREATOR_IMPLEMENT
#include "StringConverters.h"
/*************************************************************************/
// Pass 2, GetSerializedLength
#define NMT_CREATOR_PASS_GETLENGTH
#define START_NMTS()
#define END_NMTS()
#define START_NMT_CLASS(_nm, _tp) \
START_NMT_CLASS_DERIVED(CNetMessage, _nm, _tp)
#define START_NMT_CLASS_DERIVED(_base, _nm, _tp) \
size_t _nm::GetSerializedLength() const \
{ \
size_t ret=_base::GetSerializedLength(); \
const _nm *thiz=this;\
UNUSED2(thiz); // preempt any "unused" warning
#define NMT_START_ARRAY(_nm) \
std::vector <ARRAY_STRUCT_PREFIX(_nm)>::const_iterator it=_nm.begin(); \
while (it != _nm.end()) \
{ \
const ARRAY_STRUCT_PREFIX(_nm) *thiz=&*it;\
UNUSED2(thiz); // preempt any "unused" warning
#define NMT_END_ARRAY() \
++it; \
}
#define NMT_FIELD_INT(_nm, _hosttp, _netsz) \
ret += _netsz;
#define NMT_FIELD(_tp, _nm) \
ret += thiz->_nm.GetSerializedLength();
#define END_NMT_CLASS() \
return ret; \
};
#include "NMTCreator.h"
#undef NMT_CREATOR_PASS_GETLENGTH
/*************************************************************************/
// Pass 3, Serialize
#define NMT_CREATOR_PASS_SERIALIZE
#define START_NMTS()
#define END_NMTS()
#define START_NMT_CLASS(_nm, _tp) \
START_NMT_CLASS_DERIVED(CNetMessage, _nm, _tp)
#define START_NMT_CLASS_DERIVED(_base, _nm, _tp) \
u8 *_nm::Serialize(u8 *buffer) const \
{ \
/*printf("In " #_nm "::Serialize()\n");*/ \
u8 *pos=_base::Serialize(buffer); \
const _nm *thiz=this;\
UNUSED2(thiz); // preempt any "unused" warning
#define NMT_START_ARRAY(_nm) \
std::vector <ARRAY_STRUCT_PREFIX(_nm)>::const_iterator it=_nm.begin(); \
while (it != _nm.end()) \
{ \
const ARRAY_STRUCT_PREFIX(_nm) *thiz=&*it;\
UNUSED2(thiz); // preempt any "unused" warning
#define NMT_END_ARRAY() \
++it; \
}
#define NMT_FIELD_INT(_nm, _hosttp, _netsz) \
Serialize_int_##_netsz(pos, thiz->_nm); \
#define NMT_FIELD(_tp, _nm) \
pos=thiz->_nm.Serialize(pos);
#define END_NMT_CLASS() \
return pos; \
}
#include "NMTCreator.h"
#undef NMT_CREATOR_PASS_SERIALIZE
/*************************************************************************/
// Pass 4, Deserialize
#define NMT_CREATOR_PASS_DESERIALIZE
#define START_NMTS()
#define END_NMTS()
#define BAIL_DESERIALIZER return NULL
#define START_NMT_CLASS(_nm, _tp) \
START_NMT_CLASS_DERIVED(CNetMessage, _nm, _tp)
#define START_NMT_CLASS_DERIVED(_base, _nm, _tp) \
const u8 *_nm::Deserialize(const u8 *pos, const u8 *end) \
{ \
pos=_base::Deserialize(pos, end); \
_nm *thiz=this; \
/*printf("In Deserialize" #_nm "\n"); */\
UNUSED2(thiz); // preempt any "unused" warning
#define NMT_START_ARRAY(_nm) \
while (pos < end) \
{ \
ARRAY_STRUCT_PREFIX(_nm) *thiz=&*_nm.insert(_nm.end(), ARRAY_STRUCT_PREFIX(_nm)());\
UNUSED2(thiz); // preempt any "unused" warning
#define NMT_END_ARRAY() \
}
#define NMT_FIELD_INT(_nm, _hosttp, _netsz) \
if (pos+_netsz > end) BAIL_DESERIALIZER; \
Deserialize_int_##_netsz(pos, thiz->_nm); \
/*printf("\t" #_nm " == 0x%x\n", thiz->_nm);*/
#define NMT_FIELD(_tp, _nm) \
if ((pos=thiz->_nm.Deserialize(pos, end)) == NULL) BAIL_DESERIALIZER;
#define END_NMT_CLASS() \
return pos; \
}
#include "NMTCreator.h"
#undef BAIL_DESERIALIZER
#undef NMT_CREATOR_PASS_DESERIALIZE
/*************************************************************************/
// Pass 5, String Representation
#define START_NMTS()
#define END_NMTS()
#define START_NMT_CLASS(_nm, _tp) \
CStr _nm::ToString() const \
{ \
CStr ret=#_nm " { "; \
return ret + ToStringRaw() + " }"; \
} \
CStr _nm::ToStringRaw() const \
{ \
CStr ret; \
const _nm *thiz=this;\
UNUSED2(thiz); // preempt any "unused" warning
#define START_NMT_CLASS_DERIVED(_base, _nm, _tp) \
CStr _nm::ToString() const \
{ \
CStr ret=#_nm " { "; \
return ret + ToStringRaw() + " }"; \
} \
CStr _nm::ToStringRaw() const \
{ \
CStr ret=_base::ToStringRaw() + ", "; \
const _nm *thiz=this;\
UNUSED2(thiz); // preempt any "unused" warning
#define NMT_START_ARRAY(_nm) \
ret+=#_nm ": { "; \
std::vector < ARRAY_STRUCT_PREFIX(_nm) >::const_iterator it=_nm.begin(); \
while (it != _nm.end()) \
{ \
ret+=" { "; \
const ARRAY_STRUCT_PREFIX(_nm) *thiz=&*it;\
UNUSED2(thiz); // preempt any "unused" warning
#define NMT_END_ARRAY() \
++it; \
ret=ret.substr(0, ret.length()-2)+" }, "; \
} \
ret=ret.substr(0, ret.length()-2)+" }, ";
#define NMT_FIELD_INT(_nm, _hosttp, _netsz) \
ret += #_nm ": "; \
ret += NetMessageStringConvert(thiz->_nm); \
ret += ", ";
#define NMT_FIELD(_tp, _nm) \
ret += #_nm ": "; \
ret += NetMessageStringConvert(thiz->_nm); \
ret += ", ";
#define END_NMT_CLASS() \
return ret.substr(0, ret.length()-2); \
}
#include "NMTCreator.h"
#endif // #ifdef NMT_CREATOR_IMPLEMENT
/*************************************************************************/
// Cleanup
#undef NMT_CREATE_HEADER_NAME
#undef NMT_CREATOR_IMPLEMENT
#undef CREATING_NMT
#endif // #ifdef NMT_CREATE_HEADER_NAME
#endif // #ifndef CREATING_NMT
|