Pyrogenesis  trunk
NMTCreator.h
Go to the documentation of this file.
1 /* Copyright (C) 2020 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_FIELD_SECRET
33 #undef NMT_START_ARRAY
34 #undef NMT_END_ARRAY
35 #undef END_NMT_CLASS
36 
37 #else
38 // If not within the creation process, and called with argument, perform the
39 // creation process with the header specified
40 #ifdef NMT_CREATE_HEADER_NAME
41 
42 #ifndef ARRAY_STRUCT_PREFIX
43 #define ARRAY_STRUCT_PREFIX(_nm) S_##_nm
44 #endif
45 
46 #define CREATING_NMT
47 
48 #ifndef NMT_CREATOR_IMPLEMENT
49 
50 /*************************************************************************/
51 // Pass 1, class definition
52 #define NMT_CREATOR_PASS_CLASSDEF
53 #define START_NMTS()
54 #define END_NMTS()
55 
56 #define START_NMT_CLASS(_nm, _tp) \
57  START_NMT_CLASS_DERIVED(CNetMessage, _nm, _tp)
58 
59 /**
60  * Start the definition of a network message type.
61  *
62  * @param _base The name of the base class of the message
63  * @param _nm The name of the class
64  * @param _tp The NetMessageType associated with the class. It is *not* safe to
65  * have several classes with the same value of _tp in the same executable
66  */
67 #define START_NMT_CLASS_DERIVED(_base, _nm, _tp) \
68 CNetMessage *Deserialize##_nm(const u8 *, size_t); \
69 class _nm: public _base \
70 { \
71 protected: \
72  _nm(NetMessageType type): _base(type) {}\
73  \
74  /* This one is for subclasses that want to use the base class' string */ \
75  /* converters to get SubMessage { <parent fields>, ... } */ \
76  CStr ToStringRaw() const;\
77 public: \
78  _nm(): _base(_tp) {} \
79  virtual size_t GetSerializedLength() const; \
80  virtual u8 *Serialize(u8 *buffer) const; \
81  virtual const u8 *Deserialize(const u8 *pos, const u8 *end); \
82  virtual CStr ToString() const; \
83  inline operator CStr () const \
84  { return ToString(); }
85 
86 /**
87  * Add an integer field to the message type.
88  *
89  * @param _nm The name of the field
90  * @param _hosttp The local type of the field (the data type used in the field
91  * definition)
92  * @param _netsz The number of bytes that should be serialized. If the variable
93  * has a value larger than the maximum value of the specified network size,
94  * higher order bytes will be discarded.
95  */
96 #define NMT_FIELD_INT(_nm, _hosttp, _netsz) \
97  _hosttp _nm;
98 
99 /**
100  * Add a generic field to the message type. The data type must be a class
101  * implementing the ISerializable interface
102  *
103  * @param _tp The local data type of the field
104  * @param _nm The name of the field
105  * @see ISerializable
106  */
107 #define NMT_FIELD(_tp, _nm) \
108  _tp _nm;
109 
110 /**
111  * Likewise, but the string representation is hidden.
112  * NB: the data length is not hidden, so make sure to use fixed-length data if confidentiality is desirable.
113  */
114 #define NMT_FIELD_SECRET(_tp, _nm) \
115  _tp _nm;
116 
117 #define NMT_START_ARRAY(_nm) \
118  struct ARRAY_STRUCT_PREFIX(_nm); \
119  std::vector <ARRAY_STRUCT_PREFIX(_nm)> _nm; \
120  struct ARRAY_STRUCT_PREFIX(_nm) {
121 
122 #define NMT_END_ARRAY() \
123  };
124 
125 #define END_NMT_CLASS() };
126 
127 #include "NMTCreator.h"
128 #undef NMT_CREATOR_PASS_CLASSDEF
129 
130 #else // NMT_CREATOR_IMPLEMENT
131 
132 #include "StringConverters.h"
133 
134 /*************************************************************************/
135 // Pass 2, GetSerializedLength
136 #define NMT_CREATOR_PASS_GETLENGTH
137 #define START_NMTS()
138 #define END_NMTS()
139 
140 #define START_NMT_CLASS(_nm, _tp) \
141  START_NMT_CLASS_DERIVED(CNetMessage, _nm, _tp)
142 #define START_NMT_CLASS_DERIVED(_base, _nm, _tp) \
143 size_t _nm::GetSerializedLength() const \
144 { \
145  size_t ret=_base::GetSerializedLength(); \
146  const _nm *thiz=this;\
147  UNUSED2(thiz); // preempt any "unused" warning
148 
149 #define NMT_START_ARRAY(_nm) \
150  std::vector <ARRAY_STRUCT_PREFIX(_nm)>::const_iterator it=_nm.begin(); \
151  while (it != _nm.end()) \
152  { \
153  const ARRAY_STRUCT_PREFIX(_nm) *thiz=&*it;\
154  UNUSED2(thiz); // preempt any "unused" warning
155 
156 #define NMT_END_ARRAY() \
157  ++it; \
158  }
159 
160 #define NMT_FIELD_INT(_nm, _hosttp, _netsz) \
161  ret += _netsz;
162 
163 #define NMT_FIELD(_tp, _nm) \
164  ret += thiz->_nm.GetSerializedLength();
165 
166 #define NMT_FIELD_SECRET(_tp, _nm) \
167  ret += thiz->_nm.GetSerializedLength();
168 
169 #define END_NMT_CLASS() \
170  return ret; \
171 };
172 
173 #include "NMTCreator.h"
174 #undef NMT_CREATOR_PASS_GETLENGTH
175 
176 /*************************************************************************/
177 // Pass 3, Serialize
178 
179 #define NMT_CREATOR_PASS_SERIALIZE
180 
181 #define START_NMTS()
182 #define END_NMTS()
183 
184 #define START_NMT_CLASS(_nm, _tp) \
185  START_NMT_CLASS_DERIVED(CNetMessage, _nm, _tp)
186 #define START_NMT_CLASS_DERIVED(_base, _nm, _tp) \
187 u8 *_nm::Serialize(u8 *buffer) const \
188 { \
189  /*printf("In " #_nm "::Serialize()\n");*/ \
190  u8 *pos=_base::Serialize(buffer); \
191  const _nm *thiz=this;\
192  UNUSED2(thiz); // preempt any "unused" warning
193 
194 #define NMT_START_ARRAY(_nm) \
195  std::vector <ARRAY_STRUCT_PREFIX(_nm)>::const_iterator it=_nm.begin(); \
196  while (it != _nm.end()) \
197  { \
198  const ARRAY_STRUCT_PREFIX(_nm) *thiz=&*it;\
199  UNUSED2(thiz); // preempt any "unused" warning
200 
201 #define NMT_END_ARRAY() \
202  ++it; \
203  }
204 
205 #define NMT_FIELD_INT(_nm, _hosttp, _netsz) \
206  Serialize_int_##_netsz(pos, thiz->_nm); \
207 
208 #define NMT_FIELD(_tp, _nm) \
209  pos=thiz->_nm.Serialize(pos);
210 
211 #define NMT_FIELD_SECRET(_tp, _nm) \
212  pos=thiz->_nm.Serialize(pos);
213 
214 #define END_NMT_CLASS() \
215  return pos; \
216 }
217 
218 #include "NMTCreator.h"
219 
220 #undef NMT_CREATOR_PASS_SERIALIZE
221 
222 /*************************************************************************/
223 // Pass 4, Deserialize
224 
225 #define NMT_CREATOR_PASS_DESERIALIZE
226 
227 #define START_NMTS()
228 #define END_NMTS()
229 
230 #define BAIL_DESERIALIZER return NULL
231 
232 #define START_NMT_CLASS(_nm, _tp) \
233  START_NMT_CLASS_DERIVED(CNetMessage, _nm, _tp)
234 #define START_NMT_CLASS_DERIVED(_base, _nm, _tp) \
235 const u8 *_nm::Deserialize(const u8 *pos, const u8 *end) \
236 { \
237  pos=_base::Deserialize(pos, end); \
238  if (pos == NULL) BAIL_DESERIALIZER;\
239  _nm *thiz=this; \
240  /*printf("In Deserialize" #_nm "\n"); */\
241  UNUSED2(thiz); // preempt any "unused" warning
242 
243 
244 #define NMT_START_ARRAY(_nm) \
245  while (pos < end) \
246  { \
247  ARRAY_STRUCT_PREFIX(_nm) *thiz=&*_nm.insert(_nm.end(), ARRAY_STRUCT_PREFIX(_nm)());\
248  UNUSED2(thiz); // preempt any "unused" warning
249 
250 #define NMT_END_ARRAY() \
251  }
252 
253 #define NMT_FIELD_INT(_nm, _hosttp, _netsz) \
254  if (pos+_netsz > end) BAIL_DESERIALIZER; \
255  Deserialize_int_##_netsz(pos, thiz->_nm); \
256  /*printf("\t" #_nm " == 0x%x\n", thiz->_nm);*/
257 
258 #define NMT_FIELD(_tp, _nm) \
259  if ((pos=thiz->_nm.Deserialize(pos, end)) == NULL) BAIL_DESERIALIZER;
260 
261 #define NMT_FIELD_SECRET(_tp, _nm) \
262  if ((pos=thiz->_nm.Deserialize(pos, end)) == NULL) BAIL_DESERIALIZER;
263 
264 #define END_NMT_CLASS() \
265  return pos; \
266 }
267 
268 #include "NMTCreator.h"
269 
270 #undef BAIL_DESERIALIZER
271 
272 #undef NMT_CREATOR_PASS_DESERIALIZE
273 
274 /*************************************************************************/
275 // Pass 5, String Representation
276 
277 #define START_NMTS()
278 #define END_NMTS()
279 
280 #define START_NMT_CLASS(_nm, _tp) \
281 CStr _nm::ToString() const \
282 { \
283  CStr ret=#_nm " { "; \
284  return ret + ToStringRaw() + " }"; \
285 } \
286 CStr _nm::ToStringRaw() const \
287 { \
288  CStr ret; \
289  const _nm *thiz=this;\
290  UNUSED2(thiz); // preempt any "unused" warning
291 
292 #define START_NMT_CLASS_DERIVED(_base, _nm, _tp) \
293 CStr _nm::ToString() const \
294 { \
295  CStr ret=#_nm " { "; \
296  return ret + ToStringRaw() + " }"; \
297 } \
298 CStr _nm::ToStringRaw() const \
299 { \
300  CStr ret=_base::ToStringRaw() + ", "; \
301  const _nm *thiz=this;\
302  UNUSED2(thiz); // preempt any "unused" warning
303 
304 #define NMT_START_ARRAY(_nm) \
305  ret+=#_nm ": { "; \
306  std::vector < ARRAY_STRUCT_PREFIX(_nm) >::const_iterator it=_nm.begin(); \
307  while (it != _nm.end()) \
308  { \
309  ret+=" { "; \
310  const ARRAY_STRUCT_PREFIX(_nm) *thiz=&*it;\
311  UNUSED2(thiz); // preempt any "unused" warning
312 
313 #define NMT_END_ARRAY() \
314  ++it; \
315  ret=ret.substr(0, ret.length()-2)+" }, "; \
316  } \
317  ret=ret.substr(0, ret.length()-2)+" }, ";
318 
319 #define NMT_FIELD_INT(_nm, _hosttp, _netsz) \
320  ret += #_nm ": "; \
321  ret += NetMessageStringConvert(thiz->_nm); \
322  ret += ", ";
323 
324 #define NMT_FIELD(_tp, _nm) \
325  ret += #_nm ": "; \
326  ret += NetMessageStringConvert(thiz->_nm); \
327  ret += ", ";
328 
329 #define NMT_FIELD_SECRET(_tp, _nm) \
330  ret += #_nm ": [secret], ";
331 
332 #define END_NMT_CLASS() \
333  return ret.substr(0, ret.length()-2); \
334 }
335 
336 #include "NMTCreator.h"
337 
338 #endif // #ifdef NMT_CREATOR_IMPLEMENT
339 
340 /*************************************************************************/
341 // Cleanup
342 #undef NMT_CREATE_HEADER_NAME
343 #undef NMT_CREATOR_IMPLEMENT
344 #undef CREATING_NMT
345 
346 #endif // #ifdef NMT_CREATE_HEADER_NAME
347 #endif // #ifndef CREATING_NMT