Created
May 4, 2020 11:27
-
-
Save nlyan/6a1ba372acd7051f75aeed0a75ff1e8b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <array> | |
#include <boost/fusion/adapted/adt/adapt_adt.hpp> | |
#include <boost/preprocessor.hpp> | |
#include <stdexcept> | |
#include "faef.hpp" | |
#define DEFINE_INIT_LIST_PLACEHOLDER_0_END | |
#define DEFINE_INIT_LIST_PLACEHOLDER_1_END | |
#define DEFINE_INIT_LIST_PLACEHOLDER_0(X, Y, Z) \ | |
((X, Y, Z)) DEFINE_INIT_LIST_PLACEHOLDER_1 | |
#define DEFINE_INIT_LIST_PLACEHOLDER_1(X, Y, Z) \ | |
((X, Y, Z)) DEFINE_INIT_LIST_PLACEHOLDER_0 | |
#define DEFINE_INIT_LIST_STRIP_PARENS(Z, N, ARGS) \ | |
BOOST_PP_REMOVE_PARENS (BOOST_PP_SEQ_ELEM (N, ARGS)) | |
#define DEFINE_INIT_LIST(EXPRS) \ | |
BOOST_PP_ENUM (BOOST_PP_SEQ_SIZE (BOOST_PP_VARIADIC_SEQ_TO_SEQ (EXPRS)), \ | |
DEFINE_INIT_LIST_STRIP_PARENS, \ | |
BOOST_PP_CAT (DEFINE_INIT_LIST_PLACEHOLDER_0 EXPRS, _END)) | |
#define DEFINE_FIX_FIELD_ACCESSORS(TAG, TYPE, NAME) \ | |
auto NAME () const { \ | |
faef::Field field; \ | |
if (!d_message->getField (&field, TAG)) { \ | |
throw std::runtime_error ("Access to missing '" #NAME \ | |
"'' field (tag " #TAG ")"); \ | |
} \ | |
return faef::FieldExtractor<faef::getBaseType ( \ | |
faef::DataType::e_##TYPE)>::getValue (field); \ | |
} \ | |
\ | |
template <typename T> \ | |
auto NAME (T&&) { \ | |
faef::Field field; \ | |
} | |
#define DEFINE_FIX_FIELD_ACCESSORS_FROM_SEQ(R, ARG, FIELD) \ | |
BOOST_PP_EXPAND (DEFINE_FIX_FIELD_ACCESSORS FIELD) | |
struct FieldDescriptor { | |
int tag; | |
char const* type; | |
char const* name; | |
}; | |
#define INIT_FIELD_DESCRIPTOR(TAG, TYPE, NAME) \ | |
(FieldDescriptor{TAG, #TYPE, #NAME}) | |
#define INIT_FIELD_DESCRIPTOR_FROM_SEQ(R, ARG, FIELD) \ | |
BOOST_PP_EXPAND (INIT_FIELD_DESCRIPTOR FIELD) | |
#define INIT_ALL_FIELD_DESCRIPTORS(FIELDS) \ | |
DEFINE_INIT_LIST ( \ | |
BOOST_PP_SEQ_FOR_EACH (INIT_FIELD_DESCRIPTOR_FROM_SEQ, \ | |
_, \ | |
BOOST_PP_VARIADIC_SEQ_TO_SEQ (FIELDS))) | |
#define ADAPT_FIELD(TAG, TYPE, NAME) (obj.NAME (), obj.NAME (val)) | |
#define ADAPT_FIELDS(R, ARG, FIELD) BOOST_PP_EXPAND (ADAPT_FIELD FIELD) | |
#define DEFINE_FIX_MESSAGE(NAME, FIELDS) \ | |
class NAME { \ | |
public: \ | |
explicit NAME (faef::Message* message) noexcept \ | |
: d_message (message) { \ | |
} \ | |
\ | |
BOOST_PP_SEQ_FOR_EACH (DEFINE_FIX_FIELD_ACCESSORS_FROM_SEQ, _, \ | |
BOOST_PP_VARIADIC_SEQ_TO_SEQ (FIELDS)); \ | |
\ | |
inline static std::array< \ | |
FieldDescriptor, BOOST_PP_SEQ_SIZE (BOOST_PP_VARIADIC_SEQ_TO_SEQ ( \ | |
FIELDS))> const constexpr fields = { \ | |
INIT_ALL_FIELD_DESCRIPTORS (FIELDS)}; \ | |
\ | |
private: \ | |
faef::Message* d_message = 0; \ | |
}; \ | |
\ | |
BOOST_FUSION_ADAPT_ADT ( \ | |
NAME, \ | |
BOOST_PP_SEQ_FOR_EACH ( \ | |
ADAPT_FIELDS, _, BOOST_PP_VARIADIC_SEQ_TO_SEQ (FIELDS))); | |
/* clang-format off */ | |
DEFINE_FIX_MESSAGE ( | |
Trade, | |
(100, String, id) | |
(101, Price, price) | |
(102, Integer, volume) | |
(104, UTCTimestamp, time) | |
); | |
/* clang-format on */ | |
#include <iostream> | |
#include <boost/fusion/algorithm/transformation/zip.hpp> | |
#include <boost/fusion/algorithm/iteration/for_each.hpp> | |
#include <boost/fusion/functional/invocation/invoke.hpp> | |
#include <boost/fusion/adapted/std_array.hpp> | |
namespace bf = ::boost::fusion; | |
int | |
main () { | |
faef::Message message; // Underlying faef::Message is still exposed | |
Trade trade (&message); // Construction is practically free | |
bf::for_each (bf::zip (Trade::fields, trade), [] (auto zipped) { | |
bf::invoke ( | |
[] (auto const& field, auto const& value) { | |
std::cout << "<" << field.name << " tag=\"" << field.tag << "\"" | |
<< " type=\"" << field.type << "\">" << value.get () | |
<< "</" << field.name << ">" | |
<< "\n"; | |
}, | |
zipped); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment