Commit 467a4493 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

described the RRParamRegistry class and did some cleanup


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/jinmei-dnsrrparams@464 e5f2f494-b856-4b98-b285-d166d9295462
parent 50f60d19
......@@ -127,7 +127,7 @@ private:
/// \c MessageRenderer.
///
/// The implementation is hidden from applications. We can refer to specific
/// members of this class only within this file.
/// members of this class only within the implementation source file.
///
struct MessageRendererImpl {
/// \brief Constructor from an output buffer.
......
......@@ -32,7 +32,7 @@ namespace dns {
RRClass::RRClass(const string& classstr)
{
classcode_ = RRParamRegistry::getRegistry().getClassCode(classstr);
classcode_ = RRParamRegistry::getRegistry().textToClassCode(classstr);
}
RRClass::RRClass(InputBuffer& buffer)
......@@ -46,7 +46,7 @@ RRClass::RRClass(InputBuffer& buffer)
const string
RRClass::toText() const
{
return (RRParamRegistry::getRegistry().getClassText(classcode_));
return (RRParamRegistry::getRegistry().codeToClassText(classcode_));
}
void
......
......@@ -38,23 +38,11 @@ namespace isc {
namespace dns {
namespace {
bool CICharEqual(char c1, char c2)
{
return (tolower(static_cast<unsigned char>(c1)) ==
tolower(static_cast<unsigned char>(c2)));
}
bool
caseStringEqual(const string& s1, const string& s2, size_t n)
{
if (s1.size() < n || s2.size() < n) {
return (false);
}
return (mismatch(s1.begin(), s1.begin() + n, s2.begin(), CICharEqual).first
== s1.begin() + n);
}
///
/// The following function and class are a helper to define case-insensitive
/// equivalence relationship on strings. They are used in the mapping
/// containers below.
///
bool
CICharLess(char c1, char c2)
{
......@@ -123,11 +111,22 @@ const size_t RRClassParam::UNKNOWN_MAXLEN =
RRClassParam::UNKNOWN_MAX.size();
}
///
/// \brief The \c RRParamRegistryImpl class is the actual implementation of
/// \c RRParamRegistry.
///
/// The implementation is hidden from applications. We can refer to specific
/// members of this class only within the implementation source file.
///
struct RRParamRegistryImpl {
StrRRClassMap str2classmap;
CodeRRClassMap code2classmap;
/// Mappings from RR type codes to textual representations.
StrRRTypeMap str2typemap;
/// Mappings from textual representations of RR types to integer codes.
CodeRRTypeMap code2typemap;
/// Mappings from RR class codes to textual representations.
StrRRClassMap str2classmap;
/// Mappings from textual representations of RR classes to integer codes.
CodeRRClassMap code2classmap;
};
RRParamRegistry::RRParamRegistry()
......@@ -137,10 +136,10 @@ RRParamRegistry::RRParamRegistry()
// set up parameters for well-known RRs
// XXX: this should eventually be more automatic.
try {
add("IN", 1, "A", 1);
add("IN", 1, "NS", 2);
add("A", 1, "IN", 1);
add("NS", 2, "IN", 1);
add("CH", 3, "A", 1);
add("A", 1, "CH", 3);
} catch (...) {
delete impl_;
throw;
......@@ -162,8 +161,8 @@ RRParamRegistry::getRegistry()
}
void
RRParamRegistry::add(const string& classcode_string, uint16_t classcode,
const string& typecode_string, uint16_t typecode
RRParamRegistry::add(const string& typecode_string, uint16_t typecode,
const string& classcode_string, uint16_t classcode
/* rdata_factory (notyet) */)
{
// Rollback logic on failure is complicated. If adding the new type or
......@@ -185,10 +184,8 @@ RRParamRegistry::add(const string& classcode_string, uint16_t classcode,
}
try {
addType(typecode_string, typecode);
type_added = true;
addClass(classcode_string, classcode);
class_added = true;
type_added = addType(typecode_string, typecode);
class_added = addClass(classcode_string, classcode);
} catch (...) {
if (will_add_type && type_added) {
removeType(typecode);
......@@ -201,6 +198,29 @@ RRParamRegistry::add(const string& classcode_string, uint16_t classcode,
}
namespace {
///
/// These are helper functions to implement case-insensitive string comparison.
/// This could be simplified using strncasecmp(), but unfortunately it's not
/// included in <cstring>. To be as much as portable within the C++ standard
/// we take the "in house" approach here.
///
bool CICharEqual(char c1, char c2)
{
return (tolower(static_cast<unsigned char>(c1)) ==
tolower(static_cast<unsigned char>(c2)));
}
bool
caseStringEqual(const string& s1, const string& s2, size_t n)
{
if (s1.size() < n || s2.size() < n) {
return (false);
}
return (mismatch(s1.begin(), s1.begin() + n, s2.begin(), CICharEqual).first
== s1.begin() + n);
}
/// Code logic for RRTypes and RRClasses is mostly common except (C++) type and
/// member names. So we define type-independent templates to describe the
/// common logic and let concrete classes to avoid code duplicates.
......@@ -212,7 +232,7 @@ namespace {
/// ET: exception type for error handling: either InvalidRRType or
/// InvalidRRClass
template <typename PT, typename MC, typename MS, typename ET>
inline void
inline bool
addParam(const string& code_string, uint16_t code, MC& codemap, MS& stringmap)
{
// Duplicate type check
......@@ -221,7 +241,7 @@ addParam(const string& code_string, uint16_t code, MC& codemap, MS& stringmap)
if (found->second->code_string_ != code_string) {
dns_throw(ET, "Duplicate RR parameter registration");
}
return;
return (false);
}
typedef shared_ptr<PT> ParamPtr;
......@@ -238,6 +258,8 @@ addParam(const string& code_string, uint16_t code, MC& codemap, MS& stringmap)
codemap.erase(code);
throw;
}
return (true);
}
template <typename MC, typename MS>
......@@ -261,7 +283,7 @@ removeParam(uint16_t code, MC& codemap, MS& stringmap)
template <typename PT, typename MS, typename ET>
inline uint16_t
getCode(const string& code_str, MS& stringmap)
textToCode(const string& code_str, MS& stringmap)
{
typename MS::const_iterator found;
......@@ -287,7 +309,7 @@ getCode(const string& code_str, MS& stringmap)
template <typename PT, typename MC>
inline string
getText(uint16_t code, MC& codemap)
codeToText(uint16_t code, MC& codemap)
{
typename MC::const_iterator found;
......@@ -302,11 +324,11 @@ getText(uint16_t code, MC& codemap)
}
}
void
bool
RRParamRegistry::addType(const string& type_string, uint16_t code)
{
addParam<RRTypeParam, CodeRRTypeMap, StrRRTypeMap, RRTypeExist>
(type_string, code, impl_->code2typemap, impl_->str2typemap);
return (addParam<RRTypeParam, CodeRRTypeMap, StrRRTypeMap, RRTypeExist>
(type_string, code, impl_->code2typemap, impl_->str2typemap));
}
bool
......@@ -317,23 +339,23 @@ RRParamRegistry::removeType(uint16_t code)
}
uint16_t
RRParamRegistry::getTypeCode(const string& type_str) const
RRParamRegistry::textToTypeCode(const string& type_string) const
{
return (getCode<RRTypeParam, StrRRTypeMap,
InvalidRRType>(type_str, impl_->str2typemap));
return (textToCode<RRTypeParam, StrRRTypeMap,
InvalidRRType>(type_string, impl_->str2typemap));
}
string
RRParamRegistry::getTypeText(uint16_t code) const
RRParamRegistry::codeToTypeText(uint16_t code) const
{
return (getText<RRTypeParam, CodeRRTypeMap>(code, impl_->code2typemap));
return (codeToText<RRTypeParam, CodeRRTypeMap>(code, impl_->code2typemap));
}
void
bool
RRParamRegistry::addClass(const string& class_string, uint16_t code)
{
addParam<RRClassParam, CodeRRClassMap, StrRRClassMap, RRClassExist>
(class_string, code, impl_->code2classmap, impl_->str2classmap);
return (addParam<RRClassParam, CodeRRClassMap, StrRRClassMap, RRClassExist>
(class_string, code, impl_->code2classmap, impl_->str2classmap));
}
bool
......@@ -345,16 +367,16 @@ RRParamRegistry::removeClass(uint16_t code)
}
uint16_t
RRParamRegistry::getClassCode(const string& class_str) const
RRParamRegistry::textToClassCode(const string& class_string) const
{
return (getCode<RRClassParam, StrRRClassMap,
InvalidRRClass>(class_str, impl_->str2classmap));
return (textToCode<RRClassParam, StrRRClassMap,
InvalidRRClass>(class_string, impl_->str2classmap));
}
string
RRParamRegistry::getClassText(uint16_t code) const
RRParamRegistry::codeToClassText(uint16_t code) const
{
return (getText<RRClassParam, CodeRRClassMap>(code, impl_->code2classmap));
return (codeToText<RRClassParam, CodeRRClassMap>(code, impl_->code2classmap));
}
}
}
......@@ -26,6 +26,7 @@
namespace isc {
namespace dns {
// forward declarations
struct RRParamRegistryImpl;
///
......@@ -48,34 +49,230 @@ public:
isc::dns::Exception(file, line, what) {}
};
///
/// The \c RRParamRegistry class represents a registry of parameters to
/// manipulate DNS resource records (RRs).
///
/// A \c RRParamRegistry class object stores a mapping between RR types or
/// classes and their textual representations. It will also have knowledge of
/// how to create an RDATA object for a specific pair of RR type and class
/// (not implemented in this version).
///
/// Normal applications that only handle standard DNS protocols won't have to
/// care about this class. This is mostly an internal class to the DNS library
/// to manage standard parameters. Some advanced applications may still need
/// to use this class explicitly. For example, if an application wants to
/// define and use an experimental non-standard RR type, it may want to register
/// related protocol parameters for its convenience. This class is designed to
/// allow such usage without modifying the library source code or rebuilding
/// the library.
///
/// It is assumed that at most one instance of this class can exist so that
/// the application uses the consistent set of registered parameters. To ensure
/// this, this class is designed and implemented as a "singleton class": the
/// constructor is intentionally private, and applications must get access to
/// the single instance via the \c getRegistry() static member function.
///
/// Note: the implementation of this class is incomplete: we should at least
/// add RDATA related parameters. This will be done in a near future version,
/// at which point some of method signatures will be changed.
class RRParamRegistry {
///
/// \name Constructors and Destructor
///
/// These are intentionally hidden (see the class description).
//@{
private:
RRParamRegistry();
~RRParamRegistry();
//@}
public:
void add(const std::string& class_string, uint16_t class_code,
const std::string& type_string, uint16_t type_code);
static RRParamRegistry& getRegistry();
void addClass(const std::string& class_string, uint16_t class_code);
bool removeClass(uint16_t class_code);
///
/// \name Registry Update Methods
///
//@{
///
/// \brief Add a set of parameters for a pair of RR type and class.
///
/// This method adds to the registry a specified set of RR parameters,
/// including mappings between type/class codes and their textual
/// representations.
///
/// Regarding the mappings between textual representations and integer
/// codes, this methods behaves in the same way as \c addType() and
/// \c addClass(). That is, it ignores any overriding attempt as
/// long as the mapping is the same; otherwise the corresponding exception
/// will be thrown.
///
/// This method provides the strong exception guarantee: unless an
/// exception is thrown the entire specified set of parameters must be
/// stored in the registry; if this method throws an exception the
/// registry will remain in the state before this method is called.
///
/// Note: this method will be extended to support more parameters in a
/// near future version.
///
/// \param type_string The textual representation of the RR type.
/// \param type_code The integer code of the RR type.
/// \param class_string The textual representation of the RR class.
/// \param class_code The integer code of the RR class.
void add(const std::string& type_string, uint16_t type_code,
const std::string& class_string, uint16_t class_code);
/// Note:
/// Duplicate type check: if the given type is already registered with the
/// same type string, simply ignore the new attempt.
void addType(const std::string& type_string, uint16_t type_code);
/// \brief Add mappings between RR type code and textual representation.
///
/// This method adds a mapping from the type code of an RR to its textual
/// representation and the reverse mapping in the registry.
///
/// If the given RR type is already registered with the same textual
/// representation, this method simply ignores the duplicate mapping;
/// if the given type is registered and a new pair with a different
/// textual representation is being added,an exception of class
/// \c RRTypeExist will be thrown.
/// To replace an existing mapping with a different textual representation,
/// the existing one must be removed by the \c removeType() method
/// beforehand.
///
/// In addition, if resource allocation for the new mapping entries fails,
/// a corresponding standard exception will be thrown.
///
/// This method provides the strong exception guarantee: unless an exception
/// is thrown the specified mappings must be stored in the registry
/// (although it may be an already existing one) on completion of the
/// method; if this method throws an exception the registry will remain
/// in the state before this method is called.
///
/// \param type_string The textual representation of the RR type.
/// \param type_code The integer code of the RR type.
/// \return \c true if a new mapping is added to the repository; \c false
/// if the same mapping is already registered.
bool addType(const std::string& type_string, uint16_t type_code);
/// \brief Remove mappings between RR type code and textual representation
/// for a given type.
///
/// This method can safely be called whether or not the specified mappings
/// exist in the registry. If not, this method simply ignores the attempt
/// and returns \c false.
///
/// This method never throw an exception.
///
/// \param type_code The integer code of the RR type.
/// \return \c true if mappings for the specified RR type exists and is
/// removed; \c false if no such mapping is in the registry.
bool removeType(uint16_t type_code);
/// Convert type string to the corresponding 16-bit integer code.
uint16_t getClassCode(const std::string& class_str) const;
/// Convert type code into its textual representation.
std::string getClassText(uint16_t class_code) const;
/// \brief Add mappings between RR class code and textual representation.
///
/// This method adds a mapping from the class code of an RR to its textual
/// representation and the reverse mapping in the registry.
///
/// If the given RR class is already registered with the same textual
/// representation, this method simply ignores the duplicate mapping;
/// if the given class is registered and a new pair with a different
/// textual representation is being added,an exception of class
/// \c RRClassExist will be thrown.
/// To replace an existing mapping with a different textual representation,
/// the existing one must be removed by the \c removeClass() method
/// beforehand.
///
/// In addition, if resource allocation for the new mapping entries fails,
/// a corresponding standard exception will be thrown.
///
/// This method provides the strong exception guarantee: unless an exception
/// is thrown the specified mappings must be stored in the registry
/// (although it may be an already existing one) on completion of the
/// method; if this method throws an exception the registry will remain
/// in the state before this method is called.
///
/// \param class_string The textual representation of the RR class.
/// \param class_code The integer code of the RR class.
/// \return
bool addClass(const std::string& class_string, uint16_t class_code);
/// \brief Remove mappings between RR class code and textual representation
/// for a given class.
///
/// This method can safely be called whether or not the specified mappings
/// exist in the registry. If not, this method simply ignores the attempt
/// and returns \c false.
///
/// This method never throw an exception.
///
/// \param class_code The integer code of the RR class.
/// \return
bool removeClass(uint16_t class_code);
//@}
/// Convert type string to the corresponding 16-bit integer code.
uint16_t getTypeCode(const std::string& type_str) const;
/// Convert type code into its textual representation.
std::string getTypeText(uint16_t type_code) const;
///
/// \name Parameter Conversion Methods
///
//@{
/// \brief Convert a textual representation of an RR type to the
/// corresponding 16-bit integer code.
///
/// This method searches the \c RRParamRegistry for the mapping from the
/// given textual representation of RR type to the corresponding integer
/// code. If a mapping is found, it returns the associated type code;
/// otherwise, if the given string is in the form of "TYPEnnnn", it returns
/// the corresponding number as the type code; otherwise, it throws an
/// exception of class \c InvalidRRType.
///
/// \param type_string The textual representation of the RR type.
/// \return The RR type code for \c type_string.
uint16_t textToTypeCode(const std::string& type_string) const;
/// \brief Convert type code into its textual representation.
///
/// This method searches the \c RRParamRegistry for the mapping from the
/// given RR type code to its textual representation.
/// If a mapping is found, it returns (a copy of) the associated string;
/// otherwise, this method creates a new string in the form of "TYPEnnnn"
/// where "nnnn" is the decimal representation of the type code, and
/// returns the new string.
///
/// If resource allocation for the returned string fails,
/// a corresponding standard exception will be thrown.
/// This method never fails otherwise.
///
/// \param type_code The integer code of the RR type.
/// \return A textual representation of the RR type for code \c type_code.
std::string codeToTypeText(uint16_t type_code) const;
/// \brief Convert a textual representation of an RR class to the
/// corresponding 16-bit integer code.
///
/// This method searches the \c RRParamRegistry for the mapping from the
/// given textual representation of RR class to the corresponding integer
/// code. If a mapping is found, it returns the associated class code;
/// otherwise, if the given string is in the form of "CLASSnnnn", it returns
/// the corresponding number as the class code; otherwise, it throws an
/// exception of class \c InvalidRRClass.
///
/// \param class_string The textual representation of the RR class.
/// \return The RR class code for \c class_string.
uint16_t textToClassCode(const std::string& class_string) const;
/// \brief Convert class code into its textual representation.
///
/// This method searches the \c RRParamRegistry for the mapping from the
/// given RR class code to its textual representation.
/// If a mapping is found, it returns (a copy of) the associated string;
/// otherwise, this method creates a new string in the form of "CLASSnnnn"
/// where "nnnn" is the decimal representation of the class code, and
/// returns the new string.
///
/// If resource allocation for the returned string fails,
/// a corresponding standard exception will be thrown.
/// This method never fails otherwise.
///
/// \param class_code The integer code of the RR class.
/// \return A textual representation of the RR class for code \c class_code.
std::string codeToClassText(uint16_t class_code) const;
//@}
static RRParamRegistry& getRegistry();
private:
RRParamRegistryImpl* impl_;
};
......
......@@ -57,8 +57,8 @@ const string RRParamRegistryTest::test_type_str("TESTTYPE");
TEST_F(RRParamRegistryTest, addRemove)
{
RRParamRegistry::getRegistry().add(test_class_str, test_class_code,
test_type_str, test_type_code);
RRParamRegistry::getRegistry().add(test_type_str, test_type_code,
test_class_str, test_class_code);
EXPECT_EQ(65533, RRClass("TESTCLASS").getCode());
EXPECT_EQ(65534, RRType("TESTTYPE").getCode());
......@@ -72,16 +72,16 @@ TEST_F(RRParamRegistryTest, addError)
{
// An attempt to override a pre-registered class should fail with an
// exception, and the pre-registered one should remain in the registry.
EXPECT_THROW(RRParamRegistry::getRegistry().add(test_class_str, 1,
test_type_str,
test_type_code),
EXPECT_THROW(RRParamRegistry::getRegistry().add(test_type_str,
test_type_code,
test_class_str, 1),
RRClassExist);
EXPECT_EQ("IN", RRClass(1).toText());
// Same for RRType
EXPECT_THROW(RRParamRegistry::getRegistry().add(test_class_str,
test_class_code,
test_type_str, 1),
EXPECT_THROW(RRParamRegistry::getRegistry().add(test_type_str, 1,
test_class_str,
test_class_code),
RRTypeExist);
EXPECT_EQ("A", RRType(1).toText());
}
......
......@@ -33,7 +33,7 @@ namespace dns {
RRType::RRType(const string& typestr)
{
typecode_ = RRParamRegistry::getRegistry().getTypeCode(typestr);
typecode_ = RRParamRegistry::getRegistry().textToTypeCode(typestr);
}
RRType::RRType(InputBuffer& buffer)
......@@ -47,7 +47,7 @@ RRType::RRType(InputBuffer& buffer)
const string
RRType::toText() const
{
return (RRParamRegistry::getRegistry().getTypeText(typecode_));
return (RRParamRegistry::getRegistry().codeToTypeText(typecode_));
}
void
......
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