[svn] commit: r366 - in /branches/jinmei-dnsmessageapi/src/lib/dns/cpp: name.cc name.h name_unittest.cc

BIND 10 source code commits bind10-changes at lists.isc.org
Tue Dec 15 05:00:33 UTC 2009


Author: jinmei
Date: Tue Dec 15 05:00:32 2009
New Revision: 366

Log:
added Name::split() method.

Modified:
    branches/jinmei-dnsmessageapi/src/lib/dns/cpp/name.cc
    branches/jinmei-dnsmessageapi/src/lib/dns/cpp/name.h
    branches/jinmei-dnsmessageapi/src/lib/dns/cpp/name_unittest.cc

Modified: branches/jinmei-dnsmessageapi/src/lib/dns/cpp/name.cc
==============================================================================
--- branches/jinmei-dnsmessageapi/src/lib/dns/cpp/name.cc (original)
+++ branches/jinmei-dnsmessageapi/src/lib/dns/cpp/name.cc Tue Dec 15 05:00:32 2009
@@ -17,6 +17,7 @@
 #include <cctype>
 #include <cassert>
 #include <iterator>
+#include <functional>
 
 #include "buffer.h"
 #include "name.h"
@@ -525,10 +526,12 @@
 }
 
 namespace {                     // hide the local class
+///
+/// A helper functor class to add an additional offset to an offset vector.
+///
 struct OffsetAdjuster : public std::binary_function<unsigned char,
-                                                    unsigned int,
-                                                    unsigned char> {
-    unsigned char operator()(unsigned char ch, unsigned int offset) const
+                                                    int, unsigned char> {
+    unsigned char operator()(unsigned char ch, int offset) const
     {
         return (ch + offset);
     }
@@ -554,6 +557,11 @@
     assert(retname.ndata_.size() == length);
     retname.length_ = length;
 
+    //
+    // Setup the offsets vector.  Copy the offsets of this (prefix) name,
+    // excluding that for the trailing dot, and append the offsets of the
+    // suffix name with the additional offset of the length of the prefix.
+    //
     unsigned int labels = this->labels_ + suffix.labels_ - 1;
     assert(labels <= Name::MAX_LABELS);
     retname.offsets_.reserve(labels);
@@ -568,12 +576,38 @@
     return (retname);
 }
 
+Name
+Name::split(unsigned int first, unsigned int n) const
+{
+    if (n == 0 || first + n > labels_) {
+        dns_throw(OutOfRange, "Name::split: invalid split range");
+    }
+
+    Name retname;
+    unsigned int newlabels = (first + n == labels_) ? n : n + 1;
+
+    retname.offsets_.reserve(newlabels);
+    transform(offsets_.begin() + first, offsets_.begin() + first + newlabels,
+              back_inserter(retname.offsets_),
+              bind2nd(OffsetAdjuster(), -offsets_[first]));
+
+    retname.ndata_.reserve(retname.offsets_.back() + 1);
+    retname.ndata_.assign(ndata_, offsets_[first], retname.offsets_.back());
+    // add a trailing dot
+    retname.ndata_.push_back(0);
+
+    retname.length_ = retname.ndata_.size();
+    retname.labels_ = retname.offsets_.size();
+    assert(retname.labels_ == newlabels);
+
+    return (retname);
+}
+}
+}
+
 std::ostream&
-operator<<(std::ostream& os, const Name& name)
+operator<<(std::ostream& os, const isc::dns::Name& name)
 {
     os << name.toText();
     return (os);
 }
-
-}
-}

Modified: branches/jinmei-dnsmessageapi/src/lib/dns/cpp/name.h
==============================================================================
--- branches/jinmei-dnsmessageapi/src/lib/dns/cpp/name.h (original)
+++ branches/jinmei-dnsmessageapi/src/lib/dns/cpp/name.h Tue Dec 15 05:00:32 2009
@@ -244,7 +244,7 @@
     ///
     /// This function assumes the name is in proper uncompressed wire format.
     /// If it finds an unexpected label character including compression pointer,
-    /// an exception of class \c isc::dns::BadLabelType will be thrown.
+    /// an exception of class \c BadLabelType will be thrown.
     //
     /// \param omit_final_dot whether to omit the trailing dot in the output.
     /// \return a string representation of the <code>Name</code>.
@@ -361,19 +361,43 @@
     //@{
     /// \brief Extract a specified subpart of Name.
     ///
-    /// Note: we may want to have different versions (signatures) of this
-    /// method.  For example, we want to split the Name based on a given suffix
-    /// name.
-    ///
-    /// \param first the start position of the extracted name
-    /// \param n number of labels of the extracted name
-    /// \return a new Name object based on the Name containing <code>n</code>
+    /// <code>name.split(first, n)</code> constructs a new name starting from
+    /// the <code>first</code>-th label of the \c name, and subsequent \c n
+    /// labels including the \c first one.  Since names in this current
+    /// implementation are always "absolute", if the specified range doesn't
+    /// contain the trailing dot of the original \c name, then a dot will be
+    /// appended to the resulting name.  As a result, the number of labels
+    /// will be <code>n + 1</code>, rather than \c n.  For example,
+    /// when \c n is <code>Name("www.example.com")</code>,
+    /// both <code>n.split(1, 2)</code> and <code>n.split(1, 3)</code>
+    /// will produce a name corresponding to "example.com.", which has 3 labels.
+    /// Note also that labels are counted from 0, and so <code>first = 1</code>
+    /// in this example specified the label "example", not "www".
+    ///
+    /// Parameter \c n must be larger than 0, and the range specified by
+    /// \c first and \c n must not exceed the valid range of the original name;
+    /// otherwise, an exception of class \c OutOfRange will be thrown.
+    ///
+    /// Note to developers: we may want to have different versions (signatures)
+    /// of this method.  For example, we want to split the Name based on a given
+    /// suffix name.
+    ///
+    /// \param first The start position (in labels) of the extracted name
+    /// \param n Number of labels of the extracted name
+    /// \return A new Name object based on the Name containing <code>n</code>
     /// labels including and following the <code>first</code> label.  
     Name split(unsigned int first, unsigned int n) const;
 
