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