Browse Source

[2053] Add toText() method to dns::LabelSequence

Mukund Sivaraman 13 years ago
parent
commit
0bebde9e25

+ 5 - 0
src/lib/dns/labelsequence.cc

@@ -112,5 +112,10 @@ LabelSequence::getHash(bool case_sensitive) const {
     return (hash_val);
 }
 
+std::string
+LabelSequence::toText() const {
+    return (name_.toText(!isAbsolute(), first_label_, last_label_));
+}
+
 } // end namespace dns
 } // end namespace isc

+ 16 - 0
src/lib/dns/labelsequence.h

@@ -123,6 +123,22 @@ public:
     /// \return The number of labels
     size_t getLabelCount() const { return (last_label_ - first_label_); }
 
+    /// \brief Convert the LabelSequence to a string.
+    ///
+    /// This method returns a <code>std::string</code> object representing the
+    /// LabelSequence as a string.  The returned string ends with a dot
+    /// '.' if the label sequence is absolute.
+    ///
+    /// This function assumes the underlying name is in proper
+    /// uncompressed wire format.  If it finds an unexpected label
+    /// character including compression pointer, an exception of class
+    /// \c BadLabelType will be thrown.  In addition, if resource
+    /// allocation for the result string fails, a corresponding standard
+    /// exception will be thrown.
+    //
+    /// \return a string representation of the <code>LabelSequence</code>.
+    std::string toText() const;
+
     /// \brief Returns the original Name object associated with this
     ///        LabelSequence
     ///

+ 25 - 2
src/lib/dns/name.cc

@@ -427,7 +427,15 @@ Name::toWire(AbstractMessageRenderer& renderer) const {
 }
 
 std::string
-Name::toText(bool omit_final_dot) const {
+Name::toText(bool omit_final_dot,
+             unsigned int first_label,
+             unsigned int last_label) const {
+    if ((first_label > labelcount_) ||
+        (last_label > labelcount_) ||
+        (first_label > last_label)) {
+        isc_throw(BadValue, "Bad first label indices were passed");
+    }
+
     if (length_ == 1) {
         //
         // Special handling for the root label.  We ignore omit_final_dot.
@@ -438,7 +446,7 @@ Name::toText(bool omit_final_dot) const {
 
     NameString::const_iterator np = ndata_.begin();
     NameString::const_iterator np_end = ndata_.end();
-    unsigned int labels = labelcount_; // use for integrity check
+    unsigned int labels = last_label - first_label; // use for integrity check
     // init with an impossible value to catch error cases in the end:
     unsigned int count = MAX_LABELLEN + 1;
 
@@ -447,6 +455,11 @@ Name::toText(bool omit_final_dot) const {
     std::string result;
     result.reserve(length_);
 
+    for (unsigned int i = 0; i < first_label; i++) {
+        count = *np++;
+        np += count;
+    }
+
     while (np != np_end) {
         labels--;
         count = *np++;
@@ -458,6 +471,11 @@ Name::toText(bool omit_final_dot) const {
             break;
         }
             
+        if (labels == 0) {
+            count = 0;
+            break;
+        }
+
         if (count <= MAX_LABELLEN) {
             assert(np_end - np >= count);
 
@@ -505,6 +523,11 @@ Name::toText(bool omit_final_dot) const {
     return (result);
 }
 
+std::string
+Name::toText(bool omit_final_dot) const {
+    return toText(omit_final_dot, 0, labelcount_);
+}
+
 NameComparisonResult
 Name::compare(const Name& other) const {
     // Determine the relative ordering under the DNSSEC order relation of

+ 27 - 0
src/lib/dns/name.h

@@ -359,6 +359,33 @@ public:
     /// \return a string representation of the <code>Name</code>.
     std::string toText(bool omit_final_dot = false) const;
 
+private:
+    /// \brief Convert the Name to a string.
+    ///
+    /// This method returns a <code>std::string</code> object representing the
+    /// Name as a string.  Unless <code>omit_final_dot</code> is
+    /// <code>true</code>, the returned string ends with a dot '.'; the default
+    /// is <code>false</code>.  The default value of this parameter is
+    /// <code>true</code>; converted names will have a trailing dot by default.
+    ///
+    /// 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 BadLabelType will be thrown.
+    /// In addition, if resource allocation for the result string fails, a
+    /// corresponding standard exception will be thrown.
+    ///
+    /// This function only returns a string for the range of labels
+    /// between <code>first_label</code> and <code>last_label</code>.
+    //
+    /// \param omit_final_dot whether to omit the trailing dot in the output.
+    /// \param first_label the first label which should be contained in the result.
+    /// \param last_label the last label which should be contained in the result.
+    /// \return a string representation of the <code>Name</code>.
+    std::string toText(bool omit_final_dot,
+                       unsigned int first_label,
+                       unsigned int last_label) const;
+
+public:
     /// \brief Render the <code>Name</code> in the wire format with compression.
     ///
     /// This method dumps the Name in wire format with help of \c renderer,

+ 21 - 0
src/lib/dns/tests/labelsequence_unittest.cc

@@ -292,6 +292,27 @@ TEST_F(LabelSequenceTest, isAbsolute) {
     ASSERT_TRUE(ls3.isAbsolute());
 }
 
+TEST_F(LabelSequenceTest, toText) {
+    EXPECT_EQ("example.org.", ls1.toText());
+    ls1.stripLeft(1);
+    EXPECT_EQ("org.", ls1.toText());
+    ls1.stripLeft(1);
+    EXPECT_EQ(".", ls1.toText());
+
+    EXPECT_EQ("example.com.", ls2.toText());
+    ls2.stripRight(1);
+    EXPECT_EQ("example", ls2.toText());
+    ls2.stripRight(1);
+    EXPECT_EQ("", ls2.toText());
+
+    EXPECT_EQ("foo.example.org.bar.", ls8.toText());
+    ls8.stripRight(2);
+    EXPECT_EQ("foo.example", ls8.toText());
+
+    EXPECT_EQ(".", ls7.toText());
+    EXPECT_THROW(ls7.stripLeft(1), isc::OutOfRange);
+}
+
 // The following are test data used in the getHash test below.  Normally
 // we use example/documentation domain names for testing, but in this case
 // we'd specifically like to use more realistic data, and are intentionally