yang-cli: Make parsing strict by default and add flag

Change-Id: I941b0c4c43c94804cc3e429d1ab00ca6f1ad402e
diff --git a/src/cli.cpp b/src/cli.cpp
index efa9f7c..fec77d1 100644
--- a/src/cli.cpp
+++ b/src/cli.cpp
@@ -40,15 +40,16 @@
   will be used to find a schema for that module.
 
 Usage:
-  yang-cli [--configonly] [-s <search_dir>] [-e enable_features]... [-i data_file]... <schema_file_or_module_name>...
+  yang-cli [--configonly] [--ignore-unknown-data] [-s <search_dir>] [-e enable_features]... [-i data_file]... <schema_file_or_module_name>...
   yang-cli (-h | --help)
   yang-cli --version
 
 Options:
-  -s <search_dir>       Set search for schema lookup
-  -e <enable_features>  Feature to enable after modules are loaded. This option can be supplied more than once. Format: <module_name>:<feature>
-  -i <data_file>        File to import data from
-  --configonly          Disable editing of operational data)";
+  -s <search_dir>        Set search for schema lookup
+  -e <enable_features>   Feature to enable after modules are loaded. This option can be supplied more than once. Format: <module_name>:<feature>
+  -i <data_file>         File to import data from
+  --configonly           Disable editing of operational data
+  --ignore-unknown-data  Silently ignore data with no available schema file)";
 #elif defined(NETCONF_CLI)
 // FIXME: improve usage
 static const auto usage = R"(CLI interface for NETCONF
@@ -154,9 +155,12 @@
             }
         }
     }
+
+    auto strict = args.at("--ignore-unknown-data").asBool() ? StrictDataParsing::No : StrictDataParsing::Yes;
+
     if (const auto& dataFiles = args["-i"]) {
         for (const auto& dataFile : dataFiles.asStringList()) {
-            datastore->addDataFile(dataFile);
+            datastore->addDataFile(dataFile, strict);
         }
     }
 #elif defined(NETCONF_CLI)
diff --git a/src/yang_access.cpp b/src/yang_access.cpp
index b8631d5..0555616 100644
--- a/src/yang_access.cpp
+++ b/src/yang_access.cpp
@@ -312,14 +312,19 @@
     m_schema->enableFeature(module, feature);
 }
 
-void YangAccess::addDataFile(const std::string& path)
+void YangAccess::addDataFile(const std::string& path, const StrictDataParsing strict)
 {
     std::ifstream fs(path);
     char firstChar;
     fs >> firstChar;
 
     std::cout << "Parsing \"" << path << "\" as " << (firstChar == '{' ? "JSON" : "XML") << "...\n";
-    auto dataNode = lyd_parse_path(m_ctx.get(), path.c_str(), firstChar == '{' ? LYD_JSON : LYD_XML, LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB | LYD_OPT_TRUSTED);
+
+    auto parseFlags = LYD_OPT_DATA | LYD_OPT_DATA_NO_YANGLIB | LYD_OPT_TRUSTED;
+    if (strict == StrictDataParsing::Yes) {
+        parseFlags |= LYD_OPT_STRICT;
+    }
+    auto dataNode = lyd_parse_path(m_ctx.get(), path.c_str(), firstChar == '{' ? LYD_JSON : LYD_XML, parseFlags);
 
     if (!dataNode) {
         throw std::runtime_error("Supplied data file " + path + " couldn't be parsed.");
diff --git a/src/yang_access.hpp b/src/yang_access.hpp
index c009420..64538f0 100644
--- a/src/yang_access.hpp
+++ b/src/yang_access.hpp
@@ -13,6 +13,11 @@
  *     \brief Implementation of DatastoreAccess with a local libyang data node instance
  */
 
+enum class StrictDataParsing {
+    Yes,
+    No
+};
+
 class YangSchema;
 
 struct ly_ctx;
@@ -41,7 +46,7 @@
     void loadModule(const std::string& name);
     void addSchemaFile(const std::string& path);
     void addSchemaDir(const std::string& path);
-    void addDataFile(const std::string& path);
+    void addDataFile(const std::string& path, const StrictDataParsing strict);
 
 private:
     std::vector<ListInstance> listInstances(const std::string& path) override;