2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 // Stefan Bund <g0dil@berlios.be>
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the
18 // Free Software Foundation, Inc.,
19 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 \brief PacketParser public header */
24 /** \defgroup packetparser The PacketParser facility
26 The PacketParser facility provides a framework to implement very lightweight classes which parse
27 the raw content of a packet into meaningful values. PacketParsers are always passed around
28 <em>by value</em>, they can be understood as pointers into the packet data with added type
29 information providing parsing functions.
31 Packet parsers are \e only used within the packet framework. You should never allocate a new
32 parser instance directly, you should the Packet library let that do for you (either by having
33 the parser as a packet parser in a packet type or by having a member in the packet parser which
34 allocates the parser as a sub-parser).
36 Parsers are built hierarchically. A high-level parser will return other parsers when accessing
37 an element (Example: Asking an EthernetParser for the ethertype field by calling the parsers \c
38 type() member will return an \c UInt16 parser). The lowest level building blocks then return the
39 values. This hierarchical structure greatly simplifies building complex parsers.
41 Since parsers are very lightweight and are passed by value, packet fields are accessed using the
42 corresponding accessor method:
47 // Assign new value to an integer parser
50 // Write out above value
51 std::cerr << p->someField() << "\n";
53 // Use the generic parser-assignment operator '<<' to copy field values
54 p->someVector()[1].someOtherField() << q->someField();
55 p->someVector() << q->someVector()
58 Here \c someField(), \c someOtherField() and \c someVector() are accessor methods named after
59 the field name. Each returns a parser object. Simple parsers can be used like their
60 corresponding basic type (e.g. a Parse_UInt16 field can be used like an unsigned integer), more
61 complex parsers provide type specific access members. Assigning a value to a parser will change
62 the underlying representation (the packet data).
64 Parsers can be grouped into several categories. These categories are not all defined rigorously
65 but are nevertheless helpful when working with the parsers:
66 \li <em>\ref parserimpl_value</em> provide the lowest level parsers (e.g. senf::Parse_UInt16 which
67 returns an integer value).
68 \li <em>\ref parserimpl_collection</em> are parsers which model a collection of sub-elements like
69 senf::Parse_List or senf::Parse_Vector.
70 \li <em>\ref parserimpl_composite</em> collect several fields of arbitrary type into a new
71 parser. Parsers defined using the \ref packetparsermacros fall under this category.
72 \li <em>\ref parserimpl_packet</em> are used to define a packet type.
74 \warning Parsers are like iterators: They are invalidated <em>whenever the size of the packet's
75 data is changed</em>. You should not store a parser anywhere. If you want to keep a parser
76 reference, use the senf::SafePacketParser wrapper. You still will need to take extra care to
77 ensure the parser is not invalidated.
79 \section parserimpl Packet parser categories
81 Every parser is derived from senf::PacketParserBase. This class provides the necessary
82 housekeeping information and provides the parsers with access to the data. You may in principle
83 define arbitrary methods as parser members (e.g. methods to calculate a checksum, methods
84 processing fields in some way and so on). You should however be very wary to access data outside
85 the range assigned to the packet (the range starting at \c i() and with a size of senf::bytes()
88 Each parser type has specific features
90 \subsection parserimpl_value Value parsers
92 For a parser \a SomeParser to be a value parser, the following expressions must be valid:
94 // SomeParser must have a 'value_type', The 'value_type' must be default constructible, copy
95 // constructible and assignable
96 SomeParser::value_type v;
98 // An instance of 'SomeParser' must have a 'value' member which returns a value which may be
99 // assigned to a variable of type 'value_type'
100 v = p.someParserField().value()
102 // It must be possible to assign a new value using the 'value' member
103 p.someParserField().value(v)
106 If at all possible, the 'value_type' should not reference the packet data using iterators or
107 pointers, it should hold a copy of the value (it's Ok for \c value() to return such a reference
108 as long as assigning it to a \c value_type variable will copy the value).
110 \subsection parserimpl_collection Collection parsers
112 A collection parser \a SomeParser should model STL containers. The parsers themselves will
113 probably only // provide a reduced interface, but the collection parser should have a \c
114 collection member which is a wrapper providing the full interface.
116 SomeParser::container c (p.someParserField());
119 You will probably only very seldom need to implement a completely new collection
120 parser. Instead, you can rely on senf::Parse_Vector or senf::Parse_List and implement new
123 \subsection parserimpl_composite Composite parsers
125 If possible, composite parsers should be implemented using the \ref packetparsermacros. In
126 addition to the normal parser requirements, these macros ensure, that for each field,
127 <em>fieldname</em><tt>_t</tt> is a typedef for the fields parser and
128 <em>fieldname</em><tt>_offset</tt> is the offset of the field in bytes from the beginning of the
129 parser (either a constant for fixed size parsers or a member function for dynamically sized
130 parsers). When defining composite parsers without the help of the \ref packetparsermacros, you
131 should provide those same members.
133 \subsection parserimpl_packet Packet parsers
135 Packet parsers are composite parsers with relaxed requirements. Since a packet parser will never
136 be used as a sub-parser (it will not be used within another composite parser or as value type in
137 a collection parser), the value returned by senf::bytes for this parser must not necessarily
138 cover the complete packet (e.g. if the packet has a trailer, the trailer will live outside the
139 range given by senf::bytes). You may define any member you want to have in your packets field
140 interface. These members may access the packet data in any way. You just need to ensure, that
141 the integration into the packet-type is correct (the senf::PacketTypeMixin will by default use
142 senf::bytes() to find the end of the header).
147 #ifndef HH_PacketParser_
148 #define HH_PacketParser_ 1
151 #include <boost/utility/enable_if.hpp>
152 #include <boost/type_traits.hpp>
153 #include <boost/optional.hpp>
154 #include "../Utils/SafeBool.hh"
155 #include "PacketTypes.hh"
156 #include "PacketData.hh"
158 #include "PacketParser.mpp"
159 ///////////////////////////////hh.p////////////////////////////////////////
165 /** \brief Parser Base class
167 Parsers come in two flavors: fixed and dynamically sized parsers. A <em>fixed size
168 parser</em> has a constant size, it will always parse a fixed number of bytes. The low-level
169 'final' parsers (like the integer parsers) are fixed size parsers as are composite parsers
170 built up only of fixed-size fields.
172 A <em>dynamically sized</em> parser on the other hand infers it's size from the contents of
173 the data parsed. Any parser containing at least one dynamically sized sub-parser will itself
174 be dynamically sized.
176 Both kinds of parser need to derive from PacketParserBase and implement several required
177 members. Which members to implement depends on the parsers flavor. There are two ways how to
179 \li If the parser just consists of a simple sequence of consecutive fields (sub-parsers),
180 the \ref SENF_PACKET_PARSER_DEFINE_FIELDS and \ref
181 SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS macros provide a simple and convenient way to
183 \li In more complex cases, you need to implement the necessary members manually.
185 This documentation is about the manual implementation. You should nevertheless read through
186 this to understand, what above macros are doing.
188 The following example documents the interface (which must be) provided by a parser:
190 struct FooParser : public PacketParserBase
192 FooParser(data_iterator i, state_type s) : PacketParserBase(i,s) {}
194 // If this parser has a fixed size, you must define this size here This definition
195 // allows the parser to be used within the list, vector and array parsers static
196 static const size_type fixed_bytes = some_constant_size;
198 // If the parser does not have a fixed size, you must implement the bytes() member to
199 // return the size. ONLY EVER DEFINE ONE OF fixed_bytes OR bytes().
200 size_type bytes() const;
202 // If you define bytes(), you also need to define the init_bytes. This is the number
203 // of bytes to allocate when creating a new object
204 static const size_type init_bytes = some_constant_size;
206 // You also may define an init() member. This will be called to initialize a newly
207 // created data object. The default implementation just does nothing.
210 // ////////////////////////////////////////////////////////////////////////
212 // Add here members returning (sub-)parsers for the fields. The 'parse' member is
213 // used to construct the sub-parsers. This member either takes an iterator to the
214 // data to be parsed or just an offset in bytes.
216 senf::Parse_UInt16 type() const { return parse<Parse_UInt16>( 0 ); }
217 senf::Parse_UInt16 size() const { return parse<Parse_UInt16>( 2 ); }
221 You should never call the \c bytes() member of a parser directly. Instead you should use the
222 freestanding senf::bytes() function. This function will return the correct size irrespective
223 of the parsers flavor. You may access \c fixed_bytes directly, however be aware that this
224 will restrict your code to fixed size parsers (which depending on the circumstances may be
225 exactly what you want).
227 In the same way, don't access \c init_bytes directly, always use the senf::init_bytes
228 meta-function class which correctly supports fixed size parsers.
230 \ingroup packetparser
232 class PacketParserBase
235 ///////////////////////////////////////////////////////////////////////////
238 typedef detail::packet::iterator data_iterator; ///< Raw data iterator type
239 typedef detail::packet::size_type size_type; ///< Unsigned integral type
240 typedef detail::packet::difference_type difference_type; ///< Signed integral type
241 typedef detail::packet::byte byte; ///< Unsigned 8bit value, the raw value type
242 typedef PacketData * state_type; ///< Type of the 'state' parameter
244 ///////////////////////////////////////////////////////////////////////////
245 ///\name Structors and default members
248 // no default constructor
250 // default destructor
251 // no conversion constructors
254 ///////////////////////////////////////////////////////////////////////////
256 data_iterator i() const; ///< Return beginning of data to parse
257 /**< The parser is expected to interpret the data beginning
258 here. The size of the interpreted is given by
259 <tt>senf::bytes(</tt><em>parser
260 instance</em><tt>)</tt>. */
261 state_type state() const; ///< Return state of this parser
262 /**< The value returned should be interpreted as an opaque
263 value provided just to be forwarded to other
265 PacketData & data() const; ///< Access the packets raw data container
266 /**< This member will return the raw data container holding
267 the data which is parsed by \c this parser. */
269 void init() const; ///< Default implementation
270 /**< This is just an empty default
271 implementation. Re-implement this member in your own
272 parsers if needed. */
275 PacketParserBase(data_iterator i, state_type s); ///< Standard constructor
276 /**< This is the constructor used by most parsers. The
277 parameters are just forwarded from the derived classes
278 constructor parameters. */
279 PacketParserBase(data_iterator i, state_type s, size_type size);
280 ///< Size checking constructor
281 /**< In addition to the standard constructor, this
282 constructor will validate, that there is enough data in
283 the raw data container to parse \a size bytes after \a
286 This constructor is called by all 'final' parsers
287 (e.g. the integer parsers) and \e only by those
288 parsers. Most parsers do \e not check the validity of
289 the iterator, this is delayed until the very last
290 parser. This allows to partial parse truncated
293 \throw TruncatedPacketException if the raw data
294 container does not hold at least \a size bytes
295 beginning at \a i. */
297 bool check(size_type size) const; ///< Check size of data container
298 /**< \returns \c true, if the data container holds at least
299 \a size beginning at i(), \c false otherwise. */
300 void validate(size_type size) const; ///< Validate size of data container
301 /**< \throws TruncatedPacketException if the raw data
302 container does not hold at least \a size bytes
305 template <class Parser> Parser parse(data_iterator i) const; ///< Create sub-parser
306 /**< Creates a new instance of \a Parser to parse data
307 beginning at \a i. Automatically passes \a state() to
309 template <class Parser> Parser parse(size_type n) const; ///< Create sub-parser
310 /**< Creates a new instance of \a Parser to parse data
311 * beginning at i()<tt> + </tt>\a n. Automatically passes \a
312 state() to the new parser. */
314 void defaultInit() const; ///< Default implementation
315 /**< This is just an empty default
316 implementation. Re-implement this member in your own
317 parsers if needed. */
319 Packet packet() const; ///< Get packet this parser is parsing from
320 /**< \important This member should only be used from packet
321 parsers when access to previous or following packets is
322 needed e.g. for calculating checksums etc. */
325 data_iterator end() const;
330 template <class Parser> friend class SafePacketParser;
333 /** \brief Return raw size parsed by the given parser object
335 This function will either call <tt>p.bytes()</tt> or return <tt>Parser::fixed_bytes</tt>
336 depending on the type of parser.
338 The value returned does \e not take into account the amount of data actually available. So
339 you always need to validate this value against the packet size if you directly access the
340 data. The standard low-level parses all do this check automatically to guard against
343 \param[in] p Parser object to check
344 \returns number of bytes this parser expects to parser
345 \ingroup packetparser
347 template <class Parser>
348 PacketParserBase::size_type bytes(Parser p);
350 namespace detail { template <class Parser> class ParserInitBytes; }
352 /** \brief Return number of bytes to allocate to new object of given type
354 This meta-function is called like
356 senf::init_bytes<SomeParser>::value
359 This expression evaluates to a compile-time constant integral expression of type
360 senf::PacketParserBase::size_type. This meta-function will return \c Parser::fixed_bytes or
361 \c Parser::init_bytes depending on the type of parser.
363 \param[in] Parser The Parser to return init_bytes for
364 \returns Number of bytes to allocate to the new object
365 \ingroup packetparser
367 template <class Parser>
368 struct init_bytes : public detail::ParserInitBytes<Parser>
372 template <class Parser>
373 typename boost::enable_if<
374 boost::is_base_of<PacketParserBase, Parser>,
376 operator<<(Parser target, Parser source);
378 /** \brief Generic parser copying
381 This operator allows to copy the values of identical parsers. This operation does \e not
382 depend on the parsers detailed implementation, it will just replace the data bytes of the
383 target parser with those from the source parser. This allows to easily copy around complex
384 packet substructures.
386 This operation is different from the ordinary assignment operator: It does not change the \a
387 target parser, it changes the data referenced by the \a target parser.
389 \ingroup packetparser
391 template <class Parser>
392 Parser operator<<(Parser target, Parser source);
396 template <class Parser, class Value>
397 typename boost::enable_if_c <
398 boost::is_base_of<PacketParserBase, Parser>::value
399 && ! boost::is_base_of<PacketParserBase, Value>::value,
401 operator<<(Parser target, Value const & value);
403 /** \brief Generic parser value assignment
405 This operator allows to assign a value to parsers which implement a <tt>value(</tt>\a
406 value<tt>)</tt> member. This operator allows to use a common syntax for assigning values or
409 \ingroup packetparser
411 template <class Parser, class Value>
412 Parser operator<<(Parser target, Value const & value);
416 template <class Parser, class Value>
417 typename boost::enable_if_c <
418 boost::is_base_of<PacketParserBase, Parser>::value
419 && ! boost::is_base_of<PacketParserBase, Value>::value,
421 operator<<(Parser target, boost::optional<Value> const & value);
423 /** \brief Generic parser value assignment
425 This operator allows to assign a value to parsers which implement a <tt>value(</tt>\a
426 value<tt>)</tt> member. This special version allows to assign optional values: IF the
427 optional value is not set, the assignment will be skipped.
429 This operator allows to use a common syntax for assigning values or parsers to a parser.
431 \ingroup packetparser
433 template <class Parser, class Value>
434 Parser operator<<(Parser target, boost::optional<Value> const & value);
437 /** \defgroup packetparsermacros Helper macros for defining new packet parsers
439 To simplify the definition of simple packet parsers, several macros are provided. Before
440 using these macros you should familiarize yourself with the packet parser interface as
441 described in senf::PacketParserBase.
443 These macros simplify providing the above defined interface. A typical packet declaration
444 using these macros has the following form (This is a concrete example from the definition of
445 the ethernet packet in <tt>DefaultBundle/EthernetPacket.hh</tt>)
448 struct Parse_EthVLan : public PacketParserBase
450 typedef Parse_UIntField < 0, 3 > Parse_Priority;
451 typedef Parse_Flag < 3 > Parse_CFI;
452 typedef Parse_UIntField < 4, 16 > Parse_VLanId;
453 typedef Parse_UInt16 Parse_Type;
455 SENF_PACKET_PARSER_INIT(Parse_EthVLan);
457 SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS(
458 ((OverlayField)( priority, Parse_Priority ))
459 ((OverlayField)( cfi, Parse_CFI ))
460 ((Field )( vlanId, Parse_VLanId ))
461 ((Field )( type, Parse_Type )) );
465 The macros take care of the following:
466 \li They define the accessor functions returning parsers of the given type.
467 \li They automatically calculate the offset of the fields from the preceding fields.
468 \li The macros provide a definition for \c init()
469 \li The macros define the \c bytes(), \c fixed_bytes and \c init_bytes members as needed.
471 You may define either a fixed or a dynamically sized parser. Fixed size parsers are defined
472 using \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS, dynamically sized parsers are defined
473 using \ref SENF_PACKET_PARSER_DEFINE_FIELDS. The different members are implemented such
476 \li The needed parser constructor is defined
477 \li \c init() calls \c defaultInit(). \c defaultInit() is defined to call \c init() on each
479 \li \c bytes() (on dynamically sized parser) respectively \c fixed_bytes (on fixed size
480 parsers) is defined to return the sum of the sizes of all fields.
481 \li On dynamically sized parsers, \c init_bytes is defined to return the sum of the
482 \c init_size's of all fields
484 The central definition macros are \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS and \ref
485 SENF_PACKET_PARSER_DEFINE_FIELDS. The argument to both has the same structure. It is a
486 (boost preprocessor style) sequence of field definitions where each field definition
487 provides the builder macro to use and the name and type of the field to define:
489 SENF_PACKET_PARSER_DEFINE[_FIXED]_FIELDS(
490 (( <builder> )( <name>, <type> ))
495 For each field, this command will define
496 \li A method \a name() returning an instance of the \a type parser
497 \li \a name<tt>_t</tt> as a typedef for \a type, the fields value
498 \li \a name<tt>_offset</tt> to give the offset of the field from the beginning of the
499 parser. If the parser is a fixed size parser, this will be a static constant, otherwise
502 The \a builder argument selects, how the field is defined
503 \li <tt>Field</tt> defines a field and increments the current position by the size of the
505 \li <tt>OverlayField</tt> defines a field like <tt>Field</tt> but does \e not increment the
506 position. In the above example, this is used to overlay the different bitfield parsers:
507 All overlaying bitfield parser except the last one (the one with the highest bit
508 numbers) is marked as OverlayField.
510 The \a name argument defines the name of the accessor method.
512 The \a type argument is the parser to return for that field. Since none of the arguments may
513 contain a comma, <em>This argument cannot be a multi-parameter template</em>. Always use
514 typedefs to access templated parsers as shown above.
516 The \ref SENF_PACKET_PARSER_INIT macro defines the constructor and the \c init() member. If
517 you want to provide your own \c init() implementation, use \ref
518 SENF_PACKET_PARSER_NO_INIT. The first statement in your init method should probably to call
519 \c defaultInit(). This will call the \c init() member of all the fields. Afterwards you can
520 set up the field values as needed:
522 struct SomePacket : public senf::PacketParserBase
524 SENF_PACKET_PARSER_NO_INIT(SomePacket);
526 typedef senf::Parse_UInt8 Parse_Type;
527 typedef senf::Parse_Vector< senf::Parse_UInt32,
528 senf::SimpleVectorSizer<senf::Parse_UInt16>
531 SENF_PACKET_PARSER_DEFINE_FIELDS(
532 ((Field)( type, Parse_Type ))
533 ((Field)( elements, Parse_Elements ))
539 elements().push_back(0x01020304u);
544 \ingroup packetparser
547 /** \brief Define initialization members of a parser
549 This macro defines the packet parser constructor and the \c init() member. \c init() is
550 defined to just call \c defaultInit() which is defined by the other macros to call \c init()
551 on each of the parsers fields.
553 \ingroup packetparsermacros
556 # define SENF_PACKET_PARSER_INIT(name) \
557 name(data_iterator i, state_type s) : senf::PacketParserBase(i,s) {} \
558 void init() const { defaultInit(); }
560 /** \brief Define initialization members of a parser except init()
562 This macro is like SENF_PACKET_PARSER_INIT but does \e not define \c init(). This allows you
563 to provide your own implementation. You should call \c defaultInit() first before
564 initializing your data fields.
566 \ingroup packetparsermacros
569 # define SENF_PACKET_PARSER_NO_INIT(name) \
570 name(data_iterator i, state_type s) : senf::PacketParserBase(i,s) {}
572 /** \brief Define fields for a dynamically sized parser
574 Define the fields as specified in \a fields. This macro supports dynamically sized
575 subfields, the resulting parser will be dynamically sized.
577 \ingroup packetparsermacros
580 # define SENF_PACKET_PARSER_DEFINE_FIELDS(fields) \
581 SENF_PACKET_PARSER_I_DEFINE_FIELDS(0,fields)
583 /** \brief Define fields for a dynamically sized parser (with offset)
585 Define the fields as specified in \a fields. This macro supports dynamically sized
586 subfields, the resulting parser will be dynamically sized.
588 The \a offset argument gives the byte offset at which to start parsing the fields. This
589 helps defining extended parser deriving from a base parser:
591 struct ExtendedParser : public BaseParser
593 ExtendedParser(data_iterator i, state_type s) : BaseParser(i,s) {}
595 SENF_PACKET_PARSER_DEFINE_FIELDS_OFFSET(senf::bytes(BaseParser(*this)),
596 ( ... fields ... ) );
606 \ingroup packetparsermacros
609 # define SENF_PACKET_PARSER_DEFINE_FIELDS_OFFSET(offset,fields) \
610 SENF_PACKET_PARSER_I_DEFINE_FIELDS(offset,fields)
612 /** \brief Define fields for a fixed size parser
614 Define the fields as specified in \a fields. This macro only supports fixed size
615 subfields, the resulting parser will also be a fixed size parser.
617 \ingroup packetparsermacros
620 # define SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS(fields) \
621 SENF_PACKET_PARSER_I_DEFINE_FIXED_FIELDS(0,fields)
623 /** \brief Define fields for a fixed size parser
625 Define the fields as specified in \a fields. This macro only supports fixed size
626 subfields, the resulting parser will also be a fixed size parser.
628 The \a offset argument gives the byte offset at which to start parsing the fields. This
629 helps defining extended parser deriving from a base parser:
631 struct ExtendedParser : public BaseParser
633 ExtendedParser(data_iterator i, state_type s) : BaseParser(i,s) {}
635 SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS_OFFSET(BaseParser::fixed_bytes,
636 ( ... fields ... ) );
646 \ingroup packetparsermacros
649 # define SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS_OFFSET(offset,fields) \
650 SENF_PACKET_PARSER_I_DEFINE_FIXED_FIELDS(offset,fields)
652 /** \brief Default parser parsing nothing
654 struct VoidPacketParser
655 : public PacketParserBase
657 SENF_PACKET_PARSER_INIT(VoidPacketParser);
660 /** \brief Iterator re-validating Parser wrapper
662 An ordinary parser will be invalidated whenever the raw data container's size is
663 changed. This can complicate some algorithms considerably.
665 This wrapper will update the parsers iterator (the value returned by the i() member) on
666 every access. This ensures that the iterator will stay valid.
668 \attention Beware however, if you insert or remove data before the safe wrapper, the
669 location will \e not be updated accordingly and therefore the parser will be
672 Additionally a SafePacketParser has an uninitialized state. The only allowed operations in
673 this state are the boolean test for validity and assigning another parser.
675 \ingroup packetparser
677 template <class Parser>
678 class SafePacketParser
679 : public SafeBool< SafePacketParser<Parser> >
682 ///////////////////////////////////////////////////////////////////////////
685 ///////////////////////////////////////////////////////////////////////////
686 ///\name Structors and default members
689 // default copy constructor
690 // default copy assignment
691 // default destructor
692 SafePacketParser(); ///< Create an empty uninitialized SafePacketParser
694 // conversion constructors
695 SafePacketParser(Parser parser); ///< Initialize SafePacketParser from \a parser
697 SafePacketParser & operator=(Parser parser); ///< Assign \a parser to \c this
700 ///////////////////////////////////////////////////////////////////////////
702 Parser operator*() const; ///< Access the stored parser
703 /**< On every access, the stored parsers iterator will be
704 updated / re-validated. */
705 Parser const * operator->() const; ///< Access the stored parser
706 /**< On every access, the stored parsers iterator will be
707 updated / re-validated. */
708 bool boolean_test() const; ///< Check validity
713 mutable boost::optional<Parser> parser_;
714 senf::safe_data_iterator i_;
719 ///////////////////////////////hh.e////////////////////////////////////////
721 #if !defined(SENF_PACKETS_DECL_ONLY) && !defined(HH_PacketParser_i_)
722 #define HH_PacketParser_i_
723 #include "PacketParser.cci"
724 #include "PacketParser.ct"
725 #include "PacketParser.cti"
732 // c-file-style: "senf"
733 // indent-tabs-mode: nil
734 // ispell-local-dictionary: "american"
735 // compile-command: "scons -u test"
736 // comment-column: 40