Browse Source

[2096] Auxiliary methods of the reader

The Result, empty callbacks, etc.
Michal 'vorner' Vaner 12 years ago
parent
commit
6694e40b41

+ 0 - 3
src/lib/datasrc/memory/rdata_encoder.cc

@@ -13,7 +13,6 @@
 // PERFORMANCE OF THIS SOFTWARE.
 
 #include "rdata_encoder.h"
-#include "rdata_field.h"
 
 #include <exceptions/exceptions.h>
 
@@ -30,8 +29,6 @@
 #include <cstring>
 #include <vector>
 
-#include <stdint.h>
-
 using namespace isc::dns;
 using std::vector;
 

+ 2 - 12
src/lib/datasrc/memory/rdata_encoder.h

@@ -15,6 +15,8 @@
 #ifndef DATASRC_MEMORY_RDATA_ENCODER_H
 #define DATASRC_MEMORY_RDATA_ENCODER_H 1
 
+#include "rdata_field.h"
+
 #include <exceptions/exceptions.h>
 
 #include <dns/labelsequence.h>
@@ -106,18 +108,6 @@ public:
         Exception(file, line, what) {}
 };
 
-/// \brief Attributes of domain name fields of encoded RDATA.
-///
-/// The enum values define special traits of the name that can affect how
-/// it should be handled in rendering or query processing.
-enum RdataNameAttributes {
-    NAMEATTR_NONE = 0,          ///< No special attributes
-    NAMEATTR_COMPRESSIBLE = 1,  ///< Name should be compressed when rendered
-    NAMEATTR_ADDITIONAL = (NAMEATTR_COMPRESSIBLE << 1) ///< Name requires
-                                                      ///< Additional section
-                                                      ///< handling
-};
-
 /// \brief RDATA encoder.
 ///
 /// This class provides interfaces to encode a set of RDATA of a specific

+ 3 - 0
src/lib/datasrc/memory/rdata_field.cc

@@ -14,6 +14,9 @@
 
 #include "rdata_field.h"
 
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
 #include <boost/static_assert.hpp>
 
 using namespace isc::dns;

+ 13 - 1
src/lib/datasrc/memory/rdata_field.h

@@ -15,7 +15,7 @@
 #ifndef DATASRC_MEMORY_RDATA_FIELD
 #define DATASRC_MEMORY_RDATA_FIELD
 
-#include "rdata_encoder.h"
+#include <stdint.h>
 
 /// \file rdata_field.h
 ///
