Commit efb3f334 authored by Mukund Sivaraman's avatar Mukund Sivaraman
Browse files

[2053] Move toText() implementation from Name to LabelSequence class

parent fb5902b0
......@@ -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&
......
......@@ -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 <code>std::string</code> object representing the
/// LabelSequence as a string. The returned string ends with a dot
/// '.' if <code>omit_final_dot</code> is <code>false</code>.
///
/// 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 <code>LabelSequence</code>.
std::string toText(bool omit_final_dot) const;
/// \brief Convert the LabelSequence to a string.
///
/// This method returns a <code>std::string</code> object representing the
......
......@@ -25,6 +25,7 @@
#include <dns/name.h>
#include <dns/name_internal.h>
#include <dns/messagerenderer.h>
#include <dns/labelsequence.h>
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
......
......@@ -359,33 +359,6 @@ 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,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment