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&
/// \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
#include <dns/name.h>
#include <dns/name_internal.h>
#include <dns/messagerenderer.h>
+#include <dns/labelsequence.h>
using namespace std;
using namespace isc::util;
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
/// \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,