4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 /** \page parsermacro_expand_example Example macro-expansion of packet parser helper macros
25 Debugging the packet parser makros is somwhat difficult since the makro expansion will place
26 everything in a single line. To help pin down problems, I use
29 $ g++ -DSENF_MPL_SLOT_NOEXPAND -o <path-to-file>.ii -E -DSENF_DEBUG -Iinclude <path-to-file>.cc
30 $ sed -i -e 's/}/}\\n/g' -e '/^#.*$/d' <path-to-file>.ii
31 $ astyle --style=linux -b <path-to-file>.ii
34 I normally just cut-and-paste the \c g++ command from a normal build and add
35 <tt>-DSENF_MPL_SLOT_NOEXPAND</tt>. \c astyle is found at http://astyle.sourceforge.net/. If
36 needed, I then reissue this file (the precessed \.ii file) back to the compiler using the
37 original commandline (just replacing the \c .cc with \c .ii) to get error messages with
38 meaningful line numbers.
40 The following packet parser definition (taken from VariantParser.test.cc) has been subject to
41 macro-expansion (and a lot of manual reformatting) to show the inner workings of the packet
44 struct TestParser : public senf::PacketParserBase
46 # include SENF_PARSER()
48 SENF_PARSER_SKIP_BITS( 4 );
49 SENF_PARSER_BITFIELD_RO( type, 4, unsigned );
50 SENF_PARSER_PRIVATE_VARIANT( content_, type,
51 ( novalue( nocontent, key(10, senf::VoidPacketParser)) )
52 ( id( content, SubParser ) )
55 SENF_PARSER_FINALIZE(TestParser);
59 Here the reformated and sparsly commented expansion. I have left all the \c SENF_MPL_SLOT_ calls
60 unexpanded, otherwise the code would be absolutely unreadable. This is quite a lot of
61 source-code which however should create only a small amount of additional compiled code.
63 Also remember, that all this code is generated by C++ makros. Some detours are needed to work
64 around makro problems (e.g. templates with multiple arguments are parsed as seperate makro
65 arguments at each komma, inability to redefine a makro from another makro ...).
68 struct TestParser : public senf::PacketParserBase
70 // /////////////////////////////////////////////////////////////////////////
71 // #include SENF_PARSER()
74 SENF_MPL_SLOT_INIT_ZERO(index);
75 SENF_MPL_SLOT_INIT_ZERO(init_bytes);
76 SENF_MPL_SLOT_INIT_ZERO(bit);
77 SENF_MPL_SLOT_INIT_ZERO(bitfield_size);
78 SENF_MPL_SLOT_INIT_ZERO(group);
80 void init_chain (senf::mpl::rv <0> *) const {}
81 size_type field_offset_ (senf::mpl::rv <0> *) const { return 0; }
83 // /////////////////////////////////////////////////////////////////////////
84 // SENF_PARSER_SKIP_BITS( 4 );
86 SENF_MPL_SLOT_SET(bit, SENF_MPL_SLOT_GET(bit) + 4);
88 // /////////////////////////////////////////////////////////////////////////
89 // SENF_PARSER_BITFIELD_RO( type, 4, unsigned );
92 static size_type const type_bit = SENF_MPL_SLOT_GET(bit);
95 SENF_MPL_SLOT_SET(bit, type_bit + 4);
96 typedef senf::UIntFieldParser <type_bit, type_bit + 4> type_bit_t;
99 typedef type_bit_t type_t;
100 static size_type const type_index = SENF_MPL_SLOT_GET(index) + 1;
103 SENF_MPL_SLOT_SET(index, type_index);
104 void init_chain (senf::mpl::rv<type_index> *) const
106 init_chain (static_cast<senf::mpl::rv<type_index - 1> *>(0));
110 size_type type_offset() const
112 return field_offset_(static_cast<senf::mpl::rv<type_index - 1> *>(0)) -
113 SENF_MPL_SLOT_GET(bitfield_size);
115 static size_type const type_init_bytes =
116 SENF_MPL_SLOT_GET(init_bytes) - SENF_MPL_SLOT_GET(bitfield_size);
117 size_type type_next_offset () const
119 return type_offset() + type_t::fixed_bytes;
121 static size_type const type_next_init_bytes = type_init_bytes + type_t::fixed_bytes;
124 size_type field_offset_(senf::mpl::rv<type_index> *) const
126 return type_next_offset();
128 SENF_MPL_SLOT_SET(init_bytes, type_next_init_bytes);
129 static size_type const type_group = SENF_MPL_SLOT_GET(group) + 0;
130 SENF_MPL_SLOT_SET(group, type_group);
131 SENF_MPL_SLOT_SET(bitfield_size, type_t::fixed_bytes);
134 return parse <type_bit_t> (type_offset ());
138 type_t::value_type type() const
143 // /////////////////////////////////////////////////////////////////////////
144 // SENF_PARSER_PRIVATE_VARIANT( content_, type,
145 // ( novalue( nocontent, key(10, senf::VoidPacketParser)) )
146 // ( id( content, SubParser ) )
150 typedef boost::mpl::vector <senf::VoidPacketParser, SubParser> content__parsers;
151 typedef type_t::value_type content__chooser_value_type;
152 static content__chooser_value_type content__key_0 ()
156 static content__chooser_value_type content__key_1 ()
160 template <content__chooser_value_type (*KeyFn) ()>
161 struct content__key_value_template
162 : public senf::detail::VariantKey<content__chooser_value_type, KeyFn> {};
163 template <class T, T (*K)()> friend class senf::detail::VariantKey;
164 typedef senf::detail::VariantKeyTransform<
165 content__chooser_value_type,
166 boost::mpl::vector< content__key_value_template<&content__key_0>,
167 content__key_value_template<&content__key_1> > >
169 typedef senf::detail::VariantParserTraits<content__parsers, content__transform>
172 // start SENF_PARSER_COLLECTION_I
173 static bool const content__aux_fixed = (SENF_MPL_SLOT_GET(group) - type_group) == 0;
174 typedef senf::detail::ParserAuxPolicySelect <
176 SENF_MPL_SLOT_GET(init_bytes) - type_init_bytes,
178 >::type content__aux_policy;
179 typedef content__traits::parser<content__aux_policy, senf::detail::auxtag::none>::type
180 content__collection_t;
181 SENF_MPL_SLOT_SET(bit, 0);
182 SENF_MPL_SLOT_SET(bitfield_size, 0);
183 typedef content__collection_t content__t;
184 static size_type const content__index = SENF_MPL_SLOT_GET(index) + 1;
185 SENF_MPL_SLOT_SET(index, content__index);
186 void init_chain (senf::mpl::rv<content__index> *) const
188 init_chain (static_cast<senf::mpl::rv<content__index - 1> *>(0));
191 size_type content__offset() const
193 return field_offset_ (static_cast<senf::mpl::rv<content__index - 1> *>(0));
195 static size_type const content__init_bytes = SENF_MPL_SLOT_GET(init_bytes);
196 size_type content__next_offset () const
198 return content__offset() + senf::bytes(content__());
200 static size_type const content__next_init_bytes =
201 content__init_bytes + senf::init_bytes<content__collection_t>::value;
202 size_type field_offset_(senf::mpl::rv<content__index> *) const
204 return content__next_offset();
206 SENF_MPL_SLOT_SET(init_bytes, content__next_init_bytes);
207 static size_type const content__group =
208 SENF_MPL_SLOT_GET(group) + (senf::is_fixed<content__collection_t>::value ? 0 : 1);
209 SENF_MPL_SLOET_SET(group, content__group);
211 T content__dispatch (boost::true_type) const
213 return parse<T>(content__offset());
216 T content__dispatch(boost::false_type) const
218 return parse<T>(type(), content__offset());
221 content__t content__() const
223 return content__dispatch<content__t>(
224 boost::integral_constant<bool, content__aux_fixed>());
226 content__t content_() const
230 // end SENF_PARSER_COLLECTION_I
233 void nocontent() const
235 content_().init<0>();
237 typedef SubParser content_t;
238 SubParser content() const
240 return content_().get<1>();
242 void init_content() const
244 content_().init<1>();
246 bool has_content() const
248 return content_().variant() == 1;
251 // /////////////////////////////////////////////////////////////////////////
252 // SENF_PARSER_FINALIZE(TestParser);
254 void defaultInit() const
256 init_chain(static_cast<senf::mpl::rv<SENF_MPL_SLOT_GET(index)> *>(0));
258 TestParser(data_iterator i, state_type s)
259 : parser_base_type (i, s)
274 size_type bytes() const
276 return field_offset_(static_cast<senf::mpl::rv<SENF_MPL_SLOT_GET(index)> *>(0));
278 static size_type const init_bytes = SENF_MPL_SLOT_GET(init_bytes);
287 // comment-column: 40
288 // c-file-style: "senf"
289 // indent-tabs-mode: nil
290 // ispell-local-dictionary: "american"
291 // compile-command: "scons -u test"