// $Id$ // // Copyright (C) 2008 // Fraunhofer Institute for Open Communication Systems (FOKUS) // Competence Center NETwork research (NET), St. Augustin, GERMANY // Stefan Bund // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /** \page parsermacro_expand_example Example macro-expansion of packet parser helper macros The following packet parser definition (taken from VariantParser.test.cc) has been subject to macro-expansion (and a lot of reformatting) to show the inner workings of the packet parser macros: \code struct TestParser : public senf::PacketParserBase { # include SENF_PARSER() SENF_PARSER_SKIP_BITS( 4 ); SENF_PARSER_BITFIELD_RO( type, 4, unsigned ); SENF_PARSER_PRIVATE_VARIANT( content_, type, ( novalue( nocontent, key(10, senf::VoidPacketParser)) ) ( id( content, SubParser ) ) ); SENF_PARSER_FINALIZE(TestParser); }; \endcode Here the reformated and sparsly commented expansion. I have left all the \c SENF_MPL_SLOT_ calls unexpanded, otherwise the code would be absolutely unreadable. This is quite a lot of source-code which however should create only a small amount of additional compiled code. Also remember, that all this code is generated by C++ makros. Some detours are needed to work around makro problems (e.g. templates with multiple arguments are parsed as seperate makro arguments at each komma, inability to redefine a makro from another makro ...). \code struct TestParser : public senf::PacketParserBase { // ///////////////////////////////////////////////////////////////////////// // #include SENF_PARSER() private: SENF_MPL_SLOT_INIT_ZERO(index); SENF_MPL_SLOT_INIT_ZERO(init_bytes); SENF_MPL_SLOT_INIT_ZERO(bit); SENF_MPL_SLOT_INIT_ZERO(bitfield_size); SENF_MPL_SLOT_INIT_ZERO(group); void init_chain (senf::mpl::rv <0> *) const {} size_type field_offset_ (senf::mpl::rv <0> *) const { return 0; } // ///////////////////////////////////////////////////////////////////////// // SENF_PARSER_SKIP_BITS( 4 ); SENF_MPL_SLOT_SET(bit, SENF_MPL_SLOT_GET(bit) + 4); // ///////////////////////////////////////////////////////////////////////// // SENF_PARSER_BITFIELD_RO( type, 4, unsigned ); public: static size_type const type_bit = SENF_MPL_SLOT_GET(bit); private: SENF_MPL_SLOT_SET(bit, type_bit + 4); typedef senf::UIntFieldParser type_bit_t; public: typedef type_bit_t type_t; static size_type const type_index = SENF_MPL_SLOT_GET(index) + 1; private: SENF_MPL_SLOT_SET(index, type_index); void init_chain (senf::mpl::rv *) const { init_chain (static_cast *>(0)); } public: size_type type_offset () const { return field_offset_(static_cast *>(0)) - SENF_MPL_SLOT_GET(bitfield_size); } static size_type const type_init_bytes = SENF_MPL_SLOT_GET(init_bytes) - SENF_MPL_SLOT_GET(bitfield_size); size_type type_next_offset () const { return type_offset() + type_t::fixed_bytes; } static size_type const type_next_init_bytes = type_init_bytes + type_t::fixed_bytes; private: size_type field_offset_(senf::mpl::rv *) const { return type_next_offset(); } SENF_MPL_SLOT_SET(init_bytes, type_next_init_bytes); static size_type const type_group = SENF_MPL_SLOT_GET(group) + 0; SENF_MPL_SLOT_SET(group, type_group); SENF_MPL_SLOT_SET(bitfield_size, type_t::fixed_bytes); type_t type_ () const { return parse (type_offset ()); } public: type_t::value_type type () const { return type_(); } // ///////////////////////////////////////////////////////////////////////// // SENF_PARSER_PRIVATE_VARIANT( content_, type, // ( novalue( nocontent, key(10, senf::VoidPacketParser)) ) // ( id( content, SubParser ) ) // ); private: typedef boost::mpl::vector content__parsers; typedef type_t::value_type content__chooser_value_type; static content__chooser_value_type content__key_0 () { return 10; } static content__chooser_value_type content__key_1 () { return 1; } template struct content__key_value_template : public senf::detail::VariantKey {}; template friend class senf::detail::VariantKey; typedef senf::detail::VariantKeyTransform< content__chooser_value_type, boost::mpl::vector< content__key_value_template<&content__key_0>, content__key_value_template<&content__key_1> > > content__transform; typedef senf::detail::VariantParserTraits content__traits; // start SENF_PARSER_COLLECTION_I static bool const content__aux_fixed = (SENF_MPL_SLOT_GET(group) - type_group) == 0; typedef senf::detail::ParserAuxPolicySelect < type_t, SENF_MPL_SLOT_GET(init_bytes) - type_init_bytes, content__aux_fixed >::type content__aux_policy; typedef content__traits::parser::type content__collection_t; SENF_MPL_SLOT_SET(bit, 0); SENF_MPL_SLOT_SET(bitfield_size, 0); typedef content__collection_t content__t; static size_type const content__index = SENF_MPL_SLOT_GET(index) + 1; SENF_MPL_SLOT_SET(index, content__index); void init_chain (senf::mpl::rv *) const { init_chain (static_cast *>(0)); content_().init(); } size_type content__offset() const { return field_offset_ (static_cast *>(0)); } static size_type const content__init_bytes = SENF_MPL_SLOT_GET(init_bytes); size_type content__next_offset () const { return content__offset() + senf::bytes(content__()); } static size_type const content__next_init_bytes = content__init_bytes + senf::init_bytes::value; size_type field_offset_(senf::mpl::rv *) const { return content__next_offset(); } SENF_MPL_SLOT_SET(init_bytes, content__next_init_bytes); static size_type const content__group = SENF_MPL_SLOT_GET(group) + (senf::is_fixed::value ? 0 : 1); SENF_MPL_SLOET_SET(group, content__group); template < class T > T content__dispatch (boost::true_type) const { return parse(content__offset()); } template < class T > T content__dispatch (boost::false_type) const { return parse(type(), content__offset()); } content__t content__() const { return content__dispatch( boost::integral_constant()); } content__t content_ () const { return content__ (); } // end SENF_PARSER_COLLECTION_I public: void nocontent() const { content_().init<0>(); } typedef SubParser content_t; SubParser content() const { return content_().get<1>(); } void init_content() const { content_().init<1>(); } bool has_content() const { return content_().variant() == 1; }; // ///////////////////////////////////////////////////////////////////////// // SENF_PARSER_FINALIZE(TestParser); void defaultInit () const { init_chain(static_cast *>(0)); } TestParser(data_iterator i, state_type s) : parser_base_type (i, s) {} private: template void init(T) const { defaultInit (); } public: void init() const { init (0); } size_type bytes() const { return field_offset_(static_cast *>(0)); } static size_type const init_bytes = SENF_MPL_SLOT_GET(init_bytes); }; \endcode */ // Local Variables: // mode: c++ // fill-column: 100 // comment-column: 40 // c-file-style: "senf" // indent-tabs-mode: nil // ispell-local-dictionary: "american" // compile-command: "scons -u test" // mode: flyspell // mode: auto-fill // End: