Browse Source

[2522] add MasterLexer constructor for MINFO

Paul Selkirk 12 years ago
parent
commit
323d64cc14

+ 53 - 25
src/lib/dns/rdata/generic/minfo_14.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2013  Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -21,14 +21,22 @@
 #include <dns/name.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
+#include <dns/rdata/generic/detail/lexer_util.h>
 
 using namespace std;
 using namespace isc::dns;
 using namespace isc::util;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
 
 // BEGIN_ISC_NAMESPACE
 // BEGIN_RDATA_NAMESPACE
 
+// helper function for string and lexer constructors
+void MINFO::constructFromLexer(MasterLexer& lexer, const Name* origin) {
+    rmailbox_ = createNameFromLexer(lexer, origin);
+    emailbox_ = createNameFromLexer(lexer, origin);
+}
+
 /// \brief Constructor from string.
 ///
 /// \c minfo_str must be formatted as follows:
@@ -39,12 +47,10 @@ using namespace isc::util;
 /// An example of valid string is:
 /// \code "rmail.example.com. email.example.com." \endcode
 ///
-/// <b>Exceptions</b>
-///
-/// \exception InvalidRdataText The number of RDATA fields (must be 2) is
+/// \throw InvalidRdataText The number of RDATA fields (must be 2) is
 /// incorrect.
-/// \exception std::bad_alloc Memory allocation for names fails.
-/// \exception Other The constructor of the \c Name class will throw if the
+/// \throw std::bad_alloc Memory allocation for names fails.
+/// \throw Other The constructor of the \c Name class will throw if the
 /// names in the string is invalid.
 MINFO::MINFO(const std::string& minfo_str) :
     // We cannot construct both names in the initialization list due to the
@@ -52,21 +58,43 @@ MINFO::MINFO(const std::string& minfo_str) :
     // name and replace them later.
     rmailbox_(Name::ROOT_NAME()), emailbox_(Name::ROOT_NAME())
 {
-    istringstream iss(minfo_str);
-    string rmailbox_str, emailbox_str;
-    iss >> rmailbox_str >> emailbox_str;
-
-    // Validation: A valid MINFO RR must have exactly two fields.
-    if (iss.bad() || iss.fail()) {
-        isc_throw(InvalidRdataText, "Invalid MINFO text: " << minfo_str);
-    }
-    if (!iss.eof()) {
-        isc_throw(InvalidRdataText, "Invalid MINFO text (redundant field): "
-                  << minfo_str);
+    try {
+        std::istringstream ss(minfo_str);
+        MasterLexer lexer;
+        lexer.pushSource(ss);
+
+        constructFromLexer(lexer, NULL);
+
+        if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+            isc_throw(InvalidRdataText, "extra input text for MINFO: "
+                      << minfo_str);
+        }
+    } catch (const MasterLexer::LexerError& ex) {
+        isc_throw(InvalidRdataText, "Failed to construct MINFO from '" <<
+                  minfo_str << "': " << ex.what());
     }
+}
 
-    rmailbox_ = Name(rmailbox_str);
-    emailbox_ = Name(emailbox_str);
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an MINFO RDATA.  The RMAILBOX and EMAILBOX fields can be non-absolute
+/// if \c origin is non-NULL, in which case \c origin is used to make them
+/// absolute.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name and constructors if construction of
+/// textual fields as these objects fail.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+/// \param origin If non NULL, specifies the origin of SERVER when it
+/// is non-absolute.
+MINFO::MINFO(MasterLexer& lexer, const Name* origin,
+       MasterLoader::Options, MasterLoaderCallbacks&) :
+    rmailbox_(Name::ROOT_NAME()), emailbox_(Name::ROOT_NAME())
+{
+    constructFromLexer(lexer, origin);
 }
 
 /// \brief Constructor from wire-format data.
@@ -75,8 +103,8 @@ MINFO::MINFO(const std::string& minfo_str) :
 /// length) for parsing.
 /// If necessary, the caller will check consistency.
 ///
-/// \exception std::bad_alloc Memory allocation for names fails.
-/// \exception Other The constructor of the \c Name class will throw if the
+/// \throw std::bad_alloc Memory allocation for names fails.
+/// \throw Other The constructor of the \c Name class will throw if the
 /// names in the wire is invalid.
 MINFO::MINFO(InputBuffer& buffer, size_t) :
     rmailbox_(buffer), emailbox_(buffer)
