Parcourir la source

addressed review comments 2 of 3 (or 4)

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac172@2296 e5f2f494-b856-4b98-b285-d166d9295462
Jelte Jansen il y a 15 ans
Parent
commit
bd8add5608
3 fichiers modifiés avec 132 ajouts et 20 suppressions
  1. 73 13
      src/lib/cc/data.cc
  2. 16 0
      src/lib/cc/data.h
  3. 43 7
      src/lib/cc/data_unittests.cc

+ 73 - 13
src/lib/cc/data.cc

@@ -30,6 +30,8 @@
 
 using namespace std;
 
+#define MAX_LABEL_LENGTH 255
+
 namespace isc {
 namespace data {
 
@@ -347,6 +349,11 @@ word_from_stringstream(std::istream &in, int& pos) {
 inline int
 count_chars_i(int i) {
     int result = 1;
+    if (i < 0) {
+        i = -i;
+        // account for the '-' symbol
+        result += 1;
+    }
     while (i > 10) {
         ++result;
         i = i / 10;
@@ -359,7 +366,7 @@ count_chars_i(int i) {
 // value is larger than an int can handle)
 ElementPtr
 from_stringstream_number(std::istream &in, int &pos) {
-    int i, d_i;
+    int i = 0;
     double d = 0.0;
     bool is_double = false;
 
@@ -369,6 +376,7 @@ from_stringstream_number(std::istream &in, int &pos) {
         isc_throw(JSONError, "Bad integer or overflow");
     }
     if (in.peek() == '.') {
+        int d_i = 0;
         is_double = true;
         in.get();
         pos++;
@@ -376,7 +384,14 @@ from_stringstream_number(std::istream &in, int &pos) {
         if (in.fail()) {
             isc_throw(JSONError, "Bad real or overflow");
         }
-        d = i + (double)d_i / 10;
+        d = (double)d_i / 10;
+        while (d > 1.0) {
+            d = d / 10;
+        }
+        if (i < 0) {
+            d = - d;
+        }
+        d += i;
         pos += count_chars_i(d_i);
     }
     if (in.peek() == 'e' || in.peek() == 'E') {
@@ -481,11 +496,6 @@ from_stringstream_map(std::istream &in, const std::string& file, int& line,
     } else {
         while (c != EOF && c != '}') {
             std::string key = str_from_stringstream(in, file, line, pos);
-            if (key.length() > 255) {
-                // Map tag has one-byte length field in wire format, so the
-                // length cannot exceed 255.
-                throwJSONError("Map tag is too long", file, line, pos);
-            }
 
             skip_to(in, file, line, pos, ":", " \t\n");
             // skip the :
@@ -504,6 +514,54 @@ from_stringstream_map(std::istream &in, const std::string& file, int& line,
 }
 }
 
+std::string
+Element::typeToName(Element::types type)
+{
+    switch(type) {
+    case Element::integer:
+        return std::string("integer");
+    case Element::real:
+        return std::string("real");
+    case Element::boolean:
+        return std::string("boolean");
+    case Element::string:
+        return std::string("string");
+    case Element::list:
+        return std::string("list");
+    case Element::map:
+        return std::string("map");
+    case Element::null:
+        return std::string("null");
+    case Element::any:
+        return std::string("any");
+    default:
+        return std::string("unknown");
+    }
+}
+
+Element::types
+Element::nameToType(const std::string& type_name) {
+    if (type_name == "integer") {
+        return Element::integer;
+    } else if (type_name == "real") {
+        return Element::real;
+    } else if (type_name == "boolean") {
+        return Element::boolean;
+    } else if (type_name == "string") {
+        return Element::string;
+    } else if (type_name == "list") {
+        return Element::list;
+    } else if (type_name == "map") {
+        return Element::map;
+    } else if (type_name == "null") {
+        return Element::null;
+    } else if (type_name == "any") {
+        return Element::any;
+    } else {
+        isc_throw(TypeError, type_name + " is not a valid type name");
+    }
+}
+
 ElementPtr
 Element::fromJSON(std::istream& in) throw(JSONError) {
     int line = 1, pos = 1;
@@ -538,10 +596,15 @@ Element::fromJSON(std::istream &in, const std::string& file, int& line, int& pos
             case '8':
             case '9':
             case '0':
+            case '-':
                 in.putback(c);
                 element = from_stringstream_number(in, pos);
                 el_read = true;
                 break;
+            case '+':
+                element = from_stringstream_number(in, pos);
+                el_read = true;
+                break;
             case 't':
             case 'T':
             case 'f':
@@ -551,6 +614,7 @@ Element::fromJSON(std::istream &in, const std::string& file, int& line, int& pos
                 el_read = true;
                 break;
             case 'n':
+            case 'N':
                 in.putback(c);
                 element = from_stringstream_null(in, file, line, pos);
                 el_read = true;
@@ -606,7 +670,7 @@ DoubleElement::toJSON(std::ostream& ss)
 void
 BoolElement::toJSON(std::ostream& ss)
 {
-    if (b) {
+    if (boolValue()) {
         ss << "true";
     } else {
         ss << "false";
@@ -714,11 +778,7 @@ Element::fromWire(std::stringstream& in, int length) {
 
 void
 MapElement::set(const std::string& key, ElementPtr value) {
-    if (key.length() <= 255) {
-        m[key] = value;
-    } else {
-        isc_throw(TypeError, "Map key too long");
-    }
+    m[key] = value;
 }
 
 bool

+ 16 - 0
src/lib/cc/data.h

@@ -316,6 +316,22 @@ public:
     static ElementPtr fromJSON(std::istream& in, const std::string& file, int& line, int &pos) throw(JSONError);
     //@}
 
+    /// \name Type name conversion functions
+
+    /// Returns the name of the given type as a string
+    ///
+    /// \param type The type to return the name of
+    /// \return The name of the type, or "unknown" if the type
+    ///         is not known.
+    static std::string typeToName(Element::types type);
+
+    /// Converts the string to the corresponding type
+    /// Throws a TypeError if the name is unknown.
+    ///
+    /// \param type_name The name to get the type of
+    /// \return the corresponding type value
+    static Element::types nameToType(const std::string& type_name);
+
     /// \name Wire format factory functions
 
     /// These function pparse the wireformat at the given stringstream

+ 43 - 7
src/lib/cc/data_unittests.cc

@@ -47,6 +47,28 @@ TEST(Element, type) {
 
 }
 
+TEST(Element, TypeNameConversion) {
+    EXPECT_EQ(Element::integer, Element::nameToType("integer"));
+    EXPECT_EQ(Element::real, Element::nameToType("real"));
+    EXPECT_EQ(Element::boolean, Element::nameToType("boolean"));
+    EXPECT_EQ(Element::string, Element::nameToType("string"));
+    EXPECT_EQ(Element::list, Element::nameToType("list"));
+    EXPECT_EQ(Element::map, Element::nameToType("map"));
+    EXPECT_EQ(Element::null, Element::nameToType("null"));
+    EXPECT_EQ(Element::any, Element::nameToType("any"));
+    EXPECT_THROW(Element::nameToType("somethingunknown"), TypeError);
+
+    EXPECT_EQ("integer", Element::typeToName(Element::integer));
+    EXPECT_EQ("real", Element::typeToName(Element::real));
+    EXPECT_EQ("boolean", Element::typeToName(Element::boolean));
+    EXPECT_EQ("string", Element::typeToName(Element::string));
+    EXPECT_EQ("list", Element::typeToName(Element::list));
+    EXPECT_EQ("map", Element::typeToName(Element::map));
+    EXPECT_EQ("null", Element::typeToName(Element::null));
+    EXPECT_EQ("any", Element::typeToName(Element::any));
+    EXPECT_EQ("unknown", Element::typeToName((Element::types)123));
+}
+
 TEST(Element, from_and_to_json) {
     // this test checks whether the str() method returns the same
     // string that was used for creation
@@ -62,7 +84,13 @@ TEST(Element, from_and_to_json) {
     sv.push_back("[ 1, 2, 3, 4 ]");
     sv.push_back("{ \"name\": \"foo\", \"value\": 47806 }");
     sv.push_back("[ { \"a\": 1, \"b\": \"c\" }, { \"a\": 2, \"b\": \"d\" } ]");
-
+    sv.push_back("8.23");
+    sv.push_back("123.456");
+    sv.push_back("null");
+    sv.push_back("-1");
+    sv.push_back("-1.234");
+    sv.push_back("-123.456");
+    
     BOOST_FOREACH(std::string s, sv) {
         // test << operator, which uses Element::str()
         std::ostringstream stream;
@@ -101,8 +129,12 @@ TEST(Element, from_and_to_json) {
 
     // some json specific format tests, here the str() output is
     // different from the string input
+    EXPECT_EQ("100", Element::fromJSON("+100")->str());
     EXPECT_EQ("100", Element::fromJSON("1e2")->str());
+    EXPECT_EQ("100", Element::fromJSON("+1e2")->str());
+    EXPECT_EQ("-100", Element::fromJSON("-1e2")->str());
     EXPECT_EQ("0.01", Element::fromJSON("1e-2")->str());
+    EXPECT_EQ("-0.01", Element::fromJSON("-1e-2")->str());
     EXPECT_EQ("1.2", Element::fromJSON("1.2")->str());
     EXPECT_EQ("1", Element::fromJSON("1.0")->str());
     EXPECT_EQ("120", Element::fromJSON("1.2e2")->str());
@@ -111,6 +143,12 @@ TEST(Element, from_and_to_json) {
     EXPECT_EQ("0.01", Element::fromJSON("1.0e-2")->str());
     EXPECT_EQ("0.012", Element::fromJSON("1.2e-2")->str());
     EXPECT_EQ("0.012", Element::fromJSON("1.2E-2")->str());
+    EXPECT_EQ("null", Element::fromJSON("Null")->str());
+    EXPECT_EQ("null", Element::fromJSON("NULL")->str());
+    EXPECT_EQ("false", Element::fromJSON("False")->str());
+    EXPECT_EQ("false", Element::fromJSON("FALSE")->str());
+    EXPECT_EQ("true", Element::fromJSON("True")->str());
+    EXPECT_EQ("true", Element::fromJSON("TRUE")->str());
 
     // number overflows
     EXPECT_THROW(Element::fromJSON("12345678901234567890")->str(), JSONError);
@@ -326,13 +364,11 @@ TEST(Element, MapElement) {
     el->set(long_maptag, Element::create("bar"));
     EXPECT_EQ("bar", el->find(long_maptag)->stringValue());
 
-    // A one-byte longer tag should trigger an exception.
+    // A one-byte longer tag should still be allowed
     long_maptag.push_back('f');
-    EXPECT_THROW(Element::fromJSON("{ \"" + long_maptag +
-                                           "\": \"bar\"}"),
-                 JSONError);
-
-    EXPECT_THROW(el->set(long_maptag, Element::create("bar")), TypeError);
+    el = Element::fromJSON("{ \"" + long_maptag + "\": \"bar\"}");
+    el->set(long_maptag, Element::create("bar"));
+    EXPECT_EQ("bar", el->find(long_maptag)->stringValue());
 
 }