@@ -32,6 +32,18 @@ class RRClass;
 namespace datasrc {
 namespace memory {
 
+/// \brief Attributes of domain name fields of encoded RDATA.
+///
+/// The enum values define special traits of the name that can affect how
+/// it should be handled in rendering or query processing.
+enum RdataNameAttributes {
+    NAMEATTR_NONE = 0,          ///< No special attributes
+    NAMEATTR_COMPRESSIBLE = 1,  ///< Name should be compressed when rendered
+    NAMEATTR_ADDITIONAL = (NAMEATTR_COMPRESSIBLE << 1) ///< Name requires
+                                                      ///< Additional section
+                                                      ///< handling
+};
+
 /// Specification of a single RDATA field in terms of internal encoding.
 struct RdataFieldSpec {
     enum FieldType {

+ 37 - 0
src/lib/datasrc/memory/rdata_reader.cc

@@ -13,3 +13,40 @@
 // PERFORMANCE OF THIS SOFTWARE.
 
 #include "rdata_reader.h"
+
+namespace isc {
+namespace datasrc {
+namespace memory {
+
+void
+RdataReader::emptyNameAction(const dns::LabelSequence&, unsigned) {
+    // Do nothing here. On purpose, it's not unfinished.
+}
+
+void
+RdataReader::emptyDataAction(const uint8_t*, size_t) {
+    // Do nothing here. On purpose, it's not unfinished.
+}
+
+RdataReader::Result::Result(const dns::LabelSequence& label,
+                            unsigned attributes) :
+    label_(label),
+    data_(NULL),
+    size_(0),
+    type_(NAME),
+    compressible_((attributes & NAMEATTR_COMPRESSIBLE) != 0),
+    additional_((attributes & NAMEATTR_ADDITIONAL) != 0)
+{}
+
+RdataReader::Result::Result(const uint8_t* data, size_t size) :
+    label_(dns::Name::ROOT_NAME()),
+    data_(data),
+    size_(size),
+    type_(DATA),
+    compressible_(false),
+    additional_(false)
+{}
+
+}
+}
+}

+ 65 - 15
src/lib/datasrc/memory/rdata_reader.h

@@ -15,12 +15,16 @@
 #ifndef DATASRC_MEMORY_RDATA_READER_H
 #define DATASRC_MEMORY_RDATA_READER_H 1
 
+#include "rdata_field.h"
+
 #include <boost/function.hpp>
 
+#include <dns/labelsequence.h>
+#include <dns/name.h>
+
 namespace isc {
 // Some forward declarations
 namespace dns{
-class LabelSequence;
 class RRClass;
 class RRType;
 }
@@ -47,7 +51,7 @@ namespace memory {
 ///     ...
 /// }
 ///
-/// RDataReader reader(RRClass::IN(), RRType::AAAA(), size, data,
+/// RdataReader reader(RRClass::IN(), RRType::AAAA(), size, data,
 ///                    &handleLabel, handleData);
 /// reader.iterate();
 /// \endcode
@@ -58,25 +62,25 @@ namespace memory {
 /// there's no much difference on the technical side.
 ///
 /// \code
-/// RDataReader reader(RRClass::IN(), RRType::AAAA(), size, data,
+/// RdataReader reader(RRClass::IN(), RRType::AAAA(), size, data,
 ///                    &handleLabel, handleData);
-/// RDataReader::Result data;
+/// RdataReader::Result data;
 /// while (data = reader.next()) {
 ///     switch(data.type()) {
-///         case RDataReader::NAME:
+///         case RdataReader::NAME:
 ///             ...
 ///             break;
-///         case RDataReader::DATA:
+///         case RdataReader::DATA:
 ///             ...
 ///             break;
 ///         default: assert(0); // Can not happen
 ///     }
 /// }
 /// \endcode
-class RDataReader {
+class RdataReader {
 public:
     /// \brief Function called on each name encountered in the data.
-    typedef boost::function<void(const dns::LabelSequence&, unsigned int)>
+    typedef boost::function<void(const dns::LabelSequence&, unsigned)>
         NameAction;
     /// \brief Function called on each data field in the data.
     typedef boost::function<void(const uint8_t*, size_t)> DataAction;
@@ -86,7 +90,7 @@ public:
     /// This is a NameAction function that does nothing. It is used
     /// as a default in the constructor.
     static void emptyNameAction(const dns::LabelSequence& label,
-                                unsigned int attributes);
+                                unsigned attributes);
     /// \brief a DataAction that does nothing.
     ///
     /// This is a DataAction function that does nothing. It is used
@@ -106,7 +110,7 @@ public:
     /// \param data The actual data.
     /// \param name_action The callback to be called on each encountered name.
     /// \param data_action The callback to be called on each data chunk.
-    RDataReader(const dns::RRClass& rrclass, const dns::RRType& rrtype,
+    RdataReader(const dns::RRClass& rrclass, const dns::RRType& rrtype,
                 size_t size, const uint8_t* data,
                 const NameAction& name_action = &emptyNameAction,
                 const DataAction& data_action = &emptyDataAction);
@@ -122,27 +126,66 @@ public:
     ///
     /// Each time you call next() or nextSig(), it returns some data.
     /// This holds the data.
+    ///
+    /// It is valid only for as long as the RdataReader that returned it.
+    ///
+    /// All the methods can be called under any circumstances. However,
+    /// if the required property is not valid for the given type (eg.
+    /// when calling size() on type() == NAME), it returns some "empty"
+    /// value (0, NULL, or the like).
     class Result {
     public:
+        /// \brief Default constructor
+        ///
+        /// It creates an empty result (with no data) of type END.
+        Result() :
+            // TODO: Do we maybe want to have a static one to copy
+            // instead of constructing new one from the root Name?
+            label_(dns::Name::ROOT_NAME()),
+            data_(NULL),
+            size_(0),
+            type_(END),
+            compressible_(false),
+            additional_(false)
+        {}
+        /// \brief Constructor from a domain label
+        ///
+        /// Creates the NAME type result. Used internally from RdataReader.
+        ///
+        /// \param label The label to hold
+        /// \param attributes The attributes, as stored by the serialized
+        ///     data.
+        Result(const dns::LabelSequence& label, unsigned attributes);
+        /// \brief Constructor from data
+        ///
+        /// Creates the DATA type result. Used internally from RdataReader.
+        ///
+        /// \param data The data pointer to hold.
+        /// \param size The size to hold.
+        Result(const uint8_t* data, size_t size);
         /// \brief The type of data returned.
-        DataType type() const;
+        DataType type() const { return (type_); }
         /// \brief The raw data.
         ///
         /// This is only valid if type() == DATA.
-        const uint8_t* data() const;
+        const uint8_t* data() const { return (data_); }
         /// \brief The size of the raw data.
         ///
         /// This is the number of bytes the data takes. It is valid only
         /// if type() == DATA.
-        size_t size() const;
+        size_t size() const { return (size_); }
         /// \brief The domain label.
         ///
         /// This holds the domain label. It is only valid if type() == NAME.
-        const dns::LabelSequence& label() const;
+        const dns::LabelSequence& label() const { return (label_); }
         /// \brief Is the name in label() compressible?
         ///
         /// This is valid only if type() == NAME.
-        bool compressible() const;
+        bool compressible() const { return (compressible_); }
+        /// \brief Does the name expect additional processing?
+        ///
+        /// This is valid only if type() == NAME.
+        bool additional() const { return (additional_); }
         /// \brief If there are data returned.
         ///
         /// This returns if there are any data at all returned. This is
@@ -151,6 +194,13 @@ public:
         operator bool() const {
             return (type() != END);
         }
+    private:
+        dns::LabelSequence label_;
+        const uint8_t* data_;
+        size_t size_;
+        DataType type_;
+        bool compressible_;
+        bool additional_;
     };
 
     /// \brief Step to next piece of data.

+ 49 - 7
src/lib/datasrc/memory/tests/rdata_serialization_unittest.cc

@@ -322,15 +322,15 @@ public:
                        const vector<uint8_t>& encoded_data,
                        MessageRenderer& renderer)
     {
-        RDataReader reader(rrclass, rrtype, encoded_data.size(),
+        RdataReader reader(rrclass, rrtype, encoded_data.size(),
                            &encoded_data[0]);
-        RDataReader::Result field;
+        RdataReader::Result field;
         while (field = reader.next()) {
             switch (field.type()) {
-                case RDataReader::DATA:
+                case RdataReader::DATA:
                     renderer.writeData(field.data(), field.size());
                     break;
-                case RDataReader::NAME:
+                case RdataReader::NAME:
                     renderer.writeName(field.label(), field.compressible());
                     break;
                 default:
@@ -342,7 +342,7 @@ public:
 
         while (field = reader.nextSig()) {
             switch (field.type()) {
-                case RDataReader::DATA:
+                case RdataReader::DATA:
                     renderer.writeData(field.data(), field.size());
                     break;
                 default: // There are also no NAME fields in RRSigs
@@ -361,7 +361,7 @@ public:
                        const vector<uint8_t>& encoded_data,
                        MessageRenderer& renderer)
     {
-        RDataReader reader(rrclass, rrtype, encoded_data.size(),
+        RdataReader reader(rrclass, rrtype, encoded_data.size(),
                            &encoded_data[0],
                            boost::bind(renderNameField, &renderer,
                                        additionalRequired(rrtype), _1, _2),
@@ -381,7 +381,7 @@ public:
                        const vector<uint8_t>& encoded_data,
                        MessageRenderer& renderer)
     {
-        RDataReader reader(rrclass, rrtype, encoded_data.size(),
+        RdataReader reader(rrclass, rrtype, encoded_data.size(),
                            &encoded_data[0],
                            boost::bind(renderNameField, &renderer,
                                        additionalRequired(rrtype), _1, _2),
@@ -680,4 +680,46 @@ TEST_F(RdataSerializationTest, badAddSIGRdata) {
     encoder_.start(RRClass::IN(), RRType::A());
     EXPECT_THROW(encoder_.addSIGRdata(big_sigrdata), RdataEncodingError);
 }
+
+// Test the result returns what it was constructed with.
+TEST_F(RdataSerializationTest, readerResult) {
+    // Default constructor
+    RdataReader::Result empty;
+    // Everything should be at the "empty" values, type END
+    EXPECT_EQ(RdataReader::END, empty.type());
+    EXPECT_EQ(NULL, empty.data());
+    EXPECT_EQ(0, empty.size());
+    EXPECT_TRUE(empty.label().equals(LabelSequence(Name::ROOT_NAME())));
+    EXPECT_FALSE(empty);
+    EXPECT_FALSE(empty.compressible());
+    EXPECT_FALSE(empty.additional());
+    // Constructor from label sequence
+    LabelSequence seq(Name("example.org"));
+    RdataReader::Result compressible(seq, NAMEATTR_COMPRESSIBLE);
+    EXPECT_EQ(RdataReader::NAME, compressible.type());
+    EXPECT_EQ(NULL, compressible.data());
+    EXPECT_EQ(0, compressible.size());
+    EXPECT_TRUE(compressible.label().equals(seq));
+    EXPECT_TRUE(compressible);
+    EXPECT_TRUE(compressible.compressible());
+    EXPECT_FALSE(empty.additional());
+    RdataReader::Result incompressible(seq, NAMEATTR_ADDITIONAL);
+    EXPECT_EQ(RdataReader::NAME, incompressible.type());
+    EXPECT_EQ(NULL, incompressible.data());
+    EXPECT_EQ(0, incompressible.size());
+    EXPECT_TRUE(incompressible.label().equals(seq));
+    EXPECT_TRUE(incompressible);
+    EXPECT_FALSE(incompressible.compressible());
+    EXPECT_TRUE(empty.additional());
+    // Constructor from data
+    uint8_t byte;
+    RdataReader::Result data(&byte, 1);
+    EXPECT_EQ(RdataReader::DATA, data.type());
+    EXPECT_EQ(&byte, data.data());
+    EXPECT_EQ(1, data.size());
+    EXPECT_TRUE(data.label().equals(LabelSequence(Name::ROOT_NAME())));
+    EXPECT_FALSE(data);
+    EXPECT_FALSE(data.compressible());
+    EXPECT_FALSE(empty.additional());
+}
 }