Packet: Implement createInsertBefore() API
g0dil [Fri, 30 Apr 2010 10:35:53 +0000 (10:35 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1610 270642c3-0616-0410-b53a-bc976706d245

12 files changed:
senf/Packets/Packet.cti
senf/Packets/Packet.hh
senf/Packets/Packet.test.cc
senf/Packets/PacketImpl.cc
senf/Packets/PacketImpl.hh
senf/Packets/PacketImpl.test.cc
senf/Packets/PacketInterpreter.cci
senf/Packets/PacketInterpreter.ct
senf/Packets/PacketInterpreter.cti
senf/Packets/PacketInterpreter.hh
senf/Packets/PacketInterpreter.test.cc
senf/Packets/main.test.hh

index 8e56512..21600c6 100644 (file)
@@ -267,6 +267,20 @@ senf::ConcretePacket<PacketType>::createBefore(Packet const & packet, senf::NoIn
     return ConcretePacket(interpreter::createBefore(packet.ptr(), senf::noinit));
 }
 
+template <class PacketType>
+prefix_ senf::ConcretePacket<PacketType>
+senf::ConcretePacket<PacketType>::createInsertBefore(Packet const & packet)
+{
+    return ConcretePacket(interpreter::createInsertBefore(packet.ptr()));
+}
+
+template <class PacketType>
+prefix_ senf::ConcretePacket<PacketType>
+senf::ConcretePacket<PacketType>::createInsertBefore(Packet const & packet, senf::NoInit_t)
+{
+    return ConcretePacket(interpreter::createInsertBefore(packet.ptr(), senf::noinit));
+}
+
 // Create a clone of the current packet
 
 template <class PacketType>
index ffe8d5d..00b00f7 100644 (file)
@@ -172,9 +172,9 @@ namespace senf {
 
         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,129 +182,124 @@ namespace senf {
         ///\name Interpreter chain access
         ///@{
 
-        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 */
+        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 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 */
+                                        ///< 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 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 */
+                                        ///< 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. */
+                                        ///< 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
-        /**< \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 */
+                                        ///< 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
+                                        /**< \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 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 */
+                                        ///< 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 */
+                                        ///< 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. */
+                                        ///< 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. */
+                                        ///< 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 in chain and cast
-        /**< \throws std::bad_cast if the first() packet is not of
-             type \a OtherPacket */
+        Packet      first() const;      ///< Return first packet in chain
+        template <class OtherPacket> OtherPacket first() const; 
+                                        ///< 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
+        Packet      last() const;       ///< Return last packet in chain
         template <class OtherPacket> OtherPacket last() const;
-        ///< Return last packet in chain and cast
-        /**< \throws std::bad_cast if the last() packet is not of
-             type \a OtherPacket  */
+                                        ///< 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;
-        ///< 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() ) */
+                                        ///< 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() ) */
+                                        ///< 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 upcast to the given
-             ConcretePacket type which have been instantiated before.
-             \throws std::bad_cast if the current packet is not of
-                 type \a OtherPacket */
+                                        ///< Cast current packet to the given type
+                                        /**< This operations returns a handle to the same packet
+                                             header/interpreter however upcast to the given
+                                             ConcretePacket type which have been instantiated
+                                             before.
+                                             \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. */
+                                        /**< 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. */
 
         ///@}
 
@@ -330,9 +325,9 @@ namespace senf {
                                              struct.
 
                                              \code
-                                                 struct MyAnnotation {
+                                             struct MyAnnotation {
                                                  int value;
-                                                 };
+                                             };
 
                                              senf::Packet p (...);
 
@@ -351,11 +346,11 @@ namespace senf {
                                              lead to a program crash.
 
                                              \code
-                                                 struct MyStringAnnotation : senf::ComplexAnnotation {
+                                             struct MyStringAnnotation : senf::ComplexAnnotation {
                                                  std::string value;
-                                                 };
+                                             };
                                              \endcode
-                                                 (This type is not POD since \c std::string is not POD)
+                                             (This type is not POD since \c std::string is not POD)
 
                                              \see \ref packet_usage_annotation
 
@@ -562,40 +557,40 @@ 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. */
+                                        /**< 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. */
+                                        /**< 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. */
+                                        /**< 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. */
+                                        ///< 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(
@@ -604,56 +599,56 @@ namespace senf {
 #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 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. */
+                                        ///< 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. */
+                                        ///< 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. */
+                                        ///< 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. */
+                                        ///< 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(
@@ -664,34 +659,36 @@ namespace senf {
         template <class ForwardReadableRange>
         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 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. */
+                                        ///< 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 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 createInsertBefore(Packet const & packet);
+        static ConcretePacket createInsertBefore(Packet const & packet, senf::NoInit_t);
 
         // Create a clone of the current packet
 
index 21362e7..0581add 100644 (file)
@@ -281,6 +281,21 @@ SENF_AUTO_UNIT_TEST(concretePacket)
     BOOST_CHECK_EQUAL( FooPacket::createBefore(packet,senf::noinit).size(), 10u );
     BOOST_CHECK_EQUAL( packet.size(), 10u );
 
+    BOOST_CHECK_EQUAL( FooPacket::createInsertBefore(packet).size(), 14u );
+    BOOST_CHECK_EQUAL( packet.size(), 10u );
+    BOOST_REQUIRE( packet.prev() );
+    BOOST_CHECK_EQUAL( packet.prev().size(), 14u );
+    BOOST_REQUIRE( packet.prev().prev() );
+    BOOST_CHECK_EQUAL( packet.prev().prev().size(), 14u );
+
+    BOOST_CHECK_EQUAL( FooPacket::createInsertBefore(packet,senf::noinit).size(), 10u );
+    BOOST_CHECK_EQUAL( packet.size(), 10u );
+    BOOST_REQUIRE_NO_THROW( packet.prev().prev().prev() );
+    BOOST_CHECK_THROW( packet.prev().prev().prev().prev(), senf::InvalidPacketChainException );
+    BOOST_CHECK_EQUAL( packet.prev().size(), 10u );
+    BOOST_CHECK_EQUAL( packet.prev().prev().size(), 14u );
+    BOOST_CHECK_EQUAL( packet.prev().prev().prev().size(), 14u );
+
     SENF_CHECK_NOT_EQUAL( packet.clone(), packet );
     BOOST_CHECK_EQUAL( BarPacket::create()->reserved(), 0xA0A0u );
 }
index 5b0ad43..5fc7bf9 100644 (file)
@@ -76,6 +76,14 @@ prefix_ void senf::detail::PacketImpl::prependInterpreter(PacketInterpreterBase
     p->assignImpl(this);
 }
 
+prefix_ void senf::detail::PacketImpl::prependInterpreter(PacketInterpreterBase * p,
+                                                          PacketInterpreterBase * before)
+{
+    interpreter_list::iterator i (interpreter_list::current(*before));
+    interpreters_.insert(i, *p);
+    p->assignImpl(this);
+}
+
 // Data container
 
 prefix_ void senf::detail::PacketImpl::clear(PacketData * self)
index 489c6e2..e98a8c6 100644 (file)
@@ -174,6 +174,7 @@ namespace detail {
 
         void appendInterpreter    (PacketInterpreterBase * p);
         void prependInterpreter   (PacketInterpreterBase * p);
+        void prependInterpreter   (PacketInterpreterBase * p, PacketInterpreterBase * before);
         void truncateInterpreters (PacketInterpreterBase * p);
         void truncateInterpretersBackwards (PacketInterpreterBase * p);
 
index a6c08df..2a2b74a 100644 (file)
@@ -153,25 +153,30 @@ SENF_AUTO_UNIT_TEST(packetImpl_interpreters)
     p->add_ref();
 
     {
-        senf::PacketInterpreterBase::ptr pi2 (
+        senf::PacketInterpreterBase::ptr pi3 (
             senf::detail::packet::test::TestDriver::create<VoidPacket>(
                 p,p->begin(),p->end(),senf::PacketInterpreterBase::Append));
-        senf::PacketInterpreterBase::ptr pi3 (
+        senf::PacketInterpreterBase::ptr pi4 (
             senf::detail::packet::test::TestDriver::create<VoidPacket>(
                 p,p->end(),p->end(),senf::PacketInterpreterBase::Append));
         senf::PacketInterpreterBase::ptr pi1 (
             senf::detail::packet::test::TestDriver::create<VoidPacket>(
                 p,p->begin(),p->end(),senf::PacketInterpreterBase::Prepend));
+        senf::PacketInterpreterBase::ptr pi2 (
+            senf::detail::packet::test::TestDriver::create<VoidPacket>(
+                p,p->begin(),p->end(),pi3));
 
         BOOST_CHECK_EQUAL(p->first(), pi1.get());
         BOOST_CHECK_EQUAL(p->next(p->first()), pi2.get());
         BOOST_CHECK_EQUAL(p->next(p->next(p->first())), pi3.get());
-        BOOST_CHECK( !p->next(p->next(p->next(p->first()))) );
-
-        BOOST_CHECK_EQUAL(p->last(), pi3.get());
-        BOOST_CHECK_EQUAL(p->prev(p->last()), pi2.get());
-        BOOST_CHECK_EQUAL(p->prev(p->prev(p->last())), pi1.get());
-        BOOST_CHECK( !p->prev(p->prev(p->prev(p->last()))) );
+        BOOST_CHECK_EQUAL(p->next(p->next(p->next(p->first()))), pi4.get());
+        BOOST_CHECK( !p->next(p->next(p->next(p->next(p->first())))) );
+
+        BOOST_CHECK_EQUAL(p->last(), pi4.get());
+        BOOST_CHECK_EQUAL(p->prev(p->last()), pi3.get());
+        BOOST_CHECK_EQUAL(p->prev(p->prev(p->last())), pi2.get());
+        BOOST_CHECK_EQUAL(p->prev(p->prev(p->prev(p->last()))), pi1.get());
+        BOOST_CHECK( !p->prev(p->prev(p->prev(p->prev(p->last())))) );
 
         p->insert(&pi2->data(),p->begin(),10,0x00u);
         BOOST_CHECK_EQUAL(pi1->data().size(), 10u);
index fef8049..7eec8e5 100644 (file)
@@ -116,7 +116,15 @@ prefix_ senf::PacketInterpreterBase::PacketInterpreterBase(detail::PacketImpl *
     : PacketData(std::distance(impl->begin(),b),
                  std::distance(impl->begin(),e))
 {
-        impl->prependInterpreter(this);
+    impl->prependInterpreter(this);
+}
+
+prefix_ senf::PacketInterpreterBase::PacketInterpreterBase(detail::PacketImpl * impl,
+                                                           iterator b, iterator e, ptr before)
+    : PacketData(std::distance(impl->begin(),b),
+                 std::distance(impl->begin(),e))
+{
+    impl->prependInterpreter(this, before.get());
 }
 
 prefix_ senf::PacketInterpreterBase::ptr
index 49a34e1..2278181 100644 (file)
@@ -147,10 +147,29 @@ senf::PacketInterpreter<PacketType>::createBefore(PacketInterpreterBase::ptr pac
 {
     if (packet->prev())
         packet->impl().truncateInterpretersBackwards(packet->prev().get());
-    
+
     return create(&packet->impl(),packet->data().begin(),packet->data().end(),Prepend);
 }
 
+template <class PacketType>
+prefix_ typename senf::PacketInterpreter<PacketType>::ptr
+senf::PacketInterpreter<PacketType>::createInsertBefore(PacketInterpreterBase::ptr packet)
+{
+    ptr pi (createInsertBefore(packet, senf::noinit));
+    pi->data().insert(pi->data().begin(),initHeadSize(),byte(0x00u));
+    pi->data().insert(pi->data().end(),initSize()-initHeadSize(),byte(0x00u));
+    pi->init();
+    return pi;
+}
+
+template <class PacketType>
+prefix_ typename senf::PacketInterpreter<PacketType>::ptr
+senf::PacketInterpreter<PacketType>::createInsertBefore(PacketInterpreterBase::ptr packet,
+                                                        senf::NoInit_t)
+{
+    return create(&packet->impl(),packet->data().begin(),packet->data().end(),packet);
+}
+
 ////////////////////////////////////////
 // private members
 
@@ -332,6 +351,24 @@ createBefore(PacketInterpreterBase::ptr packet, senf::NoInit_t)
     return senf::PacketInterpreter<PacketType>::createBefore(packet,senf::noinit);
 }
 
+template <class PacketType>
+prefix_ senf::PacketInterpreterBase::ptr
+senf::PacketInterpreter<PacketType>::FactoryImpl::
+createInsertBefore(PacketInterpreterBase::ptr packet)
+    const
+{
+    return senf::PacketInterpreter<PacketType>::createInsertBefore(packet);
+}
+
+template <class PacketType>
+prefix_ senf::PacketInterpreterBase::ptr
+senf::PacketInterpreter<PacketType>::FactoryImpl::
+createInsertBefore(PacketInterpreterBase::ptr packet, senf::NoInit_t)
+    const
+{
+    return senf::PacketInterpreter<PacketType>::createInsertBefore(packet,senf::noinit);
+}
+
 // Parse next packet in chain
 
 template <class PacketType>
index 8dd19a9..29eee09 100644 (file)
@@ -148,6 +148,14 @@ senf::PacketInterpreter<PacketType>::create(detail::PacketImpl * impl, iterator
 }
 
 template <class PacketType>
+prefix_ typename senf::PacketInterpreter<PacketType>::ptr
+senf::PacketInterpreter<PacketType>::create(detail::PacketImpl * impl, iterator b, iterator e,
+                                            PacketInterpreterBase::ptr before)
+{
+    return ptr(new PacketInterpreter(impl,b,e,before));
+}
+
+template <class PacketType>
 prefix_ senf::PacketInterpreter<PacketType>::PacketInterpreter(detail::PacketImpl * impl,
                                                                iterator b, iterator e, Append_t)
     : PacketInterpreterBase(impl,b,e,Append)
@@ -159,6 +167,14 @@ prefix_ senf::PacketInterpreter<PacketType>::PacketInterpreter(detail::PacketImp
     : PacketInterpreterBase(impl,b,e,Prepend)
 {}
 
+template <class PacketType>
+prefix_
+senf::PacketInterpreter<PacketType>::PacketInterpreter(detail::PacketImpl * impl, iterator b,
+                                                       iterator e,
+                                                       PacketInterpreterBase::ptr before)
+    : PacketInterpreterBase(impl,b,e,before)
+{}
+
 // PacketType access
 
 template <class PacketType>
index e2591cf..0a546a6 100644 (file)
@@ -111,6 +111,9 @@ namespace senf {
             virtual ptr createBefore(PacketInterpreterBase::ptr packet) const = 0;
             virtual ptr createBefore(PacketInterpreterBase::ptr packet, senf::NoInit_t) const = 0;
 
+            virtual ptr createInsertBefore(PacketInterpreterBase::ptr packet) const = 0;
+            virtual ptr createInsertBefore(PacketInterpreterBase::ptr packet, senf::NoInit_t) const = 0;
+
             // Parse next packet in chain
 
             virtual ptr parseNext(ptr packet) const = 0;
@@ -186,6 +189,7 @@ namespace senf {
 
         PacketInterpreterBase(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
         PacketInterpreterBase(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
+        PacketInterpreterBase(detail::PacketImpl * impl, iterator b, iterator e, ptr before);
 
         ptr appendClone(detail::PacketImpl * impl, iterator base, iterator new_base);
         ptr appendClone(detail::PacketImpl * impl, range r);
@@ -282,6 +286,9 @@ namespace senf {
         static ptr createBefore(PacketInterpreterBase::ptr packet);
         static ptr createBefore(PacketInterpreterBase::ptr packet, senf::NoInit_t);
 
+        static ptr createInsertBefore(PacketInterpreterBase::ptr packet);
+        static ptr createInsertBefore(PacketInterpreterBase::ptr packet, senf::NoInit_t);
+
         // Create a clone of the current packet
 
         ptr clone();
@@ -305,9 +312,13 @@ namespace senf {
 
         PacketInterpreter(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
         PacketInterpreter(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
+        PacketInterpreter(detail::PacketImpl * impl, iterator b, iterator e,
+                          PacketInterpreterBase::ptr before);
 
         static ptr create(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
         static ptr create(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
+        static ptr create(detail::PacketImpl * impl, iterator b, iterator e,
+                          PacketInterpreterBase::ptr before);
 
         // PacketType access
 
@@ -360,6 +371,12 @@ namespace senf {
                                                             senf::NoInit_t) 
                 const;
 
+            virtual PacketInterpreterBase::ptr createInsertBefore(PacketInterpreterBase::ptr packet) 
+                const;
+            virtual PacketInterpreterBase::ptr createInsertBefore(PacketInterpreterBase::ptr packet,
+                                                                  senf::NoInit_t)
+                const;
+
             // Parse next packet in chain
 
             virtual PacketInterpreterBase::ptr parseNext(PacketInterpreterBase::ptr packet) 
index 0afb7bb..7d796c9 100644 (file)
@@ -208,6 +208,13 @@ SENF_AUTO_UNIT_TEST(packetInterpreter)
                 p,senf::noinit));
 
         BOOST_CHECK_EQUAL( p3->data().size(), 10u );
+
+        senf::PacketInterpreter<OtherPacket>::ptr p4
+            (senf::PacketInterpreter<OtherPacket>::createInsertBefore(p));
+
+        BOOST_CHECK_EQUAL( p->data().size(), 10u );
+        BOOST_CHECK_EQUAL( p4->data().size(), 18u );
+        BOOST_CHECK_EQUAL( p3->data().size(), 18u );
     }
 
 }
@@ -275,11 +282,15 @@ SENF_AUTO_UNIT_TEST(packetInterpreter_factory)
         BOOST_CHECK( ! p->prev()->prev() );
         BOOST_CHECK_EQUAL( p->prev()->data().size(), 12u );
 
-        BOOST_CHECK_EQUAL(
-            factory->createBefore(p,senf::noinit)->data().size(), 4u );
+        BOOST_CHECK_EQUAL( factory->createBefore(p,senf::noinit)->data().size(), 4u );
         BOOST_REQUIRE( p->prev() );
         BOOST_CHECK( ! p->prev()->prev() );
         BOOST_CHECK_EQUAL( p->prev()->data().size(), 4u );
+
+        BOOST_CHECK_EQUAL( factory->createInsertBefore(p,senf::noinit)->data().size(), 4u );
+        BOOST_REQUIRE( p->prev() );
+        BOOST_REQUIRE( p->prev()->prev() );
+        BOOST_CHECK( ! p->prev()->prev()->prev() );
     }
 
     {
index df95156..9801594 100644 (file)
@@ -47,6 +47,11 @@ namespace test {
                                                          PacketInterpreterBase::Prepend_t)
             { return PacketInterpreter<T>::create(impl,b,e,PacketInterpreterBase::Prepend); }
 
+        template <class T>
+        static typename PacketInterpreter<T>::ptr create(PacketImpl * impl, iterator b, iterator e,
+                                                         PacketInterpreterBase::ptr before)
+            { return PacketInterpreter<T>::create(impl,b,e,before); }
+
         static PacketImpl * impl(PacketInterpreterBase::ptr p)
             { return &p->impl(); }
     };