Fixes for boost-1.36 + gcc-4.3
[senf.git] / Packets / Packet.hh
index 18b3020..bb2ac90 100644 (file)
@@ -28,7 +28,8 @@
 
 // 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"
@@ -313,6 +314,66 @@ 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)
+
+                                             \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.
+                                          */
+
+        ///@}
+
         ///\name Other methods
         ///@{
 
@@ -329,17 +390,72 @@ 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 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
@@ -465,6 +581,12 @@ namespace senf {
                                              \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
@@ -475,6 +597,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
 
@@ -516,6 +639,13 @@ namespace senf {
                                              \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 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);
@@ -530,6 +660,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