Packets: Restructure documentation
[senf.git] / Packets / PacketParser.hh
index 3585280..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>\ref parserimpl_value</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>\ref parserimpl_collection</em> are parsers which model a collection of sub-elements like
-        senf::Parse_List or senf::Parse_Vector.
+        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::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
+    parser. Instead, you can rely on senf::VectorParser or senf::ListParser and implement new
     policies.
 
+    \see parsecollection
+
     \subsection parserimpl_composite Composite parsers
     
     If possible, composite parsers should be implemented using the \ref packetparsermacros. In
     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>
  */
 #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"
@@ -177,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
@@ -214,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
         
@@ -260,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. */
@@ -278,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
@@ -299,6 +317,7 @@ namespace senf {
         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
@@ -308,18 +327,30 @@ 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
-                                        /**< \important This member should only be used from packet
+                                        /**< \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. */
 
@@ -329,7 +360,7 @@ namespace senf {
         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
@@ -350,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
 
@@ -370,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< 
@@ -445,63 +495,6 @@ namespace senf {
         SENF_PARSER_FINALIZE(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_;
-    };
-
 }
 
 ///////////////////////////////hh.e////////////////////////////////////////