Alchemy
1.0
A framework to robustly process network messages and structured data
Main Page
Related Pages
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Pages
Hg
msg_def.h
1
// @file Hg/msg_def.h
2
//
3
// Internal implementation MACROS for message format definitions.
4
//
5
// Contains declaration MACROs implementation to define message buffer formats.
6
// The implementations are hidden behind a second layer to simplify the
7
// header file the user will interact with.
8
//
9
// @note This header file must not be included directly and the
10
// MACROS defined in this file should not be accessed
11
// directly. Include and used the definitions from the file
12
// **<alchemy.h>** instead.
13
//
14
/// The MIT License(MIT)
15
/// @copyright 2014 Paul M Watt
16
// ****************************************************************************
17
#ifndef MSG_DEF_H_INCLUDED
18
#define MSG_DEF_H_INCLUDED
19
// Private Usage Include Guard ************************************************
20
// Only allow this header file to be included through alchemy.h
21
#ifndef ALCHEMY_H_INCLUDED
22
# error Do not include this file directly. Use <alchemy.h> instead
23
#endif
24
25
// ****************************************************************************
26
// We're potentially using some pretty long type definitions.
27
// For any moderately complex message format, we will almost certainly
28
// trigger this warning with Visual C++.
29
#if defined(_MSC_VER)
30
#pragma warning(disable : 4503) // decorated name length exceeded, name was truncated
31
#endif
32
33
34
// ****************************************************************************
35
// Declaration MACROs used for converting from the generic Alchemy definition.
36
// ****************************************************************************
37
38
// ****************************************************************************
39
// Helps convert generic ALCHEMY datum declarations to elemental declarations.
40
//
41
#define ELEMENTAL_PARAM(r, data, i, x) \
42
, BOOST_PP_CAT(data, x)
43
44
// TODO: It's possible, GCC may accept this form. If not, refer to the EACH_PARAM MACRO below.
45
46
// ****************************************************************************
47
// Iterates through each parameter declared in an Alchemy struct declaration.
48
// This for-loop uses the ELEMENTAL_PARAM MACRO above to prepend the
49
// supplied element prefix to the parameter declaration.
50
//
51
#define STRUCT_PARAMS(NAME, EL,S) \
52
(NAME BOOST_PP_SEQ_FOR_EACH_I(ELEMENTAL_PARAM, EL, S))
53
54
// ****************************************************************************
55
// The generic Alchemy struct definition.
56
// This definition can be converted into any elemental type definition
57
// that is defined for Alchemy.
58
//
59
#define DECLARE_STRUCT(NAME, EL, ...) \
60
EL##DECLARE_STRUCT_HEADER \
61
STRUCT_PARAMS(NAME, EL, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
62
63
64
65
// ****************************************************************************
66
// Helps convert generic ALCHEMY datum declarations to elemental declarations.
67
//
68
#define ELEMENTAL_BITS(r, data, i, x) \
69
, BOOST_PP_CAT(data, x)
70
71
// ****************************************************************************
72
// Iterates through each parameter declared in an Alchemy struct declaration.
73
// This for-loop uses the ELEMENTAL_PARAM MACRO above to prepend the
74
// supplied element prefix to the parameter declaration.
75
//
76
#define PACKED_PARAMS(TYPE, NAME, EL,S) \
77
(TYPE, NAME BOOST_PP_SEQ_FOR_EACH_I(ELEMENTAL_BITS, EL, S))
78
79
// ****************************************************************************
80
// The generic Alchemy struct definition.
81
// This definition can be converted into any elemental type definition
82
// that is defined for Alchemy.
83
//
84
#define DECLARE_PACKED(TYPE, NAME, EL, ...) \
85
EL##DECLARE_PACKED_HEADER \
86
PACKED_PARAMS(TYPE, NAME, EL,BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
87
88
89
// ****************************************************************************
90
// The version of MACROs defined below are dependent upon the language.
91
//
92
#ifdef __cplusplus
93
94
// Includes *******************************************************************
95
#include <Pb/meta_fwd.h>
96
#include <Pb/auto_index.h>
97
#include <
Pb/byte_order.h
>
98
#include <Pb/length.h>
99
#include <Pb/offset_of.h>
100
#include <Pb/size_at.h>
101
#include <Pb/size_of.h>
102
#include <Pb/meta_math.h>
103
#include <Pb/dynamic.h>
104
#include <Hg/deduce_msg_type_list.h>
105
#include <Hg/make_Hg_type_list.h>
106
#include <Hg/proxy/deduce_proxy_type.h>
107
108
109
// ****************************************************************************
110
// Utility Constructs For Use With Hg Message Types ***************************
111
// ****************************************************************************
112
113
namespace
Hg
114
{
115
116
// Typedefs *******************************************************************
117
typedef
size_t (*pfnGetDatumSize)(
const
uint8_t*, size_t);
118
119
120
// ****************************************************************************
121
/// Indicates the type size the specified message is, static or dynamic.
122
///
123
/// @paramt T A TypeList definition.
124
///
125
/// @return A typedef called *type* is defined to return the size trait.
126
/// - static_size_trait indicates a fixed-size message whose
127
/// size is completely known at compile-time.
128
/// - dynamic_size_trait indicates a dyanmically sized message.
129
/// At least some part of the message requires
130
/// runtime processing to determine the size
131
/// of the message.
132
///
133
template
<
typename
T >
134
struct
message_size_trait
135
: std::conditional
136
< has_dynamic<T>::value,
137
dynamic_size_trait,
138
static_size_trait
139
>
140
{ };
141
142
}
// namespace Hg
143
144
// ****************************************************************************
145
// Abstracted Message Definition MACROS ***************************************
146
// Simplified user MACROS use these definitions.
147
// These definitions have been abstracted to simplify the user header files.
148
// ****************************************************************************
149
150
// ****************************************************************************
151
#define DO_REMOVE(...) __VA_ARGS__
152
#define REMOVE_PARENS(N) DO_REMOVE N
153
154
#define BOOST_PP_REMOVE_PARENS(param) \
155
BOOST_PP_IIF \
156
( \
157
BOOST_PP_IS_BEGIN_PARENS(param), \
158
DO_REMOVE, \
159
BOOST_PP_IDENTITY \
160
) \
161
(param)() \
162
163
// ****************************************************************************
164
#define EACH_TYPE(r, data, i, x) \
165
REMOVE_PARENS(BOOST_PP_TUPLE_ELEM(3,0,x)),
166
167
#define EACH_PARAM(r, data, i, x) \
168
BOOST_PP_TUPLE_ELEM(3,1,x)(BOOST_PP_TUPLE_ELEM(3,2,x));
169
170
#define DEFINE_TYPELIST(N,...)\
171
typedef TypeList < __VA_ARGS__ > N;
172
173
174
#if defined(_MSC_VER)
175
#define DEFINE_STRUCT_TYPELIST(N, S) \
176
DEFINE_TYPELIST(N, \
177
BOOST_PP_SEQ_FOR_EACH_I(EACH_TYPE, unused, BOOST_PP_VARIADIC_TO_SEQ(S)) Hg::MT)
178
179
180
#define DEFINE_STRUCT_PARAMS(S) \
181
BOOST_PP_SEQ_FOR_EACH_I(EACH_PARAM, unused, BOOST_PP_VARIADIC_TO_SEQ(S))
182
183
#else
184
185
#define DEFINE_STRUCT_TYPELIST(N, ...) \
186
DEFINE_TYPELIST(N, \
187
BOOST_PP_SEQ_FOR_EACH_I(EACH_TYPE, unused, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) Hg::MT)
188
189
190
#define DEFINE_STRUCT_PARAMS(...) \
191
BOOST_PP_SEQ_FOR_EACH_I(EACH_PARAM, unused, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
192
193
#endif
194
195
// TODO: Temporarily will try to put the source back together the way it is currently
196
// structured. Then will move the placement of the definitions to
197
// solve some of the incompatibilities for duplicate types.
198
199
// ****************************************************************************
200
// Defines the outer value container as well as the formatted type-list.
201
//
202
#define Hg_DECLARE_STRUCT_HEADER(F, ...) \
203
BEGIN_NAMESPACE(Hg) \
204
DEFINE_STRUCT_TYPELIST(F##_tl, __VA_ARGS__) \
205
typedef Hg::make_Hg_type_list<F##_tl>::type F##_Hg; \
206
\
207
struct F \
208
: nested_trait \
209
{ \
210
typedef F this_type; \
211
typedef F##_tl format_type; \
212
enum { k_size = SizeOf<format_type>::value }; \
213
enum { k_length = length<format_type>::value }; \
214
\
215
template< size_t IDX> \
216
Datum<IDX, format_type>& FieldAt() \
217
{ \
218
typedef Datum < IDX, \
219
format_type> datum_type_t; \
220
return this_type::FieldAtIndex((datum_type_t*)0); \
221
} \
222
template< size_t IDX> \
223
const Datum<IDX, format_type>& const_FieldAt() const \
224
{ \
225
return const_cast<this_type*>(this)->FieldAt<IDX>(); \
226
} \
227
BEGIN_COUNTER \
228
\
229
DEFINE_STRUCT_PARAMS(__VA_ARGS__) \
230
Hg_DECLARE_STRUCT_FOOTER(F)
231
232
233
// ****************************************************************************
234
#define Hg_DECLARE_STRUCT_FOOTER(F) \
235
private: \
236
template <typename T, typename U> \
237
size_t DatumSize(T value, U*) \
238
{ \
239
return value; \
240
} \
241
\
242
template <typename U> \
243
size_t DatumSize(pfnGetDatumSize ftor, U* buffer) \
244
{ \
245
if (buffer->empty()) { return 0; } \
246
return ftor(buffer->data(), buffer->size()); \
247
} \
248
}; \
249
BEGIN_NAMESPACE(detail) \
250
template <> \
251
struct field_data_t <F##_Hg> \
252
{ \
253
typedef F value_type; \
254
}; \
255
END_NAMESPACE(detail) \
256
END_NAMESPACE(Hg)
257
258
259
// ****************************************************************************
260
#define DECLARE_DATUM_ENTRY_IDX(IDX,P) \
261
typedef \
262
Hg::detail::DeduceProxyType < IDX, \
263
format_type>::type Proxy##P; \
264
typedef Proxy##P::datum_type datum_##P; \
265
Proxy##P P; \
266
\
267
datum_##P& FieldAtIndex(const datum_##P*) \
268
{ return *static_cast<datum_##P*>(&P); } \
269
\
270
const char* FieldName(const Proxy##P&) { return #P; }
271
272
// ****************************************************************************
273
#define DECLARE_DATUM_ENTRY_X(P) \
274
INC_COUNTER \
275
DECLARE_DATUM_ENTRY_IDX((COUNTER_VALUE), P)
276
277
// ****************************************************************************
278
#define D_FUNDAMENTAL(...) DECLARE_DATUM_ENTRY_X __VA_ARGS__
279
#define D_DATUM_X(T,P) (T,D_FUNDAMENTAL,(P))
280
281
// ****************************************************************************
282
#define DECLARE_ARRAY(T,N) std::array<T,N>
283
284
// ****************************************************************************
285
#define DECLARE_VECTOR(T) std::vector<T>
286
287
// ****************************************************************************
288
#define DECLARE_VECTOR_ALLOCATED(T,A) std::vector<T,A>
289
290
// ****************************************************************************
291
#define D_ARRAY(T, N, P) D_DATUM_X((DECLARE_ARRAY(T,N)), P)
292
293
// ****************************************************************************
294
#define D_DYNAMIC(N,P) \
295
DECLARE_DATUM_ENTRY_X(P) \
296
public: \
297
template <typename U> \
298
size_t Size(U& buffer, datum_##P*) { return DatumSize(N, &buffer); }
299
300
301
#define D_DYNAMIC2(...) D_DYNAMIC __VA_ARGS__
302
#define D_VECTOR(T,N,P) ((DECLARE_VECTOR(T)),D_DYNAMIC2,(N,P))
303
304
305
// ****************************************************************************
306
#define Hg_DECLARE_DATUM(T,P) D_DATUM_X((T),P)
307
#define Hg_DECLARE_ARRAY_DATUM(T, N, P) D_ARRAY(T, N, P)
308
#define Hg_DECLARE_VECTOR_DATUM(T, N, P) D_VECTOR(T, N, P)
309
#define Hg_DECLARE_ALLOCATOR_DATUM(T, A, N, P) D_VECTOR(DECLARE_VECTOR_ALLOCATED(T,A), N, P)
310
311
312
313
// ****************************************************************************
314
// Packed Bit Fields **********************************************************
315
// ****************************************************************************
316
#define Eval_Hg(x) x
317
#define Hg_EACH_BIT_FIELD(r, data, i, x) \
318
BOOST_PP_CAT(data, x)
319
320
321
#if defined(_MSC_VER)
322
323
#define Hg_DEFINE_PACKED_FIELDS(S) \
324
BOOST_PP_SEQ_FOR_EACH_I(Hg_EACH_BIT_FIELD, Eval_, BOOST_PP_VARIADIC_TO_SEQ(S))
325
// BOOST_PP_SEQ_FOR_EACH_I(Hg_EACH_BIT_FIELD, unused, S)
326
327
#else
328
329
#define Hg_DEFINE_PACKED_FIELDS(...) \
330
BOOST_PP_SEQ_FOR_EACH_I(C_EACH_BIT_FIELD, unused, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
331
332
#endif
333
334
335
// ****************************************************************************
336
#define Hg_DECLARE_PACKED_HEADER(T,C,...) \
337
BEGIN_NAMESPACE(Hg) \
338
struct C; \
339
template <> \
340
struct ContainerSize<C> \
341
: std::integral_constant<size_t, sizeof(T)> { }; \
342
\
343
struct C \
344
: public PackedBits<T> \
345
{ \
346
typedef C this_type; \
347
typedef T value_type; \
348
typedef PackedBits<T> base_type; \
349
\
350
C() \
351
: base_type() \
352
{ } \
353
\
354
C(const value_type &data_field) \
355
: base_type() \
356
{ value(data_field); } \
357
\
358
C(value_type &data_field) \
359
: base_type(data_field) \
360
{ } \
361
\
362
C& operator=(const C &rhs) \
363
{ value(rhs.value()); \
364
return *this; \
365
} \
366
C& operator=(const value_type &data_field) \
367
{ value(data_field); \
368
return *this; \
369
} \
370
\
371
enum { k_offset_0 = 0 }; \
372
Hg_DEFINE_PACKED_FIELDS(__VA_ARGS__) \
373
}; \
374
END_NAMESPACE(Hg)
375
376
// *****************************************************************************
377
#define Eval_Hg_DECLARE_BIT_FIELD(IDX,P,N) \
378
typedef FieldIndex< IDX, this_type,N> idx_##IDX; \
379
struct P##_tag \
380
{ static ptrdiff_t offset() \
381
{ return offsetof(this_type, P); } \
382
}; \
383
\
384
typedef BitField < this_type, P##_tag, k_offset_##IDX, N, value_type > P##_t; \
385
enum { TMP_PASTE(k_offset_, TMP_INC(IDX)) = k_offset_##IDX + N }; \
386
\
387
P##_t P;
388
389
390
#else
391
392
// ****************************************************************************
393
// Declare empty Hg MACROS for non-C++ builds.
394
//
395
#define Hg_DECLARE_STRUCT_HEADER(NAME, ...)
396
#define Hg_DECLARE_DATUM(TYPE,NAME)
397
#define Hg_DECLARE_ARRAY_DATUM(TYPE,COUNT,NAME)
398
#define Hg_DECLARE_VECTOR_DATUM(TYPE,COUNT,NAME)
399
#define Hg_DECLARE_ALLOCATOR_DATUM(TYPE,ALLOCATOR,COUNT,NAME)
400
#define Hg_DECLARE_STRUCT_FOOTER(TYPE_LIST)
401
402
#define Hg_DECLARE_PACKED_HEADER(TYPE,NAME, ...)
403
#define Hg_DECLARE_BIT_FIELD(INDEX, NAME, COUNT)
404
#define Hg_DECLARE_PACKED_FOOTER
405
406
#endif // __cplusplus
407
408
#endif
Generated on Sat May 9 2015 21:25:05 for Alchemy by
1.8.3.1