4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
25 // Stefan Bund <g0dil@berlios.de>
28 /** \page parsermacro_expand_example Example macro-expansion of packet parser helper macros
30 Debugging the packet parser makros is somwhat difficult since the makro expansion will place
31 everything in a single line. To help pin down problems, I use
34 $ g++ -DSENF_MPL_SLOT_NOEXPAND -o <path-to-file>.ii -E -DSENF_DEBUG -Iinclude <path-to-file>.cc
35 $ sed -i -e 's/}/}\\n/g' -e '/^#.*$/d' <path-to-file>.ii
36 $ astyle --style=linux -b <path-to-file>.ii
39 I normally just cut-and-paste the \c g++ command from a normal build and add
40 <tt>-DSENF_MPL_SLOT_NOEXPAND</tt>. \c astyle is found at http://astyle.sourceforge.net/. If
41 needed, I then reissue this file (the precessed \.ii file) back to the compiler using the
42 original commandline (just replacing the \c .cc with \c .ii) to get error messages with
43 meaningful line numbers.
45 The following packet parser definition (taken from VariantParser.test.cc) has been subject to
46 macro-expansion (and a lot of manual reformatting) to show the inner workings of the packet
49 struct TestParser : public senf::PacketParserBase
51 # include SENF_PARSER()
53 SENF_PARSER_SKIP_BITS( 4 );
54 SENF_PARSER_BITFIELD_RO( type, 4, unsigned );
55 SENF_PARSER_PRIVATE_VARIANT( content_, type,
56 ( novalue( nocontent, key(10, senf::VoidPacketParser)) )
57 ( id( content, SubParser ) )
60 SENF_PARSER_FINALIZE(TestParser);
64 Here the reformated and sparsly commented expansion. I have left all the \c SENF_MPL_SLOT_ calls
65 unexpanded, otherwise the code would be absolutely unreadable. This is quite a lot of
66 source-code which however should create only a small amount of additional compiled code.
68 Also remember, that all this code is generated by C++ makros. Some detours are needed to work
69 around makro problems (e.g. templates with multiple arguments are parsed as seperate makro
70 arguments at each komma, inability to redefine a makro from another makro ...).
73 struct TestParser : public senf::PacketParserBase
75 //-/////////////////////////////////////////////////////////////////////////
76 // #include SENF_PARSER()
79 SENF_MPL_SLOT_INIT_ZERO(index);
80 SENF_MPL_SLOT_INIT_ZERO(init_bytes);
81 SENF_MPL_SLOT_INIT_ZERO(bit);
82 SENF_MPL_SLOT_INIT_ZERO(bitfield_size);
83 SENF_MPL_SLOT_INIT_ZERO(group);
85 void init_chain (senf::mpl::rv <0> *) const {}
86 size_type field_offset_ (senf::mpl::rv <0> *) const { return 0; }
88 //-/////////////////////////////////////////////////////////////////////////
89 // SENF_PARSER_SKIP_BITS( 4 );
91 SENF_MPL_SLOT_SET(bit, SENF_MPL_SLOT_GET(bit) + 4);
93 //-/////////////////////////////////////////////////////////////////////////
94 // SENF_PARSER_BITFIELD_RO( type, 4, unsigned );
97 static size_type const type_bit = SENF_MPL_SLOT_GET(bit);
100 SENF_MPL_SLOT_SET(bit, type_bit + 4);
101 typedef senf::UIntFieldParser <type_bit, type_bit + 4> type_bit_t;
104 typedef type_bit_t type_t;
105 static size_type const type_index = SENF_MPL_SLOT_GET(index) + 1;
108 SENF_MPL_SLOT_SET(index, type_index);
109 void init_chain (senf::mpl::rv<type_index> *) const
111 init_chain (static_cast<senf::mpl::rv<type_index - 1> *>(0));
115 size_type type_offset() const
117 return field_offset_(static_cast<senf::mpl::rv<type_index - 1> *>(0)) -
118 SENF_MPL_SLOT_GET(bitfield_size);
120 static size_type const type_init_bytes =
121 SENF_MPL_SLOT_GET(init_bytes) - SENF_MPL_SLOT_GET(bitfield_size);
122 size_type type_next_offset () const
124 return type_offset() + type_t::fixed_bytes;
126 static size_type const type_next_init_bytes = type_init_bytes + type_t::fixed_bytes;
129 size_type field_offset_(senf::mpl::rv<type_index> *) const
131 return type_next_offset();
133 SENF_MPL_SLOT_SET(init_bytes, type_next_init_bytes);
134 static size_type const type_group = SENF_MPL_SLOT_GET(group) + 0;
135 SENF_MPL_SLOT_SET(group, type_group);
136 SENF_MPL_SLOT_SET(bitfield_size, type_t::fixed_bytes);
139 return parse <type_bit_t> (type_offset ());
143 type_t::value_type type() const
148 //-/////////////////////////////////////////////////////////////////////////
149 // SENF_PARSER_PRIVATE_VARIANT( content_, type,
150 // ( novalue( nocontent, key(10, senf::VoidPacketParser)) )
151 // ( id( content, SubParser ) )
155 typedef boost::mpl::vector <senf::VoidPacketParser, SubParser> content__parsers;
156 typedef type_t::value_type content__chooser_value_type;
157 static content__chooser_value_type content__key_0 ()
161 static content__chooser_value_type content__key_1 ()
165 template <content__chooser_value_type (*KeyFn) ()>
166 struct content__key_value_template
167 : public senf::detail::VariantKey<content__chooser_value_type, KeyFn> {};
168 template <class T, T (*K)()> friend class senf::detail::VariantKey;
169 typedef senf::detail::VariantKeyTransform<
170 content__chooser_value_type,
171 boost::mpl::vector< content__key_value_template<&content__key_0>,
172 content__key_value_template<&content__key_1> > >
174 typedef senf::detail::VariantParserTraits<content__parsers, content__transform>
177 // start SENF_PARSER_COLLECTION_I
178 static bool const content__aux_fixed = (SENF_MPL_SLOT_GET(group) - type_group) == 0;
179 typedef senf::detail::ParserAuxPolicySelect <
181 SENF_MPL_SLOT_GET(init_bytes) - type_init_bytes,
183 >::type content__aux_policy;
184 typedef content__traits::parser<content__aux_policy, senf::detail::auxtag::none>::type
185 content__collection_t;
186 SENF_MPL_SLOT_SET(bit, 0);
187 SENF_MPL_SLOT_SET(bitfield_size, 0);
188 typedef content__collection_t content__t;
189 static size_type const content__index = SENF_MPL_SLOT_GET(index) + 1;
190 SENF_MPL_SLOT_SET(index, content__index);
191 void init_chain (senf::mpl::rv<content__index> *) const
193 init_chain (static_cast<senf::mpl::rv<content__index - 1> *>(0));
196 size_type content__offset() const
198 return field_offset_ (static_cast<senf::mpl::rv<content__index - 1> *>(0));
200 static size_type const content__init_bytes = SENF_MPL_SLOT_GET(init_bytes);
201 size_type content__next_offset () const
203 return content__offset() + senf::bytes(content__());
205 static size_type const content__next_init_bytes =
206 content__init_bytes + senf::init_bytes<content__collection_t>::value;
207 size_type field_offset_(senf::mpl::rv<content__index> *) const
209 return content__next_offset();
211 SENF_MPL_SLOT_SET(init_bytes, content__next_init_bytes);
212 static size_type const content__group =
213 SENF_MPL_SLOT_GET(group) + (senf::is_fixed<content__collection_t>::value ? 0 : 1);
214 SENF_MPL_SLOET_SET(group, content__group);
216 T content__dispatch (boost::true_type) const
218 return parse<T>(content__offset());
221 T content__dispatch(boost::false_type) const
223 return parse<T>(type(), content__offset());
226 content__t content__() const
228 return content__dispatch<content__t>(
229 boost::integral_constant<bool, content__aux_fixed>());
231 content__t content_() const
235 // end SENF_PARSER_COLLECTION_I
238 void nocontent() const
240 content_().init<0>();
242 typedef SubParser content_t;
243 SubParser content() const
245 return content_().get<1>();
247 void init_content() const
249 content_().init<1>();
251 bool has_content() const
253 return content_().variant() == 1;
256 //-/////////////////////////////////////////////////////////////////////////
257 // SENF_PARSER_FINALIZE(TestParser);
259 void defaultInit() const
261 init_chain(static_cast<senf::mpl::rv<SENF_MPL_SLOT_GET(index)> *>(0));
263 TestParser(data_iterator i, state_type s)
264 : parser_base_type (i, s)
279 size_type bytes() const
281 return field_offset_(static_cast<senf::mpl::rv<SENF_MPL_SLOT_GET(index)> *>(0));
283 static size_type const init_bytes = SENF_MPL_SLOT_GET(init_bytes);
292 // comment-column: 40
293 // c-file-style: "senf"
294 // indent-tabs-mode: nil
295 // ispell-local-dictionary: "american"
296 // compile-command: "scons -u test"