-// Copyright (C) 2007
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
-// Stefan Bund <g0dil@berlios.de>
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.be>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
/** \defgroup packetparser The PacketParser facility
The PacketParser facility provides a framework to implement very lightweight classes which parse
- the raw content of a packet into meaningful values. PacketParsers are always passed around by
- value, they can be understood as pointers into the data structure with added type information
- providing parsing functions.
-
- Parsers are built hirarchically. A high-level parser will return other parsers when returning
- some element (Example: Asking an EthernetParser for the ethertype field by calling the parsers
- \c type() member will return an UInt16 parser). The lowest level building blocks then return the
+ the raw content of a packet into meaningful values. PacketParsers are always passed around
+ <em>by value</em>, they can be understood as pointers into the packet data with added type
+ information providing parsing functions.
+
+ Packet parsers are \e only used within the packet framework. You should never allocate a new
+ parser instance directly, you should the Packet library let that do for you (either by having
+ the parser as a packet parser in a packet type or by having a member in the packet parser which
+ allocates the parser as a sub-parser).
+
+ Parsers are built hierarchically. A high-level parser will return other parsers when accessing
+ an element (Example: Asking an EthernetParser for the ethertype field by calling the parsers \c
+ type() member will return an \c UInt16 parser). The lowest level building blocks then return the
values. This hierarchical structure greatly simplifies building complex parsers.
- Every parser is derived from senf::PacketParserBase. This parser provides the necessary
- housekeeping information and provides the parsers with access to the data.
+ Since parsers are very lightweight and are passed by value, packet fields are accessed using the
+ corresponding accessor method:
+ \code
+ SomePacket p (...)
+ SomePacket q (...)
+
+ // Assign new value to an integer parser
+ p->someField() = 10;
+
+ // Write out above value
+ std::cerr << p->someField() << "\n";
+
+ // Use the generic parser-assignment operator '<<' to copy field values
+ p->someVector()[1].someOtherField() << q->someField();
+ p->someVector() << q->someVector()
+ \endcode
+
+ Here \c someField(), \c someOtherField() and \c someVector() are accessor methods named after
+ the field name. Each returns a parser object. Simple parsers can be used like their
+ corresponding basic type (e.g. a UInt16Parser field can be used like an unsigned integer), more
+ complex parsers provide type specific access members. Assigning a value to a parser will change
+ the underlying representation (the packet data).
+
+ Parsers can be grouped into several categories. These categories are not all defined rigorously
+ but are nevertheless helpful when working with the parsers:
+ \li <em>\ref parserimpl_value</em> provide the lowest level parsers (e.g. senf::UInt16Parser which
+ returns an integer value).
+ \li <em>\ref parserimpl_collection</em> are parsers which model a collection of sub-elements like
+ senf::ListParser or senf::VectorParser.
+ \li <em>\ref parserimpl_composite</em> collect several fields of arbitrary type into a new
+ parser. Parsers defined using the \ref packetparsermacros fall under this category.
+ \li <em>\ref parserimpl_packet</em> are used to define a packet type.
+
+ \warning Parsers are like iterators: They are invalidated <em>whenever the size of the packet's
+ data is changed</em>. You should not store a parser anywhere. If you want to keep a parser
+ reference, use the senf::SafePacketParserWrapper wrapper. You still will need to take extra care to
+ ensure the parser is not invalidated.
+
+ \section parserimpl Packet parser categories
+
+ Every parser is derived from senf::PacketParserBase. This class provides the necessary
+ housekeeping information and provides the parsers with access to the data. You may in principle
+ define arbitrary methods as parser members (e.g. methods to calculate a checksum, methods
+ processing fields in some way and so on). You should however be very wary to access data outside
+ the range assigned to the packet (the range starting at \c i() and with a size of senf::bytes()
+ bytes).
+
+ Each parser type has specific features
+
+ \subsection parserimpl_value Value parsers
+
+ For a parser \a SomeParser to be a value parser, the following expressions must be valid:
+ \code
+ // SomeParser must have a 'value_type', The 'value_type' must be default constructible, copy
+ // constructible and assignable
+ SomeParser::value_type v;
+
+ // An instance of 'SomeParser' must have a 'value' member which returns a value which may be
+ // assigned to a variable of type 'value_type'
+ v = p.someParserField().value()
+
+ // It must be possible to assign a new value using the 'value' member
+ p.someParserField().value(v)
+ \endcode
+
+ If at all possible, the 'value_type' should not reference the packet data using iterators or
+ pointers, it should hold a copy of the value (it's Ok for \c value() to return such a reference
+ as long as assigning it to a \c value_type variable will copy the value).
+
+ \see parseint
+
+ \subsection parserimpl_collection Collection parsers
+
+ A collection parser \a SomeParser should model STL containers. The parsers themselves will
+ probably only // provide a reduced interface, but the collection parser should have a \c
+ collection member which is a wrapper providing the full interface.
+ \code
+ SomeParser::container c (p.someParserField());
+ \endcode
+
+ You will probably only very seldom need to implement a completely new collection
+ parser. Instead, you can rely on senf::VectorParser or senf::ListParser and implement new
+ policies.
+
+ \see parsecollection
- The PacketParser facility predefines several parsers to be used as building blocks in defining
- more complex parsers (integer parsers, several parsers for repetitive constructs)
+ \subsection parserimpl_composite Composite parsers
+
+ If possible, composite parsers should be implemented using the \ref packetparsermacros. In
+ addition to the normal parser requirements, these macros ensure, that for each field,
+ <em>fieldname</em><tt>_t</tt> is a typedef for the fields parser and
+ <em>fieldname</em><tt>_offset</tt> is the offset of the field in bytes from the beginning of the
+ parser (either a constant for fixed size parsers or a member function for dynamically sized
+ parsers). When defining composite parsers without the help of the \ref packetparsermacros, you
+ should provide those same members.
+
+ \subsection parserimpl_packet Protocol parsers
+
+ Protocol parsers are composite parsers with relaxed requirements. Since a Protocol parser will
+ never be used as a sub-parser (it will not be used within another composite parser or as value
+ type in a collection parser), the value returned by senf::bytes for this parser must not
+ necessarily cover the complete packet (e.g. if the packet has a trailer, the trailer will live
+ outside the range given by senf::bytes). You may define any member you want to have in your
+ packets field interface. These members may access the packet data in any way. You just need to
+ ensure, that the integration into the packet-type is correct (the senf::PacketTypeMixin will by
+ default use senf::bytes() to find the end of the header).
+
+ <hr>
*/
#ifndef HH_PacketParser_
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
#include <boost/optional.hpp>
-#include "Utils/SafeBool.hh"
+#include "../Utils/safe_bool.hh"
#include "PacketTypes.hh"
-#define HH_PacketData_DeclOnly
#include "PacketData.hh"
-#undef HH_PacketData_DeclOnly
+#include "ParseHelpers.hh"
-#include "PacketParser.mpp"
+//#include "PacketParser.mpp"
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
+
+ class Packet;
- /** \brief Parser Baseclass
+ /** \brief Parser Base class
+
+ Parsers come in two flavors: fixed and dynamically sized parsers. A <em>fixed size
+ parser</em> has a constant size, it will always parse a fixed number of bytes. The low-level
+ 'final' parsers (like the integer parsers) are fixed size parsers as are composite parsers
+ built up only of fixed-size fields.
- To implement a packet parser, you need to derive from PacketParserBase and implement several
- required members. There are two ways how to do this.
- \li If the parser just consists of a simple sequence of consecutive fields, the
- SENF_PACKET_PARESR_DEFINE_FIELDS and SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS macros
- provide a simple an convenient way to define the packet
+ A <em>dynamically sized</em> parser on the other hand infers it's size from the contents of
+ the data parsed. Any parser containing at least one dynamically sized sub-parser will itself
+ be dynamically sized.
+
+ Both kinds of parser need to derive from PacketParserBase and implement several required
+ members. Which members to implement depends on the parsers flavor. There are two ways how to
+ do this.
+ \li If the parser just consists of sequence of consecutive fields (sub-parsers), the \ref
+ packetparsermacros provide a simple yet flexible way to define a packet parser.
\li In more complex cases, you need to implement the necessary members manually.
- The following example documents the interface (which must be) provided by a parser.
+ This documentation is about the manual implementation. You should nevertheless read through
+ this to understand, what above macros are doing.
+
+ The following example documents the interface (which must be) provided by a parser:
\code
struct FooParser : public PacketParserBase
{
// of bytes to allocate when creating a new object
static const size_type init_bytes = some_constant_size;
- // You also mey define an init() member. This will be called to initialize a newly
+ // You also may define an init() member. This will be called to initialize a newly
// created data object. The default implementation just does nothing.
void init() const;
// used to construct the sub-parsers. This member either takes an iterator to the
// data to be parsed or just an offset in bytes.
- senf::Parse_UInt16 type() const { return parse<Parse_UInt16>( 0 ); }
- senf::Parse_UInt16 size() const { return parse<Parse_UInt16>( 2 ); }
+ senf::UInt16Parser type() const { return parse<UInt16Parser>( 0 ); }
+ senf::UInt16Parser size() const { return parse<UInt16Parser>( 2 ); }
};
\endcode
You should never call the \c bytes() member of a parser directly. Instead you should use the
- freestanding senf::bytes() functon. This function will return the correct size even for
- fixed-size parsers. You may access \c fixed_bytes directly, however be aware that this will
- restrict your code to fixed size parsers (which depending on the circumstances may be
+ freestanding senf::bytes() function. This function will return the correct size irrespective
+ of the parsers flavor. You may access \c fixed_bytes directly, however be aware that this
+ will restrict your code to fixed size parsers (which depending on the circumstances may be
exactly what you want).
- In the same way, dont access \c init_bytes directly, always use the senf::init_bytes
- metafunction class which will correctly support fixed size parsers.
+ In the same way, don't access \c init_bytes directly, always use the senf::init_bytes
+ meta-function class which correctly supports fixed size parsers.
\ingroup packetparser
*/
///////////////////////////////////////////////////////////////////////////
// Types
- typedef detail::packet::iterator data_iterator;
- typedef detail::packet::size_type size_type;
- typedef detail::packet::difference_type difference_type;
- typedef detail::packet::byte byte;
- typedef PacketData * state_type;
+ typedef detail::packet::iterator data_iterator; ///< Raw data iterator type
+ typedef detail::packet::size_type size_type; ///< Unsigned integral type
+ typedef detail::packet::difference_type difference_type; ///< Signed integral type
+ typedef detail::packet::byte byte; ///< Unsigned 8bit value, the raw value type
+ typedef PacketData * state_type; ///< Type of the 'state' parameter
+ typedef PacketParserBase parser_base_type; ///< Base type of the next parser
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@}
///////////////////////////////////////////////////////////////////////////
- data_iterator i() const;
- state_type state() const;
- PacketData & data() const;
-
- void init() const;
+ data_iterator i() const; ///< Return beginning of data to parse
+ /**< The parser is expected to interpret the data beginning
+ here. The size of the interpreted is given by
+ <tt>senf::bytes(</tt><em>parser
+ instance</em><tt>)</tt>. */
+
+ data_iterator i(size_type offset) const; ///< Return iterator \a offset bytes from the start
+ /**< The return value is the same as i() + \a
+ offset. However, the parser checks, that the iterator is
+ still within range of the raw data
+ container. Otherwise a TruncatedPacketException is
+ thrown.
+
+ \throws TruncatedPacketException if the raw data
+ container does not hold at least \a offset bytes
+ starting at i(). */
+
+ state_type state() const; ///< Return state of this parser
+ /**< The value returned should be interpreted as an opaque
+ value provided just to be forwarded to other
+ parsers. */
+
+ PacketData & data() const; ///< Access the packets raw data container
+ /**< This member will return the raw data container holding
+ the data which is parsed by \c this parser. */
+
+ void init() const; ///< Default implementation
+ /**< This is just an empty default
+ implementation. Re-implement this member in your own
+ parsers if needed. */
protected:
- PacketParserBase(data_iterator i, state_type s);
- PacketParserBase(data_iterator i, state_type s, size_type size);
-
- bool check(size_type size);
- void validate(size_type size);
-
- template <class Parser> Parser parse(data_iterator i) const;
- template <class Parser> Parser parse(size_type n) const;
-
- void defaultInit() const;
+ PacketParserBase(data_iterator i, state_type s); ///< Standard constructor
+ /**< This is the constructor used by most parsers. The
+ parameters are just forwarded from the derived classes
+ constructor parameters. */
+
+ PacketParserBase(data_iterator i, state_type s, size_type size);
+ ///< Size checking constructor
+ /**< In addition to the standard constructor, this
+ constructor will validate, that there is enough data in
+ the raw data container to parse \a size bytes after \a
+ i.
+
+ This constructor is called by all 'final' parsers
+ (e.g. the integer parsers) and \e only by those
+ parsers. Most parsers do \e not check the validity of
+ the iterator, this is delayed until the very last
+ parser. This allows to partial parse truncated
+ packets.
+
+ \throw TruncatedPacketException if the raw data
+ container does not hold at least \a size bytes
+ beginning at \a i. */
+
+ bool check(size_type size) const; ///< Check size of data container
+ /**< \returns \c true, if the data container holds at least
+ \a size beginning at i(), \c false otherwise. */
+
+ void validate(size_type size) const; ///< Validate size of data container
+ /**< \throws TruncatedPacketException if the raw data
+ container does not hold at least \a size bytes
+ beginning at i(). */
+
+ template <class Parser> Parser parse(data_iterator i) const; ///< Create sub-parser
+ /**< Creates a new instance of \a Parser to parse data
+ beginning at \a i. Automatically passes \a state() to
+ the new parser. */
+
+ template <class Parser, class Arg> Parser parse(Arg const & arg, data_iterator i) const;
+ ///< Create sub-parser
+ /**< This is like parse(data_iterator), however it passes
+ the extra argument \a arg to the \a Parser
+ constructor. */
+
+ template <class Parser> Parser parse(size_type n) const; ///< Create sub-parser
+ /**< Creates a new instance of \a Parser to parse data
+ * beginning at i()<tt> + </tt>\a n. Automatically passes \a
+ state() to the new parser. */
+
+ template <class Parser, class Arg> Parser parse(Arg const & arg, size_type n) const;
+ ///< Create sub-parser
+ /**< This is like parse(size_type), however it passes the
+ extra argument \a arg to the \a Parser constructor. */
+
+ void defaultInit() const; ///< Default implementation
+ /**< This is just an empty default
+ implementation. Re-implement this member in your own
+ parsers if needed. */
+
+ Packet packet() const; ///< Get packet this parser is parsing from
+ /**< \note This member should only be used from packet
+ parsers when access to previous or following packets is
+ needed e.g. for calculating checksums etc. */
private:
- data_iterator end();
+ data_iterator end() const;
data_iterator i_;
PacketData * data_;
- template <class Parser> friend class SafePacketParser;
+ template <class Parser> friend class SafePacketParserWrapper;
};
/** \brief Return raw size parsed by the given parser object
PacketParserBase::size_type bytes(Parser p);
namespace detail { template <class Parser> class ParserInitBytes; }
+ namespace detail { template <class Parser> class ParserIsFixed; }
/** \brief Return number of bytes to allocate to new object of given type
- This metafcuntion is called like
+ This meta-function is called like
\code
senf::init_bytes<SomeParser>::value
\endcode
- This expression evaluates to a compile-time constant itegral expression of type
- senf::PacketParserBase::size_type. This metafunction will return \c Parser::fixed_bytes or
+ This expression evaluates to a compile-time constant integral expression of type
+ senf::PacketParserBase::size_type. This meta-function will return \c Parser::fixed_bytes or
\c Parser::init_bytes depending on the type of parser.
- \param[in] Parser Parser to return init_bytes for
+ \param[in] Parser The Parser to return init_bytes for
\returns Number of bytes to allocate to the new object
\ingroup packetparser
*/
struct init_bytes : public detail::ParserInitBytes<Parser>
{};
+ /** \brief Test, whether a parser is a fixed-size parser
+
+ This meta-function is called like
+ \code
+ senf::is_fixed<SomeParser>::value
+ \endcode
+
+ This expression evaluates to a compile-time constant boolean expression which is \c true, if
+ \a SomeParser is a fixed size parser, \c false otherwise
+
+ \param[in] Parser The Parser to test
+ \returns \c true, if \a Parser is fixed size, \c false otherwise
+ \ingroup packetparser
+ */
+ template <class Parser>
+ struct is_fixed : public detail::ParserIsFixed<Parser>
+ {};
+
+# ifndef DOXYGEN
template <class Parser>
typename boost::enable_if<
boost::is_base_of<PacketParserBase, Parser>,
Parser >::type
operator<<(Parser target, Parser source);
+# else
+ /** \brief Generic parser copying
+
+
+ This operator allows to copy the values of identical parsers. This operation does \e not
+ depend on the parsers detailed implementation, it will just replace the data bytes of the
+ target parser with those from the source parser. This allows to easily copy around complex
+ packet substructures.
+
+ This operation is different from the ordinary assignment operator: It does not change the \a
+ target parser, it changes the data referenced by the \a target parser.
+
+ \ingroup packetparser
+ */
+ template <class Parser>
+ Parser operator<<(Parser target, Parser source);
+# endif
+# ifndef DOXYGEN
template <class Parser, class Value>
typename boost::enable_if_c <
boost::is_base_of<PacketParserBase, Parser>::value
&& ! boost::is_base_of<PacketParserBase, Value>::value,
Parser >::type
operator<<(Parser target, Value const & value);
+# else
+ /** \brief Generic parser value assignment
- /** \defgroup packetparsermacros Helper macros for defining new packet parsers
-
- To simplify the definition of simple packet parsers, several macros are provided. Before
- using these macros you should familarize yourself with the packet parser interface as
- described in senf::PacketParserBase.
-
- These macros simplify providing the above defined interface. A typical packet declaration
- using these macros has the following form (This is a concrete example from the definition of
- the ethernet packet in <tt>DefaultBundle//EthernetPacket.hh</tt>)
- \code
- struct Parse_EthVLan : public senf::PacketParserBase
- {
- SENF_PACKET_PARSER_INIT(Parse_EthVLan);
-
- // ////////////////////////////////////////////////////////////////////////
-
- typedef senf::Parse_UIntField < 0, 3 > Parse_Priority;
- typedef senf::Parse_Flag < 3 > Parse_CFI;
- typedef senf::Parse_UIntField < 4, 16 > Parse_VLanId;
- typedef senf::Parse_UInt16 Parse_Type;
-
- SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS(
- ((OverlayField)( priority, Parse_Priority ))
- ((OverlayField)( cfi, Parse_CFI ))
- ((Field )( vlanId, Parse_VLanId ))
- ((Field )( type, Parse_Type ))
- );
- };
- \endcode
-
- The macros take care of the following:
- \li They define the accessor functions returning parsers of the given type.
- \li They automatically calculate the offset of the fields from the preceding fields.
- \li The macros provide a definition for \c init()
- \li The macros define the \c bytes(), \c fixed_bytes and \c init_bytes members as needed.
+ This operator allows to assign a value to parsers which implement a <tt>value(</tt>\a
+ value<tt>)</tt> member. This operator allows to use a common syntax for assigning values or
+ parsers to a parser.
- You may define either a fixed or a dynamically sized parser. Fixed size parsers are defined
- using \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS, dynamically sized parsers are defined
- using \ref SENF_PACKET_PARSER_DEFINE_FIELDS. The different members are implemented such
- that:
-
- \li The needed parser constructor is defined
- \li \c init() calls \c defaultInit(). \c defaultInit() is defined to call \c init() on each
- of the fields.
- \li \c bytes() (on dynamically sized parser) respectively \c fixed_bytes (on fixed size
- parsers) is defined to return the sum of the sizes of all fields.
- \li On dynamically sized parsers, \c init_bytes is defined to return the sum of the
- \c init_size's of all fields
-
- The central definition macros are \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS and \ref
- SENF_PACKET_PARSER_DEFINE_FIELDS. The argument to both has the same structure. It is a
- (boost preprocessor style) sequence of field definitions where each field definition
- provides the builder macro to use and the name and type of the field to define:
- \code
- SENF_PACKET_PARSER_DEFINE[_FIXED]_FIELDS(
- (( <builder> )( <name>, <type> ))
- ...
- )
- \endcode
-
- The \a builder argument selects, how the field is defined
- \li <tt>Field</tt> defines a field and increments the current position by the size of the
- field
- \li <tt>OverlayField</tt> defines a field like <tt>Field</tt> but does \e not increment the
- position. In the above example, this is used to overlay the different bitfield parsers:
- All overlaying bitfield parser except the last one (the one with the highest bit
- numbers) is marked as OverlayField.
-
- The \a name argument defines the name of the accessor method.
-
- The \a type argument is the parser to return for that field. Since none of the arguments may
- contain a komma, <em>This argument cannot be a template</em>. Always use typedefs to access
- tempalte parsers as shown above.
-
- The \ref SENF_PACKET_PARSER_INIT makro defines the constructor and the \c init() member. If
- you want to provide your own \c init() implementation, use \ref
- SENF_PACKET_PARSER_NO_INIT. The first statement in your init method should probably to call
- \c defaultInit(). This will call the \c init() member of all the fields. Afterwards you can
- set up the field values as needed:
- \code
- struct SomePacket : public senf::PacketParserBase
- {
- SENF_PACKET_PARSER_NO_INIT(SomePacket);
-
- typedef senf::Parse_UInt8 Parse_Type;
- typedef senf::Parse_Vector< senf::Parse_UInt32,
- senf::SimpleVectorSizer<senf::Parse_UInt16>
- > Parse_Elements;
-
- SENF_PACKET_PARSER_DEFINE_FIELDS(
- ((Field)( type, Parse_Type ))
- ((Field)( elements, Parse_Elements ))
- );
-
- void init() const {
- defaultInit();
- type() = 0x01;
- elements().push_back(0x01020304u);
- }
- }
- \endcode
-
\ingroup packetparser
*/
+ template <class Parser, class Value>
+ Parser operator<<(Parser target, Value const & value);
+# endif
- /** \brief Define initialization members of a parser
-
- This macro defines the packet parser constructor and the \c init() member. \c init() is
- defined to just call \c defaultInit() which is defined by the other macros to call \c init()
- on each of the parsers fields.
-
- \ingroup packetparsermacros
- \hideinitializer
- */
-# define SENF_PACKET_PARSER_INIT(name) \
- name(data_iterator i, state_type s) : senf::PacketParserBase(i,s) {} \
- void init() const { defaultInit(); }
-
- /** \brief Define initialization mebers of a parser except init()
-
- This macro is like SENF_PACKET_PARSER_INIT but does \e not define \c init(). This allows you
- to provide your own implementation. You should call \c defaultInit() first before
- initializing your data fields.
-
- \ingroup packetparsermacros
- \hideinitializer
- */
-# define SENF_PACKET_PARSER_NO_INIT(name) \
- name(data_iterator i, state_type s) : senf::PacketParserBase(i,s) {}
+# ifndef DOXYGEN
+ template <class Parser, class Value>
+ typename boost::enable_if_c <
+ boost::is_base_of<PacketParserBase, Parser>::value
+ && ! boost::is_base_of<PacketParserBase, Value>::value,
+ Parser >::type
+ operator<<(Parser target, boost::optional<Value> const & value);
+# else
+ /** \brief Generic parser value assignment
- /** \brief Define fields for a dynamically sized parser
+ This operator allows to assign a value to parsers which implement a <tt>value(</tt>\a
+ value<tt>)</tt> member. This special version allows to assign optional values: IF the
+ optional value is not set, the assignment will be skipped.
- Define the fields as specified in \a fields. This macro supports dynamically sized
- subfields, the resulting parser will be dynamically sized.
+ This operator allows to use a common syntax for assigning values or parsers to a parser.
- \ingroup packetparsermacros
- \hideinitializer
+ \ingroup packetparser
*/
-# define SENF_PACKET_PARSER_DEFINE_FIELDS(fields) \
- SENF_PACKET_PARSER_I_DEFINE_FIELDS(fields)
-
- /** \brief Define fields for a fixed size parser
-
- Define the fields as specified in \a fields. This macro only supports fixed size
- subfields, the resulting parser will also be a fixed size parser.
+ template <class Parser, class Value>
+ Parser operator<<(Parser target, boost::optional<Value> const & value);
+# endif
- \ingroup packetparsermacros
- \hideinitializer
+ /** \brief Default parser parsing nothing
*/
-# define SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS(fields) \
- SENF_PACKET_PARSER_I_DEFINE_FIXED_FIELDS(fields)
-
struct VoidPacketParser
: public PacketParserBase
{
- SENF_PACKET_PARSER_INIT(VoidPacketParser);
- };
-
- /** \brief
- */
- template <class Parser>
- class SafePacketParser
- : public SafeBool< SafePacketParser<Parser> >
- {
- public:
- ///////////////////////////////////////////////////////////////////////////
- // Types
-
- ///////////////////////////////////////////////////////////////////////////
- ///\name Structors and default members
- ///@{
-
- // default default constructor
- // default copy constructor
- // default copy assignment
- // default destructor
- SafePacketParser();
-
- // conversion constructors
- SafePacketParser(Parser parser);
-
- SafePacketParser & operator=(Parser parser);
-
- ///@}
- ///////////////////////////////////////////////////////////////////////////
-
- Parser operator*() const;
- Parser const * operator->() const;
- bool boolean_test() const;
-
- protected:
-
- private:
- mutable boost::optional<Parser> parser_;
- senf::safe_data_iterator i_;
+# include SENF_FIXED_PARSER()
+ SENF_PARSER_FINALIZE(VoidPacketParser);
};
}
///////////////////////////////hh.e////////////////////////////////////////
+#endif
+#if !defined(HH_Packets__decls_) && !defined(HH_PacketParser_i_)
+#define HH_PacketParser_i_
#include "PacketParser.cci"
#include "PacketParser.ct"
#include "PacketParser.cti"
// c-file-style: "senf"
// indent-tabs-mode: nil
// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// comment-column: 40
// End:
+