4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 // Stefan Bund <stefan.bund@fokus.fraunhofer.de>
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.
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.
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.
24 \brief Parser framework
27 #ifndef HH_ParserBase_
28 #define HH_ParserBase_ 1
32 #include <boost/iterator/iterator_facade.hpp>
33 #include <boost/type_traits/is_member_function_pointer.hpp>
35 #include "ParserBase.ih"
36 ///////////////////////////////hh.p////////////////////////////////////////
41 namespace impl { struct ParserBase; }
44 : public boost::iterator_facade<nil,char,boost::random_access_traversal_tag>
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;
54 int distance_to(nil other) const;
57 /** \brief Parser framework
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
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
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.
78 To implement a new parser, write a template implementing the
82 template <class Iterator=nil, class IPacket=nil>
84 : protected senf::ParserBase<Iterator,IPacket>
86 // fixed interface of all parser classes
88 template <class I=nil, class P=nil>
89 struct rebind { typedef Parse_Example<I,P> parser; }
90 typedef Iterator byte_iterator;
93 Parse_Example(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {}
95 [static] unsigned bytes()
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
104 static bool check(Iterator const & begin, Iterator const & end)
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, whether the data is truncated
111 return static_cast<unsigned>(end-begin) >= bytes();
114 // optional, only needed if bytes() is non-static
115 static unsigned min_bytes()
117 // return the minimum size of the header. This
118 // is the amount of space needed to allocate
119 // an otherwise empty packet
126 // initialize the packet if necessary
130 void init(Iterator b, Iterator e)
132 // initialize the packet with given payload
135 // example methods to parse fields
137 typedef Parse_UInt16 < Iterator > Parse_Field1;
138 typedef Parse_Array < 3, Parse_UInt32<>, Iterator > Parser_Field2
140 Parse_Field1 field1() const { return Parse_Field1 (this->i()); }
141 Parse_Field2 field2() const { return Parse_Field2 (this->i()+2); }
145 Every parser must have some mandatory fixed members which are:
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
155 - byte_iterator: A typedef for the Iterator class used
157 - Non Iterator constructor: This constructor is only used when
158 the parser is inherited into a Packet class.
160 - Iterator constructor: This constructor must call the
161 corresponding ParserBase constructor.
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
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.
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.
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
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.
205 - The parser then contains any additional methods to parse the
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.
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.
216 This implementation ensures, that a parser can either be
217 inherited into a Packet class or be used as a temporary.
219 template <class Iterator, class IPacket=nil>
220 class ParserBase : public impl::ParserBase
223 ///////////////////////////////////////////////////////////////////////////
224 ///\name Structors and default members
227 // default default constructor
228 // default copy constructor
229 // default copy assignment
230 // default destructor
231 // no conversion constructors
234 ///////////////////////////////////////////////////////////////////////////
237 static void init() {};
243 template <class Iterator>
244 class ParserBase<Iterator,nil> : public impl::ParserBase
247 ///////////////////////////////////////////////////////////////////////////
248 ///\name Structors and default members
251 explicit ParserBase(Iterator const & i);
253 // no default constructor
254 // default copy constructor
255 // default copy assignment
256 // default destructor
257 // no conversion constructors
260 ///////////////////////////////////////////////////////////////////////////
263 static void init() {}
264 template <class SomePacket>
265 static void init(typename SomePacket::ptr) {}
272 /** \brief Addtiional Parser information
274 Parser_traits provides 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.
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;
285 template <class I=nil, class P=nil>
287 typedef typename Parser::template rebind<I,P>::parser parser;
291 template <class Parser, class Iterator>
292 bool check(Iterator const & b, Iterator const & e);
294 template <class Parser>
295 unsigned min_bytes();
299 ///////////////////////////////hh.e////////////////////////////////////////
300 //#include "ParserBase.cci"
301 //#include "ParserBase.ct"
302 #include "ParserBase.cti"
309 // c-file-style: "senf"
310 // indent-tabs-mode: nil
311 // ispell-local-dictionary: "american"