-    /// \brief Concatenate two names
-    ///
-    /// This method appends \c suffix to \c this Name.
+    /// \brief Concatenate two names.
+    ///
+    /// This method appends \c suffix to \c this Name.  The trailing dot of
+    /// \c this Name will be removed.  For example, if \c this is "www."
+    /// and \c suffix is "example.com.", a successful return of this method
+    /// will be a name of "www.example.com."
+    ///
+    ///The resulting length of the concatenated name must not exceed
+    /// \c Name::MAX_WIRE; otherwise an exception of class
+    /// \c TooLongName will be thrown.
     ///
     /// \param suffix a Name object to be appended to the Name.
     /// \return a new Name object concatenating \c suffix to \c this Name.
@@ -416,10 +440,10 @@
 
     void fromString(const std::string& namestr);
 };
-
-std::ostream& operator<<(std::ostream& os, const Name& name);
 }
 }
+
+std::ostream& operator<<(std::ostream& os, const isc::dns::Name& name);
 #endif // __NAME_H
 
 // Local Variables: 

Modified: branches/jinmei-dnsmessageapi/src/lib/dns/cpp/name_unittest.cc
==============================================================================
--- branches/jinmei-dnsmessageapi/src/lib/dns/cpp/name_unittest.cc (original)
+++ branches/jinmei-dnsmessageapi/src/lib/dns/cpp/name_unittest.cc Tue Dec 15 05:00:32 2009
@@ -72,11 +72,11 @@
 
     std::vector<std::string>::const_iterator it;
     for (it = strnames.begin(); it != strnames.end(); ++it) {
-        EXPECT_EQ(true, example_name == Name(*it));
+        EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name, Name(*it));
     }
 
     // root names
-    EXPECT_EQ(true, Name("@") == Name("."));
+    EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, Name("@"), Name("."));
 
     // downcase
     EXPECT_EQ(Name("Www.eXample.coM", true).toText(), example_name.toText());
@@ -149,8 +149,9 @@
     // test cases derived from BIND9 tests.
     //
     // normal case with a compression pointer
-    EXPECT_EQ(true, nameFactoryFromWire("testdata/name_fromWire1", 25) ==
-              Name("vix.com"));
+    EXPECT_PRED_FORMAT2(UnitTestUtil::matchName,
+                        nameFactoryFromWire("testdata/name_fromWire1", 25),
+                        Name("vix.com"));
     // bogus label character (looks like a local compression pointer)
     EXPECT_THROW(nameFactoryFromWire("testdata/name_fromWire2", 25),
                  isc::dns::BadLabelType);
@@ -174,8 +175,9 @@
     EXPECT_THROW(nameFactoryFromWire("testdata/name_fromWire7", 25),
                  isc::dns::IncompleteName);
     // many hops of compression but valid.  should succeed.
-    EXPECT_EQ(true, nameFactoryFromWire("testdata/name_fromWire8", 383) ==
-              Name("vix.com"));
+    EXPECT_PRED_FORMAT2(UnitTestUtil::matchName,
+                        nameFactoryFromWire("testdata/name_fromWire8", 383),
+                        Name("vix.com"));
 
     //
     // Additional test cases
@@ -307,5 +309,31 @@
 
     result = example_name.compare(example_name.concatenate(Name(".")));
     EXPECT_EQ(NameComparisonResult::EQUAL, result.getRelation());
-}
-}
+
+    // concatenating two valid names would result in too long a name.
+    Name n1("123456789.123456789.123456789.123456789.123456789."
+            "123456789.123456789.123456789.123456789.123456789."
+            "123456789.123456789.123456789.123456789.123456789.");
+    Name n2("123456789.123456789.123456789.123456789.123456789."
+            "123456789.123456789.123456789.123456789.123456789."
+            "1234.");
+    EXPECT_THROW(n1.concatenate(n2), isc::dns::TooLongName);
+}
+
+TEST_F(NameTest, split)
+{
+    // normal cases with or without explicitly specifying the trailing dot.
+    EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(1, 2),
+                        Name("example.com."));
+    EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(1, 3),
+                        Name("example.com."));
+    // edge cases: only the first or last label.
+    EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(0, 1),
+                        Name("www."));
+    EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(3, 1),
+                        Name("."));
+    // invalid range: an exception should be thrown.
+    EXPECT_THROW(example_name.split(1, 0), isc::dns::OutOfRange);
+    EXPECT_THROW(example_name.split(2, 3), isc::dns::OutOfRange);
+}
+}




More information about the bind10-changes mailing list