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/type_traits/is_member_function_pointer.hpp>
34 #include "ParserBase.ih"
35 ///////////////////////////////hh.p////////////////////////////////////////
40 namespace impl { struct ParserBase; }
44 /** \brief Parser framework
46 This class is the baseclass for all parser classes of the
47 parser framework. The parser framework is used to interpret
48 byte-oriented data from arbitrary random access iterators. The
49 framework is hierarchical in the sense, that parsers can be
52 All parser framework classes are as lightweight as
53 possible. Most parser classes only have a single iterator as
54 data member and (depending on the container) therefore have
55 the same size as a single pointer. Parsers are therefore
56 conceptually and in essence simply pointers decorated with
59 It is very important for parser classes to be lightweight and
60 to have only simple constructors since parsers are passed
61 around by value. Parser instances most of the time are
62 temporaries. However, since they are only 'decorated'
63 pointers, this should not have any performance impact.
65 To implement a new parser, write a template implementing the
69 template <class Iterator=nil, class IPacket=nil>
71 : protected satcom::pkf::ParserBase<Iterator,IPacket>
73 // fixed interface of all parser classes
75 template <class I=nil, class P=nil>
76 struct rebind { typedef Parse_Example<I,P> parser; }
77 typedef Iterator byte_iterator;
80 Parse_Example(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {}
82 [static] unsigned bytes()
84 // return the size of the parsed header. This
85 // method must be declared static if the size is
86 // constant, otherwise it must be a non-static
91 static bool check(Iterator const & begin, Iterator const & end)
93 BOOST_ASSERT( end>=begin );
94 // return true, if the data in the range [begin,end)
95 // can be safely interpreted by the parser without
96 // causing invalid memory access. This means,
97 // check, wether the data is truncated
98 return static_cast<unsigned>(end-begin) >= bytes();
101 // optional, only needed if bytes() is non-static
102 static unsigned min_bytes()
104 // return the minimum size of the header. This
105 // is the amount of space needed to allocate
106 // an otherwise empty packet
113 // initialize the packet if necessary
117 void init(Iterator b, Iterator e)
119 // initialize the packet with given payload
122 // example methods to parse fields
124 typedef Parse_UInt16 < Iterator > Parse_Field1;
125 typedef Parse_Array < 3, Parse_UInt32<>, Iterator > Parser_Field2
127 Parse_Field1 field1() const { return Parse_Field1 (this->i()); }
128 Parse_Field2 field2() const { return Parse_Field2 (this->i()+2); }
132 Every parser must have some mandatory fixed members which are:
134 - struct rebind: This structure allows the parser to be
135 converted to a parser of the same type but with a different
136 iterator. Parser may have more than the two standard
137 template parameters. These parameters must then be added in
138 front of the standard parameters. The rebind structure must
139 however always have only two parameters. Additional
140 parameters must be provided from the outside template
142 - byte_iterator: A typedef for the Iterator class used
144 - Non Iterator constructor: This constructor is only used when
145 the parser is inherited into a Packet class.
147 - Iterator constructor: This constructor must call the
148 corresponding ParserBase constructor.
150 - unsigned bytes() member: This member must return the number
151 of bytes the parser interprets. This will be the size of the
152 implemented header. If the header has a fixed size, this
153 member must be static, if it is dynamic the member must be
156 - static bool check(Iterator b, Iterator e) member: This
157 method must return true \e only if the range [b,e) contains
158 a \e complete packet, that is, e-b >= bytes(). However, the
159 call to bytes() might involve accessing data bytes which
160 might not exist. The bytes() call cannot check this (it has
161 no access to the \e end of the valid range). To keep the
162 performance up, the validity check is performed once. The
163 parser has to ensure, that validity is maintained even when
164 changing the values. Validity in this context does not
165 imply, that the packet is semantically correct, it only
166 implies, that the packet can be parsed without risking
167 invalid memory access.
169 - The min_bytes() member is optional. It is only used, if the
170 Parser implements a non-fixed-size Packet, that is, if the
171 bytes() member is non-static. In this case, min_bytes() has
172 to be implemented and must return the amount of space
173 necessary to construct an empty instance. The construction
174 will proceed by first allocating the necessary space
175 somewhere, initializing this space with all zeros. Then a
176 Parser instance is created at that space and the Parsers
177 init() method is called.
179 - The init() member is optional. If all-zero initialization of
180 a new Packet is enough, this member can be
181 skipped. Otherwise, the init() member can assume to have
182 access to a min_buytes() sized area which is all-zero
185 - The init(Packet::ptr payload) member is optional. By default
186 it just calls the init() member. Here, special
187 initialization regarding the payload may be done. As for
188 min_bytes(Packet::ptr), the argument type is allowed to be
189 templatized or may be a specific packet ptr thereby
190 restricting the permissible payload packet types.
192 - The parser then contains any additional methods to parse the
195 ParserBase provides the parser classes with access to the
196 packet iterator. This class is templatized on the Iterator
197 type and an optional baseclass type.
199 If the baseclass is given, it is used to access the iterator
200 directly using 'begin'. If it is not given, the instance has
201 to be constructed with an iterator.
203 This implementation ensures, that a parser can either be
204 inherited into a Packet class or be used as a temporary.
206 template <class Iterator, class IPacket=nil>
207 class ParserBase : public impl::ParserBase
210 ///////////////////////////////////////////////////////////////////////////
211 ///\name Structors and default members
214 // default default constructor
215 // default copy constructor
216 // default copy assignment
217 // default destructor
218 // no conversion constructors
221 ///////////////////////////////////////////////////////////////////////////
224 static void init() {};
230 template <class Iterator>
231 class ParserBase<Iterator,nil> : public impl::ParserBase
234 ///////////////////////////////////////////////////////////////////////////
235 ///\name Structors and default members
238 explicit ParserBase(Iterator const & i);
240 // no default constructor
241 // default copy constructor
242 // default copy assignment
243 // default destructor
244 // no conversion constructors
247 ///////////////////////////////////////////////////////////////////////////
250 static void init() {}
251 template <class SomePacket>
252 static void init(typename SomePacket::ptr) {}
259 /** \brief Addtiional Parser information
261 Parser_traits provids abstract information about an unknown
262 parser. Besides the information already available within the
263 Parser it provides an additional 'fixed_sized' member which is
264 true if and only if the Parser has a static bytes() member.
266 template <class Parser>
267 struct Parser_traits {
268 typedef Parser parser;
269 typedef typename Parser::byte_iterator byte_iterator;
270 static const bool fixed_size = impl::Parser_traits_fixed_size<Parser>::fixed_size;
272 template <class I=nil, class P=nil>
274 typedef typename Parser::template rebind<I,P>::parser parser;
278 template <class Parser, class Iterator>
279 bool check(Iterator const & b, Iterator const & e);
281 template <class Parser>
282 unsigned min_bytes();
286 ///////////////////////////////hh.e////////////////////////////////////////
287 //#include "ParserBase.cci"
288 //#include "ParserBase.ct"
289 #include "ParserBase.cti"
295 // c-file-style: "satcom"