moved statistics classes from NetEmu to SENF
[senf.git] / Packets / Packet.hh
index 59f7d56..d148598 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.de>
 //
 // This program is free software; you can redistribute it and/or modify
 /** \file
     \brief Packet public header */
 
-#ifndef HH_Packet_
-#define HH_Packet_ 1
+#ifndef HH_SENF_Packets_Packet_
+#define HH_SENF_Packets_Packet_ 1
 
 // Custom includes
 #include <boost/operators.hpp>
-
+#include <boost/utility.hpp>
+#include <boost/type_traits/is_integral.hpp>
 #include "../Utils/Exception.hh"
-#include "../Utils/SafeBool.hh"
+#include "../Utils/Tags.hh"
+#include "../Utils/safe_bool.hh"
 #include "PacketInterpreter.hh"
 
 //#include "Packet.mpp"
@@ -38,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).
@@ -95,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
         
@@ -130,12 +134,12 @@ 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
-      */
+     */
     class Packet
-        : public SafeBool<Packet>,
+        : public safe_bool<Packet>,
           public boost::equality_comparable<Packet>
     {
     public:
@@ -143,13 +147,10 @@ namespace senf {
         // Types
         
         typedef void type;              ///< Type of the packet.
-        typedef senf::detail::packet::size_type size_type; ///< Unsigned type to represent packet size
+        typedef senf::detail::packet::size_type size_type;
+        ///< Unsigned type to represent packet size
         typedef PacketInterpreterBase::factory_t factory_t; ///< Packet factory type (see below)
 
-                                        /// Special argument flag
-                                        /** Used in some ConcretePacket constructors */
-        enum NoInit_t { noinit };       
-
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
         ///@{
@@ -159,22 +160,22 @@ namespace senf {
         // default destructor
         
         Packet();                       ///< Create uninitialized packet handle
-                                        /**< An uninitialized handle is not valid(). It does not
+                                        /**< An uninitialized handle is in - valid(). It does not
                                              allow any operation except assignment and checking for
                                              validity. */
         Packet clone() const;           ///< Create copy packet
-                                        /**< clone() will create a complete copy the packet. The
-                                             returned packet will have the same data and packet
-                                             chain. It does however not share any data with the
-                                             original packet. */
+                                        /**< clone() will create a complete copy of \c this
+                                             packet. The returned packet will have the same data and
+                                             packet chain. It does however not share any data with
+                                             the original packet. */
 
         // conversion constructors
 
         template <class PacketType>     
         Packet(ConcretePacket<PacketType> packet); ///< Copy-construct Packet from ConcretePacket
-                                        /**< This constructor allows to convert an arbitrary
-                                             ConcretePacket into a general Packet, loosing the
-                                             protocol specific interface. */
+        /**< This constructor allows to convert an arbitrary
+             ConcretePacket into a general Packet, loosing the
+             protocol specific interface. */
 
         ///@}
         ///////////////////////////////////////////////////////////////////////////
@@ -182,132 +183,129 @@ namespace senf {
         ///\name Interpreter chain access
         ///@{
 
-                                     Packet      next() const; 
-                                        ///< Get next packet in chain
-                                        /**< \returns in - valid() packet, if no next packet 
-                                             exists */
+        Packet      next() const; 
+        ///< Get next packet in chain
+        /**< \throws InvalidPacketChainException if no next packet 
+             exists */
+        Packet      next(NoThrow_t) const; 
+        ///< Get next packet in chain
+        /**< \returns in - valid() packet if no next packet 
+             exists */
         template <class OtherPacket> OtherPacket next() const; 
-                                        ///< Get next packet of given type in chain
-                                        /**< \throws InvalidPacketChainException if no such packet
-                                             is found */
+        ///< Get next packet in chain and cast to \a OtherPacket
+        /**< \throws std::bad_cast if the next() packet is not of
+             type \a OtherPacket
+             \throws InvalidPacketChainException if no next packet
+                 exists */
         template <class OtherPacket> OtherPacket next(NoThrow_t) const; 
-                                        ///< Get next packet of given type in chain
-                                        /**< \param[in] nothrow This argument always has the value
-                                             \c senf::nothrow
-                                             \returns in - valid() packet, if no such packet is
-                                             found */
-        template <class OtherPacket> OtherPacket findNext() const;
-                                        ///< Find next packet of given type in chain
-                                        /**< findNext() is like next(), it will however return \c
-                                             *this if it is of the given type. 
-                                             \throws InvalidPacketChainException if no such packet
-                                                 is found */
-        template <class OtherPacket> OtherPacket findNext(NoThrow_t) const;
-                                        ///< Find next packet of given type in chain
-                                        /**< findNext() is like next(), it will however return \c
-                                             *this if it is of the given type.
-                                             \param[in] nothrow This argument always has the value
-                                             \c senf::nothrow
-                                             \returns in - valid() packet, if no such packet is
-                                             found */
+        ///< Get next packet in chain and cast to \a OtherPacket
+        /**< \throws std::bad_cast if the next() packet is not of
+             type \a OtherPacket
+             \returns in - valid() packet if no next packet
+                 exists */
+        template <class OtherPacket> OtherPacket find() const;
+        ///< Search chain forward for packet of type \a OtherPacket
+        /**< The search will start with the current packet.
+             \throws InvalidPacketChainException if no packet of
+                 type \a OtherPacket can be found. */
+        template <class OtherPacket> OtherPacket find(NoThrow_t) const;
+        ///< Search chain forward for packet of type \a OtherPacket
+        /**< The search will start with the current packet.
+             \returns in - valid() packet if no packet of type \a
+                 OtherPacket can be found. */
         
-
-                                     Packet      prev() const; 
-                                        ///< Get previous packet in chain
-                                        /**< \returns in - valid() packet, if no previous packet 
-                                             exists */
+        Packet      prev() const; 
+        ///< Get previous packet in chain
+        /**< \throws InvalidPacketChainException if no previous
+             packet exists */
+        Packet      prev(NoThrow_t) const; 
+        ///< Get previous packet in chain
+        /**< \returns in - valid() packet if no previous packet
+             exists */
         template <class OtherPacket> OtherPacket prev() const; 
-                                        ///< Get previous packet of given type in chain
-                                        /**< \throws InvalidPacketChainException if no such packet
-                                             is found */
-        template <class OtherPacket> OtherPacket prev(NoThrow_t) const;
-                                        ///< Get previous packet of given type in chain
-                                        /**< \param[in] nothrow This argument always has the value
-                                             \c senf::nothrow
-                                             \returns in - valid() packet, if no such packet is
-                                             found */
-        template <class OtherPacket> OtherPacket findPrev() const;
-                                        ///< Find previous packet of given type in chain
-                                        /**< findPrev() is like prev(), it will however return \c
-                                             *this if it is of the type 
-                                             \throws InvalidPacketChainException if no such packet
-                                                 is found */
-        template <class OtherPacket> OtherPacket findPrev(NoThrow_t) const;
-                                        ///< Find previous packet of given type in chain
-                                        /**< findPrev() is like prev(), it will however return \c
-                                             *this if it is of the type 
-                                             \param[in] nothrow This argument always has the value
-                                             \c senf::nothrow
-                                             \returns in - valid() packet, if no such packet is
-                                             found */
-
-
-                                     Packet      first() const;
-                                        ///< Return first packet in chain
+        ///< Get previous packet in chain and cast to \a OtherPacket
+        /**< \throws std::bad_cast, if the previous packet is not of
+             type \a OtherPacket
+             \throws InvalidPacketChainException if no previous
+                 packet exists */
+        template <class OtherPacket> OtherPacket prev(NoThrow_t) const; 
+        ///< Get previous packet in chain and cast to \a OtherPacket
+        /**< \throws std::bad_cast, if the previous packet is not of
+             type \a OtherPacket
+             \returns in - valid() packet if no previous packet 
+                 exists */
+        template <class OtherPacket> OtherPacket rfind() const;
+        ///< Search chain backwards for packet of type \a OtherPacket
+        /**< The search will start with the current packet.
+             \throws InvalidPacketChainException if no packet of
+                 type \a OtherPacket can be found. */
+        template <class OtherPacket> OtherPacket rfind(NoThrow_t) const;
+        ///< Search chain backwards for packet of type \a OtherPacket
+        /**< The search will start with the current packet.
+             \returns in - valid() packet if no packet of type \a
+                 OtherPacket can be found. */
+
+
+        Packet      first() const;
+        ///< Return first packet in chain
         template <class OtherPacket> OtherPacket first() const;
-                                        ///< Return first packet of given type in chain
-                                        /**< \throws InvalidPacketChainException if no such packet
-                                             is found */
-        template <class OtherPacket> OtherPacket first(NoThrow_t) const;
-                                        ///< Return first packet of given type in chain
-                                        /**< \param[in] nothrow This argument always has the value
-                                             \c senf::nothrow
-                                             \returns in - valid() packet, if no such packet is
-                                             found */
-
-                                     Packet      last() const;
-                                        ///< Return last packet in chain
+        ///< Return first packet in chain and cast
+        /**< \throws std::bad_cast if the first() packet is not of
+             type \a OtherPacket */
+
+        Packet      last() const;
+        ///< Return last packet in chain
         template <class OtherPacket> OtherPacket last() const;
-                                        ///< Return last packet of given type in chain
-                                        /**< \throws InvalidPacketChainException if no such packet
-                                             is found */
-        template <class OtherPacket> OtherPacket last(NoThrow_t) const;
-                                        ///< Return last packet of given type in chain
-                                        /**< \param[in] nothrow This argument always has the value
-                                             \c senf::nothrow
-                                             \returns in - valid() packet, if no such packet is
-                                             found */
+        ///< Return last packet in chain and cast
+        /**< \throws std::bad_cast if the last() packet is not of
+             type \a OtherPacket  */
 
 
         template <class OtherPacket> OtherPacket parseNextAs() const;
-                                        ///< Parse payload as given by \a OtherPacket and add packet
-                                        /**< parseNextAs() will throw away the packet chain after
-                                             the current packet if necessary. It will then parse the
-                                             payload section of \c this packet as given by \a
-                                             OtherPacket. The new packet is added to the chain after
-                                             \c this.
-                                             \returns new packet instance sharing the same data and
-                                                 placed after \c this packet in the chain. */
-                                     Packet      parseNextAs(factory_t factory) const;
-                                        ///< Parse payload as given by \a factory and add packet
-                                        /**< parseNextAs() will throw away the packet chain after
-                                             the current packet if necessary. It will then parse the
-                                             payload section of \c this packet as given by \a
-                                             OtherPacket. The new packet is added to the chain after
-                                             \c this.
-                                             \returns new packet instance sharing the same data and
-                                                 placed after \c this packet in the chain. */
+        ///< Interpret payload of \c this as \a OtherPacket
+        /**< parseNextAs() will throw away the packet chain after
+             the current packet if necessary. It will then parse the
+             payload section of \c this packet as given by \a
+             OtherPacket. The new packet is added to the chain after
+             \c this.
+             \returns new packet instance sharing the same data and
+                 placed after \c this packet in the chain. 
+             \throws InvalidPacketChainException if no next
+                 packet header is allowed (viz. nextPacketRange() of the the current
+                 PacketType returns no_range() ) */
+        Packet      parseNextAs(factory_t factory) const;
+        ///< Interpret payload of \c this as \a factory type packet
+        /**< parseNextAs() will throw away the packet chain after
+             the current packet if necessary. It will then parse the
+             payload section of \c this packet as given by \a
+             factory. The new packet is added to the chain after
+             \c this.
+             \returns new packet instance sharing the same data and
+                 placed after \c this packet in the chain.
+             \throws InvalidPacketChainException if no next
+                 packet header is allowed (viz. nextPacketRange() of the the current
+                 PacketType returns no_range() ) */
+
         template <class OtherPacket> bool        is() const;
-                                        ///< Check, whether \c this packet is of the given type
+        ///< Check, whether \c this packet is of the given type
         template <class OtherPacket> OtherPacket as() const;
-                                        ///< Cast current packet to the given type
-                                        /**< This operations returns a handle to the same packet
-                                             header/interpreter however cast to the given
-                                             ConcretePacket type. <b>This conversion is
-                                             unchecked</b>. If the packet really is of a different
-                                             type, this will wreak havoc with the packet
-                                             data-structures. You can validate whether the
-                                             conversion is valid using is(). */
-
-        Packet append(Packet packet) const; ///< Append the given packet to \c this packet
-                                        /**< This operation will replace the payload section of \c
-                                             this packet with \a packet. This operation will replace
-                                             the packet chain after \c this packet with a clone of
-                                             \a packet and will replace the raw data of the payload
-                                             of \c this with the raw data if \a packet.
-                                             \returns Packet handle to the cloned \a packet, placed
-                                                 after \c this in the packet/header/interpreter
-                                                 chain. */
+        ///< Cast current packet to the given type
+        /**< This operations returns a handle to the same packet
+             header/interpreter however cast to the given
+             ConcretePacket type.
+             \throws std::bad_cast if the current packet is not of
+                 type \a OtherPacket */
+
+        Packet append(Packet const & packet) const; ///< Append the given packet to \c this packet
+        /**< This operation will replace the payload section of \c
+             this packet with \a packet. This operation will replace
+             the packet chain after \c this packet with a clone of
+             \a packet and will replace the raw data of the payload
+             of \c this with the raw data of \a packet. \c this
+             packet will not share any date with \a packet.
+             \returns Packet handle to the cloned \a packet, placed
+                 after \c this in the packet/header/interpreter
+                 chain. */
 
         ///@}
 
@@ -322,12 +320,78 @@ namespace senf {
         
         ///@}
 
+        ///\name Annotations
+        ///@{
+
+        template <class Annotation>
+        Annotation & annotation();      ///< Get packet annotation
+                                        /**< This member will retrieve an arbitrary packet
+                                             annotation. Every annotation is identified by a unique
+                                             \a Annotation type. This type should \e always be a \c
+                                             struct.
+
+                                             \code
+                                                 struct MyAnnotation {
+                                                 int value;
+                                                 };
+
+                                             senf::Packet p (...);
+                                            
+                                             p.annotation<MyAnnotation>().value = 1;
+                                             \endcode
+                                             
+                                             Annotations are shared by all headers / interpreters
+                                             within a single packet chain.
+
+                                             If an annotation is \e not a POD type (more
+                                             specifically, if it's constructor or destructor is not
+                                             trivial including base classes and members), the \a
+                                             Annotation type \e must inherit from
+                                             senf::ComplexAnnotation. Failing to follow this rule
+                                             will result in undefined behavior and will probably
+                                             lead to a program crash.
+
+                                             \code
+                                                 struct MyStringAnnotation : senf::ComplexAnnotation {
+                                                 std::string value;
+                                                 };
+                                             \endcode
+                                                 (This type is not POD since \c std::string is not POD)
+
+                                             \see \ref packet_usage_annotation
+
+                                             \implementation The annotation system is implemented
+                                                 quite efficiently since annotations are stored
+                                                 within a packet embedded vector of fixed size (the
+                                                 size is determined automatically at runtime by the
+                                                 number of different annotations
+                                                 used). Additionally, non-complex small annotations
+                                                 require no additional memory management (\c new /
+                                                 \c delete).
+                                             
+                                             \idea Pool the annotation vectors: In the destructor
+                                                 swap the vector into a vector graveyard (swapping
+                                                 two vectors is an O(1) no allocation operation). In
+                                                 the constructor, if there is a vector in the
+                                                 graveyard, swap it in from there. Of course, it
+                                                 would be better to do away with the vector and just
+                                                 allocate the space together with the packet but
+                                                 that looks quite complicated to do ... especially
+                                                 considering that the packetimpl itself uses a pool.
+                                          */
+
+        ///@}
+
+        template <class Annotation>
+        Annotation const & annotation() const; ///< Get packet annotation
+                                        /**< \see annotation() */
+
         ///\name Other methods
         ///@{
 
-        bool operator==(Packet other) const; ///< Check for packet identity
-                                        /**< Two packet handles compare equal if they really are the
-                                             same packet header in the same packet chain. */
+        bool operator==(Packet const & other) const; ///< Check for packet identity
+        /**< Two packet handles compare equal if they really are the
+             same packet header in the same packet chain. */
         bool boolean_test() const;      ///< Check, whether the packet is valid()
                                         /**< \see valid() */
         bool valid() const;             ///< Check, whether the packet is valid()
@@ -338,37 +402,92 @@ 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
-                                        /**< 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().
-
-                                             finalize() will automatically process all
+        void finalizeThis();            ///< Update calculated fields
+                                        /**< The finalize() fammily of members will update
+                                             calculated packet fields: checksums, size fields and so
+                                             on. This includes any field, 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
+                                        /**< The finalize() fammily of members will update
+                                             calculated packet fields: checksums, size fields and so
+                                             on. This includes any field, 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 \e first
+                                             occurrence of packet type \a Other (beginning at \c
+                                             this packet searching forward towards deeper nested
+                                             packets) backwards up to \c this. 
+                                             
+                                             This call is equivalent to
+                                             \code
+                                                 p.finalizeTo(p.next<Other>())
+                                             \endcode */
+
+        void finalizeTo(Packet const & other);  ///< Update calculated fields
+        /**< The finalize() fammily of members will update
+             calculated packet fields: checksums, size fields and so
+             on. This includes any field, which can be set from
+             other information in the packet. Each concrete packet
+             type should document, which fields are set by
+             finalize().
+
+             finalizeTo(other) will automatically process all
+             packets/headers/interpreters beginning at \a other
+             backwards towards outer packets up to \c this. */
+
+        void finalizeAll();             ///< Update calculated fields
+                                        /**< The finalize() fammily of members will update
+                                             calculated packet fields: checksums, size fields and so
+                                             on. This includes any field, which can be set from
+                                             other information in the packet. Each concrete packet
+                                             type should document, which fields are set by
+                                             finalize().
+
+                                             finalizeAll() will automatically process all
                                              packets/headers/interpreters from the end of the chain
-                                             backwards up to \c this. */
+                                             (the most inner packet) backwards up to \c this. 
+
+                                             This call is equivalent to
+                                             \code
+                                                 p.finalizeTo(p.last())
+                                             \endcode 
+
+                                             Beware, that finalizeAll() will \e not finalize any
+                                             headers before \c this, it will \e only process inner
+                                             headers. */
 
         void dump(std::ostream & os) const; ///< Write out a printable packet representation
-                                        /**< This method is provided mostly to help debugging packet
-                                             problems. Each concrete packet should implement a dump
-                                             method writing out all fields of the packet in a
-                                             readable representation. dump() will call this member
-                                             for each packet/header/interpreter in the chain from \c
-                                             this packet up to the end of the chain. */
+        /**< This method is provided mostly to help debugging packet
+             problems. Each concrete packet should implement a dump
+             method writing out all fields of the packet in a
+             readable representation. dump() will call this member
+             for each packet/header/interpreter in the chain from \c
+             this packet up to the end of the chain. */
 
         TypeIdValue typeId() const;     ///< Get id of \c this packet
-                                        /**< This value is used e.g. in the packet registry to
-                                             associate packet types with other information.
-                                             \returns A type holding the same information as a
-                                                 type_info object, albeit assignable */
+        /**< This value is used e.g. in the packet registry to
+             associate packet types with other information.
+             \returns A type holding the same information as a
+                 type_info object, albeit assignable */
         factory_t factory() const;      ///< Return factory instance of \c this packet
-                                        /**< The returned factory instance can be used to create new
-                                             packets of the given type without knowing the concrete
-                                             type of the packet. The value may be stored away for
-                                             later use if needed. */
-        
+        /**< The returned factory instance can be used to create new
+             packets of the given type without knowing the concrete
+             type of the packet. The value may be stored away for
+             later use if needed. */
+
         ///@}
 
     protected:
@@ -379,9 +498,9 @@ namespace senf {
     private:
         Packet checkNext() const;
         Packet checkLast() const;
-        
+
         PacketInterpreterBase::ptr packet_;
-        
+
         template <class PacketType>
         friend class ConcretePacket;
         friend class PacketParserBase;
@@ -399,13 +518,13 @@ namespace senf {
 
         The new members provided by ConcretePacket over packet are mostly comprised of the packet
         constructors. These come in three major flavors:
-        
+
         \li The create() family of constructors will create completely new packets.
         \li The createAfter() family of constructors will create new packets (with new data for the
             packet) \e after a given existing packet.
         \li The createBefore()  family of constructors will create new packets (again with new data)
             \e before a given existing packet.
-        
+
         Whereas create() will create a completely new packet with it's own chain and data storage,
         createAfter() and createBefore() extend a packet with additional
         headers/interpreters. createAfter() will set the payload of the given packet to the new
@@ -415,10 +534,10 @@ namespace senf {
         createAfter() differs from Packet::parseNextAs() in that the former creates a new packet \e
         replacing any possibly existing data whereas the latter will interpret the already \e
         existing data as given by the type argument.
-        
+
         \see \ref PacketTypeBase for a specification of the interface to be provided by the \a
             PacketType policy class.
-      */
+     */
     template <class PacketType>
     class ConcretePacket 
         : public Packet
@@ -426,8 +545,9 @@ namespace senf {
     public:
         ///////////////////////////////////////////////////////////////////////////
         // Types
-        
+
         typedef PacketType type;
+        typedef typename PacketType::parser Parser;
 
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
@@ -439,131 +559,154 @@ namespace senf {
         // no conversion constructors
 
         ConcretePacket();               ///< Create uninitialized packet handle
-                                        /**< An uninitialized handle is not valid(). It does not
-                                             allow any operation except assignment and checking for
-                                             validity. */
+        /**< An uninitialized handle is not valid(). It does not
+             allow any operation except assignment and checking for
+             validity. */
 
         static factory_t factory();     ///< Return factory for packets of specific type
-                                        /**< This \e static member is like Packet::factory() for a
-                                             specific packet of type \a PacketType */
+        /**< This \e static member is like Packet::factory() for a
+             specific packet of type \a PacketType */
 
         // Create completely new packet
 
         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
-                                        /**< This will create a completely empty and uninitialized
-                                             packet with <tt>size() == 0</tt>.
-                                             \param[in] noinit This parameter must always have the
-                                                 value \c senf::noinit. */
+        /**< The packet will be initialized to it's default empty
+             state. */
+        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] 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
-                                             with the given size. If the size parameter is smaller
-                                             than the minimum allowed packet size an exception will
-                                             be thrown.
-                                             \param[in] size Size of the packet to create in bytes.
-                                             \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
-                                        /**< 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
-                                                 value \c senf::noinit. */
+        /**< This member will create a default initialized packet
+             with the given size. If the size parameter is smaller
+             than the minimum allowed packet size an exception will
+             be thrown.
+             \param[in] size Size of the packet to create in bytes.
+             \throws TruncatedPacketException if \a size is smaller
+                 than the smallest permissible size for this type of
+                 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] 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
-                                        /**< The packet will be created from a copy of the given
-                                             data. The data from the range will be copied directly
-                                             into the packet representation. The data will \e not be
-                                             validated in any way.
-                                             \param[in] range <a
-                                                 href="http://www.boost.org/libs/range/index.html">Boost.Range</a> 
-                                                 of data to construct packet from. */
+        ///< Create packet from given data
+        /**< The packet will be created from a copy of the given
+             data. The data from the range will be copied directly
+             into the packet representation. The data will \e not be
+             validated in any way.
+             \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
 
-        static ConcretePacket createAfter(Packet packet); 
-                                        ///< Create default initialized packet after \a packet
-                                        /**< The packet will be initialized to it's default empty
-                                             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);
-                                        ///< 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
-                                                 value \c senf::noinit. */
-        static ConcretePacket createAfter(Packet packet, size_type size);
-                                        ///< Create default initialized packet after \a packet
-                                        /**< This member will create a default initialized packet
-                                             with the given size. If the size parameter is smaller
-                                             than the minimum allowed packet size an exception will
-                                             be thrown. 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] size Size of the packet to create in bytes.
-                                             \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);
-                                        ///< Create uninitialized packet after \a packet
-                                        /**< Creates an uninitialized (all-zero) packet of the exact
-                                             given size.  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] size Size of the packet to create in bytes
-                                             \param[in] noinit This parameter must always have the
-                                                 value \c senf::noinit. */
+        static ConcretePacket createAfter(Packet const & packet); 
+        ///< Create default initialized packet after \a packet
+        /**< The packet will be initialized to it's default empty
+             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 const & 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] senf::noinit This parameter must always have the
+                 value \c senf::noinit. */
+        static ConcretePacket createAfter(Packet const & packet, size_type size);
+        ///< Create default initialized packet after \a packet
+        /**< This member will create a default initialized packet
+             with the given size. If the size parameter is smaller
+             than the minimum allowed packet size an exception will
+             be thrown. 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] size Size of the packet to create in bytes.
+             \throws TruncatedPacketException if \a size is smaller
+                 than the smallest permissible size for this type of
+                 packet. */
+        static ConcretePacket createAfter(Packet const & 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
+             header/interpreter after \a packet in that packets
+             interpreter chain.
+             \param[in] packet Packet to append new packet to.
+             \param[in] size Size of the packet to create in bytes
+             \param[in] senf::noinit This parameter must always have the
+                 value \c senf::noinit. */
+#ifndef DOXYGEN
+        template <class ForwardReadableRange>
+        static ConcretePacket createAfter(
+            Packet const & packet, 
+            ForwardReadableRange const & range,
+            typename boost::disable_if< boost::is_integral<ForwardReadableRange> >::type * = 0);
+#else
         template <class ForwardReadableRange>
-        static ConcretePacket createAfter(Packet packet, 
+        static ConcretePacket createAfter(Packet const & packet, 
                                           ForwardReadableRange const & range);
-                                        ///< Create packet from given data after \a packet
-                                        /**< The packet will be created from a copy of the given
-                                             data. The data from the range will be copied directly
-                                             into the packet representation. The data will \e not be
-                                             validated in any way.  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] range <a
-                                                 href="http://www.boost.org/libs/range/index.html">Boost.Range</a> 
-                                                 of data to construct packet from. */
+        ///< Create packet from given data after \a packet
+        /**< The packet will be created from a copy of the given
+             data. The data from the range will be copied directly
+             into the packet representation. The data will \e not be
+             validated in any way.  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] 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
 
-        static ConcretePacket createBefore(Packet packet); 
-                                        ///< Create default initialized packet before \a packet
-                                        /**< The packet will be initialized to it's default empty
-                                             state. It will be prepended as previous
-                                             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);
-                                        ///< Create uninitialized empty packet before \a packet
-                                        /**< Creates a completely empty and uninitialized packet. It
-                                             will be prepended as previous header/interpreter before
-                                             \a packet in that packets interpreter chain.
-                                             \param[in] packet Packet to prepend new packet to. */
+        static ConcretePacket createBefore(Packet const & packet); 
+        ///< Create default initialized packet before \a packet
+        /**< The packet will be initialized to it's default empty
+             state. It will be prepended as previous
+             header/interpreter before \a packet in that packets
+             interpreter chain.
+             \param[in] packet Packet to prepend new packet to. */
+        static ConcretePacket createBefore(Packet const & 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
+             \a packet in that packets interpreter chain.
+             \param[in] packet Packet to prepend new packet to. */
         
         // Create a clone of the current packet
 
         ConcretePacket clone() const;
-
+         
         ///@}
         ///////////////////////////////////////////////////////////////////////////
-
+         
         // Field access
-
-        typename type::parser * operator->() const; ///< Access packet fields
+         
+        struct ParserProxy 
+        {
+            ParserProxy(Parser const & p) : p_ (p) {}
+            Parser * operator->() { return &p_; }
+            Parser p_;
+        };
+
+        ParserProxy operator->() const;    ///< Access packet fields
                                         /**< This operator allows to access the parsed fields of the
                                              packet using the notation <tt>packet->field()</tt>. The
                                              fields of the packet are specified by the PacketType's
@@ -575,6 +718,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:
@@ -588,14 +738,23 @@ namespace senf {
         friend class PacketInterpreter<PacketType>;
     };
 
+    /** \brief Generic parser copying
+
+        This operator allows to copy the value 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 packet.
+     */
+    template <class PacketType, class Parser>
+    Parser operator<<(Parser target, ConcretePacket<PacketType> const & packet);
+
     ///@}
 
 }
 
 ///////////////////////////////hh.e////////////////////////////////////////
 #endif
-#if !defined(SENF_PACKETS_DECL_ONLY) && !defined(HH_Packet_i_)
-#define HH_Packet_i_
+#if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_Packet_i_)
+#define HH_SENF_Packets_Packet_i_
 #include "Packet.cci"
 #include "Packet.ct"
 #include "Packet.cti"