Commit bd8add56 authored by Jelte Jansen's avatar Jelte Jansen

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
parent a4939e49
......@@ -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
......
......@@ -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
......
......@@ -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());
}
......
Markdown is supported
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