@@ -84,7 +112,7 @@ MINFO::MINFO(InputBuffer& buffer, size_t) :
 
 /// \brief Copy constructor.
 ///
-/// \exception std::bad_alloc Memory allocation fails in copying internal
+/// \throw std::bad_alloc Memory allocation fails in copying internal
 /// member variables (this should be very rare).
 MINFO::MINFO(const MINFO& other) :
     Rdata(), rmailbox_(other.rmailbox_), emailbox_(other.emailbox_)
@@ -95,7 +123,7 @@ MINFO::MINFO(const MINFO& other) :
 /// The output of this method is formatted as described in the "from string"
 /// constructor (\c MINFO(const std::string&))).
 ///
-/// \exception std::bad_alloc Internal resource allocation fails.
+/// \throw std::bad_alloc Internal resource allocation fails.
 ///
 /// \return A \c string object that represents the \c MINFO object.
 std::string
@@ -105,7 +133,7 @@ MINFO::toText() const {
 
 /// \brief Render the \c MINFO in the wire format without name compression.
 ///
-/// \exception std::bad_alloc Internal resource allocation fails.
+/// \throw std::bad_alloc Internal resource allocation fails.
 ///
 /// \param buffer An output buffer to store the wire data.
 void
@@ -128,7 +156,7 @@ MINFO::operator=(const MINFO& source) {
 /// As specified in RFC3597, TYPE MINFO is "well-known", the rmailbox and
 /// emailbox fields (domain names) will be compressed.
 ///
-/// \exception std::bad_alloc Internal resource allocation fails.
+/// \throw std::bad_alloc Internal resource allocation fails.
 ///
 /// \param renderer DNS message rendering context that encapsulates the
 /// output buffer and name compression information.

+ 6 - 3
src/lib/dns/rdata/generic/minfo_14.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2013  Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -45,7 +45,7 @@ public:
 
     /// \brief Return the value of the rmailbox field.
     ///
-    /// \exception std::bad_alloc If resource allocation for the returned
+    /// \throw std::bad_alloc If resource allocation for the returned
     /// \c Name fails.
     ///
     /// \note
@@ -64,11 +64,14 @@ public:
 
     /// \brief Return the value of the emailbox field.
     ///
-    /// \exception std::bad_alloc If resource allocation for the returned
+    /// \throw std::bad_alloc If resource allocation for the returned
     /// \c Name fails.
     Name getEmailbox() const { return (emailbox_); }
 
 private:
+    // helper function for string and lexer constructors
+    void constructFromLexer(MasterLexer& lexer, const Name* origin);
+
     Name rmailbox_;
     Name emailbox_;
 };

+ 5 - 5
src/lib/dns/tests/rdata_minfo_unittest.cc

@@ -1,6 +1,6 @@
-// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2013  Internet Systems Consortium, Inc. ("ISC")
 //
-// Permission to use, copy, modify, and/or distribute this software for generic
+// Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
 // copyright notice and this permission notice appear in all copies.
 //
@@ -27,15 +27,15 @@
 
 using isc::UnitTestUtil;
 using namespace std;
-using namespace isc::dns;
 using namespace isc::util;
+using namespace isc::dns;
 using namespace isc::dns::rdata;
 
 // minfo text
 const char* const minfo_txt = "rmailbox.example.com. emailbox.example.com.";
 const char* const minfo_txt2 = "root.example.com. emailbox.example.com.";
 const char* const too_long_label = "01234567890123456789012345678901234567"
-                                   "89012345678901234567890123";
+                                   "89012345678901234567890123.";
 
 namespace {
 class Rdata_MINFO_Test : public RdataTest {
@@ -61,7 +61,7 @@ TEST_F(Rdata_MINFO_Test, badText) {
     EXPECT_THROW(generic::MINFO("root.example.com."),
                  InvalidRdataText);
     // number of fields (must be 2) is incorrect
-    EXPECT_THROW(generic::MINFO("root.example.com emailbox.example.com. "
+    EXPECT_THROW(generic::MINFO("root.example.com. emailbox.example.com. "
                                 "example.com."),
                  InvalidRdataText);
     // bad rmailbox name