1#ifndef MESSAGE_MACROS_H
2#define MESSAGE_MACROS_H
14 class MessageSenderInterface;
30 return !t2 || !strcmp(t2,
"");
34 return !
t1 || !strcmp(
t1,
"");
36 return !strcmp(
t1, t2);
44 if (msgType != classType)
45 throw std::runtime_error(
"Type mismatch in message_macros: msg type " + std::to_string(msgType) +
" , class type " + std::to_string(classType));
49 template <
class T,
class Enable =
void>
56 struct ValueOrRef<T, typename std::enable_if<std::is_arithmetic<T>::value || std::is_pointer<T>::value>
::type>
75#define STOP_RECURSION()
78#define SELECT(NAME, NUM) CAT(NAME##_, NUM)
80#define GET_COUNT(_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, COUNT, ...) COUNT
81#define VA_SIZE(...) EXPAND(GET_COUNT(__VA_ARGS__, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 09, 08, 07, 06, 05, 04, 03, 02, 01))
83#define VA_SELECT(NAME, ...) \
84 EXPAND(SELECT(NAME, EXPAND(VA_SIZE(__VA_ARGS__)))) \
87#define MY_OVERLOADED(...) EXPAND(VA_SELECT(MY_OVERLOADED, __VA_ARGS__))
89#define MY_OVERLOADED_01(ClassName, MacroName, MacroNameLast, _1) STOP_RECURSION()
90#define MY_OVERLOADED_03(ClassName, MacroName, MacroNameLast, _1, _2, _3) STOP_RECURSION()
91#define MY_OVERLOADED_05(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5) STOP_RECURSION()
92#define MY_OVERLOADED_07(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7) STOP_RECURSION()
93#define MY_OVERLOADED_09(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9) STOP_RECURSION()
94#define MY_OVERLOADED_11(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) STOP_RECURSION()
95#define MY_OVERLOADED_13(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) STOP_RECURSION()
96#define MY_OVERLOADED_15(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) STOP_RECURSION()
97#define MY_OVERLOADED_17(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) STOP_RECURSION()
98#define MY_OVERLOADED_19(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19) STOP_RECURSION()
99#define MY_OVERLOADED_21(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21) STOP_RECURSION()
100#define MY_OVERLOADED_23(ClassName, MacroName, MacroNameLast, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23) STOP_RECURSION()
101#define MY_OVERLOADED_25(ClassName, MacroName, MacroNameLast, _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) STOP_RECURSION()
102#define MY_OVERLOADED_27(ClassName, MacroName, MacroNameLast, _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) STOP_RECURSION()
104#define MY_OVERLOADED_02(MacroName, MacroNameLast, T00, N00) MacroNameLast(T00, N00)
105#define MY_OVERLOADED_04(MacroName, MacroNameLast, T00, N00, T01, N01) MacroName(T00, N00) MY_OVERLOADED_02(MacroName, MacroNameLast, T01, N01)
106#define MY_OVERLOADED_06(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02) MacroName(T00, N00) MY_OVERLOADED_04(MacroName, MacroNameLast, T01, N01, T02, N02)
107#define MY_OVERLOADED_08(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03) MacroName(T00, N00) MY_OVERLOADED_06(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03)
108#define MY_OVERLOADED_10(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04) MacroName(T00, N00) MY_OVERLOADED_08(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04)
109#define MY_OVERLOADED_12(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05) MacroName(T00, N00) MY_OVERLOADED_10(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05)
110#define MY_OVERLOADED_14(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06) MacroName(T00, N00) MY_OVERLOADED_12(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06)
111#define MY_OVERLOADED_16(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07) MacroName(T00, N00) MY_OVERLOADED_14(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07)
112#define MY_OVERLOADED_18(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08) MacroName(T00, N00) MY_OVERLOADED_16(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08)
113#define MY_OVERLOADED_20(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09) MacroName(T00, N00) MY_OVERLOADED_18(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09)
114#define MY_OVERLOADED_22(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09, T10, N10) MacroName(T00, N00) MY_OVERLOADED_20(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09, T10, N10)
115#define MY_OVERLOADED_24(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09, T10, N10, T11, N11) MacroName(T00, N00) MY_OVERLOADED_22(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09, T10, N10, T11, N11)
116#define MY_OVERLOADED_26(MacroName, MacroNameLast, T00, N00, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09, T10, N10, T11, N11, T12, N12) MacroName(T00, N00) MY_OVERLOADED_24(MacroName, MacroNameLast, T01, N01, T02, N02, T03, N03, N04, T04, T05, N05, T06, N06, T07, N07, T08, N08, T09, N09, T10, N10, T11, N11, T12, N12)
118#define ACCESSOR(type, name) \
119 typename covise::detail::ValueOrRef<type>::RetVal name() const { return CAT(m_, name); }\
121#define DECLARATION(type, name) \
124#define CONSTRUCTOR_ELEMENT_LAST(type, name) \
125 typename covise::detail::ValueOrRef<type>::RetVal name
127#define CONSTRUCTOR_ELEMENT(type, name) \
128 CONSTRUCTOR_ELEMENT_LAST(type, name),
130#define CONSTRUCTOR_INITIALIZER_ELEM_LAST(type, name) \
133#define CONSTRUCTOR_INITIALIZER_ELEM(type, name) \
134 CONSTRUCTOR_INITIALIZER_ELEM_LAST(type, name),
137#define CONSTRUCTOR_INITIALIZER_TB_LAST(type, name) \
138 CAT(m_, name)(covise::detail::get<type>(tb))
140#define CONSTRUCTOR_INITIALIZER_TB(type, name) \
141 CONSTRUCTOR_INITIALIZER_TB_LAST(type, name),
143#define FILL_TOKENBUFFER(type, name) \
146#define TAKE_FROM_TOKENBUFFER(type, name) \
149#define PRINT_CLASS(type, name) \
150 os << #name << ": "; \
151 covise::tryPrintWithError(os, msg.name(), #type, " is not printable"); \
154#define CHECK_EQUALITY(type, name) \
155 covise::detail::equals(c1.name(), c2.name()) &&
159#define DECL_TB_SERIALIZABLE_STRUCT(ClassName, export, ...) \
160 struct export ClassName{ \
161 EXPAND(MY_OVERLOADED(DECLARATION, DECLARATION, __VA_ARGS__)) \
162 EXPAND(MY_OVERLOADED(ACCESSOR, ACCESSOR, __VA_ARGS__))}; \
163 export covise::TokenBuffer &operator<<(covise::TokenBuffer &tb, const ClassName &msg); \
164 export covise::TokenBuffer &operator>>(covise::TokenBuffer &tb, ClassName &msg); \
165 export std::ostream &operator<<(std::ostream &os, const ClassName &msg);
167#define IMPL_TB_SERIALIZABLE_STRUCT(ClassName, ...) \
168 covise::TokenBuffer &operator<<(covise::TokenBuffer &tb, const ClassName &msg) \
170 tb EXPAND(MY_OVERLOADED(FILL_TOKENBUFFER, FILL_TOKENBUFFER, __VA_ARGS__)); \
173 covise::TokenBuffer &operator>>(covise::TokenBuffer &tb, ClassName &msg) \
175 tb EXPAND(MY_OVERLOADED(TAKE_FROM_TOKENBUFFER, TAKE_FROM_TOKENBUFFER, __VA_ARGS__)); \
178 std::ostream &operator<<(std::ostream &os, const ClassName &msg) \
180 os << #ClassName << ":" << std::endl; \
181 EXPAND(MY_OVERLOADED(PRINT_CLASS, PRINT_CLASS, __VA_ARGS__)); \
194#define DECL_MESSAGE_CLASS(ClassName, export, ...) \
195 struct export ClassName \
197 static constexpr covise::detail::MessageSyle Style = covise::detail::MessageSyle::Primary; \
198 ClassName(EXPAND(MY_OVERLOADED(CONSTRUCTOR_ELEMENT, CONSTRUCTOR_ELEMENT_LAST, __VA_ARGS__))); \
199 explicit ClassName(const covise::Message &msg); \
200 covise::Message createMessage() const; \
201 EXPAND(MY_OVERLOADED(ACCESSOR, ACCESSOR, __VA_ARGS__)) \
204 EXPAND(MY_OVERLOADED(DECLARATION, DECLARATION, __VA_ARGS__)) \
205 ClassName(covise::detail::Dummy, covise::TokenBuffer &&tb); \
207 export covise::TokenBuffer &operator<<(covise::TokenBuffer &tb, const ClassName &msg); \
208 export std::ostream &operator<<(std::ostream &tb, const ClassName &exe); \
209 export bool sendCoviseMessage(const ClassName &msg, const covise::MessageSenderInterface &sender); \
210 export bool operator==(const ClassName &c1, const ClassName &c2);
213#define IMPL_MESSAGE_CLASS(ClassName, ...) \
214 ClassName::ClassName(EXPAND(MY_OVERLOADED(CONSTRUCTOR_ELEMENT, CONSTRUCTOR_ELEMENT_LAST, __VA_ARGS__))) \
215 : EXPAND(MY_OVERLOADED(CONSTRUCTOR_INITIALIZER_ELEM, CONSTRUCTOR_INITIALIZER_ELEM_LAST, __VA_ARGS__)) {} \
216 ClassName::ClassName(const covise::Message &msg) : ClassName(covise::detail::typeCheck(msg.type, covise::CAT(COVISE_MESSAGE_, ClassName)), covise::TokenBuffer{&msg}) {} \
217 ClassName::ClassName(covise::detail::Dummy, covise::TokenBuffer &&tb) \
218 : EXPAND(MY_OVERLOADED(CONSTRUCTOR_INITIALIZER_TB, CONSTRUCTOR_INITIALIZER_TB_LAST, __VA_ARGS__)) {} \
219 covise::Message ClassName::createMessage() const \
221 covise::TokenBuffer tb; \
223 covise::Message m{tb}; \
224 m.type = covise::CAT(COVISE_MESSAGE_, ClassName); \
227 covise::TokenBuffer &operator<<(covise::TokenBuffer &tb, const ClassName &msg) \
229 tb EXPAND(MY_OVERLOADED(FILL_TOKENBUFFER, FILL_TOKENBUFFER, __VA_ARGS__)); \
232 bool sendCoviseMessage(const ClassName &msg, const covise::MessageSenderInterface &sender) \
234 auto m = msg.createMessage(); \
235 return sender.send(&m); \
237 std::ostream &operator<<(std::ostream &os, const ClassName &msg) \
239 os << #ClassName << ":" << std::endl; \
240 EXPAND(MY_OVERLOADED(PRINT_CLASS, PRINT_CLASS, __VA_ARGS__)); \
244 bool operator==(const ClassName &c1, const ClassName &c2) \
246 return EXPAND(MY_OVERLOADED(CHECK_EQUALITY, CHECK_EQUALITY, __VA_ARGS__)) true; \
249#define DECL_SUB_MESSAGE_CLASS_DETAIL(ClassName, FullClassName, EnumClass, EnumType, export, ...) \
250 struct export FullClassName : public ClassName \
252 friend struct ClassName; \
253 static constexpr covise::detail::MessageSyle Style = covise::detail::MessageSyle::SubMessage; \
254 typedef ClassName Base; \
255 explicit FullClassName(EXPAND(MY_OVERLOADED(CONSTRUCTOR_ELEMENT, CONSTRUCTOR_ELEMENT_LAST, __VA_ARGS__))); \
256 FullClassName(const FullClassName &) = delete; \
257 FullClassName(FullClassName &&) = default; \
258 FullClassName &operator=(const FullClassName &) = delete; \
259 FullClassName &operator=(FullClassName &&) = default; \
260 ~FullClassName() = default; \
261 covise::Message createMessage() const; \
262 EXPAND(MY_OVERLOADED(ACCESSOR, ACCESSOR, __VA_ARGS__)) \
264 static const EnumClass subType = EnumClass::EnumType; \
266 EXPAND(MY_OVERLOADED(DECLARATION, DECLARATION, __VA_ARGS__)) \
267 explicit FullClassName(const covise::Message &msg); \
268 explicit FullClassName(covise::detail::Dummy, covise::TokenBuffer &&tb); \
270 export covise::TokenBuffer &operator<<(covise::TokenBuffer &tb, const FullClassName &msg); \
271 export std::ostream &operator<<(std::ostream &tb, const FullClassName &exe); \
272 export bool sendCoviseMessage(const FullClassName &msg, const covise::MessageSenderInterface &sender);
274#define DECL_SUB_MESSAGE_CLASS(ClassName, EnumClass, EnumType, export, ...) \
275 DECL_SUB_MESSAGE_CLASS_DETAIL(ClassName, ClassName##_##EnumType, EnumClass, EnumType, export, __VA_ARGS__)
277#define IMPL_SUB_MESSAGE_CLASS_DETAIL(ClassName, FullClassName, EnumClass, EnumType, ...) \
278 FullClassName::FullClassName(EXPAND(MY_OVERLOADED(CONSTRUCTOR_ELEMENT, CONSTRUCTOR_ELEMENT_LAST, __VA_ARGS__))) \
279 : ClassName(EnumClass::EnumType), EXPAND(MY_OVERLOADED(CONSTRUCTOR_INITIALIZER_ELEM, CONSTRUCTOR_INITIALIZER_ELEM_LAST, __VA_ARGS__)) {} \
280 FullClassName::FullClassName(const covise::Message &msg) : FullClassName(covise::detail::typeCheck(msg.type, covise::CAT(COVISE_MESSAGE_, ClassName)), covise::TokenBuffer{&msg}) {} \
281 FullClassName::FullClassName(covise::detail::Dummy, covise::TokenBuffer &&tb) \
282 : ClassName(static_cast<EnumClass>(covise::detail::get<int>(tb))), EXPAND(MY_OVERLOADED(CONSTRUCTOR_INITIALIZER_TB, CONSTRUCTOR_INITIALIZER_TB_LAST, __VA_ARGS__)) {} \
283 covise::Message FullClassName::createMessage() const \
285 covise::TokenBuffer tb; \
287 covise::Message m{tb}; \
288 m.type = covise::CAT(COVISE_MESSAGE_, ClassName); \
291 covise::TokenBuffer &operator<<(covise::TokenBuffer &tb, const FullClassName &msg) \
293 tb << static_cast<int>(msg.type) EXPAND(MY_OVERLOADED(FILL_TOKENBUFFER, FILL_TOKENBUFFER, __VA_ARGS__)); \
296 bool sendCoviseMessage(const FullClassName &msg, const covise::MessageSenderInterface &sender) \
298 auto m = msg.createMessage(); \
299 return sender.send(&m); \
301 std::ostream &operator<<(std::ostream &os, const FullClassName &msg) \
303 os << #FullClassName << ":" << std::endl; \
304 EXPAND(MY_OVERLOADED(PRINT_CLASS, PRINT_CLASS, __VA_ARGS__)); \
309#define IMPL_SUB_MESSAGE_CLASS(ClassName, EnumClass, EnumType, ...) \
310 IMPL_SUB_MESSAGE_CLASS_DETAIL(ClassName, ClassName##_##EnumType, EnumClass, EnumType, __VA_ARGS__)
312#define DECL_MESSAGE_WITH_SUB_CLASSES(ClassName, EnumClass, export) \
313 struct export ClassName \
315 ClassName(const covise::Message &msg); \
316 virtual ~ClassName() = default; \
317 const EnumClass type; \
318 static constexpr int MessageType = covise::CAT(COVISE_MESSAGE_, ClassName); \
319 template <typename Derived> \
320 const Derived &unpackOrCast() const \
322 covise::detail::typeCheck(static_cast<int>(Derived::subType), static_cast<int>(type)); \
325 return *dynamic_cast<const Derived *>(this); \
329 m_subMsg.reset(new Derived(*m_msg)); \
331 return *dynamic_cast<const Derived *>(m_subMsg.get()); \
333 template <typename Derived> \
334 Derived createDerived() const \
337 return Derived{*m_msg}; \
341 ClassName(EnumClass); \
344 ClassName(covise::detail::Dummy, covise::TokenBuffer &&tb, const covise::Message &msg); \
345 const covise::Message *m_msg = nullptr; \
346 mutable std::shared_ptr<ClassName> m_subMsg; \
349#define IMPL_MESSAGE_WITH_SUB_CLASSES(ClassName, EnumClass) \
350 ClassName::ClassName(const covise::Message &msg) : ClassName(covise::detail::typeCheck(msg.type, covise::CAT(COVISE_MESSAGE_, ClassName)), covise::TokenBuffer(&msg), msg) {} \
351 ClassName::ClassName(covise::detail::Dummy, covise::TokenBuffer &&tb, const covise::Message &msg) \
352 : type(static_cast<EnumClass>(covise::detail::get<int>(tb))), m_msg(&msg) {} \
353 ClassName::ClassName(EnumClass t) \
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
Definition: khronos-glext.h:13144
GLenum type
Definition: khronos-glext.h:6279
list of all chemical elements
Definition: coConfig.h:27
Dummy typeCheck(int msgType, int classType)
Definition: message_macros.h:42
bool equals< char const * >(const char *const &t1, const char *const &t2)
Definition: message_macros.h:26
bool equals(const T &t1, const T &t2)
Definition: message_macros.h:20
MessageSyle
Definition: message_macros.h:62
Definition: message_macros.h:39
Definition: message_macros.h:51
const T & RetVal
Definition: message_macros.h:52
T RetVal
Definition: message_macros.h:58