Merge "Build with libyang"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1ba791a..cae063a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -58,6 +58,7 @@
add_definitions(-DBOOST_SPIRIT_X3_NO_FILESYSTEM)
set(parser_SRCS
+ src/static_schema.cpp
src/schema.cpp
src/parser.cpp
src/ast_commands.cpp
diff --git a/src/main.cpp b/src/main.cpp
index e498db0..0c02ecf 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -13,7 +13,7 @@
#include "NETCONF_CLI_VERSION.h"
#include "interpreter.hpp"
#include "parser.hpp"
-#include "schema.hpp"
+#include "static_schema.hpp"
static const char usage[] =
@@ -46,23 +46,23 @@
true);
std::cout << "Welcome to netconf-cli" << std::endl;
- Schema schema;
- schema.addContainer("", "a", yang::ContainerTraits::Presence);
- schema.addContainer("", "b");
- schema.addLeaf("", "leafString", yang::LeafDataTypes::String);
- schema.addLeaf("", "leafDecimal", yang::LeafDataTypes::Decimal);
- schema.addLeaf("", "leafBool", yang::LeafDataTypes::Bool);
- schema.addLeaf("", "leafInt", yang::LeafDataTypes::Int);
- schema.addLeaf("", "leafUint", yang::LeafDataTypes::Uint);
- schema.addLeafEnum("", "leafEnum", {"lol", "data", "coze"});
- schema.addContainer("a", "a2");
- schema.addLeaf("a", "leafa", yang::LeafDataTypes::String);
- schema.addContainer("b", "b2", yang::ContainerTraits::Presence);
- schema.addContainer("a/a2", "a3", yang::ContainerTraits::Presence);
- schema.addContainer("b/b2", "b3");
- schema.addList("", "list", {"number"});
- schema.addContainer("list", "contInList", yang::ContainerTraits::Presence);
- schema.addList("", "twoKeyList", {"number", "name"});
+ auto schema = std::make_shared<StaticSchema>();
+ schema->addContainer("", "a", yang::ContainerTraits::Presence);
+ schema->addContainer("", "b");
+ schema->addLeaf("", "leafString", yang::LeafDataTypes::String);
+ schema->addLeaf("", "leafDecimal", yang::LeafDataTypes::Decimal);
+ schema->addLeaf("", "leafBool", yang::LeafDataTypes::Bool);
+ schema->addLeaf("", "leafInt", yang::LeafDataTypes::Int);
+ schema->addLeaf("", "leafUint", yang::LeafDataTypes::Uint);
+ schema->addLeafEnum("", "leafEnum", {"lol", "data", "coze"});
+ schema->addContainer("a", "a2");
+ schema->addLeaf("a", "leafa", yang::LeafDataTypes::String);
+ schema->addContainer("b", "b2", yang::ContainerTraits::Presence);
+ schema->addContainer("a/a2", "a3", yang::ContainerTraits::Presence);
+ schema->addContainer("b/b2", "b3");
+ schema->addList("", "list", {"number"});
+ schema->addContainer("list", "contInList", yang::ContainerTraits::Presence);
+ schema->addList("", "twoKeyList", {"number", "name"});
Parser parser(schema);
while (true) {
@@ -74,7 +74,7 @@
try {
command_ cmd = parser.parseCommand(input, std::cout);
- boost::apply_visitor(Interpreter(parser, schema), cmd);
+ boost::apply_visitor(Interpreter(parser, *schema), cmd);
} catch (InvalidCommandException& ex) {
std::cerr << ex.what() << std::endl;
}
diff --git a/src/parser.cpp b/src/parser.cpp
index e2d0330..0c62358 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -13,7 +13,7 @@
InvalidCommandException::~InvalidCommandException() = default;
-Parser::Parser(const Schema& schema)
+Parser::Parser(const std::shared_ptr<const Schema> schema)
: m_schema(schema)
{
}
@@ -21,7 +21,7 @@
command_ Parser::parseCommand(const std::string& line, std::ostream& errorStream)
{
command_ parsedCommand;
- ParserContext ctx(m_schema, m_curDir);
+ ParserContext ctx(*m_schema, m_curDir);
auto it = line.begin();
boost::spirit::x3::error_handler<std::string::const_iterator> errorHandler(it, line.end(), errorStream);
diff --git a/src/parser.hpp b/src/parser.hpp
index 0a253c1..05e636e 100644
--- a/src/parser.hpp
+++ b/src/parser.hpp
@@ -26,12 +26,12 @@
class Parser {
public:
- Parser(const Schema& schema);
+ Parser(const std::shared_ptr<const Schema> schema);
command_ parseCommand(const std::string& line, std::ostream& errorStream);
void changeNode(const path_& name);
std::string currentNode() const;
private:
- const Schema& m_schema;
+ const std::shared_ptr<const Schema> m_schema;
path_ m_curDir;
};
diff --git a/src/schema.cpp b/src/schema.cpp
index 066dc3b..c390e31 100644
--- a/src/schema.cpp
+++ b/src/schema.cpp
@@ -7,126 +7,5 @@
*/
#include "schema.hpp"
-#include "utils.hpp"
-InvalidNodeException::~InvalidNodeException() = default;
-
-Schema::Schema()
-{
- m_nodes.emplace("", std::unordered_map<std::string, NodeType>());
-}
-
-const std::unordered_map<std::string, NodeType>& Schema::children(const std::string& name) const
-{
- return m_nodes.at(name);
-}
-
-bool Schema::nodeExists(const std::string& location, const std::string& name) const
-{
- if (name.empty())
- return true;
- const auto& childrenRef = children(location);
-
- return childrenRef.find(name) != childrenRef.end();
-}
-
-bool Schema::isContainer(const path_& location, const std::string& name) const
-{
- std::string locationString = pathToSchemaString(location);
- if (!nodeExists(locationString, name))
- return false;
-
- return children(locationString).at(name).type() == typeid(yang::container);
-}
-
-void Schema::addContainer(const std::string& location, const std::string& name, yang::ContainerTraits isPresence)
-{
- m_nodes.at(location).emplace(name, yang::container{isPresence});
-
- //create a new set of children for the new node
- std::string key = joinPaths(location, name);
- m_nodes.emplace(key, std::unordered_map<std::string, NodeType>());
-}
-
-
-bool Schema::listHasKey(const path_& location, const std::string& name, const std::string& key) const
-{
- std::string locationString = pathToSchemaString(location);
- assert(isList(location, name));
-
- const auto& child = children(locationString).at(name);
- const auto& list = boost::get<yang::list>(child);
- return list.m_keys.find(key) != list.m_keys.end();
-}
-
-const std::set<std::string>& Schema::listKeys(const path_& location, const std::string& name) const
-{
- std::string locationString = pathToSchemaString(location);
- assert(isList(location, name));
-
- const auto& child = children(locationString).at(name);
- const auto& list = boost::get<yang::list>(child);
- return list.m_keys;
-}
-
-bool Schema::isList(const path_& location, const std::string& name) const
-{
- std::string locationString = pathToSchemaString(location);
- if (!nodeExists(locationString, name))
- return false;
- const auto& child = children(locationString).at(name);
- if (child.type() != typeid(yang::list))
- return false;
-
- return true;
-}
-
-void Schema::addList(const std::string& location, const std::string& name, const std::set<std::string>& keys)
-{
- m_nodes.at(location).emplace(name, yang::list{keys});
-
- m_nodes.emplace(name, std::unordered_map<std::string, NodeType>());
-}
-
-bool Schema::isPresenceContainer(const path_& location, const std::string& name) const
-{
- if (!isContainer(location, name))
- return false;
- std::string locationString = pathToSchemaString(location);
- return boost::get<yang::container>(children(locationString).at(name)).m_presence == yang::ContainerTraits::Presence;
-}
-
-void Schema::addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type)
-{
- m_nodes.at(location).emplace(name, yang::leaf{type, {}});
-}
-
-void Schema::addLeafEnum(const std::string& location, const std::string& name, std::set<std::string> enumValues)
-{
- m_nodes.at(location).emplace(name, yang::leaf{yang::LeafDataTypes::Enum, enumValues});
-}
-
-bool Schema::leafEnumHasValue(const path_& location, const std::string& name, const std::string& value) const
-{
- std::string locationString = pathToSchemaString(location);
- assert(isLeaf(location, name));
-
- const auto& child = children(locationString).at(name);
- const auto& list = boost::get<yang::leaf>(child);
- return list.m_enumValues.find(value) != list.m_enumValues.end();
-}
-
-bool Schema::isLeaf(const path_& location, const std::string& name) const
-{
- std::string locationString = pathToSchemaString(location);
- if (!nodeExists(locationString, name))
- return false;
-
- return children(locationString).at(name).type() == typeid(yang::leaf);
-}
-
-yang::LeafDataTypes Schema::leafType(const path_& location, const std::string& name) const
-{
- std::string locationString = pathToSchemaString(location);
- return boost::get<yang::leaf>(children(locationString).at(name)).m_type;
-}
+Schema::~Schema() = default;
diff --git a/src/schema.hpp b/src/schema.hpp
index e87619b..7c05d17 100644
--- a/src/schema.hpp
+++ b/src/schema.hpp
@@ -1,3 +1,4 @@
+
/*
* Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
* Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
@@ -52,25 +53,21 @@
};
/*! \class Schema
- * \brief The class representing the schema, that the user traverses.
+ * \brief A base schema class for schemas
* */
class Schema {
public:
- Schema();
- bool nodeExists(const std::string& location, const std::string& name) const;
+ virtual ~Schema();
- bool isContainer(const path_& location, const std::string& name) const;
- void addContainer(const std::string& location, const std::string& name, yang::ContainerTraits isPresence = yang::ContainerTraits::None);
- const std::set<std::string>& listKeys(const path_& location, const std::string& name) const;
- bool listHasKey(const path_& location, const std::string& name, const std::string& key) const;
- bool isList(const path_& location, const std::string& name) const;
- void addList(const std::string& location, const std::string& name, const std::set<std::string>& keys);
- bool isPresenceContainer(const path_& location, const std::string& name) const;
- void addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type);
- void addLeafEnum(const std::string& location, const std::string& name, std::set<std::string> enumValues);
- bool leafEnumHasValue(const path_& location, const std::string& name, const std::string& value) const;
- bool isLeaf(const path_& location, const std::string& name) const;
- yang::LeafDataTypes leafType(const path_& location, const std::string& name) const;
+ virtual bool isContainer(const path_& location, const std::string& name) const = 0;
+ virtual bool isLeaf(const path_& location, const std::string& name) const = 0;
+ virtual bool isList(const path_& location, const std::string& name) const = 0;
+ virtual bool isPresenceContainer(const path_& location, const std::string& name) const = 0;
+ virtual bool leafEnumHasValue(const path_& location, const std::string& name, const std::string& value) const = 0;
+ virtual bool listHasKey(const path_& location, const std::string& name, const std::string& key) const = 0;
+ virtual bool nodeExists(const std::string& location, const std::string& name) const = 0;
+ virtual const std::set<std::string>& listKeys(const path_& location, const std::string& name) const = 0;
+ virtual yang::LeafDataTypes leafType(const path_& location, const std::string& name) const = 0;
private:
const std::unordered_map<std::string, NodeType>& children(const std::string& name) const;
diff --git a/src/static_schema.cpp b/src/static_schema.cpp
new file mode 100644
index 0000000..65debf0
--- /dev/null
+++ b/src/static_schema.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
+ * Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
+ *
+ * Written by Václav Kubernát <kubervac@fit.cvut.cz>
+ *
+*/
+
+#include "static_schema.hpp"
+#include "utils.hpp"
+
+InvalidNodeException::~InvalidNodeException() = default;
+
+StaticSchema::StaticSchema()
+{
+ m_nodes.emplace("", std::unordered_map<std::string, NodeType>());
+}
+
+const std::unordered_map<std::string, NodeType>& StaticSchema::children(const std::string& name) const
+{
+ return m_nodes.at(name);
+}
+
+bool StaticSchema::nodeExists(const std::string& location, const std::string& name) const
+{
+ if (name.empty())
+ return true;
+ const auto& childrenRef = children(location);
+
+ return childrenRef.find(name) != childrenRef.end();
+}
+
+bool StaticSchema::isContainer(const path_& location, const std::string& name) const
+{
+ std::string locationString = pathToSchemaString(location);
+ if (!nodeExists(locationString, name))
+ return false;
+
+ return children(locationString).at(name).type() == typeid(yang::container);
+}
+
+void StaticSchema::addContainer(const std::string& location, const std::string& name, yang::ContainerTraits isPresence)
+{
+ m_nodes.at(location).emplace(name, yang::container{isPresence});
+
+ //create a new set of children for the new node
+ std::string key = joinPaths(location, name);
+ m_nodes.emplace(key, std::unordered_map<std::string, NodeType>());
+}
+
+
+bool StaticSchema::listHasKey(const path_& location, const std::string& name, const std::string& key) const
+{
+ std::string locationString = pathToSchemaString(location);
+ assert(isList(location, name));
+
+ const auto& child = children(locationString).at(name);
+ const auto& list = boost::get<yang::list>(child);
+ return list.m_keys.find(key) != list.m_keys.end();
+}
+
+const std::set<std::string>& StaticSchema::listKeys(const path_& location, const std::string& name) const
+{
+ std::string locationString = pathToSchemaString(location);
+ assert(isList(location, name));
+
+ const auto& child = children(locationString).at(name);
+ const auto& list = boost::get<yang::list>(child);
+ return list.m_keys;
+}
+
+bool StaticSchema::isList(const path_& location, const std::string& name) const
+{
+ std::string locationString = pathToSchemaString(location);
+ if (!nodeExists(locationString, name))
+ return false;
+ const auto& child = children(locationString).at(name);
+ if (child.type() != typeid(yang::list))
+ return false;
+
+ return true;
+}
+
+void StaticSchema::addList(const std::string& location, const std::string& name, const std::set<std::string>& keys)
+{
+ m_nodes.at(location).emplace(name, yang::list{keys});
+
+ m_nodes.emplace(name, std::unordered_map<std::string, NodeType>());
+}
+
+bool StaticSchema::isPresenceContainer(const path_& location, const std::string& name) const
+{
+ if (!isContainer(location, name))
+ return false;
+ std::string locationString = pathToSchemaString(location);
+ return boost::get<yang::container>(children(locationString).at(name)).m_presence == yang::ContainerTraits::Presence;
+}
+
+void StaticSchema::addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type)
+{
+ m_nodes.at(location).emplace(name, yang::leaf{type, {}});
+}
+
+void StaticSchema::addLeafEnum(const std::string& location, const std::string& name, std::set<std::string> enumValues)
+{
+ m_nodes.at(location).emplace(name, yang::leaf{yang::LeafDataTypes::Enum, enumValues});
+}
+
+bool StaticSchema::leafEnumHasValue(const path_& location, const std::string& name, const std::string& value) const
+{
+ std::string locationString = pathToSchemaString(location);
+ assert(isLeaf(location, name));
+
+ const auto& child = children(locationString).at(name);
+ const auto& list = boost::get<yang::leaf>(child);
+ return list.m_enumValues.find(value) != list.m_enumValues.end();
+}
+
+bool StaticSchema::isLeaf(const path_& location, const std::string& name) const
+{
+ std::string locationString = pathToSchemaString(location);
+ if (!nodeExists(locationString, name))
+ return false;
+
+ return children(locationString).at(name).type() == typeid(yang::leaf);
+}
+
+yang::LeafDataTypes StaticSchema::leafType(const path_& location, const std::string& name) const
+{
+ std::string locationString = pathToSchemaString(location);
+ return boost::get<yang::leaf>(children(locationString).at(name)).m_type;
+}
diff --git a/src/static_schema.hpp b/src/static_schema.hpp
new file mode 100644
index 0000000..bab8bde
--- /dev/null
+++ b/src/static_schema.hpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
+ * Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
+ *
+ * Written by Václav Kubernát <kubervac@fit.cvut.cz>
+ *
+*/
+
+#pragma once
+
+#include <boost/variant.hpp>
+#include <set>
+#include <stdexcept>
+#include <unordered_map>
+#include "ast_path.hpp"
+#include "schema.hpp"
+
+
+/*! \class StaticSchema
+ * \brief Static schema, used mainly for testing
+ * */
+
+class StaticSchema : public Schema {
+public:
+ StaticSchema();
+
+ bool isContainer(const path_& location, const std::string& name) const override;
+ bool isLeaf(const path_& location, const std::string& name) const override;
+ bool isList(const path_& location, const std::string& name) const override;
+ bool isPresenceContainer(const path_& location, const std::string& name) const override;
+ bool leafEnumHasValue(const path_& location, const std::string& name, const std::string& value) const override;
+ bool listHasKey(const path_& location, const std::string& name, const std::string& key) const override;
+ bool nodeExists(const std::string& location, const std::string& name) const override;
+ const std::set<std::string>& listKeys(const path_& location, const std::string& name) const override;
+ yang::LeafDataTypes leafType(const path_& location, const std::string& name) const override;
+
+ void addContainer(const std::string& location, const std::string& name, yang::ContainerTraits isPresence = yang::ContainerTraits::None);
+ void addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type);
+ void addLeafEnum(const std::string& location, const std::string& name, std::set<std::string> enumValues);
+ void addList(const std::string& location, const std::string& name, const std::set<std::string>& keys);
+
+private:
+ const std::unordered_map<std::string, NodeType>& children(const std::string& name) const;
+
+ std::unordered_map<std::string, std::unordered_map<std::string, NodeType>> m_nodes;
+};
diff --git a/tests/cd.cpp b/tests/cd.cpp
index 8fe30ad..29187ff 100644
--- a/tests/cd.cpp
+++ b/tests/cd.cpp
@@ -9,20 +9,20 @@
#include "trompeloeil_catch.h"
#include "ast_commands.hpp"
#include "parser.hpp"
-#include "schema.hpp"
+#include "static_schema.hpp"
TEST_CASE("cd")
{
- Schema schema;
- schema.addContainer("", "a");
- schema.addContainer("", "b");
- schema.addContainer("a", "a2");
- schema.addContainer("b", "b2");
- schema.addContainer("a/a2", "a3");
- schema.addContainer("b/b2", "b3");
- schema.addList("", "list", {"number"});
- schema.addContainer("list", "contInList");
- schema.addList("", "twoKeyList", {"number", "name"});
+ auto schema = std::make_shared<StaticSchema>();
+ schema->addContainer("", "a");
+ schema->addContainer("", "b");
+ schema->addContainer("a", "a2");
+ schema->addContainer("b", "b2");
+ schema->addContainer("a/a2", "a3");
+ schema->addContainer("b/b2", "b3");
+ schema->addList("", "list", {"number"});
+ schema->addContainer("list", "contInList");
+ schema->addList("", "twoKeyList", {"number", "name"});
Parser parser(schema);
std::string input;
std::ostringstream errorStream;
diff --git a/tests/leaf_editing.cpp b/tests/leaf_editing.cpp
index 09e8504..b8c5591 100644
--- a/tests/leaf_editing.cpp
+++ b/tests/leaf_editing.cpp
@@ -9,21 +9,21 @@
#include "trompeloeil_catch.h"
#include "ast_commands.hpp"
#include "parser.hpp"
-#include "schema.hpp"
+#include "static_schema.hpp"
TEST_CASE("leaf editing")
{
- Schema schema;
- schema.addContainer("", "contA");
- schema.addLeaf("", "leafString", yang::LeafDataTypes::String);
- schema.addLeaf("", "leafDecimal", yang::LeafDataTypes::Decimal);
- schema.addLeaf("", "leafBool", yang::LeafDataTypes::Bool);
- schema.addLeaf("", "leafInt", yang::LeafDataTypes::Int);
- schema.addLeaf("", "leafUint", yang::LeafDataTypes::Uint);
- schema.addLeafEnum("", "leafEnum", {"lol", "data", "coze"});
- schema.addLeaf("contA", "leafInCont", yang::LeafDataTypes::String);
- schema.addList("", "list", {"number"});
- schema.addLeaf("list", "leafInList", yang::LeafDataTypes::String);
+ auto schema = std::make_shared<StaticSchema>();
+ schema->addContainer("", "contA");
+ schema->addLeaf("", "leafString", yang::LeafDataTypes::String);
+ schema->addLeaf("", "leafDecimal", yang::LeafDataTypes::Decimal);
+ schema->addLeaf("", "leafBool", yang::LeafDataTypes::Bool);
+ schema->addLeaf("", "leafInt", yang::LeafDataTypes::Int);
+ schema->addLeaf("", "leafUint", yang::LeafDataTypes::Uint);
+ schema->addLeafEnum("", "leafEnum", {"lol", "data", "coze"});
+ schema->addLeaf("contA", "leafInCont", yang::LeafDataTypes::String);
+ schema->addList("", "list", {"number"});
+ schema->addLeaf("list", "leafInList", yang::LeafDataTypes::String);
Parser parser(schema);
std::string input;
std::ostringstream errorStream;
diff --git a/tests/presence_containers.cpp b/tests/presence_containers.cpp
index 8958627..87957cb 100644
--- a/tests/presence_containers.cpp
+++ b/tests/presence_containers.cpp
@@ -10,18 +10,18 @@
#include "trompeloeil_catch.h"
#include "ast_commands.hpp"
#include "parser.hpp"
-#include "schema.hpp"
+#include "static_schema.hpp"
TEST_CASE("presence containers")
{
- Schema schema;
- schema.addContainer("", "a", yang::ContainerTraits::Presence);
- schema.addContainer("", "b");
- schema.addContainer("a", "a2");
- schema.addContainer("a/a2", "a3", yang::ContainerTraits::Presence);
- schema.addContainer("b", "b2", yang::ContainerTraits::Presence);
- schema.addList("", "list", {"quote"});
- schema.addContainer("list", "contInList", yang::ContainerTraits::Presence);
+ auto schema = std::make_shared<StaticSchema>();
+ schema->addContainer("", "a", yang::ContainerTraits::Presence);
+ schema->addContainer("", "b");
+ schema->addContainer("a", "a2");
+ schema->addContainer("a/a2", "a3", yang::ContainerTraits::Presence);
+ schema->addContainer("b", "b2", yang::ContainerTraits::Presence);
+ schema->addList("", "list", {"quote"});
+ schema->addContainer("list", "contInList", yang::ContainerTraits::Presence);
Parser parser(schema);
std::string input;
std::ostringstream errorStream;