Packets: Restructure documentation
[senf.git] / Packets / PacketParser.hh
index 9a3305b..59124e3 100644 (file)
@@ -1,6 +1,8 @@
-// Copyright (C) 2007 
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// $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
 
     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 Parse_UInt16 field can be used like an unsigned integer), more
+    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>Value parsers</em> provide the lowest level parsers (e.g. senf::Parse_UInt16 which
+    \li <em>\ref parserimpl_value</em> provide the lowest level parsers (e.g. senf::UInt16Parser which
         returns an integer value).
-    \li <em>Collection parsers</em> are parsers which model a collection of sub-elements like
-        senf::Parse_List or senf::Parse_Vector.
-    \li <em>Composite parsers</em> collect several fields of arbitrary type into a new
+    \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>Packet parsers</em> are used to define a packet type.
+    \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::SafePacketParser wrapper. You still will need to take extra care to
+    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
     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
     \endcode
 
     You will probably only very seldom need to implement a completely new collection
-    parser. Instead, you can rely on senf::Parse_Vector or senf::Parse_List and implement new
-    polcies.
+    parser. Instead, you can rely on senf::VectorParser or senf::ListParser and implement new
+    policies.
+
+    \see parsecollection
 
     \subsection parserimpl_composite Composite parsers
     
     parsers). When defining composite parsers without the help of the \ref packetparsermacros, you
     should provide those same members.
 
-    \subsection parserimpl_packet Packet parsers
+    \subsection parserimpl_packet Protocol parsers
 
-    Packet parsers are composite parsers with relaxed requirements. Since a packet 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).
-    
+    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"
 #include "PacketData.hh"
+#include "ParseHelpers.hh"
 
-#include "PacketParser.mpp"
+//#include "PacketParser.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
 
 namespace senf {
+
+    class Packet;
     
     /** \brief Parser Base class
 
-        Parsers come in two favors: fixed and dynamically sized parsers. A <em>fixed size
+        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.
@@ -173,10 +183,8 @@ namespace senf {
         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 a simple sequence of consecutive fields (sub-parsers),
-            the \ref SENF_PACKET_PARSER_DEFINE_FIELDS and \ref
-            SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS macros provide a simple and convenient way to
-            define the packet
+        \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.
 
         This documentation is about the manual implementation. You should nevertheless read through
@@ -210,8 +218,8 @@ namespace senf {
               // 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
         
@@ -237,6 +245,7 @@ namespace senf {
         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
@@ -255,10 +264,23 @@ namespace senf {
                                              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. */
@@ -273,6 +295,7 @@ namespace senf {
                                         /**< 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
@@ -291,10 +314,11 @@ namespace senf {
                                                  container does not hold at least \a size bytes
                                                  beginning at \a i. */
 
-        bool check(size_type size);     ///< Check size of data container
+        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);  ///< Validate size of data container
+
+        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(). */
@@ -303,23 +327,40 @@ namespace senf {
                                         /**< 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
@@ -340,6 +381,7 @@ namespace senf {
     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
 
@@ -360,6 +402,24 @@ namespace senf {
     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< 
@@ -369,6 +429,7 @@ namespace senf {
 #   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
@@ -403,277 +464,42 @@ namespace senf {
     Parser operator<<(Parser target, Value const & value);
 #   endif
 
-    /** \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 familiarize 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>)
-    
-        \dontinclude EthernetPacket.hh
-        \skipline struct Parse_EthVLan : public PacketParserBase
-        \until };
-
-        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.
-
-        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
-        
-        For each field, this command will define
-        \li A method \a name() returning an instance of the \a type parser
-        \li \a name<tt>_t</tt> as a typedef for \a type, the fields value
-        \li \a name<tt>_offset</tt> to give the offset of the field from the beginning of the
-            parser. If the parser is a fixed size parser, this will be a static constant, otherwise
-            it will be a method.
-
-        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 comma, <em>This argument cannot be a multi-parameter template</em>. Always use
-        typedefs to access templated parsers as shown above.
-
-        The \ref SENF_PACKET_PARSER_INIT macro 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
-     */
-
-    /** \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 members 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) {}
-
-    /** \brief Define fields for a dynamically sized parser
-
-        Define the fields as specified in \a fields. This macro supports dynamically sized
-        subfields, the resulting parser will be dynamically sized.
-
-        \ingroup packetparsermacros
-        \hideinitializer
-     */
-#   define SENF_PACKET_PARSER_DEFINE_FIELDS(fields)                                               \
-    SENF_PACKET_PARSER_I_DEFINE_FIELDS(0,fields)
-        
-    /** \brief Define fields for a dynamically sized parser (with offset)
-
-        Define the fields as specified in \a fields. This macro supports dynamically sized
-        subfields, the resulting parser will be dynamically sized.
-
-        The \a offset argument gives the byte offset at which to start parsing the fields. This
-        helps defining extended parser deriving from a base parser:
-        \code
-           struct ExtendedParser : public BaseParser
-           {
-               ExtendedParser(data_iterator i, state_type s) : BaseParser(i,s) {}
-        
-               SENF_PACKET_PARSER_DEFINE_FIELDS_OFFSET(senf::bytes(BaseParser(*this)),
-                 ( ... fields ... ) );
-
-               void init() {
-                   BaseParser::init();
-                   defaultInit();
-                   // other init code
-               }
-           }
-        \endcode
-
-        \ingroup packetparsermacros
-        \hideinitializer
-     */
-#   define SENF_PACKET_PARSER_DEFINE_FIELDS_OFFSET(offset,fields)                                 \
-    SENF_PACKET_PARSER_I_DEFINE_FIELDS(offset,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.
-
-        \ingroup packetparsermacros
-        \hideinitializer
-     */
-#   define SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS(fields)                                         \
-    SENF_PACKET_PARSER_I_DEFINE_FIXED_FIELDS(0,fields)
-
-    /** \brief Define fields for a fixed size parser
+#   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
 
-        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.
+        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. 
 
-        The \a offset argument gives the byte offset at which to start parsing the fields. This
-        helps defining extended parser deriving from a base parser:
-        \code
-           struct ExtendedParser : public BaseParser
-           {
-               ExtendedParser(data_iterator i, state_type s) : BaseParser(i,s) {}
-
-               SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS_OFFSET(BaseParser::fixed_bytes,
-                 ( ... fields ... ) );
-
-               void init() {
-                   BaseParser::init();
-                   defaultInit();
-                   // other init code
-               }
-           }
-        \endcode
+        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_FIXED_FIELDS_OFFSET(offset,fields)                           \
-    SENF_PACKET_PARSER_I_DEFINE_FIXED_FIELDS(offset,fields)
+    template <class Parser, class Value>
+    Parser operator<<(Parser target, boost::optional<Value> const & value);
+#   endif
 
     /** \brief Default parser parsing nothing
      */
     struct VoidPacketParser 
         : public PacketParserBase
     {
-        SENF_PACKET_PARSER_INIT(VoidPacketParser);
-    };
-
-    /** \brief Iterator re-validating Parser wrapper
-
-        An ordinary parser will be invalidated whenever the raw data container's size is
-        changed. This can complicate some algorithms considerably.
-
-        This wrapper will update the parsers iterator (the value returned by the i() member) on
-        every access. This ensures that the iterator will stay valid.
-
-        \attention Beware however, if you insert or remove data before the safe wrapper, the
-            location will \e not be updated accordingly and therefore the parser will be
-            invalid.
-
-        Additionally a SafePacketParser has an uninitialized state. The only allowed operations in
-        this state are the boolean test for validity and assigning another parser.
-
-        \ingroup packetparser
-      */
-    template <class Parser>
-    class SafePacketParser
-        : public SafeBool< SafePacketParser<Parser> >
-    {
-    public:
-        ///////////////////////////////////////////////////////////////////////////
-        // Types
-
-        ///////////////////////////////////////////////////////////////////////////
-        ///\name Structors and default members
-        ///@{
-
-        // default copy constructor
-        // default copy assignment
-        // default destructor
-        SafePacketParser();             ///< Create an empty uninitialized SafePacketParser
-
-        // conversion constructors
-        SafePacketParser(Parser parser); ///< Initialize SafePacketParser from \a parser
-
-        SafePacketParser & operator=(Parser parser); ///< Assign \a parser to \c this
-
-        ///@}
-        ///////////////////////////////////////////////////////////////////////////
-
-        Parser operator*() const;       ///< Access the stored parser
-                                        /**< On every access, the stored parsers iterator will be
-                                             updated / re-validated. */
-        Parser const * operator->() const; ///< Access the stored parser
-                                        /**< On every access, the stored parsers iterator will be
-                                             updated / re-validated. */
-        bool boolean_test() const;      ///< Check validity
-
-    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(SENF_PACKETS_DECL_ONLY) && !defined(HH_PacketParser_i_)
+#if !defined(HH_Packets__decls_) && !defined(HH_PacketParser_i_)
 #define HH_PacketParser_i_
 #include "PacketParser.cci"
 #include "PacketParser.ct"