From: Michal 'vorner' Vaner Date: Thu, 9 Aug 2012 10:04:40 +0000 (+0200) Subject: [2096] Auxiliary methods of the reader X-Git-Tag: trac2351_base~114^2~19 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6694e40b41ac8909ead7ec6e59bc23ca310573d7;p=thirdparty%2Fkea.git [2096] Auxiliary methods of the reader The Result, empty callbacks, etc. --- diff --git a/src/lib/datasrc/memory/rdata_encoder.cc b/src/lib/datasrc/memory/rdata_encoder.cc index bd86fa36ff..9b47b675c2 100644 --- a/src/lib/datasrc/memory/rdata_encoder.cc +++ b/src/lib/datasrc/memory/rdata_encoder.cc @@ -13,7 +13,6 @@ // PERFORMANCE OF THIS SOFTWARE. #include "rdata_encoder.h" -#include "rdata_field.h" #include @@ -30,8 +29,6 @@ #include #include -#include - using namespace isc::dns; using std::vector; diff --git a/src/lib/datasrc/memory/rdata_encoder.h b/src/lib/datasrc/memory/rdata_encoder.h index 7524f949cb..1fb299761b 100644 --- a/src/lib/datasrc/memory/rdata_encoder.h +++ b/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 #include @@ -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 diff --git a/src/lib/datasrc/memory/rdata_field.cc b/src/lib/datasrc/memory/rdata_field.cc index eab0011dfc..bc48a52a74 100644 --- a/src/lib/datasrc/memory/rdata_field.cc +++ b/src/lib/datasrc/memory/rdata_field.cc @@ -14,6 +14,9 @@ #include "rdata_field.h" +#include +#include + #include using namespace isc::dns; diff --git a/src/lib/datasrc/memory/rdata_field.h b/src/lib/datasrc/memory/rdata_field.h index 62e75df0b8..6d1b3ca5d4 100644 --- a/src/lib/datasrc/memory/rdata_field.h +++ b/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 /// \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 { diff --git a/src/lib/datasrc/memory/rdata_reader.cc b/src/lib/datasrc/memory/rdata_reader.cc index 2edc7e60fa..2bba63fae2 100644 --- a/src/lib/datasrc/memory/rdata_reader.cc +++ b/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) +{} + +} +} +} diff --git a/src/lib/datasrc/memory/rdata_reader.h b/src/lib/datasrc/memory/rdata_reader.h index f665f3cb18..aa1320609a 100644 --- a/src/lib/datasrc/memory/rdata_reader.h +++ b/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 +#include +#include + 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 + typedef boost::function NameAction; /// \brief Function called on each data field in the data. typedef boost::function 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. diff --git a/src/lib/datasrc/memory/tests/rdata_serialization_unittest.cc b/src/lib/datasrc/memory/tests/rdata_serialization_unittest.cc index 41ccb07dda..2032a87d13 100644 --- a/src/lib/datasrc/memory/tests/rdata_serialization_unittest.cc +++ b/src/lib/datasrc/memory/tests/rdata_serialization_unittest.cc @@ -322,15 +322,15 @@ public: const vector& 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& 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& 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()); +} }