I have in the past(2012) shown techniques to do this kind of parsing and generation in c11-tuples-and-schema-generation.html. So with a few short hours of hacking and here is the proof of concept.. The solution is meta programming black magic but hey u can define the parser and printer (and whatever else u want to add) for "SomeMessage" in basically 1 line of code per field.
// compile with: // g++ -I"c:\tools\boost_1_49_0" -L"c:\tools\boost_1_49_0\stage\lib" -static self_print_struct.cpp -o self_print_struct.exe #include <iostream> #include <boost/mpl/for_each.hpp> #include <boost/mpl/list.hpp> #include <boost/mpl/string.hpp> #include <boost/mpl/range_c.hpp> template <typename T, typename N> struct Field { typedef T Type; typedef N Name; static unsigned char* print(std::ostream& os, unsigned char* ptr) { os << boost::mpl::c_str<N>::value << " : " << *(static_cast<T*>(static_cast<void*>(ptr))); return ptr + sizeof(Type); } }; template <typename Base> struct PrintMixin { struct DoPrint { unsigned char* cursor_; DoPrint(unsigned char* cursor) : cursor_(cursor) {} template< typename U > void operator()(U x) { std::cout << " + "; U::print(std::cout, cursor_); std::cout << '\n'; cursor_ += sizeof(typename U::Type); } }; static void print(std::ostream& os, unsigned char* ptr) { boost::mpl::for_each< typename Base::Type >( DoPrint(ptr) ); } }; struct SomeMessage : PrintMixin<SomeMessage> { typedef boost::mpl::list<Field<int, boost::mpl::string<'fiel','d 1'> >, Field<char, boost::mpl::string<'fiel','d 2'> > > Type; }; struct AnotherMessage : PrintMixin<AnotherMessage> { typedef boost::mpl::list<Field<int, boost::mpl::string<'this'> >, Field<char, boost::mpl::string<'that'> >, Field<float, boost::mpl::string<'the ','othe','r'> > > Type; }; int main() { unsigned char message1[] = { 0x01,0x02,0x03,0x04, 'a' }; std::cout << "message 1\n"; SomeMessage::print(std::cout, message1); unsigned char message2[] = { 0x15, 0xCD, 0x5B, 0x07, 'b', 0x19, 0x04, 0x9e, 0x3f }; std::cout << "message 2\n"; AnotherMessage::print(std::cout, message2); }
And the output looks like:
$ self_print_struct.exe message 1 + field 1 : 67305985 + field 2 : a message 2 + this : 123456789 + that : b + the other : 1.2345
No comments:
Post a Comment