[svn] commit: r441 - in /branches/jinmei-dnsrrparams/src/lib/dns/cpp: rrparamregistry.cc rrtype_unittest.cc

BIND 10 source code commits bind10-changes at lists.isc.org
Mon Jan 11 23:12:01 UTC 2010


Author: jinmei
Date: Mon Jan 11 23:12:00 2010
New Revision: 441

Log:
templatized common logic for RRType and RRClass to avoid code duplicate

Modified:
    branches/jinmei-dnsrrparams/src/lib/dns/cpp/rrparamregistry.cc
    branches/jinmei-dnsrrparams/src/lib/dns/cpp/rrtype_unittest.cc

Modified: branches/jinmei-dnsrrparams/src/lib/dns/cpp/rrparamregistry.cc
==============================================================================
--- branches/jinmei-dnsrrparams/src/lib/dns/cpp/rrparamregistry.cc (original)
+++ branches/jinmei-dnsrrparams/src/lib/dns/cpp/rrparamregistry.cc Mon Jan 11 23:12:00 2010
@@ -73,10 +73,10 @@
 };
 
 struct RRTypeParam {
-    RRTypeParam(const string& type_string, uint16_t type_code) :
-        type_string_(type_string), type_code_(type_code) {}
-    string type_string_;
-    uint16_t type_code_;
+    RRTypeParam(const string& code_string, uint16_t code) :
+        code_string_(code_string), code_(code) {}
+    string code_string_;
+    uint16_t code_;
 
     /// magic constants
     static const unsigned int MAX_CODE = 0xffff;
@@ -87,8 +87,6 @@
 };
 
 typedef shared_ptr<RRTypeParam> RRTypeParamPtr;
-typedef pair<string, RRTypeParamPtr> StrRRTypePair;
-typedef pair<uint16_t, RRTypeParamPtr> CodeRRTypePair;
 typedef map<string, RRTypeParamPtr, CIStringLess> StrRRTypeMap;
 typedef map<uint16_t, RRTypeParamPtr> CodeRRTypeMap;
 
@@ -100,10 +98,10 @@
     RRTypeParam::UNKNOWN_MAX.size();
 
 struct RRClassParam {
-    RRClassParam(const string& class_string, uint16_t class_code) :
-        class_string_(class_string), class_code_(class_code) {}
-    string class_string_;
-    uint16_t class_code_;
+    RRClassParam(const string& code_string, uint16_t code) :
+        code_string_(code_string), code_(code) {}
+    string code_string_;
+    uint16_t code_;
 
     /// magic constants
     static const unsigned int MAX_CODE = 0xffff;
@@ -114,8 +112,6 @@
 };
 
 typedef shared_ptr<RRClassParam> RRClassParamPtr;
-typedef pair<string, RRClassParamPtr> StrRRClassPair;
-typedef pair<uint16_t, RRClassParamPtr> CodeRRClassPair;
 typedef map<string, RRClassParamPtr, CIStringLess> StrRRClassMap;
 typedef map<uint16_t, RRClassParamPtr> CodeRRClassMap;
 
@@ -166,204 +162,192 @@
 }
 
 void
-RRParamRegistry::add(const string& class_string, uint16_t class_code,
-                     const string& type_string, uint16_t type_code
+RRParamRegistry::add(const string& classcode_string, uint16_t classcode,
+                     const string& typecode_string, uint16_t typecode
                      /* rdata_factory (notyet) */)
 {
     // XXX: rollback logic on failure is complicated.
     bool add_type = false;
     bool add_class = false;
 
-    if (impl_->code2typemap.find(type_code) == impl_->code2typemap.end()) {
+    if (impl_->code2typemap.find(typecode) == impl_->code2typemap.end()) {
         add_type = true;
     }
-    if (impl_->code2classmap.find(class_code) == impl_->code2classmap.end()) {
+    if (impl_->code2classmap.find(classcode) == impl_->code2classmap.end()) {
         add_class = true;
     }
 
     try {
-        addType(type_string, type_code);
-        addClass(class_string, class_code);
+        addType(typecode_string, typecode);
+        addClass(classcode_string, classcode);
     } catch (...) {
         if (add_type) {
-            removeType(type_code);
+            removeType(typecode);
         }
         if (add_class) {
-            removeClass(class_code);
+            removeClass(classcode);
         }
         throw;
     }
 }
 
-void
-RRParamRegistry::addClass(const string& class_string, uint16_t class_code)
+namespace {
+/// 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.
+/// The following summarize template parameters used in the set of template
+/// functions:
+/// PT: parameter type, either RRTypeParam or RRClassParam
+/// MC: type of mapping class from code: either CodeRRTypeMap or CodeRRClassMap
+/// MS: type of mapping class from string: either StrRRTypeMap or StrRRClassMap
+/// ET: exception type for error handling: either InvalidRRType or
+///     InvalidRRClass
+template <typename PT, typename MC, typename MS>
+inline void
+addParam(const string& code_string, uint16_t code, MC& codemap, MS& stringmap)
 {
     // Duplicate type check
-    CodeRRClassMap::const_iterator found =
-        impl_->code2classmap.find(class_code);
-    if (found != impl_->code2classmap.end()) {
-        if (found->second->class_string_ != class_string) {
-            dns_throw(RRClassExist, "Duplicate RR class registration");
+    typename MC::const_iterator found = codemap.find(code);
+    if (codemap.find(code) != codemap.end()) {
+        if (codemap.find(code)->second->code_string_ != code_string) {
+            dns_throw(RRClassExist, "Duplicate RR parameter registration");
         }
         return;
     }
 
-    RRClassParamPtr class_param = RRClassParamPtr(new RRClassParam(class_string,
-                                                               class_code));
+    typedef shared_ptr<PT> ParamPtr;
+    typedef pair<string, ParamPtr> StrParamPair;
+    typedef pair<uint16_t, ParamPtr> CodeParamPair;
+    ParamPtr param = ParamPtr(new PT(code_string, code));
     try {
-        impl_->str2classmap.insert(StrRRClassPair(class_string, class_param));
-        impl_->code2classmap.insert(CodeRRClassPair(class_code, class_param));
+        stringmap.insert(StrParamPair(code_string, param));
+        codemap.insert(CodeParamPair(code, param));
     } catch (...) {
         // Rollback to the previous state: not all of the erase operations will
         // find the entry, but we don't care.
-        impl_->str2classmap.erase(class_string);
-        impl_->code2classmap.erase(class_code);
+        stringmap.erase(code_string);
+        codemap.erase(code);
         throw;
     }
 }
 
-bool
-RRParamRegistry::removeClass(uint16_t class_code)
-{
-    CodeRRClassMap::iterator found = impl_->code2classmap.find(class_code);
-    if (found != impl_->code2classmap.end()) {
-        size_t erased = impl_->str2classmap.erase(found->second->class_string_);
+template <typename MC, typename MS>
+inline bool
+removeParam(uint16_t code, MC& codemap, MS& stringmap)
+{
+    typename MC::iterator found = codemap.find(code);
+
+    if (found != codemap.end()) {
+        size_t erased = stringmap.erase(found->second->code_string_);
         // We must have a corresponding entry of the str2 map exists
         assert(erased == 1);
 
-        impl_->code2classmap.erase(found);
+        codemap.erase(found);
 
         return (true);
     }
 
     return (false);
+}
+
+template <typename PT, typename MS, typename ET>
+inline uint16_t
+getCode(const string& code_str, MS& stringmap)
+{
+    typename MS::const_iterator found;
+
+    found = stringmap.find(code_str);
+    if (found != stringmap.end()) {
+        return (found->second->code_);
+    }
+
+    size_t l = code_str.size();
+    if (l > PT::UNKNOWN_PREFIXLEN &&
+        l <= PT::UNKNOWN_MAXLEN &&
+        caseStringEqual(code_str, PT::UNKNOWN_PREFIX, PT::UNKNOWN_PREFIXLEN)) {
+        unsigned int code;
+        istringstream iss(code_str.substr(PT::UNKNOWN_PREFIXLEN,
+                                           l - PT::UNKNOWN_PREFIXLEN));
+        iss >> dec >> code;
+        if (iss.rdstate() == ios::eofbit && code <= PT::MAX_CODE) {
+            return (code);
+        }
+    }
+    dns_throw(ET, "Unrecognized RR parameter string");
+}
+
+template <typename PT, typename MC>
+inline string
+getText(uint16_t code, MC& codemap)
+{
+    typename MC::const_iterator found;
+
+    found = codemap.find(code);
+    if (found != codemap.end()) {
+        return (found->second->code_string_);
+    }
+
+    ostringstream ss;
+    ss << code;
+    return (PT::UNKNOWN_PREFIX + ss.str());
+}
+}
+
+void
+RRParamRegistry::addType(const string& type_string, uint16_t code)
+{
+    addParam<RRTypeParam, CodeRRTypeMap, StrRRTypeMap>(type_string, code,
+                                                       impl_->code2typemap,
+                                                       impl_->str2typemap);
+}
+
+bool
+RRParamRegistry::removeType(uint16_t code)
+{
+    return (removeParam<CodeRRTypeMap, StrRRTypeMap>(code, impl_->code2typemap,
+                                                     impl_->str2typemap));
+}
+
+uint16_t
+RRParamRegistry::getTypeCode(const string& type_str) const
+{
+    return (getCode<RRTypeParam, StrRRTypeMap,
+            InvalidRRType>(type_str, impl_->str2typemap));
+}
+
+string
+RRParamRegistry::getTypeText(uint16_t code) const
+{
+    return (getText<RRTypeParam, CodeRRTypeMap>(code, impl_->code2typemap));
+}
+
+void
+RRParamRegistry::addClass(const string& class_string, uint16_t code)
+{
+    addParam<RRClassParam, CodeRRClassMap, StrRRClassMap>(class_string, code,
+                                                          impl_->code2classmap,
+                                                          impl_->str2classmap);
+}
+
+bool
+RRParamRegistry::removeClass(uint16_t code)
+{
+    return (removeParam<CodeRRClassMap, StrRRClassMap>(code,
+                                                       impl_->code2classmap,
+                                                       impl_->str2classmap));
 }
 
 uint16_t
 RRParamRegistry::getClassCode(const string& class_str) const
 {
-    StrRRClassMap::const_iterator found;
-
-    found = impl_->str2classmap.find(class_str);
-    if (found != impl_->str2classmap.end()) {
-        return (found->second->class_code_);
-    }
-
-    size_t l = class_str.size();
-    if (l > RRClassParam::UNKNOWN_PREFIXLEN &&
-        l <= RRClassParam::UNKNOWN_MAXLEN &&
-        caseStringEqual(class_str, RRClassParam::UNKNOWN_PREFIX,
-                        RRClassParam::UNKNOWN_PREFIXLEN)) {
-        unsigned int code;
-        istringstream iss(class_str.substr(RRClassParam::UNKNOWN_PREFIXLEN,
-                                           l -
-                                           RRClassParam::UNKNOWN_PREFIXLEN));
-        iss >> dec >> code;
-        if (iss.rdstate() == ios::eofbit && code <= RRClassParam::MAX_CODE) {
-            return (code);
-        }
-    }
-    dns_throw(InvalidRRClass, "Unrecognized RR Class string");
+    return (getCode<RRClassParam, StrRRClassMap,
+            InvalidRRClass>(class_str, impl_->str2classmap));
 }
 
 string
-RRParamRegistry::getClassText(uint16_t class_code) const
-{
-    CodeRRClassMap::const_iterator found;
-
-    found = impl_->code2classmap.find(class_code);
-    if (found != impl_->code2classmap.end()) {
-        return (found->second->class_string_);
-    }
-
-    ostringstream ss;
-    ss << class_code;
-    return (RRClassParam::UNKNOWN_PREFIX + ss.str());
-}
-
-///
-/// The code logic is same as addClass(), but we only have these two variations
-/// we live with duplicate rather than trying to unify them.
-///
-void
-RRParamRegistry::addType(const string& type_string, uint16_t type_code)
-{
-    CodeRRTypeMap::const_iterator found = impl_->code2typemap.find(type_code);
-    if (found != impl_->code2typemap.end()) {
-        if (found->second->type_string_ != type_string) {
-            dns_throw(RRTypeExist, "Duplicate RR type registration");
-        }
-        return;
-    }
-
-    RRTypeParamPtr type_param = RRTypeParamPtr(new RRTypeParam(type_string,
-                                                               type_code));
-    try {
-        impl_->str2typemap.insert(StrRRTypePair(type_string, type_param));
-        impl_->code2typemap.insert(CodeRRTypePair(type_code, type_param));
-    } catch (...) {
-        impl_->str2typemap.erase(type_string);
-        impl_->code2typemap.erase(type_code);
-        throw;
-    }
-}
-
-bool
-RRParamRegistry::removeType(uint16_t type_code)
-{
-    CodeRRTypeMap::iterator found = impl_->code2typemap.find(type_code);
-    if (found != impl_->code2typemap.end()) {
-        size_t erased = impl_->str2typemap.erase(found->second->type_string_);
-        // We must have a corresponding entry of the str2 map exists
-        assert(erased == 1);
-
-        impl_->code2typemap.erase(found);
-
-        return (true);
-    }
-
-    return (false);
-}
-
-uint16_t
-RRParamRegistry::getTypeCode(const string& type_str) const
-{
-    StrRRTypeMap::const_iterator found;
-
-    found = impl_->str2typemap.find(type_str);
-    if (found != impl_->str2typemap.end()) {
-        return (found->second->type_code_);
-    }
-
-    size_t l = type_str.size();
-    if (l > RRTypeParam::UNKNOWN_PREFIXLEN &&
-        l <= RRTypeParam::UNKNOWN_MAXLEN &&
-        caseStringEqual(type_str, RRTypeParam::UNKNOWN_PREFIX,
-                        RRTypeParam::UNKNOWN_PREFIXLEN)) {
-        unsigned int code;
-        istringstream iss(type_str.substr(RRTypeParam::UNKNOWN_PREFIXLEN,
-                                          l - RRTypeParam::UNKNOWN_PREFIXLEN));
-        iss >> dec >> code;
-        if (iss.rdstate() == ios::eofbit && code <= RRTypeParam::MAX_CODE) {
-            return (code);
-        }
-    }
-    dns_throw(InvalidRRType, "Unrecognized RR Type string");
-}
-
-string
-RRParamRegistry::getTypeText(uint16_t type_code) const
-{
-    CodeRRTypeMap::const_iterator found;
-
-    found = impl_->code2typemap.find(type_code);
-    if (found != impl_->code2typemap.end()) {
-        return (found->second->type_string_);
-    }
-
-    ostringstream ss;
-    ss << type_code;
-    return (RRTypeParam::UNKNOWN_PREFIX + ss.str());
-}
-}
-}
+RRParamRegistry::getClassText(uint16_t code) const
+{
+    return (getText<RRClassParam, CodeRRClassMap>(code, impl_->code2classmap));
+}
+}
+}

Modified: branches/jinmei-dnsrrparams/src/lib/dns/cpp/rrtype_unittest.cc
==============================================================================
--- branches/jinmei-dnsrrparams/src/lib/dns/cpp/rrtype_unittest.cc (original)
+++ branches/jinmei-dnsrrparams/src/lib/dns/cpp/rrtype_unittest.cc Mon Jan 11 23:12:00 2010
@@ -35,6 +35,7 @@
 
     // bogus TYPEnnn representations: should trigger an exception
     EXPECT_THROW(RRType("TYPE"), isc::dns::InvalidRRType);
+    EXPECT_THROW(RRType("TYPE-1"), isc::dns::InvalidRRType);
     EXPECT_THROW(RRType("TYPExxx"), isc::dns::InvalidRRType);
     EXPECT_THROW(RRType("TYPE65536"), isc::dns::InvalidRRType);
     EXPECT_THROW(RRType("TYPE6500x"), isc::dns::InvalidRRType);




More information about the bind10-changes mailing list