switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Packets / ParseHelpers.dox
1 // $Id$
2 //
3 // Copyright (C) 2008
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
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
10 //
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.
14 //
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.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 //
24 // Contributor(s):
25 //   Stefan Bund <g0dil@berlios.de>
26
27
28 /** \page parsermacro_expand_example Example macro-expansion of packet parser helper macros
29
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
32
33     <pre>
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
37     </pre>
38
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.
44
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
47     parser macros:
48     \code
49     struct TestParser : public senf::PacketParserBase
50     {
51     #   include SENF_PARSER()
52
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              ) )
58             );
59
60         SENF_PARSER_FINALIZE(TestParser);
61     };
62     \endcode
63
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.
67
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 ...).
71
72     \code
73     struct TestParser : public senf::PacketParserBase
74     {
75         //-/////////////////////////////////////////////////////////////////////////
76         // #include SENF_PARSER()
77
78     private:
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);
84
85         void init_chain (senf::mpl::rv <0> *) const {}
86         size_type field_offset_ (senf::mpl::rv <0> *) const { return 0; }
87
88         //-/////////////////////////////////////////////////////////////////////////
89         // SENF_PARSER_SKIP_BITS( 4 );
90
91         SENF_MPL_SLOT_SET(bit, SENF_MPL_SLOT_GET(bit) + 4);
92
93         //-/////////////////////////////////////////////////////////////////////////
94         // SENF_PARSER_BITFIELD_RO( type, 4, unsigned );
95
96     public:
97         static size_type const type_bit = SENF_MPL_SLOT_GET(bit);
98
99     private:
100         SENF_MPL_SLOT_SET(bit, type_bit + 4);
101         typedef senf::UIntFieldParser <type_bit, type_bit + 4> type_bit_t;
102
103     public:
104         typedef type_bit_t type_t;
105         static size_type const type_index = SENF_MPL_SLOT_GET(index) + 1;
106
107     private:
108         SENF_MPL_SLOT_SET(index, type_index);
109         void init_chain (senf::mpl::rv<type_index> *) const
110             {
111                 init_chain (static_cast<senf::mpl::rv<type_index - 1> *>(0));
112             }
113
114     public:
115         size_type type_offset() const
116             {
117                 return field_offset_(static_cast<senf::mpl::rv<type_index - 1> *>(0)) -
118                     SENF_MPL_SLOT_GET(bitfield_size);
119             }
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
123             {
124                 return type_offset() + type_t::fixed_bytes;
125             }
126         static size_type const type_next_init_bytes = type_init_bytes + type_t::fixed_bytes;
127
128     private:
129         size_type field_offset_(senf::mpl::rv<type_index> *) const
130             {
131                 return type_next_offset();
132             }
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);
137         type_t type_() const
138             {
139                 return parse <type_bit_t> (type_offset ());
140             }
141
142     public:
143         type_t::value_type type() const
144             {
145                 return type_();
146             }
147
148         //-/////////////////////////////////////////////////////////////////////////
149         // SENF_PARSER_PRIVATE_VARIANT( content_, type,
150         //                                 ( novalue( nocontent, key(10, senf::VoidPacketParser)) )
151         //                                 (      id( content,           SubParser              ) )
152         //    );
153
154     private:
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 ()
158             {
159                 return 10;
160             }
161         static content__chooser_value_type content__key_1 ()
162             {
163                 return 1;
164             }
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> > >
173                 content__transform;
174         typedef senf::detail::VariantParserTraits<content__parsers, content__transform>
175             content__traits;
176
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 <
180             type_t,
181             SENF_MPL_SLOT_GET(init_bytes) - type_init_bytes,
182             content__aux_fixed
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
192             {
193                 init_chain (static_cast<senf::mpl::rv<content__index - 1> *>(0));
194                 content_().init();
195             }
196         size_type content__offset() const
197             {
198                 return field_offset_ (static_cast<senf::mpl::rv<content__index - 1> *>(0));
199             }
200         static size_type const content__init_bytes = SENF_MPL_SLOT_GET(init_bytes);
201         size_type content__next_offset () const
202             {
203                 return content__offset() + senf::bytes(content__());
204             }
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
208             {
209                 return content__next_offset();
210             }
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);
215         template < class T >
216         T content__dispatch (boost::true_type) const
217             {
218                 return parse<T>(content__offset());
219             }
220         template < class T >
221         T content__dispatch(boost::false_type) const
222             {
223                 return parse<T>(type(), content__offset());
224             }
225
226         content__t content__() const
227             {
228                 return content__dispatch<content__t>(
229                     boost::integral_constant<bool, content__aux_fixed>());
230             }
231         content__t content_() const
232             {
233                 return content__ ();
234             }
235         // end SENF_PARSER_COLLECTION_I
236
237     public:
238         void nocontent() const
239             {
240                 content_().init<0>();
241             }
242         typedef SubParser content_t;
243         SubParser content() const
244             {
245                 return content_().get<1>();
246             }
247         void init_content() const
248             {
249                 content_().init<1>();
250             }
251         bool has_content() const
252             {
253                 return content_().variant() == 1;
254             };
255
256         //-/////////////////////////////////////////////////////////////////////////
257         // SENF_PARSER_FINALIZE(TestParser);
258
259         void defaultInit() const
260             {
261                 init_chain(static_cast<senf::mpl::rv<SENF_MPL_SLOT_GET(index)> *>(0));
262             }
263         TestParser(data_iterator i, state_type s)
264             : parser_base_type (i, s)
265             {}
266
267     private:
268         template <class T>
269         void init(T) const
270             {
271                 defaultInit ();
272             }
273
274     public:
275         void init() const
276             {
277                 init (0);
278             }
279         size_type bytes() const
280             {
281                 return field_offset_(static_cast<senf::mpl::rv<SENF_MPL_SLOT_GET(index)> *>(0));
282             }
283         static size_type const init_bytes = SENF_MPL_SLOT_GET(init_bytes);
284     };
285     \endcode
286  */
287
288 \f
289 // Local Variables:
290 // mode: c++
291 // fill-column: 100
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"
297 // mode: flyspell
298 // mode: auto-fill
299 // End: