Loading...
Searching...
No Matches
24#ifndef DOXYGEN_SHOULD_IGNORE_THIS
26#define MNX_PP_CAT(a, b) MNX_PP_CAT_I(a, b)
27#define MNX_PP_CAT_I(a, b) a##b
29#define MNX_PP_NARG(...) MNX_PP_NARG_I(__VA_ARGS__, MNX_PP_RSEQ_N(), 0)
30#define MNX_PP_NARG_I(...) MNX_PP_ARG_N(__VA_ARGS__)
31#define MNX_PP_ARG_N( \
32 _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N
33#define MNX_PP_RSEQ_N() 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
35#define MNX_FOR_EACH_COMMA(m, ...) MNX_PP_CAT(MNX_FOR_EACH_COMMA_, MNX_PP_NARG(__VA_ARGS__))(m, __VA_ARGS__)
36#define MNX_FOR_EACH_COMMA_1(m, x) m(x)
37#define MNX_FOR_EACH_COMMA_2(m, x, ...) m(x), MNX_FOR_EACH_COMMA_1(m, __VA_ARGS__)
38#define MNX_FOR_EACH_COMMA_3(m, x, ...) m(x), MNX_FOR_EACH_COMMA_2(m, __VA_ARGS__)
39#define MNX_FOR_EACH_COMMA_4(m, x, ...) m(x), MNX_FOR_EACH_COMMA_3(m, __VA_ARGS__)
40#define MNX_FOR_EACH_COMMA_5(m, x, ...) m(x), MNX_FOR_EACH_COMMA_4(m, __VA_ARGS__)
41#define MNX_FOR_EACH_COMMA_6(m, x, ...) m(x), MNX_FOR_EACH_COMMA_5(m, __VA_ARGS__)
42#define MNX_FOR_EACH_COMMA_7(m, x, ...) m(x), MNX_FOR_EACH_COMMA_6(m, __VA_ARGS__)
43#define MNX_FOR_EACH_COMMA_8(m, x, ...) m(x), MNX_FOR_EACH_COMMA_7(m, __VA_ARGS__)
44#define MNX_FOR_EACH_COMMA_9(m, x, ...) m(x), MNX_FOR_EACH_COMMA_8(m, __VA_ARGS__)
45#define MNX_FOR_EACH_COMMA_10(m, x, ...) m(x), MNX_FOR_EACH_COMMA_9(m, __VA_ARGS__)
46#define MNX_FOR_EACH_COMMA_11(m, x, ...) m(x), MNX_FOR_EACH_COMMA_10(m, __VA_ARGS__)
47#define MNX_FOR_EACH_COMMA_12(m, x, ...) m(x), MNX_FOR_EACH_COMMA_11(m, __VA_ARGS__)
48#define MNX_FOR_EACH_COMMA_13(m, x, ...) m(x), MNX_FOR_EACH_COMMA_12(m, __VA_ARGS__)
49#define MNX_FOR_EACH_COMMA_14(m, x, ...) m(x), MNX_FOR_EACH_COMMA_13(m, __VA_ARGS__)
50#define MNX_FOR_EACH_COMMA_15(m, x, ...) m(x), MNX_FOR_EACH_COMMA_14(m, __VA_ARGS__)
51#define MNX_FOR_EACH_COMMA_16(m, x, ...) m(x), MNX_FOR_EACH_COMMA_15(m, __VA_ARGS__)
53#define MNX_FIELD_TYPE(pair) MNX_FIELD_TYPE_I pair
54#define MNX_FIELD_TYPE_I(type, name) type
56#define MNX_FIELD_NAME(pair) MNX_FIELD_NAME_I pair
57#define MNX_FIELD_NAME_I(type, name) name
59#define MNX_FIELD_PARAM(pair) MNX_FIELD_TYPE(pair) MNX_FIELD_NAME(pair)
60#define MNX_FIELDS_PARAMS(...) MNX_FOR_EACH_COMMA(MNX_FIELD_PARAM, __VA_ARGS__)
61#define MNX_FIELDS_NAMES(...) MNX_FOR_EACH_COMMA(MNX_FIELD_NAME, __VA_ARGS__)
75#define MNX_REQUIRED_PROPERTY(TYPE, NAME) \
76 [[nodiscard]] TYPE NAME() const { \
77 if (!ref().contains(#NAME)) { \
78 throw std::runtime_error("Missing required property: " #NAME); \
80 return ref()[#NAME].get<TYPE>(); \
82 void set_##NAME(const TYPE& value) { ref()[#NAME] = value; } \
83 static_assert(true, "")
97#define MNX_ARRAY_ELEMENT_PROPERTY(TYPE, NAME, INDEX) \
98 static_assert(std::is_integral_v<decltype(INDEX)>, "array index must be an integer type"); \
99 [[nodiscard]] TYPE NAME() const { return (*this)[INDEX]; } \
100 void set_##NAME(const TYPE& value) { (*this)[INDEX] = value; } \
101 static_assert(true, "")
119#define MNX_OPTIONAL_NAMED_PROPERTY(TYPE, NAME, KEY) \
120 [[nodiscard]] std::optional<TYPE> NAME() const { \
121 return ref().contains(KEY) ? std::optional<TYPE>(ref()[KEY].get<TYPE>()) : std::nullopt; \
123 [[nodiscard]] TYPE NAME##_or(const TYPE& defaultVal) const { \
124 return ref().contains(KEY) ? ref()[KEY].get<TYPE>() : defaultVal; \
126 void set_##NAME(const TYPE& value) { ref()[KEY] = value; } \
127 void clear_##NAME() { ref().erase(KEY); } \
128 static_assert(true, "")
143#define MNX_OPTIONAL_PROPERTY(TYPE, NAME) MNX_OPTIONAL_NAMED_PROPERTY(TYPE, NAME, #NAME)
160#define MNX_OPTIONAL_PROPERTY_WITH_DEFAULT(TYPE, NAME, DEFAULT) \
161 [[nodiscard]] TYPE NAME() const { \
162 return ref().contains(#NAME) ? ref()[#NAME].get<TYPE>() : DEFAULT; \
164 void set_##NAME(const TYPE& value) { ref()[#NAME] = value; } \
165 void clear_##NAME() { ref().erase(#NAME); } \
166 void set_or_clear_##NAME(const TYPE& value) { \
167 if (value == DEFAULT) clear_##NAME(); \
168 else set_##NAME(value); \
170 static_assert(true, "")
189#define MNX_REQUIRED_CHILD(...) \
190 MNX_PP_CAT(MNX_REQUIRED_CHILD_, MNX_PP_NARG(__VA_ARGS__))(__VA_ARGS__)
192#ifndef DOXYGEN_SHOULD_IGNORE_THIS
194#define MNX_REQUIRED_CHILD_CORE(TYPE, NAME, CREATE_BODY) \
195 [[nodiscard]] TYPE NAME() const { return getChild<TYPE>(#NAME); } \
197 static_assert(true, "")
199#define MNX_REQUIRED_CHILD_2(TYPE, NAME) \
200 MNX_REQUIRED_CHILD_CORE(TYPE, NAME, \
201 TYPE create_##NAME() { return setChild(#NAME, TYPE(*this, #NAME)); } \
204#define MNX_REQUIRED_CHILD_3(TYPE, NAME, ...) \
205 MNX_REQUIRED_CHILD_CORE(TYPE, NAME, \
206 TYPE create_##NAME(MNX_FIELDS_PARAMS(__VA_ARGS__)) { \
207 return setChild(#NAME, TYPE(*this, #NAME, MNX_FIELDS_NAMES(__VA_ARGS__))); \
211#define MNX_REQUIRED_CHILD_4(TYPE, NAME, ...) MNX_REQUIRED_CHILD_3(TYPE, NAME, __VA_ARGS__)
212#define MNX_REQUIRED_CHILD_5(TYPE, NAME, ...) MNX_REQUIRED_CHILD_3(TYPE, NAME, __VA_ARGS__)
213#define MNX_REQUIRED_CHILD_6(TYPE, NAME, ...) MNX_REQUIRED_CHILD_3(TYPE, NAME, __VA_ARGS__)
214#define MNX_REQUIRED_CHILD_7(TYPE, NAME, ...) MNX_REQUIRED_CHILD_3(TYPE, NAME, __VA_ARGS__)
215#define MNX_REQUIRED_CHILD_8(TYPE, NAME, ...) MNX_REQUIRED_CHILD_3(TYPE, NAME, __VA_ARGS__)
216#define MNX_REQUIRED_CHILD_9(TYPE, NAME, ...) MNX_REQUIRED_CHILD_3(TYPE, NAME, __VA_ARGS__)
217#define MNX_REQUIRED_CHILD_10(TYPE, NAME, ...) MNX_REQUIRED_CHILD_3(TYPE, NAME, __VA_ARGS__)
218#define MNX_REQUIRED_CHILD_11(TYPE, NAME, ...) MNX_REQUIRED_CHILD_3(TYPE, NAME, __VA_ARGS__)
219#define MNX_REQUIRED_CHILD_12(TYPE, NAME, ...) MNX_REQUIRED_CHILD_3(TYPE, NAME, __VA_ARGS__)
220#define MNX_REQUIRED_CHILD_13(TYPE, NAME, ...) MNX_REQUIRED_CHILD_3(TYPE, NAME, __VA_ARGS__)
221#define MNX_REQUIRED_CHILD_14(TYPE, NAME, ...) MNX_REQUIRED_CHILD_3(TYPE, NAME, __VA_ARGS__)
222#define MNX_REQUIRED_CHILD_15(TYPE, NAME, ...) MNX_REQUIRED_CHILD_3(TYPE, NAME, __VA_ARGS__)
223#define MNX_REQUIRED_CHILD_16(TYPE, NAME, ...) MNX_REQUIRED_CHILD_3(TYPE, NAME, __VA_ARGS__)
245#define MNX_OPTIONAL_CHILD(...) \
246 MNX_PP_CAT(MNX_OPTIONAL_CHILD_, MNX_PP_NARG(__VA_ARGS__))(__VA_ARGS__)
248#ifndef DOXYGEN_SHOULD_IGNORE_THIS
250#define MNX_OPTIONAL_CHILD_CORE(TYPE, NAME, ENSURE_BODY) \
251 [[nodiscard]] std::optional<TYPE> NAME() const { return getOptionalChild<TYPE>(#NAME); } \
253 void clear_##NAME() { ref().erase(#NAME); } \
254 static_assert(true, "")
256#define MNX_OPTIONAL_CHILD_2(TYPE, NAME) \
257 MNX_OPTIONAL_CHILD_CORE(TYPE, NAME, \
258 TYPE ensure_##NAME() { \
259 if (auto child = getOptionalChild<TYPE>(#NAME)) return child.value(); \
260 return setChild(#NAME, TYPE(*this, #NAME)); \
264#define MNX_OPTIONAL_CHILD_3(TYPE, NAME, ...) \
265 MNX_OPTIONAL_CHILD_CORE(TYPE, NAME, \
266 TYPE ensure_##NAME(MNX_FIELDS_PARAMS(__VA_ARGS__)) { \
267 if (auto child = getOptionalChild<TYPE>(#NAME)) return child.value(); \
268 return setChild(#NAME, TYPE(*this, #NAME, MNX_FIELDS_NAMES(__VA_ARGS__))); \
272#define MNX_OPTIONAL_CHILD_4(TYPE, NAME, ...) MNX_OPTIONAL_CHILD_3(TYPE, NAME, __VA_ARGS__)
273#define MNX_OPTIONAL_CHILD_5(TYPE, NAME, ...) MNX_OPTIONAL_CHILD_3(TYPE, NAME, __VA_ARGS__)
274#define MNX_OPTIONAL_CHILD_6(TYPE, NAME, ...) MNX_OPTIONAL_CHILD_3(TYPE, NAME, __VA_ARGS__)
275#define MNX_OPTIONAL_CHILD_7(TYPE, NAME, ...) MNX_OPTIONAL_CHILD_3(TYPE, NAME, __VA_ARGS__)
276#define MNX_OPTIONAL_CHILD_8(TYPE, NAME, ...) MNX_OPTIONAL_CHILD_3(TYPE, NAME, __VA_ARGS__)
277#define MNX_OPTIONAL_CHILD_9(TYPE, NAME, ...) MNX_OPTIONAL_CHILD_3(TYPE, NAME, __VA_ARGS__)
278#define MNX_OPTIONAL_CHILD_10(TYPE, NAME, ...) MNX_OPTIONAL_CHILD_3(TYPE, NAME, __VA_ARGS__)
279#define MNX_OPTIONAL_CHILD_11(TYPE, NAME, ...) MNX_OPTIONAL_CHILD_3(TYPE, NAME, __VA_ARGS__)
280#define MNX_OPTIONAL_CHILD_12(TYPE, NAME, ...) MNX_OPTIONAL_CHILD_3(TYPE, NAME, __VA_ARGS__)
281#define MNX_OPTIONAL_CHILD_13(TYPE, NAME, ...) MNX_OPTIONAL_CHILD_3(TYPE, NAME, __VA_ARGS__)
282#define MNX_OPTIONAL_CHILD_14(TYPE, NAME, ...) MNX_OPTIONAL_CHILD_3(TYPE, NAME, __VA_ARGS__)
283#define MNX_OPTIONAL_CHILD_15(TYPE, NAME, ...) MNX_OPTIONAL_CHILD_3(TYPE, NAME, __VA_ARGS__)
284#define MNX_OPTIONAL_CHILD_16(TYPE, NAME, ...) MNX_OPTIONAL_CHILD_3(TYPE, NAME, __VA_ARGS__)
288#define MNX_ASSERT_IF(TEST) \