Packets: (Re-)add (consistent) 'nothrow' variants of packet traversal functions
g0dil [Thu, 17 Jan 2008 14:45:35 +0000 (14:45 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@618 270642c3-0616-0410-b53a-bc976706d245

Packets/DefaultBundle/EthernetPacket.cc
Packets/DefaultBundle/IPv4Packet.cc
Packets/DefaultBundle/UDPPacket.cc
Packets/Packet.cc
Packets/Packet.cci
Packets/Packet.ct
Packets/Packet.cti
Packets/Packet.hh
Packets/Packet.test.cc

index ede6558..9926efc 100644 (file)
@@ -72,7 +72,7 @@ prefix_ senf::PacketInterpreterBase::factory_t senf::EthernetPacketType::nextPac
 
 prefix_ void senf::EthernetPacketType::finalize(packet p)
 {
-    optional_registry_key_t k = key(p.next());
+    optional_registry_key_t k = key(p.next(nothrow));
     if (k)
         p->type_length() << k;
     else
@@ -94,7 +94,7 @@ prefix_ void senf::EthVLanPacketType::dump(packet p, std::ostream & os)
 
 prefix_ void senf::EthVLanPacketType::finalize(packet p)
 {
-    p->type() << key(p.next());
+    p->type() << key(p.next(nothrow));
 }
 
 
index f534aa1..69ed501 100644 (file)
@@ -88,7 +88,7 @@ prefix_ void senf::IPv4PacketType::dump(packet p, std::ostream & os)
 prefix_ void senf::IPv4PacketType::finalize(packet p)
 {
     p->length()   << p.size();
-    p->protocol() << key(p.next());
+    p->protocol() << key(p.next(nothrow));
     p->checksum() << p->calcChecksum();
 }
 
index 8d4a850..bc204b3 100644 (file)
@@ -54,7 +54,7 @@ prefix_ boost::uint16_t senf::UDPPacketParser::calcChecksum()
     summer.feed( i()+checksum_offset+2, data().end() );
     
     // Now on to the awkward part: the IP pseudo header
-    IPv4Packet ipv4 (packet().rfind<IPv4Packet>());
+    IPv4Packet ipv4 (packet().rfind<IPv4Packet>(nothrow));
     if (ipv4) {
         // Pseudo header defined in RFC768
         summer.feed( ipv4->source().i(), 
@@ -70,7 +70,7 @@ prefix_ boost::uint16_t senf::UDPPacketParser::calcChecksum()
     } 
     else {
         // Pseudo header defined in RFC2460
-        IPv6Packet ipv6 (packet().rfind<IPv6Packet>());
+        IPv6Packet ipv6 (packet().rfind<IPv6Packet>(nothrow));
         if (ipv6) {
             summer.feed( ipv6->source().i(), 
                          ipv6->source().i() + IPv6Packet::Parser::source_t::fixed_bytes );
index bd3ce57..b770e93 100644 (file)
@@ -50,10 +50,10 @@ prefix_ senf::Packet senf::Packet::checkLast()
     const
 {
     Packet p (*this);
-    Packet n (p.next());
+    Packet n (p.next(nothrow));
     while (n) {
         p = n;
-        n = p.next();
+        n = p.next(nothrow);
     }
     return p;
 }
index e29f050..ea4f549 100644 (file)
@@ -47,6 +47,14 @@ prefix_ senf::Packet senf::Packet::clone()
 prefix_ senf::Packet senf::Packet::next()
     const
 {
+    Packet p (next(nothrow));
+    if (!p) throw InvalidPacketChainException();
+    return p;
+}
+
+prefix_ senf::Packet senf::Packet::next(NoThrow_t)
+    const
+{
     PacketInterpreterBase::ptr p (ptr()->next());
     return !p && ptr()->nextPacketRange() ? checkNext() : Packet(p);
 }
@@ -54,6 +62,14 @@ prefix_ senf::Packet senf::Packet::next()
 prefix_ senf::Packet senf::Packet::prev()
     const
 {
+    Packet p (prev(nothrow));
+    if (!p) throw InvalidPacketChainException();
+    return p;
+}
+
+prefix_ senf::Packet senf::Packet::prev(NoThrow_t)
+    const
+{
     return Packet(ptr()->prev());
 }
 
@@ -67,7 +83,7 @@ prefix_ senf::Packet senf::Packet::last()
     const
 {
     Packet p (ptr()->last());
-    return p.next() ? checkLast() : p;
+    return p.next(nothrow) ? checkLast() : p;
 }
 
 prefix_ senf::Packet senf::Packet::parseNextAs(factory_t factory)
index 48b83fc..7c556d7 100644 (file)
 // senf::Packet
 
 template <class OtherPacket>
-prefix_ OtherPacket senf::Packet::find()
+prefix_ OtherPacket senf::Packet::find(NoThrow_t)
     const
 {
     Packet p (*this);
     while (p && ! p.is<OtherPacket>()) 
-        p = p.next();
+        p = p.next(nothrow);
     if (p) 
         return p.as<OtherPacket>();
     else
@@ -47,12 +47,12 @@ prefix_ OtherPacket senf::Packet::find()
 }
 
 template <class OtherPacket>
-prefix_ OtherPacket senf::Packet::rfind()
+prefix_ OtherPacket senf::Packet::rfind(NoThrow_t)
     const
 {
     Packet p (*this);
     while (p && ! p.is<OtherPacket>()) 
-        p = p.prev();
+        p = p.prev(nothrow);
     if (p) 
         return p.as<OtherPacket>();
     else
index ed032da..5f67ccb 100644 (file)
@@ -69,16 +69,48 @@ template <class OtherPacket>
 prefix_ OtherPacket senf::Packet::next()
     const
 {
-    Packet p (next())
-    return p ? p.as<OtherPacket>() : OtherPacket();
+    return next().as<OtherPacket>();
+}
+
+template <class OtherPacket>
+prefix_ OtherPacket senf::Packet::next(NoThrow_t)
+    const
+{
+    Packet p (next(nothrow));
+    return p && p.is<OtherPacket>() ? p.as<OtherPacket>() : OtherPacket();
+}
+
+template <class OtherPacket>
+prefix_ OtherPacket senf::Packet::find()
+    const
+{
+    OtherPacket p (find<OtherPacket>(nothrow));
+    if (!p) throw InvalidPacketChainException();
+    return p;
 }
 
 template <class OtherPacket>
 prefix_ OtherPacket senf::Packet::prev()
     const
 {
-    Packet p (prev());
-    return p ? p.as<OtherPacket>() : OtherPacket();
+    return prev().as<OtherPacket>();
+}
+
+template <class OtherPacket>
+prefix_ OtherPacket senf::Packet::prev(NoThrow_t)
+    const
+{
+    Packet p (prev(nothrow));
+    return p && p.is<OtherPacket>() ? p.as<OtherPacket>() : OtherPacket();
+}
+
+template <class OtherPacket>
+prefix_ OtherPacket senf::Packet::rfind()
+    const
+{
+    OtherPacket p (rfind<OtherPacket>(nothrow));
+    if (!p) throw InvalidPacketChainException();
+    return p;
 }
 
 template <class OtherPacket>
index 9855adb..4fc2e1e 100644 (file)
@@ -188,33 +188,63 @@ namespace senf {
                                         ///< Get next packet in chain
                                         /**< \returns in - valid() packet, 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
                                              \returns in - valid() packet, 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 */
         template <class OtherPacket> OtherPacket find() 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. */
+        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(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
                                              \returns in - valid() packet, 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.
                                              \returns in - valid() packet, 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;
index d738f60..e79f172 100644 (file)
@@ -88,7 +88,7 @@ namespace {
                << "length: " << p->length() << "\n";
         }
         static void finalize(packet p) {
-            if (p.next())
+            if (p.next(senf::nothrow))
                 p->type() = senf::PacketRegistry<RegTag>::key(p.next());
             else
                 p->type() = -1;
@@ -113,8 +113,8 @@ BOOST_AUTO_UNIT_TEST(packet)
 
     BOOST_REQUIRE( packet );
     BOOST_CHECK( packet.next() );
-    BOOST_CHECK( ! packet.next().next() );
-    BOOST_CHECK( ! packet.prev() );
+    BOOST_CHECK( ! packet.next().next(senf::nothrow) );
+    BOOST_CHECK( ! packet.prev(senf::nothrow) );
     BOOST_CHECK( packet.next().prev() == packet );
     BOOST_CHECK( packet.next() != packet );
     BOOST_CHECK_EQUAL( packet.size(), 12u );
@@ -170,7 +170,7 @@ BOOST_AUTO_UNIT_TEST(packet)
     BOOST_CHECK_EQUAL( packet.next().size(), 11u );
     BOOST_REQUIRE( packet.next().next() );
     BOOST_CHECK( packet.next().next().is<FooPacket>() );
-    BOOST_CHECK( ! packet.next().next().next() );
+    BOOST_CHECK( ! packet.next().next().next(senf::nothrow) );
     BOOST_CHECK_EQUAL( packet.next().next().data()[0], 0x81u );
 
     BOOST_CHECK( packet.first().find<FooPacket>() == packet );