From: Mukund Sivaraman Date: Mon, 2 Jul 2012 00:47:49 +0000 (+0530) Subject: [2053] Move toText() implementation from Name to LabelSequence class X-Git-Tag: trac2351_base~209 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=efb3f3344d624ca830d07798948e01f07e118820;p=thirdparty%2Fkea.git [2053] Move toText() implementation from Name to LabelSequence class --- diff --git a/src/lib/dns/labelsequence.cc b/src/lib/dns/labelsequence.cc index 026add3bdf..1e18378424 100644 --- a/src/lib/dns/labelsequence.cc +++ b/src/lib/dns/labelsequence.cc @@ -112,9 +112,104 @@ LabelSequence::getHash(bool case_sensitive) const { return (hash_val); } +std::string +LabelSequence::toText(bool omit_final_dot) const { + if ((first_label_ > name_.labelcount_) || + (last_label_ > name_.labelcount_) || + (first_label_ > last_label_)) { + isc_throw(BadValue, "Bad first label indices were passed"); + } + + if (name_.length_ == 1) { + // + // Special handling for the root label. We ignore omit_final_dot. + // + assert(name_.labelcount_ == 1 && name_.ndata_[0] == '\0'); + return ("."); + } + + Name::NameString::const_iterator np = name_.ndata_.begin(); + Name::NameString::const_iterator np_end = name_.ndata_.end(); + 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 = Name::MAX_LABELLEN + 1; + + // result string: it will roughly have the same length as the wire format + // name data. reserve that length to minimize reallocation. + std::string result; + result.reserve(name_.length_); + + for (unsigned int i = 0; i < first_label_; i++) { + count = *np++; + np += count; + } + + while (np != np_end) { + labels--; + count = *np++; + + if (count == 0) { + if (!omit_final_dot) { + result.push_back('.'); + } + break; + } + + if (labels == 0) { + count = 0; + break; + } + + if (count <= Name::MAX_LABELLEN) { + assert(np_end - np >= count); + + if (!result.empty()) { + // just after a non-empty label. add a separating dot. + result.push_back('.'); + } + + while (count-- > 0) { + uint8_t c = *np++; + switch (c) { + case 0x22: // '"' + case 0x28: // '(' + case 0x29: // ')' + case 0x2E: // '.' + case 0x3B: // ';' + case 0x5C: // '\\' + // Special modifiers in zone files. + case 0x40: // '@' + case 0x24: // '$' + result.push_back('\\'); + result.push_back(c); + break; + default: + if (c > 0x20 && c < 0x7f) { + // append printable characters intact + result.push_back(c); + } else { + // encode non-printable characters in the form of \DDD + result.push_back(0x5c); + result.push_back(0x30 + ((c / 100) % 10)); + result.push_back(0x30 + ((c / 10) % 10)); + result.push_back(0x30 + (c % 10)); + } + } + } + } else { + isc_throw(BadLabelType, "unknown label type in name data"); + } + } + + assert(labels == 0); + assert(count == 0); // a valid name must end with a 'dot'. + + return (result); +} + std::string LabelSequence::toText() const { - return (name_.toText(!isAbsolute(), first_label_, last_label_)); + return (toText(!isAbsolute())); } std::ostream& diff --git a/src/lib/dns/labelsequence.h b/src/lib/dns/labelsequence.h index 9928a10e2f..374e6c4978 100644 --- a/src/lib/dns/labelsequence.h +++ b/src/lib/dns/labelsequence.h @@ -123,6 +123,23 @@ 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 std::string object representing the + /// LabelSequence as a string. The returned string ends with a dot + /// '.' if omit_final_dot is false. + /// + /// 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. + // + /// \param omit_final_dot whether to omit the trailing dot in the output. + /// \return a string representation of the LabelSequence. + std::string toText(bool omit_final_dot) const; + /// \brief Convert the LabelSequence to a string. /// /// This method returns a std::string object representing the diff --git a/src/lib/dns/name.cc b/src/lib/dns/name.cc index 9eb6e9249f..37c35f10f5 100644 --- a/src/lib/dns/name.cc +++ b/src/lib/dns/name.cc @@ -25,6 +25,7 @@ #include #include #include +#include using namespace std; using namespace isc::util; @@ -426,106 +427,10 @@ Name::toWire(AbstractMessageRenderer& renderer) const { renderer.writeName(*this); } -std::string -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. - // - assert(labelcount_ == 1 && ndata_[0] == '\0'); - return ("."); - } - - NameString::const_iterator np = ndata_.begin(); - NameString::const_iterator np_end = ndata_.end(); - 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; - - // result string: it will roughly have the same length as the wire format - // name data. reserve that length to minimize reallocation. - 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++; - - if (count == 0) { - if (!omit_final_dot) { - result.push_back('.'); - } - break; - } - - if (labels == 0) { - count = 0; - break; - } - - if (count <= MAX_LABELLEN) { - assert(np_end - np >= count); - - if (!result.empty()) { - // just after a non-empty label. add a separating dot. - result.push_back('.'); - } - - while (count-- > 0) { - uint8_t c = *np++; - switch (c) { - case 0x22: // '"' - case 0x28: // '(' - case 0x29: // ')' - case 0x2E: // '.' - case 0x3B: // ';' - case 0x5C: // '\\' - // Special modifiers in zone files. - case 0x40: // '@' - case 0x24: // '$' - result.push_back('\\'); - result.push_back(c); - break; - default: - if (c > 0x20 && c < 0x7f) { - // append printable characters intact - result.push_back(c); - } else { - // encode non-printable characters in the form of \DDD - result.push_back(0x5c); - result.push_back(0x30 + ((c / 100) % 10)); - result.push_back(0x30 + ((c / 10) % 10)); - result.push_back(0x30 + (c % 10)); - } - } - } - } else { - isc_throw(BadLabelType, "unknown label type in name data"); - } - } - - assert(labels == 0); - assert(count == 0); // a valid name must end with a 'dot'. - - return (result); -} - std::string Name::toText(bool omit_final_dot) const { - return toText(omit_final_dot, 0, labelcount_); + LabelSequence ls(*this); + return (ls.toText(omit_final_dot)); } NameComparisonResult diff --git a/src/lib/dns/name.h b/src/lib/dns/name.h index e71359fdc0..41024fcaa3 100644 --- a/src/lib/dns/name.h +++ b/src/lib/dns/name.h @@ -359,33 +359,6 @@ public: /// \return a string representation of the Name. std::string toText(bool omit_final_dot = false) const; -private: - /// \brief Convert the Name to a string. - /// - /// This method returns a std::string object representing the - /// Name as a string. Unless omit_final_dot is - /// true, the returned string ends with a dot '.'; the default - /// is false. The default value of this parameter is - /// true; 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 first_label and last_label. - // - /// \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 Name. - std::string toText(bool omit_final_dot, - unsigned int first_label, - unsigned int last_label) const; - -public: /// \brief Render the Name in the wire format with compression. /// /// This method dumps the Name in wire format with help of \c renderer,