Packets: Extend finalize() API
[senf.git] / Packets / Packet.hh
index 33f6317..af45ff2 100644 (file)
@@ -1,8 +1,8 @@
 // $Id$
 //
-// Copyright (C) 2007 
-// Fraunhofer Institute for Open Communication Systems (FOKUS) 
-// Competence Center NETwork research (NET), St. Augustin, GERMANY 
+// Copyright (C) 2007
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
 //     Stefan Bund <g0dil@berlios.de>
 //
 // This program is free software; you can redistribute it and/or modify
 
 // Custom includes
 #include <boost/operators.hpp>
-
+#include <boost/utility.hpp>
+#include <boost/type_traits/is_integral.hpp>
 #include "../Utils/Exception.hh"
+#include "../Utils/Tags.hh"
 #include "../Utils/safe_bool.hh"
 #include "PacketInterpreter.hh"
 
@@ -40,7 +42,7 @@ namespace senf {
 
     /** \defgroup packet_module Packet Handling
 
-        The basic groundwork of the Packet library is the packet handling:
+        The basic groundwork of the %Packet library is the packet handling:
 
         \li The packet classes provide access to a chain of packet headers (more generically called
             interpreters).
@@ -97,16 +99,16 @@ namespace senf {
     ///\addtogroup packet_module
     ///@{
     
-    /** \brief Main Packet class
+    /** \brief Main %Packet class
 
-        Packet is the main externally visible class of the packet library. Packet is a handle into
-        the internal packet representation. From Packet you may access the data of that specific
+        %Packet is the main externally visible class of the packet library. %Packet is a handle into
+        the internal packet representation. From %Packet you may access the data of that specific
         sub-packet/header/interpreter and navigate to the neighboring
         sub-packets/headers/interpreters.
 
-        Packet is protocol agnostic. This class only provides non-protocol dependent members. To
+        %Packet is protocol agnostic. This class only provides non-protocol dependent members. To
         access the protocol specific features of a packet (like header fields) the ConcretePacket
-        class extending Packet is provided.
+        class extending %Packet is provided.
 
         \section packet_semantics Semantics
         
@@ -132,7 +134,7 @@ namespace senf {
         \ref ConcretePacket < \ref EthernetPacketType >).
 
         \see 
-            \ref ConcretePacket for the type specific interface\n
+            \ref ConcretePacket for the %type specific interface\n
             \ref PacketData for the sequence interface\n
             \ref packetparser for a specification of the parser interface
       */
@@ -149,9 +151,6 @@ namespace senf {
                                         ///< Unsigned type to represent packet size
         typedef PacketInterpreterBase::factory_t factory_t; ///< Packet factory type (see below)
 
-        enum NoInit_t { noinit };       ///< Special argument flag
-                                        /**< Used in some ConcretePacket constructors */
-
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
         ///@{
@@ -331,15 +330,50 @@ namespace senf {
                                              This is an alias for boolean_test() which is called
                                              when using a packet in a boolean context. */
 
-        void finalize() const;          ///< Update calculated fields
+        void finalizeThis();            ///< Update calculated fields
+                                        /**< This call will update all calculated fields of the
+                                             packet. This includes checksums, payload size fields or
+                                             other fields, which can be set from other information
+                                             in the packet. Each concrete packet type should
+                                             document, which fields are set by finalize().
+
+                                             finalizeThis() will \e only process the current
+                                             header. Even if only changing fields in this protocol,
+                                             depending on the protocol it may not be enough to
+                                             finalize this header only. See the packet type
+                                             documentation. */
+
+        template <class Other>
+        void finalizeTo();              ///< Update calculated fields
+                                        /**< This call will update all calculated fields of the
+                                             packet. This includes checksums, payload size fields or
+                                             other fields, which can be set from other information
+                                             in the packet. Each concrete packet type should
+                                             document, which fields are set by finalize().
+
+                                             finalizeTo() will automatically process all
+                                             packets/headers/interpreters from the first occurrence
+                                             of packet type \a Other backwards up to \c this. */
+
+        void finalizeTo(Packet other);  ///< Update calculated fields
+                                        /**< This call will update all calculated fields of the
+                                             packet. This includes checksums, payload size fields or
+                                             other fields, which can be set from other information
+                                             in the packet. Each concrete packet type should
+                                             document, which fields are set by finalize().
+
+                                             finalizeAll(other) will automatically process all
+                                             packets/headers/interpreters from \a other backwards up
+                                             to \c this. */
+
+        void finalizeAll();             ///< Update calculated fields
                                         /**< This call will update all calculated fields of the
-                                             packet after it has been created or changed. This
-                                             includes checksums, payload size fields or other
-                                             fields, which can be set from other information in the
-                                             packet. Each concrete packet type should document,
-                                             which fields are set by finalize().
+                                             packet. This includes checksums, payload size fields or
+                                             other fields, which can be set from other information
+                                             in the packet. Each concrete packet type should
+                                             document, which fields are set by finalize().
 
-                                             finalize() will automatically process all
+                                             finalizeAll() will automatically process all
                                              packets/headers/interpreters from the end of the chain
                                              backwards up to \c this. */
 
@@ -446,10 +480,10 @@ namespace senf {
         static ConcretePacket create(); ///< Create default initialized packet
                                         /**< The packet will be initialized to it's default empty
                                              state. */
-        static ConcretePacket create(NoInit_t); ///< Create uninitialized empty packet
+        static ConcretePacket create(senf::NoInit_t); ///< Create uninitialized empty packet
                                         /**< This will create a completely empty and uninitialized
                                              packet with <tt>size() == 0</tt>.
-                                             \param[in] noinit This parameter must always have the
+                                             \param[in] senf::noinit This parameter must always have the
                                                  value \c senf::noinit. */
         static ConcretePacket create(size_type size); ///< Create default initialized packet
                                         /**< This member will create a default initialized packet
@@ -460,12 +494,19 @@ namespace senf {
                                              \throws TruncatedPacketException if \a size is smaller
                                                  than the smallest permissible size for this type of
                                                  packet. */
-        static ConcretePacket create(size_type size, NoInit_t); ///< Create uninitialized packet
+        static ConcretePacket create(size_type size, senf::NoInit_t); 
+                                        ///< Create uninitialized packet
                                         /**< Creates an uninitialized (all-zero) packet of the exact
                                              given size. 
                                              \param[in] size Size of the packet to create in bytes
-                                             \param[in] noinit This parameter must always have the
+                                             \param[in] senf::noinit This parameter must always have the
                                                  value \c senf::noinit. */
+#ifndef DOXYGEN
+        template <class ForwardReadableRange>
+        static ConcretePacket create(
+            ForwardReadableRange const & range,
+            typename boost::disable_if< boost::is_integral<ForwardReadableRange> >::type * = 0); 
+#else
         template <class ForwardReadableRange>
         static ConcretePacket create(ForwardReadableRange const & range); 
                                         ///< Create packet from given data
@@ -476,6 +517,7 @@ namespace senf {
                                              \param[in] range <a
                                                  href="http://www.boost.org/libs/range/index.html">Boost.Range</a> 
                                                  of data to construct packet from. */
+#endif
 
         // Create packet as new packet after a given packet
 
@@ -485,14 +527,14 @@ namespace senf {
                                              state. It will be appended as next header/interpreter
                                              after \a packet in that packets interpreter chain.
                                              \param[in] packet Packet to append new packet to. */
-        static ConcretePacket createAfter(Packet packet, NoInit_t);
+        static ConcretePacket createAfter(Packet packet, senf::NoInit_t);
                                         ///< Create uninitialized empty packet after\a packet
                                         /**< This will create a completely empty and uninitialized
                                              packet with <tt>size() == 0</tt>. It will be appended
                                              as next header/interpreter after \a packet in that
                                              packets interpreter chain.
                                              \param[in] packet Packet to append new packet to.
-                                             \param[in] noinit This parameter must always have the
+                                             \param[in] senf::noinit This parameter must always have the
                                                  value \c senf::noinit. */
         static ConcretePacket createAfter(Packet packet, size_type size);
                                         ///< Create default initialized packet after \a packet
@@ -507,7 +549,7 @@ namespace senf {
                                              \throws TruncatedPacketException if \a size is smaller
                                                  than the smallest permissible size for this type of
                                                  packet. */
-        static ConcretePacket createAfter(Packet packet, size_type size, NoInit_t);
+        static ConcretePacket createAfter(Packet packet, size_type size, senf::NoInit_t);
                                         ///< Create uninitialized packet after \a packet
                                         /**< Creates an uninitialized (all-zero) packet of the exact
                                              given size.  It will be appended as next
@@ -515,8 +557,15 @@ namespace senf {
                                              interpreter chain.
                                              \param[in] packet Packet to append new packet to.
                                              \param[in] size Size of the packet to create in bytes
-                                             \param[in] noinit This parameter must always have the
+                                             \param[in] senf::noinit This parameter must always have the
                                                  value \c senf::noinit. */
+#ifndef DOXYGEN
+        template <class ForwardReadableRange>
+        static ConcretePacket createAfter(
+            Packet packet, 
+            ForwardReadableRange const & range,
+            typename boost::disable_if< boost::is_integral<ForwardReadableRange> >::type * = 0);
+#else
         template <class ForwardReadableRange>
         static ConcretePacket createAfter(Packet packet, 
                                           ForwardReadableRange const & range);
@@ -531,6 +580,7 @@ namespace senf {
                                              \param[in] range <a
                                                  href="http://www.boost.org/libs/range/index.html">Boost.Range</a> 
                                                  of data to construct packet from. */
+#endif
 
         // Create packet as new packet (header) before a given packet
 
@@ -541,7 +591,7 @@ namespace senf {
                                              header/interpreter before \a packet in that packets
                                              interpreter chain.
                                              \param[in] packet Packet to prepend new packet to. */
-        static ConcretePacket createBefore(Packet packet, NoInit_t);
+        static ConcretePacket createBefore(Packet packet, senf::NoInit_t);
                                         ///< Create uninitialized empty packet before \a packet
                                         /**< Creates a completely empty and uninitialized packet. It
                                              will be prepended as previous header/interpreter before
@@ -569,6 +619,13 @@ namespace senf {
                                              / recreation ...)
                                              \see \ref packetparser for the parser interface. */
 
+        Parser parser() const;          ///< Access packet field parser directly
+                                        /**< Access the parser of the packet. This is the same
+                                             object returned by the operator->() operator. The
+                                             operator however does not allow to access this object
+                                             itself, only it's members.
+                                             \see \ref packetparser for the parser interface */
+
     protected:
 
     private: