Fixed whitespace in all files (no tabs)
[senf.git] / Packets / ParserBase.hh
1 // $Id$
2 //
3 // Copyright (C) 2006
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 //     Stefan Bund <stefan.bund@fokus.fraunhofer.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 /** \file
24     \brief Parser framework
25  */
26
27 #ifndef HH_ParserBase_
28 #define HH_ParserBase_ 1
29
30 // Custom includes
31 #include <utility>
32 #include <boost/iterator/iterator_facade.hpp>
33 #include <boost/type_traits/is_member_function_pointer.hpp>
34
35 #include "ParserBase.ih"
36 ///////////////////////////////hh.p////////////////////////////////////////
37
38 namespace senf {
39
40
41     namespace impl { struct ParserBase; }
42
43     struct nil
44         : public boost::iterator_facade<nil,char,boost::random_access_traversal_tag>
45     {
46         // Theese are declared to make nil a valid iterator. All
47         // access to an instance of this iterator however is invalid
48         // (these members are not implemented only declared)
49         char & dereference() const;
50         bool equal(nil other) const;
51         void increment();
52         void decrement();
53         void advance(int n);
54         int distance_to(nil other) const;
55     };
56
57     /** \brief Parser framework
58
59         This class is the baseclass for all parser classes of the
60         parser framework. The parser framework is used to interpret
61         byte-oriented data from arbitrary random access iterators. The
62         framework is hierarchical in the sense, that parsers can be
63         arbitrarily nested.
64
65         All parser framework classes are as lightweight as
66         possible. Most parser classes only have a single iterator as
67         data member and (depending on the container) therefore have
68         the same size as a single pointer. Parsers are therefore
69         conceptually and in essence simply pointers decorated with
70         type information.
71
72         It is very important for parser classes to be lightweight and
73         to have only simple constructors since parsers are passed
74         around by value. Parser instances most of the time are
75         temporaries. However, since they are only 'decorated'
76         pointers, this should not have any performance impact.
77
78         To implement a new parser, write a template implementing the
79         following members:
80
81         \code
82             template <class Iterator=nil, class IPacket=nil>
83             struct Parser_Example
84                 : protected senf::ParserBase<Iterator,IPacket>
85             {
86                 // fixed interface of all parser classes
87
88                 template <class I=nil, class P=nil>
89                 struct rebind { typedef Parse_Example<I,P> parser; }
90                 typedef Iterator byte_iterator;
91
92                 Parse_Example() {}
93                 Parse_Example(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {}
94
95                 [static] unsigned bytes()
96                 {
97                     // return the size of the parsed header. This
98                     // method must be declared static if the size is
99                     // constant, otherwise it must be a non-static
100                     // member
101                     return 14;
102                 }
103
104                 static bool check(Iterator const & begin, Iterator const & end)
105                 {
106                     BOOST_ASSERT( end>=begin );
107                     // return true, if the data in the range [begin,end)
108                     // can be safely interpreted by the parser without
109                     // causing invalid memory access. This means,
110                     // check, wether the data is truncated
111                     return static_cast<unsigned>(end-begin) >= bytes();
112                 }
113
114                 // optional, only needed if bytes() is non-static
115                 static unsigned min_bytes()
116                 {
117                     // return the minimum size of the header. This
118                     // is the amount of space needed to allocate
119                     // an otherwise empty packet
120                     return 10;
121                 }
122
123                 // optional
124                 void init()
125                 {
126                     // initialize the packet if necessary
127                 }
128
129                 // optional
130                 void init(Iterator b, Iterator e)
131                 {
132                     // initialize the packet with given payload
133                 }
134
135                 // example methods to parse fields
136
137                 typedef Parse_UInt16 < Iterator >                    Parse_Field1;
138                 typedef Parse_Array  < 3, Parse_UInt32<>, Iterator > Parser_Field2
139
140                 Parse_Field1 field1() const { return Parse_Field1 (this->i()); }
141                 Parse_Field2 field2() const { return Parse_Field2 (this->i()+2); }
142             };
143         \endcode
144
145         Every parser must have some mandatory fixed members which are:
146
147         - struct rebind: This structure allows the parser to be
148           converted to a parser of the same type but with a different
149           iterator. Parser may have more than the two standard
150           template parameters. These parameters must then be added in
151           front of the standard parameters. The rebind structure must
152           however always have only two parameters. Additional
153           parameters must be provided from the outside template
154
155         - byte_iterator: A typedef for the Iterator class used
156
157         - Non Iterator constructor: This constructor is only used when
158           the parser is inherited into a Packet class.
159
160         - Iterator constructor: This constructor must call the
161           corresponding ParserBase constructor.
162
163         - unsigned bytes() member: This member must return the number
164           of bytes the parser interprets. This will be the size of the
165           implemented header. If the header has a fixed size, this
166           member must be static, if it is dynamic the member must be
167           non-static
168
169         - static bool check(Iterator b, Iterator e) member: This
170           method must return true \e only if the range [b,e) contains
171           a \e complete packet, that is, e-b >= bytes(). However, the
172           call to bytes() might involve accessing data bytes which
173           might not exist. The bytes() call cannot check this (it has
174           no access to the \e end of the valid range). To keep the
175           performance up, the validity check is performed once. The
176           parser has to ensure, that validity is maintained even when
177           changing the values. Validity in this context does not
178           imply, that the packet is semantically correct, it only
179           implies, that the packet can be parsed without risking
180           invalid memory access.
181
182         - The min_bytes() member is optional. It is only used, if the
183           Parser implements a non-fixed-size Packet, that is, if the
184           bytes() member is non-static. In this case, min_bytes() has
185           to be implemented and must return the amount of space
186           necessary to construct an empty instance. The construction
187           will proceed by first allocating the necessary space
188           somewhere, initializing this space with all zeros. Then a
189           Parser instance is created at that space and the Parsers
190           init() method is called.
191
192         - The init() member is optional. If all-zero initialization of
193           a new Packet is enough, this member can be
194           skipped. Otherwise, the init() member can assume to have
195           access to a min_buytes() sized area which is all-zero
196           initialized.
197
198         - The init(Packet::ptr payload) member is optional. By default
199           it just calls the init() member. Here, special
200           initialization regarding the payload may be done. As for
201           min_bytes(Packet::ptr), the argument type is allowed to be
202           templatized or may be a specific packet ptr thereby
203           restricting the permissible payload packet types.
204
205         - The parser then contains any additional methods to parse the
206           header constituents.
207
208         ParserBase provides the parser classes with access to the
209         packet iterator. This class is templatized on the Iterator
210         type and an optional baseclass type.
211
212         If the baseclass is given, it is used to access the iterator
213         directly using 'begin'. If it is not given, the instance has
214         to be constructed with an iterator.
215
216         This implementation ensures, that a parser can either be
217         inherited into a Packet class or be used as a temporary.
218       */
219     template <class Iterator, class IPacket=nil>
220     class ParserBase : public impl::ParserBase
221     {
222     public:
223         ///////////////////////////////////////////////////////////////////////////
224         ///\name Structors and default members
225         ///@{
226
227         // default default constructor
228         // default copy constructor
229         // default copy assignment
230         // default destructor
231         // no conversion constructors
232
233         ///@}
234         ///////////////////////////////////////////////////////////////////////////
235
236         Iterator i() const;
237         static void init() {};
238
239     private:
240
241     };
242
243     template <class Iterator>
244     class ParserBase<Iterator,nil> : public impl::ParserBase
245     {
246     public:
247         ///////////////////////////////////////////////////////////////////////////
248         ///\name Structors and default members
249         ///@{
250
251         explicit ParserBase(Iterator const & i);
252
253         // no default constructor
254         // default copy constructor
255         // default copy assignment
256         // default destructor
257         // no conversion constructors
258
259         ///@}
260         ///////////////////////////////////////////////////////////////////////////
261
262         Iterator i() const;
263         static void init() {}
264         template <class SomePacket>
265         static void init(typename SomePacket::ptr) {}
266
267     private:
268
269         Iterator i_;
270     };
271
272     /** \brief Addtiional Parser information
273
274         Parser_traits provids abstract information about an unknown
275         parser. Besides the information already available within the
276         Parser it provides an additional 'fixed_sized' member which is
277         true if and only if the Parser has a static bytes() member.
278      */
279     template <class Parser>
280     struct Parser_traits {
281         typedef Parser parser;
282         typedef typename Parser::byte_iterator byte_iterator;
283         static const bool fixed_size = impl::Parser_traits_fixed_size<Parser>::fixed_size;
284
285         template <class I=nil, class P=nil>
286         struct rebind {
287             typedef typename Parser::template rebind<I,P>::parser parser;
288         };
289     };
290
291     template <class Parser, class Iterator>
292     bool check(Iterator const & b, Iterator const & e);
293
294     template <class Parser>
295     unsigned min_bytes();
296
297 }
298
299 ///////////////////////////////hh.e////////////////////////////////////////
300 //#include "ParserBase.cci"
301 //#include "ParserBase.ct"
302 #include "ParserBase.cti"
303 #endif
304
305 \f
306 // Local Variables:
307 // mode: c++
308 // fill-column: 100
309 // c-file-style: "senf"
310 // indent-tabs-mode: nil
311 // ispell-local-dictionary: "american"
312 // End: