]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[5351] Added comment in syntax
authorFrancis Dupont <fdupont@isc.org>
Tue, 28 Nov 2017 00:57:48 +0000 (01:57 +0100)
committerFrancis Dupont <fdupont@isc.org>
Tue, 28 Nov 2017 00:57:48 +0000 (01:57 +0100)
src/bin/dhcp4/dhcp4_lexer.ll
src/bin/dhcp4/dhcp4_parser.cc
src/bin/dhcp4/dhcp4_parser.yy
src/bin/dhcp6/dhcp6_lexer.ll
src/bin/dhcp6/dhcp6_parser.yy
src/lib/cc/data.cc
src/lib/cc/data.h
src/lib/cc/tests/data_unittests.cc

index c0ea9459dfc27814aef0ecb1c7fcbc65806d321d..459420d93da012d72268f157c79f3b9c3b493629 100644 (file)
@@ -586,6 +586,16 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     }
 }
 
+\"comment\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser4Context::SUBNET4:
+    case isc::dhcp::Parser4Context::POOLS:
+        return isc::dhcp::Dhcp4Parser::make_COMMENT(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp4Parser::make_STRING("comment", driver.loc_);
+    }
+}
+
 \"subnet\" {
     switch(driver.ctx_) {
     case isc::dhcp::Parser4Context::SUBNET4:
index e77398b20ae5b311072a6a8df48e0a9430479f5b..80922d4071f54084e75d26c864e466e65ea26b0c 100644 (file)
@@ -2304,7 +2304,7 @@ namespace isc { namespace dhcp {
   case 377:
 #line 1346 "dhcp4_parser.yy" // lalr1.cc:859
     {
-    ctx.stack_.back()->set("user-context", yystack_[0].value.as< ElementPtr > ());
+    ctx.stack_.back()->combine_set("user-context", yystack_[0].value.as< ElementPtr > ());
     ctx.leave();
 }
 #line 2311 "dhcp4_parser.cc" // lalr1.cc:859
index 66ea540244706ffcbd93d66d9caa92bb2fa933d2..5635af158f683661ae6686271ee869bec744e97b 100644 (file)
@@ -109,6 +109,7 @@ using namespace std;
   POOLS "pools"
   POOL "pool"
   USER_CONTEXT "user-context"
+  COMMENT "comment"
 
   SUBNET "subnet"
   INTERFACE "interface"
@@ -920,6 +921,7 @@ subnet4_param: valid_lifetime
              | subnet_4o6_interface_id
              | subnet_4o6_subnet
              | user_context
+             | comment
              | unknown_map_entry
              ;
 
@@ -1330,6 +1332,7 @@ pool_params: pool_param
 pool_param: pool_entry
           | option_data_list
           | user_context
+          | comment
           | unknown_map_entry
           ;
 
@@ -1344,7 +1347,16 @@ pool_entry: POOL {
 user_context: USER_CONTEXT {
     ctx.enter(ctx.NO_KEYWORD);
 } COLON map_value {
-    ctx.stack_.back()->set("user-context", $4);
+    ctx.stack_.back()->combine_set("user-context", $4);
+    ctx.leave();
+};
+
+comment: COMMENT {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON value {
+    ElementPtr e(new MapElement(ctx.loc2pos(@1)));
+    e->set("comment", $4);
+    ctx.stack_.back()->combine_set("user-context", e);
     ctx.leave();
 };
 
index 6d891067c409b3bf09e43e99180f63941bac059f..ace108b445c510b8f0a17b576e161281dc0a59d0 100644 (file)
@@ -817,6 +817,17 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     }
 }
 
+\"comment\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::POOLS:
+    case isc::dhcp::Parser6Context::PD_POOLS:
+    case isc::dhcp::Parser6Context::SUBNET6:
+        return isc::dhcp::Dhcp6Parser::make_COMMENT(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("comment", driver.loc_);
+    }
+}
+
 \"subnet\" {
     switch(driver.ctx_) {
     case isc::dhcp::Parser6Context::SUBNET6:
index 5b59e0dc5b5148adf2eb272918d4f6512aa41ec2..8c3c78957ecb12555f691ef48a0a081d90cfa7f3 100644 (file)
@@ -99,6 +99,7 @@ using namespace std;
   EXCLUDED_PREFIX_LEN "excluded-prefix-len"
   DELEGATED_LEN "delegated-len"
   USER_CONTEXT "user-context"
+  COMMENT "comment"
 
   SUBNET "subnet"
   INTERFACE "interface"
@@ -908,6 +909,7 @@ subnet6_param: preferred_lifetime
              | reservation_mode
              | relay
              | user_context
+             | comment
              | unknown_map_entry
              ;
 
@@ -1293,6 +1295,7 @@ pool_params: pool_param
 pool_param: pool_entry
           | option_data_list
           | user_context
+          | comment
           | unknown_map_entry
           ;
 
@@ -1307,7 +1310,16 @@ pool_entry: POOL {
 user_context: USER_CONTEXT {
     ctx.enter(ctx.NO_KEYWORD);
 } COLON map_value {
-    ctx.stack_.back()->set("user-context", $4);
+    ctx.stack_.back()->combine_set("user-context", $4);
+    ctx.leave();
+};
+
+comment: COMMENT {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON value {
+    ElementPtr e(new MapElement(ctx.loc2pos(@1)));
+    e->set("comment", $4);
+    ctx.stack_.back()->combine_set("user-context", e);
     ctx.leave();
 };
 
@@ -1369,6 +1381,7 @@ pd_pool_param: pd_prefix
              | excluded_prefix
              | excluded_prefix_len
              | user_context
+             | comment
              | unknown_map_entry
              ;
 
index 7f043311e9a929d923ced379e7b2086ea49f2991..c1888221967d46241ec9ed5e142212213ea363a3 100644 (file)
@@ -171,6 +171,11 @@ Element::set(const std::string&, ConstElementPtr) {
     throwTypeError("set(name, element) called on a non-map Element");
 }
 
+void
+Element::combine_set(const std::string&, ConstElementPtr) {
+    throwTypeError("combine_set(name, element) called on a non-map Element");
+}
+
 void
 Element::remove(const std::string&) {
     throwTypeError("remove(string) called on a non-map Element");
@@ -902,6 +907,18 @@ MapElement::set(const std::string& key, ConstElementPtr value) {
     m[key] = value;
 }
 
+void
+MapElement::combine_set(const std::string& key, ConstElementPtr value) {
+    auto previous = m.find(key);
+    if (previous == m.end()) {
+        m[key] = value;
+        return;
+    }
+    ElementPtr mutable_ = boost::const_pointer_cast<Element>(previous->second);
+    combine(mutable_, value);
+    m[key] = mutable_;
+}
+
 bool
 MapElement::find(const std::string& id, ConstElementPtr& t) const {
     try {
@@ -1313,13 +1330,32 @@ prettyPrint(ConstElementPtr element, std::ostream& out,
         // open the map
         out << "{\n";
 
+        bool first = true;
+        // output comment first
+        if (element->contains("comment")) {
+            // add indentation
+            out << std::string(indent + step, ' ');
+            // add keyword:
+            out << "\"comment\": ";
+            // recursive call
+            prettyPrint(element->get("comment"), out, indent + step, step);
+            // it was the first
+            first = false;
+        }
+
         // iterate on keyword: value
         typedef std::map<std::string, ConstElementPtr> MapType;
         const MapType& m = element->mapValue();
         for (MapType::const_iterator it = m.begin();
              it != m.end(); ++it) {
+            // skip comment
+            if (it->first == "comment") {
+                continue;
+            }
             // add the separator if not the first item
-            if (it != m.begin()) {
+            if (first) {
+                first = false;
+            } else {
                 out << ",\n";
             }
             // add indentation
index 3f6da3a9f1eeea0daa7c825ba69bf29d5aa12619..c711a4a3b3f9b10ad1ebc015fbb00d54b0c18979 100644 (file)
@@ -321,6 +321,12 @@ public:
     /// @param element The ElementPtr to set at the given key.
     virtual void set(const std::string& name, ConstElementPtr element);
 
+    /// Sets the ElementPtr at the given key, if there was a previous
+    /// value it is combined with it
+    /// @param name The key of the Element to set
+    /// @param element The ElementPtr to set at the given key.
+    virtual void combine_set(const std::string& name, ConstElementPtr element);
+
     /// Remove the ElementPtr at the given key
     /// @param name The key of the Element to remove
     virtual void remove(const std::string& name);
@@ -667,6 +673,7 @@ public:
     }
     using Element::set;
     void set(const std::string& key, ConstElementPtr value);
+    void combine_set(const std::string& key, ConstElementPtr value);
     using Element::remove;
     void remove(const std::string& s) { m.erase(s); }
     bool contains(const std::string& s) const {
@@ -773,6 +780,7 @@ bool isEquivalent(ConstElementPtr a, ConstElementPtr b);
 /// This operator converts the @c ConstElementPtr into a string and
 /// inserts it into the output stream @c out with an initial
 /// indentation @c indent and add at each level @c step spaces.
+/// For maps if there is a comment property it is printed first.
 ///
 /// @param element A @c ConstElementPtr to pretty print
 /// @param out A @c std::ostream on which the print operation is performed
@@ -785,6 +793,7 @@ void prettyPrint(ConstElementPtr element, std::ostream& out,
 ///
 /// This operator converts the @c ConstElementPtr into a string with
 /// an initial indentation @c indent and add at each level @c step spaces.
+/// For maps if there is a comment property it is printed first.
 ///
 /// @param element A @c ConstElementPtr to pretty print
 /// @param indent An initial number of spaces to add each new line
index dd9402b2c5276878de2d5a05514a379d390eed1a..d50380fd344ba2ee107527f5ef64b23333e6cc53 100644 (file)
@@ -654,6 +654,28 @@ TEST(Element, MapElement) {
     el->remove("value3");
     EXPECT_TRUE(isNull(el->get("value3")));
 
+    EXPECT_TRUE(isNull(el->get("value4")));
+
+    ElementPtr em = Element::fromJSON("{ \"a\": 1 }");
+    el->combine_set("value4", em);
+    ASSERT_FALSE(isNull(el->get("value4")));
+    EXPECT_EQ(em, el->get("value4"));
+
+    em = Element::fromJSON("{ \"a\": 2 }");
+    el->combine_set("value4", em);
+    ASSERT_FALSE(isNull(el->get("value4")));
+    ASSERT_EQ(Element::map, el->get("value4")->getType());
+    EXPECT_EQ(1, el->get("value4")->size());
+    ASSERT_FALSE(isNull(el->get("value4")->get("a")));
+    ASSERT_EQ(Element::list, el->get("value4")->get("a")->getType());
+    EXPECT_EQ(2, el->get("value4")->get("a")->size());
+    ASSERT_EQ(Element::integer,
+              el->get("value4")->get("a")->get(0)->getType());
+    EXPECT_EQ(1, el->get("value4")->get("a")->get(0)->intValue());
+    ASSERT_EQ(Element::integer,
+              el->get("value4")->get("a")->get(1)->getType());
+    EXPECT_EQ(2, el->get("value4")->get("a")->get(1)->intValue());
+
     EXPECT_EQ(el->find("value2/number")->intValue(), 42);
     EXPECT_TRUE(isNull(el->find("value2/nothing/")));
 
@@ -1199,6 +1221,7 @@ TEST(Element, prettyPrint) {
 
     // default step is 2, order is alphabetic, no \n at the end
     string text = "{\n"
+        "  \"comment\": \"this is an exception\",\n"
         "  \"boolean\": true,\n"
         "  \"empty-list\": [ ],\n"
         "  \"empty-map\": { },\n"