From: Marcin Siodelski Date: Tue, 22 Apr 2014 14:40:29 +0000 (+0200) Subject: [3409] Updated Element data structure to hold the file name. X-Git-Tag: trac3434_base~43^2~13 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bfe07f025a37395d8bf1fdc5878b91aaeba80fd8;p=thirdparty%2Fkea.git [3409] Updated Element data structure to hold the file name. --- diff --git a/src/lib/cc/data.cc b/src/lib/cc/data.cc index f833230db1..075447abaa 100644 --- a/src/lib/cc/data.cc +++ b/src/lib/cc/data.cc @@ -41,6 +41,19 @@ const char* const WHITESPACE = " \b\f\n\r\t"; namespace isc { namespace data { +std::string +Element::Position::str() const { + std::ostringstream ss; + ss << file_ << ":" << line_ << ":" << pos_; + return (ss.str()); +} + +std::ostream& +operator<<(std::ostream& out, const Element::Position& pos) { + out << pos.str(); + return (out); +} + std::string Element::str() const { std::stringstream ss; @@ -425,7 +438,7 @@ fromStringstreamNumber(std::istream& in, const std::string& file, if (number.find_first_of(".eE") < number.size()) { try { return (Element::create(boost::lexical_cast(number), - Element::Position(line, start_pos))); + Element::Position(file, line, start_pos))); } catch (const boost::bad_lexical_cast&) { throwJSONError(std::string("Number overflow: ") + number, file, line, start_pos); @@ -433,7 +446,7 @@ fromStringstreamNumber(std::istream& in, const std::string& file, } else { try { return (Element::create(boost::lexical_cast(number), - Element::Position(line, start_pos))); + Element::Position(file, line, start_pos))); } catch (const boost::bad_lexical_cast&) { throwJSONError(std::string("Number overflow: ") + number, file, line, start_pos); @@ -453,9 +466,11 @@ fromStringstreamBool(std::istream& in, const std::string& file, const std::string word = wordFromStringstream(in, pos); if (boost::iequals(word, "True")) { - return (Element::create(true, Element::Position(line, start_pos))); + return (Element::create(true, Element::Position(file, line, + start_pos))); } else if (boost::iequals(word, "False")) { - return (Element::create(false, Element::Position(line, start_pos))); + return (Element::create(false, Element::Position(file, line, + start_pos))); } else { throwJSONError(std::string("Bad boolean value: ") + word, file, line, start_pos); @@ -473,7 +488,7 @@ fromStringstreamNull(std::istream& in, const std::string& file, // This will move the pos to the end of the value. const std::string word = wordFromStringstream(in, pos); if (boost::iequals(word, "null")) { - return (Element::create(Element::Position(line, start_pos))); + return (Element::create(Element::Position(file, line, start_pos))); } else { throwJSONError(std::string("Bad null value: ") + word, file, line, start_pos); @@ -490,7 +505,8 @@ fromStringstreamString(std::istream& in, const std::string& file, int& line, const uint32_t start_pos = pos; // This will move the pos to the end of the value. const std::string string_value = strFromStringstream(in, file, line, pos); - return (Element::create(string_value, Element::Position(line, start_pos))); + return (Element::create(string_value, Element::Position(file, line, + start_pos))); } ElementPtr @@ -498,7 +514,7 @@ fromStringstreamList(std::istream& in, const std::string& file, int& line, int& pos) { int c = 0; - ElementPtr list = Element::createList(Element::Position(line, pos)); + ElementPtr list = Element::createList(Element::Position(file, line, pos)); ConstElementPtr cur_list_element; skipChars(in, WHITESPACE, line, pos); @@ -519,7 +535,7 @@ ElementPtr fromStringstreamMap(std::istream& in, const std::string& file, int& line, int& pos) { - ElementPtr map = Element::createMap(Element::Position(line, pos)); + ElementPtr map = Element::createMap(Element::Position(file, line, pos)); skipChars(in, WHITESPACE, line, pos); int c = in.peek(); if (c == EOF) { diff --git a/src/lib/cc/data.h b/src/lib/cc/data.h index 0850abfa38..d77d37d193 100644 --- a/src/lib/cc/data.h +++ b/src/lib/cc/data.h @@ -77,8 +77,8 @@ public: /// \brief Represents the position of the data element within a /// configuration string. /// - /// Position comprises a line number and an offset within this line - /// where the element value starts. For example, if the JSON string is + /// Position comprises a file name, line number and an offset within this + /// line where the element value starts. For example, if the JSON string is /// /// \code /// { "foo": "some string", @@ -94,26 +94,35 @@ public: /// uint32_t arguments holding line number and position within the line are /// not confused with the @c Element values passed to these functions. struct Position { - uint32_t line_; ///< Line number. - uint32_t pos_; ///< Position within the line. + std::string file_; ///< File name. + uint32_t line_; ///< Line number. + uint32_t pos_; ///< Position within the line. /// \brief Constructor. /// + /// \param file File name. /// \param line Line number. /// \param pos Position within the line. - Position(const uint32_t line, const uint32_t pos) - : line_(line), pos_(pos) { + Position(const std::string& file, const uint32_t line, + const uint32_t pos) + : file_(file), line_(line), pos_(pos) { } + + /// \brief Returns the position in the textual format. + /// + /// The returned position has the following format: file:line:pos. + std::string str() const; }; - /// \brief Returns @c Position object with line_ and pos_ set to 0. + /// \brief Returns @c Position object with line_ and pos_ set to 0, and + /// with an empty file name. /// /// The object containing two zeros is a default for most of the /// methods creating @c Element objects. The returned value is static /// so as it is not created everytime the function with the default /// position argument is called. static const Position& ZERO_POSITION() { - static Position position(0, 0); + static Position position("", 0, 0); return (position); } @@ -657,6 +666,19 @@ ConstElementPtr removeIdentical(ConstElementPtr a, ConstElementPtr b); /// Raises a TypeError if either ElementPtr is not a MapElement void merge(ElementPtr element, ConstElementPtr other); +/// +/// \brief Insert Element::Position as a string into stream. +/// +/// This operator converts the \c Element::Position into a string and +/// inserts it into the output stream \c out. +/// +/// \param out A \c std::ostream object on which the insertion operation is +/// performed. +/// \param pos The \c Element::Position structure to insert. +/// \return A reference to the same \c std::ostream object referenced by +/// parameter \c out after the insertion operation. +std::ostream& operator<<(std::ostream& out, const Element::Position& pos); + /// /// \brief Insert the Element as a string into stream. /// diff --git a/src/lib/cc/tests/data_unittests.cc b/src/lib/cc/tests/data_unittests.cc index 8e31c32a15..8ddfae9bd8 100644 --- a/src/lib/cc/tests/data_unittests.cc +++ b/src/lib/cc/tests/data_unittests.cc @@ -30,6 +30,15 @@ using std::setw; using std::string; namespace { + +TEST(Position, str) { + Element::Position position("kea.conf", 30, 20); + EXPECT_EQ("kea.conf:30:20", position.str()); + + Element::Position position2("another.conf", 123, 24); + EXPECT_EQ("another.conf:123:24", position2.str()); +} + TEST(Element, type) { // this tests checks whether the getType() function returns the // correct type @@ -931,22 +940,24 @@ TEST(Element, merge) { } TEST(Element, getPosition) { + std::istringstream ss("{\n" + " \"a\": 2,\n" + " \"b\":true,\n" + " \"cy\": \"a string\",\n" + " \"dyz\": {\n" + "\n" + " \"e\": 3,\n" + " \"f\": null\n" + "\n" + " },\n" + " \"g\": [ 5, 6,\n" + " 7 ]\n" + "}\n"); + // Create a JSON string holding different type of values. Some of the // values in the config string are not aligned, so as we can check that // the position is set correctly for the elements. - ElementPtr top = Element::fromJSON("{\n" - " \"a\": 2,\n" - " \"b\":true,\n" - " \"cy\": \"a string\",\n" - " \"dyz\": {\n" - "\n" - " \"e\": 3,\n" - " \"f\": null\n" - "\n" - " },\n" - " \"g\": [ 5, 6,\n" - " 7 ]\n" - "}\n"); + ElementPtr top = Element::fromJSON(ss, "kea.conf"); ASSERT_TRUE(top); // Element "a" @@ -954,36 +965,42 @@ TEST(Element, getPosition) { ASSERT_TRUE(level1_el); EXPECT_EQ(2, level1_el->getPosition().line_); EXPECT_EQ(11, level1_el->getPosition().pos_); + EXPECT_EQ("kea.conf", level1_el->getPosition().file_); // Element "b" level1_el = top->get("b"); ASSERT_TRUE(level1_el); EXPECT_EQ(3, level1_el->getPosition().line_); EXPECT_EQ(9, level1_el->getPosition().pos_); + EXPECT_EQ("kea.conf", level1_el->getPosition().file_); // Element "cy" level1_el = top->get("cy"); ASSERT_TRUE(level1_el); EXPECT_EQ(4, level1_el->getPosition().line_); EXPECT_EQ(11, level1_el->getPosition().pos_); + EXPECT_EQ("kea.conf", level1_el->getPosition().file_); // Element "dyz" level1_el = top->get("dyz"); ASSERT_TRUE(level1_el); EXPECT_EQ(5, level1_el->getPosition().line_); EXPECT_EQ(13, level1_el->getPosition().pos_); + EXPECT_EQ("kea.conf", level1_el->getPosition().file_); // Element "e" is a sub element of "dyz". ConstElementPtr level2_el = level1_el->get("e"); ASSERT_TRUE(level2_el); EXPECT_EQ(7, level2_el->getPosition().line_); EXPECT_EQ(12, level2_el->getPosition().pos_); + EXPECT_EQ("kea.conf", level2_el->getPosition().file_); // Element "f" is also a sub element of "dyz" level2_el = level1_el->get("f"); ASSERT_TRUE(level2_el); EXPECT_EQ(8, level2_el->getPosition().line_); EXPECT_EQ(14, level2_el->getPosition().pos_); + EXPECT_EQ("kea.conf", level2_el->getPosition().file_); // Element "g" is a list. level1_el = top->get("g"); @@ -991,24 +1008,28 @@ TEST(Element, getPosition) { EXPECT_EQ(11, level1_el->getPosition().line_); // Position indicates where the values start (excluding the "[" character)" EXPECT_EQ(11, level1_el->getPosition().pos_); + EXPECT_EQ("kea.conf", level1_el->getPosition().file_); // First element from the list. level2_el = level1_el->get(0); ASSERT_TRUE(level2_el); EXPECT_EQ(11, level2_el->getPosition().line_); EXPECT_EQ(12, level2_el->getPosition().pos_); + EXPECT_EQ("kea.conf", level2_el->getPosition().file_); // Second element from the list. level2_el = level1_el->get(1); ASSERT_TRUE(level2_el); EXPECT_EQ(11, level2_el->getPosition().line_); EXPECT_EQ(15, level2_el->getPosition().pos_); + EXPECT_EQ("kea.conf", level2_el->getPosition().file_); // Third element from the list. level2_el = level1_el->get(2); ASSERT_TRUE(level2_el); EXPECT_EQ(12, level2_el->getPosition().line_); EXPECT_EQ(14, level2_el->getPosition().pos_); + EXPECT_EQ("kea.conf", level2_el->getPosition().file_); }