[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