Util functions to validate JSON and find data files

Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
Change-Id: Ifc1537f7c8eabab08690d5a74023377572564895
diff --git a/analyzer/meson.build b/analyzer/meson.build
index abf710c..785a9d3 100644
--- a/analyzer/meson.build
+++ b/analyzer/meson.build
@@ -12,7 +12,9 @@
 analyzer_deps = [
     dbus_interfaces_dep,
     libhei_dep,
+    nlohmann_json_dep,
     sdbusplus_dep,
+    valijson_dep,
 ]
 
 # Create static library.
diff --git a/meson.build b/meson.build
index 514e94c..b7cb17e 100644
--- a/meson.build
+++ b/meson.build
@@ -77,6 +77,31 @@
 pthread = declare_dependency(link_args : '-pthread')
 lrt = declare_dependency(link_args : '-lrt')
 
+# JSON parser
+if cmplr.has_header('nlohmann/json.hpp')
+    nlohmann_json_dep = declare_dependency()
+else
+    subproject('nlohmann', required: false)
+    nlohmann_json_dep = declare_dependency(
+        include_directories: [
+            'subprojects/nlohmann/single_include',
+            'subprojects/nlohmann/single_include/nlohmann',
+        ]
+    )
+    nlohmann_json_dep = nlohmann_json_dep.as_system('system')
+endif
+
+# JSON validator
+if cmplr.has_header('valijson/validator.hpp')
+    valijson_dep = declare_dependency()
+else
+    subproject('valijson', required: false)
+    valijson_dep = declare_dependency(
+        include_directories: 'subprojects/valijson/include'
+    )
+    valijson_dep = valijson_dep.as_system('system')
+endif
+
 #-------------------------------------------------------------------------------
 # Build the local static libraries
 #-------------------------------------------------------------------------------
diff --git a/subprojects/nlohmann.wrap b/subprojects/nlohmann.wrap
new file mode 100644
index 0000000..3c028c3
--- /dev/null
+++ b/subprojects/nlohmann.wrap
@@ -0,0 +1,3 @@
+[wrap-git]
+revision = e7b3b40b5a95bc74b9a7f662830a27c49ffc01b4
+url = https://github.com/nlohmann/json.git
diff --git a/subprojects/valijson.wrap b/subprojects/valijson.wrap
new file mode 100644
index 0000000..577dd51
--- /dev/null
+++ b/subprojects/valijson.wrap
@@ -0,0 +1,3 @@
+[wrap-git]
+revision = 9183462118f58a3ca4be82b8f656f18707229737
+url = https://github.com/tristanpenman/valijson.git
diff --git a/util/data_file.cpp b/util/data_file.cpp
new file mode 100644
index 0000000..14266ca
--- /dev/null
+++ b/util/data_file.cpp
@@ -0,0 +1,44 @@
+#include <util/data_file.hpp>
+#include <valijson/adapters/nlohmann_json_adapter.hpp>
+#include <valijson/schema.hpp>
+#include <valijson/schema_parser.hpp>
+#include <valijson/validator.hpp>
+
+#include <regex>
+
+namespace fs = std::filesystem;
+
+namespace util
+{
+
+void findFiles(const fs::path& i_dirPath, const std::string& i_matchString,
+               std::vector<fs::path>& o_foundPaths)
+{
+    if (fs::exists(i_dirPath))
+    {
+        std::regex search{i_matchString};
+        for (const auto& file : fs::directory_iterator(i_dirPath))
+        {
+            std::string path = file.path().string();
+            if (std::regex_search(path, search))
+            {
+                o_foundPaths.emplace_back(file.path());
+            }
+        }
+    }
+}
+
+bool validateJson(const nlohmann::json& i_schema, const nlohmann::json& i_json)
+{
+    valijson::Schema schema;
+    valijson::SchemaParser parser;
+    valijson::adapters::NlohmannJsonAdapter schemaAdapter(i_schema);
+    parser.populateSchema(schemaAdapter, schema);
+
+    valijson::Validator validator;
+    valijson::adapters::NlohmannJsonAdapter targetAdapter(i_json);
+
+    return validator.validate(schema, targetAdapter, nullptr);
+}
+
+} // namespace util
diff --git a/util/data_file.hpp b/util/data_file.hpp
new file mode 100644
index 0000000..52e8a2e
--- /dev/null
+++ b/util/data_file.hpp
@@ -0,0 +1,27 @@
+#include <nlohmann/json.hpp>
+
+#include <filesystem>
+
+namespace util
+{
+
+/**
+ * @brief Returns a list of files in the given directory, matching the given
+ *        search string.
+ * @param i_dirPath     The target directory.
+ * @param i_matchString Matching search pattern.
+ * @param o_foundPaths  The returned list of found file paths.
+ */
+void findFiles(const std::filesystem::path& i_dirPath,
+               const std::string& i_matchString,
+               std::vector<std::filesystem::path>& o_foundPaths);
+
+/**
+ * @brief  Validates the given JSON file against the given schema.
+ * @param  i_schema Target schema document.
+ * @param  i_json   Target JSON file.
+ * @return True, if validation successful. False, otherwise.
+ */
+bool validateJson(const nlohmann::json& i_schema, const nlohmann::json& i_json);
+
+} // namespace util
diff --git a/util/meson.build b/util/meson.build
index 4e559d4..d72f515 100644
--- a/util/meson.build
+++ b/util/meson.build
@@ -1,5 +1,6 @@
 # Source files.
 util_src = files(
+    'data_file.cpp',
     'dbus.cpp',
     'ffdc_file.cpp',
     'pdbg.cpp',