Fix documentation build under maverick (doxygen 1.7.1)
[senf.git] / senf / Packets / ParseHelpers.dox
1 // $Id$
2 //
3 // Copyright (C) 2008
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
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.
12 //
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.
17 //
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.
22
23 /** \page parsermacro_expand_example Example macro-expansion of packet parser helper macros
24
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
27
28     <pre>
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
32     </pre>
33
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.
39
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
42     parser macros:
43     \code
44     struct TestParser : public senf::PacketParserBase
45     {
46     #   include SENF_PARSER()
47
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              ) )
53             );
54
55         SENF_PARSER_FINALIZE(TestParser);
56     };
57     \endcode
58
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.
62
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 ...).
66
67     \code
68     struct TestParser : public senf::PacketParserBase
69     {
70         //-/////////////////////////////////////////////////////////////////////////
71         // #include SENF_PARSER()
72
73     private:
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);
79
80         void init_chain (senf::mpl::rv <0> *) const {}
81         size_type field_offset_ (senf::mpl::rv <0> *) const { return 0; }
82
83         //-/////////////////////////////////////////////////////////////////////////
84         // SENF_PARSER_SKIP_BITS( 4 );
85
86         SENF_MPL_SLOT_SET(bit, SENF_MPL_SLOT_GET(bit) + 4);
87
88         //-/////////////////////////////////////////////////////////////////////////
89         // SENF_PARSER_BITFIELD_RO( type, 4, unsigned );
90
91     public:
92         static size_type const type_bit = SENF_MPL_SLOT_GET(bit);
93
94     private:
95         SENF_MPL_SLOT_SET(bit, type_bit + 4);
96         typedef senf::UIntFieldParser <type_bit, type_bit + 4> type_bit_t;
97
98     public:
99         typedef type_bit_t type_t;
100         static size_type const type_index = SENF_MPL_SLOT_GET(index) + 1;
101
102     private:
103         SENF_MPL_SLOT_SET(index, type_index);
104         void init_chain (senf::mpl::rv<type_index> *) const
105             {
106                 init_chain (static_cast<senf::mpl::rv<type_index - 1> *>(0));
107             }
108
109     public:
110         size_type type_offset() const
111             {
112                 return field_offset_(static_cast<senf::mpl::rv<type_index - 1> *>(0)) -
113                     SENF_MPL_SLOT_GET(bitfield_size);
114             }
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
118             {
119                 return type_offset() + type_t::fixed_bytes;
120             }
121         static size_type const type_next_init_bytes = type_init_bytes + type_t::fixed_bytes;
122
123     private:
124         size_type field_offset_(senf::mpl::rv<type_index> *) const
125             {
126                 return type_next_offset();
127             }
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);
132         type_t type_() const
133             {
134                 return parse <type_bit_t> (type_offset ());
135             }
136
137     public:
138         type_t::value_type type() const
139             {
140                 return type_();
141             }
142
143         //-/////////////////////////////////////////////////////////////////////////
144         // SENF_PARSER_PRIVATE_VARIANT( content_, type,
145         //                                 ( novalue( nocontent, key(10, senf::VoidPacketParser)) )
146         //                                 (      id( content,           SubParser              ) )
147         //    );
148
149     private:
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 ()
153             {
154                 return 10;
155             }
156         static content__chooser_value_type content__key_1 ()
157             {
158                 return 1;
159             }
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> > >
168                 content__transform;
169         typedef senf::detail::VariantParserTraits<content__parsers, content__transform>
170             content__traits;
171
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 <
175             type_t,
176             SENF_MPL_SLOT_GET(init_bytes) - type_init_bytes,
177             content__aux_fixed
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
187             {
188                 init_chain (static_cast<senf::mpl::rv<content__index - 1> *>(0));
189                 content_().init();
190             }
191         size_type content__offset() const
192             {
193                 return field_offset_ (static_cast<senf::mpl::rv<content__index - 1> *>(0));
194             }
195         static size_type const content__init_bytes = SENF_MPL_SLOT_GET(init_bytes);
196         size_type content__next_offset () const
197             {
198                 return content__offset() + senf::bytes(content__());
199             }
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
203             {
204                 return content__next_offset();
205             }
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);
210         template < class T >
211         T content__dispatch (boost::true_type) const
212             {
213                 return parse<T>(content__offset());
214             }
215         template < class T >
216         T content__dispatch(boost::false_type) const
217             {
218                 return parse<T>(type(), content__offset());
219             }
220
221         content__t content__() const
222             {
223                 return content__dispatch<content__t>(
224                     boost::integral_constant<bool, content__aux_fixed>());
225             }
226         content__t content_() const
227             {
228                 return content__ ();
229             }
230         // end SENF_PARSER_COLLECTION_I
231
232     public:
233         void nocontent() const
234             {
235                 content_().init<0>();
236             }
237         typedef SubParser content_t;
238         SubParser content() const
239             {
240                 return content_().get<1>();
241             }
242         void init_content() const
243             {
244                 content_().init<1>();
245             }
246         bool has_content() const
247             {
248                 return content_().variant() == 1;
249             };
250
251         //-/////////////////////////////////////////////////////////////////////////
252         // SENF_PARSER_FINALIZE(TestParser);
253
254         void defaultInit() const
255             {
256                 init_chain(static_cast<senf::mpl::rv<SENF_MPL_SLOT_GET(index)> *>(0));
257             }
258         TestParser(data_iterator i, state_type s)
259             : parser_base_type (i, s)
260             {}
261
262     private:
263         template <class T>
264         void init(T) const
265             {
266                 defaultInit ();
267             }
268
269     public:
270         void init() const
271             {
272                 init (0);
273             }
274         size_type bytes() const
275             {
276                 return field_offset_(static_cast<senf::mpl::rv<SENF_MPL_SLOT_GET(index)> *>(0));
277             }
278         static size_type const init_bytes = SENF_MPL_SLOT_GET(init_bytes);
279     };
280     \endcode
281  */
282
283 \f
284 // Local Variables:
285 // mode: c++
286 // fill-column: 100
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"
292 // mode: flyspell
293 // mode: auto-fill
294 // End: