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