Commit 3fc1c63d authored by Mukund Sivaraman's avatar Mukund Sivaraman
Browse files

[2430] Write API doc for MasterLoaderImpl

parent afd60816
......@@ -56,9 +56,34 @@ public:
} // end unnamed namespace
/// \brief Private implementation class for the \c MasterLoader
///
/// This class is used internally by the \c MasterLoader and is not
/// publicly visible. It is present to avoid polluting the public API
/// with internal implementation details of the \c MasterLoader.
// cppcheck-suppress noConstructor
class MasterLoader::MasterLoaderImpl {
public:
/// \brief Constructor.
///
/// \param master_file Path to the file to load.
/// \param zone_origin The origin of zone to be expected inside
/// the master file. Currently unused, but it is expected to
/// be used for some validation.
/// \param zone_class The class of zone to be expected inside the
/// master file.
/// \param callbacks The callbacks by which it should report problems.
/// Usually, the callback carries a filename and line number of the
/// input where the problem happens. There's a special case of empty
/// filename and zero line in case the opening of the top-level master
/// file fails.
/// \param add_callback The callback which would be called with each
/// loaded RR.
/// \param options Options for the parsing, which is bitwise-or of
/// the Options values or DEFAULT. If the MANY_ERRORS option is
/// included, the parser tries to continue past errors. If it
/// is not included, it stops at first encountered error.
/// \throw std::bad_alloc when there's not enough memory.
MasterLoaderImpl(const char* master_file,
const Name& zone_origin,
const RRClass& zone_class,
......@@ -83,6 +108,16 @@ public:
rr_count_(0)
{}
/// \brief Wrapper around \c MasterLexer::pushSource() (file version)
///
/// This method is used as a wrapper around the lexer's
/// \c pushSource() to also save the current origin and the last
/// seen name (to be restored upon \c popSource()). It also calls
/// \c pushSource(). See \c doInclude() implementation for more
/// details.
///
/// \param filename Path to the file to push as a new source.
/// \param current_origin The current origin name to save.
void pushSource(const std::string& filename, const Name& current_origin) {
std::string error;
if (!lexer_.pushSource(filename.c_str(), &error)) {
......@@ -100,17 +135,35 @@ public:
previous_name_ = false;
}
/// \brief Wrapper around \c MasterLexer::pushSource() (stream version)
///
/// Similar to \c pushSource(). This method need not save the
/// current origin as it is not used with $INCLUDE processing.
///
/// \param stream The input stream to use as a new source.
void pushStreamSource(std::istream& stream) {
lexer_.pushSource(stream);
initialized_ = true;
}
/// \brief Implementation of \c MasterLoader::loadIncremental()
///
/// See \c MasterLoader::loadIncremental() for details.
bool loadIncremental(size_t count_limit);
/// \brief Return the total size of the input sources pushed so
/// far. See \c MasterLexer::getTotalSourceSize().
size_t getSize() const { return (lexer_.getTotalSourceSize()); }
/// \brief Return the line number being parsed in the pushed input
/// sources. See \c MasterLexer::getPosition().
size_t getPosition() const { return (lexer_.getPosition()); }
private:
/// \brief Report an error using the callbacks that were supplied
/// during \c MasterLoader construction. Note that this method also
/// throws \c MasterLoaderError exception if necessary, so the
/// caller need not throw it.
void reportError(const std::string& filename, size_t line,
const std::string& reason)
{
......@@ -125,6 +178,12 @@ private:
}
}
/// \brief Wrapper around \c MasterLexer::popSource()
///
/// This method is used as a wrapper around the lexer's
/// \c popSource() to also restore the current origin and the last
/// seen name (at time of push). It also calls \c popSource(). See
/// \c doInclude() implementation for more details.
bool popSource() {
if (lexer_.getSourceCount() == 1) {
return (false);
......@@ -143,16 +202,43 @@ private:
return (true);
}
// Get a string token. Handle it as error if it is not string.
/// \brief Get a string token. Handle it as error if it is not string.
const string getString() {
lexer_.getNextToken(MasterToken::STRING).getString(string_token_);
return (string_token_);
}
/// \brief Parse the initial token at the beginning of a line in a
/// master file (or stream).
///
/// A helper method of \c loadIncremental(), parsing the first token
/// of a new line. If it looks like an RR, detect its owner name
/// and return a string token for the next field of the RR.
///
/// Otherwise, return either \c END_OF_LINE or \c END_OF_FILE token
/// depending on whether the loader continues to the next line or
/// completes the load, respectively. Other corner cases including
/// $-directive handling is done here.
///
/// For unexpected errors, it throws an exception, which will be
/// handled in \c loadIncremental().
MasterToken handleInitialToken();
/// \brief Helper method for \c doGenerate().
///
/// This is a helper method for \c doGenerate() that processes the
/// LHS or RHS for a single iteration in the range that is requested
/// by the $GENERATE directive and returns a generated string (that
/// is used to build a name (LHS) or RDATA (RHS) for an RR). See the
/// commented implementation for details.
std::string generateForIter(const std::string& str, const int it);
/// \brief Process the $GENERATE directive.
///
/// See the commented implementation for details.
void doGenerate();
/// \brief Process the $ORIGIN directive.
void doOrigin(bool is_optional) {
// Parse and create the new origin. It is relative to the previous
// one.
......@@ -185,6 +271,7 @@ private:
}
}
/// \brief Process the $INCLUDE directive.
void doInclude() {
// First, get the filename to include
const string
......@@ -205,11 +292,16 @@ private:
pushSource(filename, current_origin);
}
// A helper method for loadIncremental(). It parses part of an RR
// until it finds the RR type field. If TTL or RR class is
// specified before the RR type, it also recognizes and validates
// them. explicit_ttl will be set to true if this method finds a
// valid TTL field.
/// \brief Parse RR fields (TTL, CLASS and TYPE).
///
/// A helper method for \c loadIncremental(). It parses part of an
/// RR until it finds the RR type field. If TTL or RR class is
/// specified before the RR type, it also recognizes and validates
/// them.
///
/// \param explicit_ttl will be set to true if this method finds a
/// valid TTL field.
/// \param rrparam_token Pass the current (parsed) token here.
RRType parseRRParams(bool& explicit_ttl, MasterToken rrparam_token) {
// Find TTL, class and type. Both TTL and class are
// optional and may occur in any order if they exist. TTL
......@@ -249,20 +341,25 @@ private:
return (RRType(rrparam_token.getString()));
}
// Upper limit check when recognizing a specific TTL value from the
// zone file ($TTL, the RR's TTL field, or the SOA minimum). RFC2181
// Section 8 limits the range of TTL values to 2^31-1 (0x7fffffff),
// and prohibits transmitting a TTL field exceeding this range. We
// guarantee that by limiting the value at the time of zone
// parsing/loading, following what BIND 9 does. Resetting it to 0
// at this point may not be exactly what the RFC states (depending on
// the meaning of 'received'), but the end result would be the same (i.e.,
// the guarantee on transmission). Again, we follow the BIND 9's behavior
// here.
//
// post_parsing is true iff this method is called after parsing the entire
// RR and the lexer is positioned at the next line. It's just for
// calculating the accurate source line when callback is necessary.
/// \brief Check and limit TTL to maximum value.
///
/// Upper limit check when recognizing a specific TTL value from the
/// zone file ($TTL, the RR's TTL field, or the SOA minimum). RFC2181
/// Section 8 limits the range of TTL values to 2^31-1 (0x7fffffff),
/// and prohibits transmitting a TTL field exceeding this range. We
/// guarantee that by limiting the value at the time of zone
/// parsing/loading, following what BIND 9 does. Resetting it to 0
/// at this point may not be exactly what the RFC states (depending on
/// the meaning of 'received'), but the end result would be the same (i.e.,
/// the guarantee on transmission). Again, we follow the BIND 9's behavior
/// here.
///
/// \param ttl the TTL to check. If it is larger than the maximum
/// allowed, it is set to 0.
/// \param post_parsing should be true iff this method is called
/// after parsing the entire RR and the lexer is positioned at the
/// next line. It's just for calculating the accurate source line
/// when callback is necessary.
void limitTTL(RRTTL& ttl, bool post_parsing) {
if (ttl > RRTTL::MAX_TTL()) {
const size_t src_line = lexer_.getSourceLine() -
......@@ -274,19 +371,25 @@ private:
}
}
// Set/reset the default TTL. This should be from either $TTL or SOA
// minimum TTL (it's the caller's responsibility; this method doesn't
// care about where it comes from). see LimitTTL() for parameter
// post_parsing.
/// \brief Set/reset the default TTL.
///
/// This should be from either $TTL or SOA minimum TTL (it's the
/// caller's responsibility; this method doesn't care about where it
/// comes from). See \c limitTTL() for parameter post_parsing.
void setDefaultTTL(const RRTTL& ttl, bool post_parsing) {
assignTTL(default_ttl_, ttl);
limitTTL(*default_ttl_, post_parsing);
}
// Try to set/reset the current TTL from candidate TTL text. It's possible
// it does not actually represent a TTL (which is not immediately
// considered an error). Return true iff it's recognized as a valid TTL
// (and only in which case the current TTL is set).
/// \brief Try to set/reset the current TTL from candidate TTL text.
///
/// It's possible it that the text does not actually represent a TTL
/// (which is not immediately considered an error). Returns \c true
/// iff it's recognized as a valid TTL (and only in which case the
/// current TTL is set).
///
/// \param ttl_txt The text to parse as a TTL.
/// \return true if a TTL was parsed (and set as the current TTL).
bool setCurrentTTL(const string& ttl_txt) {
// We use the factory version instead of RRTTL constructor as we
// need to expect cases where ttl_txt does not actually represent a TTL
......@@ -300,14 +403,15 @@ private:
return (false);
}
// Determine the TTL of the current RR based on the given parsing context.
//
// explicit_ttl is true iff the TTL is explicitly specified for that RR
// (in which case current_ttl_ is set to that TTL).
// rrtype is the type of the current RR, and rdata is its RDATA. They
// only matter if the type is SOA and no available TTL is known. In this
// case the minimum TTL of the SOA will be used as the TTL of that SOA
// and the default TTL for subsequent RRs.
/// \brief Determine the TTL of the current RR based on the given
/// parsing context.
///
/// \c explicit_ttl is true iff the TTL is explicitly specified for that RR
/// (in which case current_ttl_ is set to that TTL).
/// \c rrtype is the type of the current RR, and \c rdata is its RDATA. They
/// only matter if the type is SOA and no available TTL is known. In this
/// case the minimum TTL of the SOA will be used as the TTL of that SOA
/// and the default TTL for subsequent RRs.
const RRTTL& getCurrentTTL(bool explicit_ttl, const RRType& rrtype,
const rdata::ConstRdataPtr& rdata) {
// We've completed parsing the full of RR, and the lexer is already
......@@ -346,6 +450,10 @@ private:
return (*current_ttl_);
}
/// \brief Handle a $DIRECTIVE
///
/// This method is called when a $DIRECTIVE is encountered in the
/// input stream.
void handleDirective(const char* directive, size_t length) {
if (iequals(directive, "INCLUDE")) {
doInclude();
......@@ -364,6 +472,7 @@ private:
}
}
/// \brief Skip tokens until end-of-line.
void eatUntilEOL(bool reportExtra) {
// We want to continue. Try to read until the end of line
for (;;) {
......@@ -446,6 +555,44 @@ public:
namespace { // begin unnamed namespace
/// \brief Generate a dotted nibble sequence.
///
/// This method generates a dotted nibble sequence and returns it as a
/// string. The nibbles are appended from the least significant digit
/// (in hex representation of \c num) to the most significant digit with
/// dots ('.') to separate the digits. If \c width is non-zero and the
/// dotted nibble sequence has not filled the requested width, the rest
/// of the width is filled with a dotted nibble sequence of 0 nibbles.
///
/// Some sample representations:
///
/// num = 0x1234, width = 0
/// "4.3.2.1"
///
/// num = 0x1234, width = 1
/// "4.3.2.1"
///
/// num = 0x1234, width = 8
/// "4.3.2.1"
///
/// num = 0x1234, width = 9
/// "4.3.2.1."
///
/// num = 0x1234, width = 10
/// "4.3.2.1.0"
///
/// num = 0x1234, width = 11
/// "4.3.2.1.0."
///
/// num = 0xabcd, width = 0, uppercase = true
/// "D.C.B.A"
///
/// \param num The number for which the dotted nibble sequence should be
/// generated.
/// \param width The width of the generated string.
/// \param uppercase Whether to use uppercase characters in nibble
/// sequence.
/// \return A string containing the dotted nibble sequence.
std::string
genNibbles(int num, unsigned int width, bool uppercase) {
static const char *hex = "0123456789abcdef0123456789ABCDEF";
......@@ -704,15 +851,6 @@ MasterLoader::MasterLoaderImpl::doGenerate() {
}
}
// A helper method of loadIncremental, parsing the first token of a new line.
// If it looks like an RR, detect its owner name and return a string token for
// the next field of the RR.
// Otherwise, return either END_OF_LINE or END_OF_FILE token depending on
// whether the loader continues to the next line or completes the load,
// respectively. Other corner cases including $-directive handling is done
// here.
// For unexpected errors, it throws an exception, which will be handled in
// loadIncremental.
MasterToken
MasterLoader::MasterLoaderImpl::handleInitialToken() {
const MasterToken& initial_token =
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment