[svn] commit: r393 - in /branches/jinmei-dnsmessageapi/src/lib/dns/cpp: name.cc name.h
BIND 10 source code commits
bind10-changes at lists.isc.org
Sat Dec 19 04:50:27 UTC 2009
Author: jinmei
Date: Sat Dec 19 04:50:27 2009
New Revision: 393
Log:
added more description about the implementation
Modified:
branches/jinmei-dnsmessageapi/src/lib/dns/cpp/name.cc
branches/jinmei-dnsmessageapi/src/lib/dns/cpp/name.h
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 Sat Dec 19 04:50:27 2009
@@ -67,14 +67,20 @@
}
namespace {
+///
+/// Textual name parser states.
+///
typedef enum {
- ft_init = 0,
- ft_start,
- ft_ordinary,
- ft_initialescape,
- ft_escape,
- ft_escdecimal,
- ft_at
+ ft_init = 0, // begin of the name
+ ft_start, // begin of a label
+ ft_ordinary, // parsing an ordinary label
+ ft_initialescape, // just found '\'
+ ft_escape, // begin of handling a '\'-escaped sequence
+ ft_escdecimal, // parsing a '\DDD' octet.
+
+ // Unused at this moment. We'll revisit this when we support master file
+ // parser where @ is used to mean an origin name.
+ ft_at
} ft_state;
}
@@ -133,7 +139,7 @@
}
// FALLTHROUGH
- case ft_start: // begin of a label
+ case ft_start:
ndata.push_back(0); // placeholder for the label length field
count = 0;
if (c == '\\') {
@@ -143,7 +149,7 @@
state = ft_ordinary;
assert(ndata.size() < Name::MAX_WIRE);
// FALLTHROUGH
- case ft_ordinary: // parsing a normal label
+ case ft_ordinary:
if (c == '.') {
if (count == 0) {
dns_throw(EmptyLabel, "duplicate period");
@@ -164,7 +170,7 @@
ndata.push_back(downcase ? maptolower[c] : c);
}
break;
- case ft_initialescape: // just found '\'
+ case ft_initialescape:
if (c == '[') {
// This looks like a bitstring label, which was deprecated.
// Intentionally drop it.
@@ -172,7 +178,7 @@
}
state = ft_escape;
// FALLTHROUGH
- case ft_escape: // begin of handling a '\'-escaped sequence
+ case ft_escape:
if (!isdigit(c & 0xff)) {
if (++count > MAX_LABELLEN) {
dns_throw(TooLongLabel, "label is too long");
@@ -185,7 +191,7 @@
value = 0;
state = ft_escdecimal;
// FALLTHROUGH
- case ft_escdecimal: // parsing a '\DDD' octet.
+ case ft_escdecimal:
if (!isdigit(c & 0xff)) {
dns_throw(BadEscape, "mixture of escaped digit and non-digit");
}
@@ -234,11 +240,16 @@
offsets_.assign(offsets.begin(), offsets.end());
}
+namespace {
+///
+/// Wire-format name parser states.
+///
typedef enum {
- fw_start = 0,
- fw_ordinary,
- fw_newcurrent
+ fw_start = 0, // beginning of a label
+ fw_ordinary, // inside an ordinary (non compressed) label
+ fw_newcurrent // beginning of a compression pointer
} fw_state;
+}
Name::Name(InputBuffer& buffer, bool downcase)
{
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 Sat Dec 19 04:50:27 2009
@@ -91,8 +91,11 @@
};
///
-/// \brief A standard DNS module exception that is thrown if the wire-format
-/// name is not a complete domain name.
+/// \brief A standard DNS module exception that is thrown if the name parser
+/// finds the input (string or wire-format data) is incomplete.
+///
+/// An attempt of constructing a name from an empty string will trigger this
+/// exception.
///
class IncompleteName : public Exception {
public:
@@ -164,11 +167,34 @@
};
///
-/// The \c Name class encapsulates DNS names. It provides interfaces
-/// to construct a name from string or wire-format data, transform a name into
-/// a string or wire-format data, compare two names, get access to attributes.
-///
-/// Note that while many other DNS APIs introduce an "absolute or relative"
+/// The \c Name class encapsulates DNS names.
+///
+/// It provides interfaces to construct a name from string or wire-format data,
+/// transform a name into a string or wire-format data, compare two names, get
+/// access to various properties of a name, etc.
+///
+/// Notes to developers: Internally, a name object maintains the name data
+/// in wire format as an instance of \c std::string. Since many string
+/// implementations adopt copy-on-write data sharing, we expect this approach
+/// will make copying a name less expensive in typical cases. If this is
+/// found to be a significant performance bottleneck later, we may reconsider
+/// the internal representation or perhaps the API.
+///
+/// A name object also maintains a vector of offsets (\c offsets_ member),
+/// each of which is the offset to a label of the name: The n-th element of
+/// the vector specifies the offset to the n-th label. For example, if the
+/// object represents "www.example.com", the elements of the offsets vector
+/// are 0, 4, 12, and 16. Note that the offset to the trailing dot (16) is
+/// included. In the BIND9 DNS library from which this implementation is
+/// derived, the offsets are optional, probably due to performance
+/// considerations (in fact, offsets can always be calculated from the name
+/// data, and in that sense are redundant). In our implementation, however,
+/// we always build and maintain the offsets. We believe we need more low
+/// level, specialized data structure and interface where we really need to
+/// pursue performance, and would rather keep this generic API and
+/// implementation simpler.
+///
+/// While many other DNS APIs introduce an "absolute or relative"
/// attribute of names as defined in RFC1035, names are always "absolute" in
/// the initial design of this API.
/// In fact, separating absolute and relative would confuse API users
@@ -199,6 +225,12 @@
public:
/// Constructor from a string
///
+ /// If the given string does not represent a valid DNS name, an exception
+ /// of class \c EmptyLabel, \c TooLongLabel, \c BadLabelType, \c BadEscape,
+ /// \c TooLongName, or \c IncompleteName will be thrown.
+ /// In addition, if resource allocation for the new name fails, a
+ /// corresponding standard exception will be thrown.
+ ///
/// \param namestr A string representation of the name to be constructed.
/// \param downcase Whether to convert upper case alphabets to lower case.
explicit Name(const std::string& namestr, bool downcase = false);
@@ -211,6 +243,12 @@
/// The input data may or may not be compressed; if it's compressed, this
/// method will automatically decompress it.
///
+ /// If the given data does not represent a valid DNS name, an exception
+ /// of class \c TooLongName, \c BadLabelType, \c BadPointer, or
+ /// \c IncompleteName will be thrown.
+ /// In addition, if resource allocation for the new name fails, a
+ /// corresponding standard exception will be thrown.
+ ///
/// \param buffer A buffer storing the wire format data.
/// \param downcase Whether to convert upper case alphabets to lower case.
explicit Name(InputBuffer& buffer, bool downcase = false);
@@ -222,6 +260,8 @@
//@{
/// \brief Gets the length of the <code>Name</code> in its wire format.
///
+ /// This method never throws an exception.
+ ///
/// \return the length of the <code>Name</code>
size_t getLength() const { return (length_); }
@@ -229,6 +269,8 @@
///
/// Note that an empty label (corresponding to a trailing '.') is counted
/// as a single label, so the return value of this method must be >0.
+ ///
+ /// This method never throws an exception.
///
/// \return the number of labels
unsigned int getLabels() const { return (labels_); }
@@ -249,6 +291,8 @@
/// 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.
//
/// \param omit_final_dot whether to omit the trailing dot in the output.
/// \return a string representation of the <code>Name</code>.
@@ -260,6 +304,9 @@
/// which encapsulates output buffer and name compression algorithm to
/// render the name.
///
+ /// If resource allocation in rendering process fails, a corresponding
+ /// standard exception will be thrown.
+ ///
/// \param renderer DNS message rendering context that encapsulates the
/// output buffer and name compression information.
void toWire(MessageRenderer& renderer) const;
@@ -267,6 +314,12 @@
/// \brief Render the <code>Name</code> in the wire format without
/// compression.
///
+ /// If resource allocation in rendering process fails, a corresponding
+ /// standard exception will be thrown. This can be avoided by preallocating
+ /// a sufficient size of \c buffer. Specifically, if
+ /// <code>buffer.getCapacity() - buffer.getLength() >= Name::MAX_WIRE</code>
+ /// then this method should not throw an exception.
+ ///
void toWire(OutputBuffer& buffer) const;
//@}
@@ -281,6 +334,8 @@
/// object.
///
/// Note that this is case-insensitive comparison.
+ ///
+ /// This method never throws an exception.
///
/// \param other the right-hand operand to compare against.
/// \return a <code>NameComparisonResult</code> object representing the
@@ -296,6 +351,8 @@
/// it would be much faster and the simple equality check would be pretty
/// common.
///
+ /// This method never throws an exception.
+ ///
/// \param other the <code>Name</code> object to compare against.
/// \return true if the two names are equal; otherwise false.
bool equals(const Name& other) const;
@@ -316,6 +373,9 @@
/// \brief Less-than or equal comparison for Name against <code>other</code>
///
/// The comparison is based on the result of the \c compare() method.
+ ///
+ /// This method never throws an exception.
+ ///
/// \param other the <code>Name</code> object to compare against.
/// \return true if <code>compare(other).getOrder() <= 0</code>;
/// otherwise false.
@@ -328,6 +388,9 @@
/// <code>other</code>
///
/// The comparison is based on the result of the \c compare() method.
+ ///
+ /// This method never throws an exception.
+ ///
/// \param other the <code>Name</code> object to compare against.
/// \return true if <code>compare(other).getOrder() >= 0</code>;
/// otherwise false.
@@ -339,6 +402,9 @@
/// \brief Less-than comparison for Name against <code>other</code>
///
/// The comparison is based on the result of the \c compare() method.
+ ///
+ /// This method never throws an exception.
+ ///
/// \param other the <code>Name</code> object to compare against.
/// \return true if <code>compare(other).getOrder() < 0</code>;
/// otherwise false.
@@ -350,6 +416,9 @@
/// \brief Greater-than comparison for Name against <code>other</code>
///
/// The comparison is based on the result of the \c compare() method.
+ ////
+ /// This method never throws an exception.
+ ///
/// \param other the <code>Name</code> object to compare against.
/// \return true if <code>compare(other).getOrder() > 0</code>;
/// otherwise false.
@@ -475,8 +544,6 @@
std::vector<unsigned char> offsets_;
unsigned int length_;
unsigned int labels_;
-
- void fromString(const std::string& namestr);
};
///
More information about the bind10-changes
mailing list