Browse Source

[3409] Updated Element data structure to hold the file name.

Marcin Siodelski 11 years ago
parent
commit
bfe07f025a
3 changed files with 88 additions and 29 deletions
  1. 24 8
      src/lib/cc/data.cc
  2. 30 8
      src/lib/cc/data.h
  3. 34 13
      src/lib/cc/tests/data_unittests.cc

+ 24 - 8
src/lib/cc/data.cc

@@ -42,6 +42,19 @@ 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;
     toJSON(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<double>(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<int64_t>(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) {

+ 30 - 8
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);
     }
 
@@ -658,6 +667,19 @@ ConstElementPtr removeIdentical(ConstElementPtr a, ConstElementPtr b);
 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.
 ///
 /// This method converts the \c ElementPtr into a string with

+ 34 - 13
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_);
 
 }