From: Michal 'vorner' Vaner Date: Tue, 7 Aug 2012 13:57:15 +0000 (+0200) Subject: [2096] Help for the RDataReader interface X-Git-Tag: trac2351_base~114^2~26 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cd1a4d1452deaa95e341d867cde73b82ef8e3804;p=thirdparty%2Fkea.git [2096] Help for the RDataReader interface Including the expected usage scenarios. Also, the interface was slightly refined - renaming of things, adding support for the RRSig iteration. --- diff --git a/src/lib/datasrc/memory/rdata_reader.h b/src/lib/datasrc/memory/rdata_reader.h index 7d0325fe27..2b8fbee72b 100644 --- a/src/lib/datasrc/memory/rdata_reader.h +++ b/src/lib/datasrc/memory/rdata_reader.h @@ -18,51 +18,178 @@ #include namespace isc { +// Some forward declarations namespace dns{ class LabelSequence; class RRClass; class RRType; } + namespace datasrc { namespace memory { +/// \brief Class to read serialized rdata +/// +/// This class allows you to read the data encoded by RDataEncoder. +/// It is rather low-level -- it provides sequence of data fields +/// and names. It does not give you convenient Rdata or RRset class. +/// +/// It allows two types of operation. First one is by providing callbacks +/// to the constructor and then iterating by repeatedly calling next, or +/// calling iterate once. The callbacks are then called with each part of +/// the data. +/// +/// \code +/// void handleLabel(const dns::LabelSequence& label, unsigned int flags) { +/// ... +/// } +/// void handleData(const uint8_t* data, size_t size) { +/// ... +/// } +/// +/// RDataReader reader(RRClass::IN(), RRType::AAAA(), size, data, +/// &handleLabel, handleData); +/// reader.iterate(); +/// \endcode +/// +/// The other way is to use the return value of next() and loop through +/// it manually. It has the inconvenience of having the type condition, but +/// the code is in one place. The used way is matter of personal preferrence, +/// there's no much difference on the technical side. +/// +/// \code +/// RDataReader reader(RRClass::IN(), RRType::AAAA(), size, data, +/// &handleLabel, handleData); +/// RDataReader::Result data; +/// while (data = reader.next()) { +/// switch(data.type()) { +/// case RDataReader::NAME: +/// ... +/// break; +/// case RDataReader::DATA: +/// ... +/// break; +/// default: assert(0); // Can not happen +/// } +/// } +/// \endcode class RDataReader { public: - // The sequence and attributes + /// \brief Function called on each name encountered in the data. typedef boost::function NameAction; + /// \brief Function called on each data field in the data. typedef boost::function DataAction; - // For the default parameters. + /// \brief a NameAction that does nothing. + /// + /// 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); + /// \brief a DataAction that does nothing. + /// + /// This is a DataAction function that does nothing. It is used + /// as a default in the constructor. static void emptyDataAction(const uint8_t* data, size_t size); + /// \brief Constructor + /// + /// This constructs the reader on top of some serialized data. + /// It does not copy the data, you have to make sure the data + /// is valid for the whole life of this object and that they + /// don't change. + /// + /// \param rrclass The class the encoded rdata belongs to. + /// \param rrtype The type of the encode rdata. + /// \param size Number of bytes the data have in serialized form. + /// \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, size_t size, const uint8_t* data, const NameAction& name_action = &emptyNameAction, const DataAction& data_action = &emptyDataAction); - enum Action { - NAME, - DATA, - END + /// \brief The type of data returned from this iteration. + enum DataType { + NAME, ///< This iteration returns domain label + DATA, ///< This iteration returns unstructuder data + END ///< No more data to return }; + /// \brief Data from one iteration + /// + /// Each time you call next() or nextSig(), it returns some data. + /// This holds the data. class Result { public: - Action action() const; + /// \brief The type of data returned. + DataType type() const; + /// \brief The raw data. + /// + /// This is only valid if type() == DATA. const uint8_t* data() const; + /// \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; + /// \brief The domain label. + /// + /// This holds the domain label. It is only valid if type() == NAME. const dns::LabelSequence& sequence; + /// \brief If there are data returned. + /// + /// This returns if there are any data at all returned. This is + /// equivalent to action != END, but it allows for more convenient + /// code of a loop through the data. operator bool() const { return (action() != END); } }; + /// \brief Step to next piece of data. + /// + /// This returns the next available data. Also, the apropriate hook + /// (name_action or data_action, depending on the data type) as passed + /// to the constructor is called. + /// + /// If there are no more data, a Result with type END is returned and + /// no callback is called. Result next(); + /// \brief Call next() until the end. + /// + /// This is just convenience method to iterate through all the data. + /// It calls next until it reaches the end (it does not revind before, + /// therefore if you already called next() yourself, it does not start + /// at the beginning). + /// + /// The method only makes sense if you set the callbacks in constructor. + void iterate() { + while (next()) { } + } + /// \brief Step to next piece of RRSig data. + /// + /// This is almost the same as next(), but it iterates through the + /// associated RRSig data, not the data for the given RRType. + Result nextSig(); + /// \brief Iterate through all RRSig data. + /// + /// This is almost the same as iterate(), but it iterates through the + /// RRSig data instead. + void iterateSig() { + while (nextSig()) { } + } + /// \brief Rewind the iterator to the beginnig of data. + /// + /// The following next() and nextSig() will start iterating from the + /// beginning again. void rewind(); + /// \brief Returns the size of associated data. + /// + /// This just returns whatever was passed to the constructor as size. size_t getSize() const; };