c0c79810d271e6bb2a561cccf61c1ce8be160955
[senf.git] / 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     The following packet parser definition (taken from VariantParser.test.cc) has been subject to
26     macro-expansion (and a lot of reformatting) to show the inner workings of the packet parser
27     macros:
28     \code
29     struct TestParser : public senf::PacketParserBase
30     {
31     #   include SENF_PARSER()
32
33         SENF_PARSER_SKIP_BITS( 4 );
34         SENF_PARSER_BITFIELD_RO( type, 4, unsigned );
35         SENF_PARSER_PRIVATE_VARIANT( content_, type,
36                                          ( novalue( nocontent, key(10, senf::VoidPacketParser)) )
37                                          (      id( content,           SubParser              ) )
38             );
39
40         SENF_PARSER_FINALIZE(TestParser);
41     };
42     \endcode
43
44     Here the reformated and sparsly commented expansion. I have left all the \c SENF_MPL_SLOT_ calls
45     unexpanded, otherwise the code would be absolutely unreadable. This is quite a lot of
46     source-code which however should create only a small amount of additional compiled code.
47
48     Also remember, that all this code is generated by C++ makros. Some detours are needed to work
49     around makro problems (e.g. templates with multiple arguments are parsed as seperate makro
50     arguments at each komma, inability to redefine a makro from another makro ...).
51
52     \code
53     struct TestParser : public senf::PacketParserBase
54     {
55         // /////////////////////////////////////////////////////////////////////////
56         // #include SENF_PARSER()
57
58     private:
59         SENF_MPL_SLOT_INIT_ZERO(index);
60         SENF_MPL_SLOT_INIT_ZERO(init_bytes);
61         SENF_MPL_SLOT_INIT_ZERO(bit);
62         SENF_MPL_SLOT_INIT_ZERO(bitfield_size);
63         SENF_MPL_SLOT_INIT_ZERO(group);
64
65         void init_chain (senf::mpl::rv <0> *) const {} 
66         size_type field_offset_ (senf::mpl::rv <0> *) const { return 0; }
67
68         // /////////////////////////////////////////////////////////////////////////
69         // SENF_PARSER_SKIP_BITS( 4 );
70
71         SENF_MPL_SLOT_SET(bit, SENF_MPL_SLOT_GET(bit) + 4);
72
73         // /////////////////////////////////////////////////////////////////////////
74         // SENF_PARSER_BITFIELD_RO( type, 4, unsigned );
75
76     public:
77         static size_type const type_bit = SENF_MPL_SLOT_GET(bit);
78
79     private:
80         SENF_MPL_SLOT_SET(bit, type_bit + 4);
81         typedef senf::UIntFieldParser <type_bit, type_bit + 4> type_bit_t;
82
83     public:
84         typedef type_bit_t type_t;
85         static size_type const type_index = SENF_MPL_SLOT_GET(index) + 1;
86
87     private:
88         SENF_MPL_SLOT_SET(index, type_index);
89         void init_chain (senf::mpl::rv<type_index> *) const
90             {
91                 init_chain (static_cast<senf::mpl::rv<type_index - 1> *>(0));
92             } 
93
94     public:
95         size_type type_offset () const
96             {
97                 return field_offset_(static_cast<senf::mpl::rv<type_index - 1> *>(0)) -
98                     SENF_MPL_SLOT_GET(bitfield_size); 
99             }
100         static size_type const type_init_bytes =
101             SENF_MPL_SLOT_GET(init_bytes) - SENF_MPL_SLOT_GET(bitfield_size);
102         size_type type_next_offset () const
103             {
104                 return type_offset() + type_t::fixed_bytes;
105             }
106         static size_type const type_next_init_bytes = type_init_bytes + type_t::fixed_bytes;
107
108     private:
109         size_type field_offset_(senf::mpl::rv<type_index> *) const
110             {
111                 return type_next_offset();
112             }
113         SENF_MPL_SLOT_SET(init_bytes, type_next_init_bytes);
114         static size_type const type_group = SENF_MPL_SLOT_GET(group) + 0;
115         SENF_MPL_SLOT_SET(group, type_group);
116         SENF_MPL_SLOT_SET(bitfield_size, type_t::fixed_bytes);
117         type_t type_ () const
118             {
119                 return parse <type_bit_t> (type_offset ());
120             }
121
122     public:
123         type_t::value_type type () const
124             {
125                 return type_();
126             }
127
128         // /////////////////////////////////////////////////////////////////////////
129         // SENF_PARSER_PRIVATE_VARIANT( content_, type,
130         //                                 ( novalue( nocontent, key(10, senf::VoidPacketParser)) )
131         //                                 (      id( content,           SubParser              ) )
132         //    );
133
134     private:
135         typedef boost::mpl::vector <senf::VoidPacketParser, SubParser> content__parsers;
136         typedef type_t::value_type content__chooser_value_type;
137         static content__chooser_value_type content__key_0 ()
138             {
139                 return 10;
140             }
141         static content__chooser_value_type content__key_1 ()
142             {
143                 return 1;
144             }
145         template <content__chooser_value_type (*KeyFn) ()>
146         struct content__key_value_template 
147             : public senf::detail::VariantKey<content__chooser_value_type, KeyFn> {};
148         template <class T, T (*K)()> friend class senf::detail::VariantKey;
149         typedef senf::detail::VariantKeyTransform<
150             content__chooser_value_type,
151             boost::mpl::vector< content__key_value_template<&content__key_0>,
152                                 content__key_value_template<&content__key_1> > >
153                 content__transform;
154         typedef senf::detail::VariantParserTraits<content__parsers, content__transform>
155             content__traits;
156
157         // start SENF_PARSER_COLLECTION_I
158         static bool const content__aux_fixed = (SENF_MPL_SLOT_GET(group) - type_group) == 0;
159         typedef senf::detail::ParserAuxPolicySelect < 
160             type_t, 
161             SENF_MPL_SLOT_GET(init_bytes) - type_init_bytes,
162             content__aux_fixed 
163             >::type content__aux_policy;
164         typedef content__traits::parser<content__aux_policy, senf::detail::auxtag::none>::type
165             content__collection_t;
166         SENF_MPL_SLOT_SET(bit, 0);
167         SENF_MPL_SLOT_SET(bitfield_size, 0);
168         typedef content__collection_t content__t;        
169         static size_type const content__index = SENF_MPL_SLOT_GET(index) + 1;
170         SENF_MPL_SLOT_SET(index, content__index);
171         void init_chain (senf::mpl::rv<content__index> *) const
172             {
173                 init_chain (static_cast<senf::mpl::rv<content__index - 1> *>(0));
174                 content_().init();
175             }
176         size_type content__offset() const
177             {
178                 return field_offset_ (static_cast<senf::mpl::rv<content__index - 1> *>(0));
179             }
180         static size_type const content__init_bytes = SENF_MPL_SLOT_GET(init_bytes);
181         size_type content__next_offset () const
182             {
183                 return content__offset() + senf::bytes(content__());
184             }
185         static size_type const content__next_init_bytes =
186             content__init_bytes + senf::init_bytes<content__collection_t>::value;
187         size_type field_offset_(senf::mpl::rv<content__index> *) const
188             {
189                 return content__next_offset();
190             }
191         SENF_MPL_SLOT_SET(init_bytes, content__next_init_bytes);
192         static size_type const content__group = 
193             SENF_MPL_SLOT_GET(group) + (senf::is_fixed<content__collection_t>::value ? 0 : 1);
194         SENF_MPL_SLOET_SET(group, content__group);
195         template < class T >
196         T content__dispatch (boost::true_type) const
197             {
198                 return parse<T>(content__offset());
199             }
200         template < class T >
201         T content__dispatch (boost::false_type) const
202             {
203                 return parse<T>(type(), content__offset());
204             }
205
206         content__t content__() const
207             {
208                 return content__dispatch<content__t>(
209                     boost::integral_constant<bool, content__aux_fixed>());
210             }
211         content__t content_ () const
212             {
213                 return content__ ();
214             }
215         // end SENF_PARSER_COLLECTION_I
216
217     public:
218         void nocontent() const
219             {
220                 content_().init<0>();
221             }
222         typedef SubParser content_t;
223         SubParser content() const
224             {
225                 return content_().get<1>();
226             }
227         void init_content() const
228             {
229                 content_().init<1>();
230             } 
231         bool has_content() const
232             {
233                 return content_().variant() == 1;
234             };
235
236         // /////////////////////////////////////////////////////////////////////////
237         // SENF_PARSER_FINALIZE(TestParser);
238
239         void defaultInit () const
240             {
241                 init_chain(static_cast<senf::mpl::rv<SENF_MPL_SLOT_GET(index)> *>(0));
242             }
243         TestParser(data_iterator i, state_type s)
244             : parser_base_type (i, s)
245             {}
246
247     private:
248         template <class T> 
249         void init(T) const
250             { 
251                 defaultInit ();
252             }
253
254     public:
255         void init() const
256             {
257                 init (0);
258             }
259         size_type bytes() const
260             {
261                 return field_offset_(static_cast<senf::mpl::rv<SENF_MPL_SLOT_GET(index)> *>(0));
262             }
263         static size_type const init_bytes = SENF_MPL_SLOT_GET(init_bytes);
264     };
265     \endcode
266  */
267
268 \f
269 // Local Variables:
270 // mode: c++
271 // fill-column: 100
272 // comment-column: 40
273 // c-file-style: "senf"
274 // indent-tabs-mode: nil
275 // ispell-local-dictionary: "american"
276 // compile-command: "scons -u test"
277 // mode: flyspell
278 // mode: auto-fill
279 // End: