summaryrefslogtreecommitdiffstats
path: root/src/lib/dns/master_lexer_state.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/dns/master_lexer_state.h')
-rw-r--r--src/lib/dns/master_lexer_state.h138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/lib/dns/master_lexer_state.h b/src/lib/dns/master_lexer_state.h
new file mode 100644
index 0000000..d328a70
--- /dev/null
+++ b/src/lib/dns/master_lexer_state.h
@@ -0,0 +1,138 @@
+// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef MASTER_LEXER_STATE_H
+#define MASTER_LEXER_STATE_H 1
+
+#include <dns/master_lexer.h>
+
+namespace isc {
+namespace dns {
+
+namespace master_lexer_internal {
+
+/// \brief Tokenization state for \c MasterLexer.
+///
+/// This is a base class of classes that represent various states of a single
+/// tokenization session of \c MasterLexer, i.e., the states used for a
+/// single call to \c MasterLexer::getNextToken().
+///
+/// It follows the convention of the state design pattern: each derived class
+/// corresponds to a specific state, and the state transition takes place
+/// through the virtual method named \c handle(). The \c handle() method
+/// takes the main \c MasterLexer object that holds all necessary internal
+/// context, and updates it as necessary; each \c State derived class is
+/// completely stateless.
+///
+/// The initial transition takes place in a static method of the base class,
+/// \c start(). This is mainly for implementation convenience; we need to
+/// pass options given to \c MasterLexer::getNextToken() for the initial
+/// state, so it makes more sense to separate the interface for the transition
+/// from the initial state.
+///
+/// If the whole lexer transition is completed within start(), it sets the
+/// identified token and returns NULL; otherwise it returns a pointer to
+/// an object of a specific state class that completes the session
+/// on the call of handle().
+///
+/// As is usual in the state design pattern, the \c State class is made
+/// a friend class of \c MasterLexer and can refer to its internal details.
+/// This is intentional; essentially its a part of \c MasterLexer and
+/// is defined as a separate class only for implementation clarity and better
+/// testability. It's defined in a publicly visible header, but that's only
+/// for testing purposes. No normal application or even no other classes of
+/// this library are expected to use this class.
+class State {
+public:
+ /// \brief Virtual destructor.
+ ///
+ /// In our usage this actually doesn't matter, but some compilers complain
+ /// about it and we need to silence them.
+ virtual ~State() {}
+
+ /// \brief Begin state transitions to get the next token.
+ ///
+ /// This is the first method that \c MasterLexer needs to call for a
+ /// tokenization session. The lexer passes a reference to itself
+ /// and options given in \c getNextToken().
+ ///
+ /// \throw MasterLexer::ReadError Unexpected I/O error
+ /// \throw std::bad_alloc Internal resource allocation failure
+ ///
+ /// \param lexer The lexer object that holds the main context.
+ /// \param options The options passed to getNextToken().
+ /// \return A pointer to the next state object or NULL if the transition
+ /// is completed.
+ static const State* start(MasterLexer& lexer,
+ MasterLexer::Options options);
+
+ /// \brief Handle the process of one specific state.
+ ///
+ /// This method is expected to be called on the object returned by
+ /// start(). In the usual state transition design pattern, it would
+ /// return the next state. But as we noticed, we never have another
+ /// state, so we simplify it by not returning anything instead of
+ /// returning NULL every time.
+ ///
+ /// \throw MasterLexer::ReadError Unexpected I/O error
+ /// \throw std::bad_alloc Internal resource allocation failure
+ ///
+ /// \param lexer The lexer object that holds the main context.
+ virtual void handle(MasterLexer& lexer) const = 0;
+
+ /// \brief Types of states.
+ ///
+ /// Specific states are basically hidden within the implementation,
+ /// but we'd like to allow tests to examine them, so we provide
+ /// a way to get an instance of a specific state.
+ enum ID {
+ CRLF, ///< Just seen a carriage-return character
+ String, ///< Handling a string token
+ QString, ///< Handling a quoted string token
+ Number ///< Handling a number
+ };
+
+ /// \brief Returns a \c State instance of the given state.
+ ///
+ /// This is provided only for testing purposes so tests can check
+ /// the behavior of each state separately. \c MasterLexer shouldn't
+ /// need this method.
+ static const State& getInstance(ID state_id);
+
+ /// \name Read-only accessors for testing purposes.
+ ///
+ /// These allow tests to inspect some selected portion of the internal
+ /// states of \c MasterLexer. These shouldn't be used except for testing
+ /// purposes.
+ ///@{
+ bool wasLastEOL(const MasterLexer& lexer) const;
+ const MasterToken& getToken(const MasterLexer& lexer) const;
+ size_t getParenCount(const MasterLexer& lexer) const;
+ ///@}
+
+protected:
+ /// \brief An accessor to the internal implementation class of
+ /// \c MasterLexer.
+ ///
+ /// This is provided for specific derived classes as they are not direct
+ /// friends of \c MasterLexer.
+ ///
+ /// \param lexer The lexer object that holds the main context.
+ /// \return A pointer to the implementation class object of the given
+ /// lexer. This is never NULL.
+ MasterLexer::MasterLexerImpl* getLexerImpl(MasterLexer& lexer) const {
+ return (lexer.impl_);
+ }
+};
+
+} // namespace master_lexer_internal
+} // namespace dns
+} // namespace isc
+#endif // MASTER_LEXER_STATE_H
+
+// Local Variables:
+// mode: c++
+// End: