sysd_monitor: Parse json file(s)

Parse the json file(s) into a c++ data object that can be used in later
commits to easily check for monitored targets and log appropriate
errors.

Accept a command line parameter to input file and call parsing function

Tested:
- Verified 100% code coverage of new parser cpp

Change-Id: I0bacd80b7f5330eb9cb03d8e3717742ab107bf94
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
diff --git a/systemd_target_parser.cpp b/systemd_target_parser.cpp
new file mode 100644
index 0000000..d2cfa86
--- /dev/null
+++ b/systemd_target_parser.cpp
@@ -0,0 +1,58 @@
+#include <cassert>
+#include <fstream>
+#include <iostream>
+#include <systemd_target_parser.hpp>
+
+void validateErrorsToMonitor(std::vector<std::string>& errorsToMonitor)
+{
+    assert(errorsToMonitor.size());
+
+    const std::vector<std::string> validErrorsToMonitor = {
+        "default", "timeout", "failed", "dependency"};
+    for (const auto& errorToMonitor : errorsToMonitor)
+    {
+        if (std::find(validErrorsToMonitor.begin(), validErrorsToMonitor.end(),
+                      errorToMonitor) == validErrorsToMonitor.end())
+        {
+            throw std::out_of_range("Found invalid error to monitor");
+        }
+    }
+}
+
+TargetErrorData parseFiles(const std::vector<std::string>& filePaths)
+{
+    TargetErrorData systemdTargetMap;
+    for (const auto& jsonFile : filePaths)
+    {
+        if (gVerbose)
+        {
+            std::cout << "Parsing input file " << jsonFile << std::endl;
+        }
+        std::ifstream fileStream(jsonFile);
+        auto j = json::parse(fileStream);
+
+        for (auto it = j["targets"].begin(); it != j["targets"].end(); ++it)
+        {
+            targetEntry entry;
+            if (gVerbose)
+            {
+                std::cout << "target: " << it.key() << " | " << it.value()
+                          << std::endl;
+            }
+
+            // Be unforgiving on invalid json files. Just throw or allow
+            // nlohmann to throw an exception if something is off
+            auto errorsToMonitor = it.value().find("errorsToMonitor");
+            entry.errorsToMonitor =
+                errorsToMonitor->get<std::vector<std::string>>();
+
+            validateErrorsToMonitor(entry.errorsToMonitor);
+
+            auto errorToLog = it.value().find("errorToLog");
+            entry.errorToLog = errorToLog->get<std::string>();
+
+            systemdTargetMap[it.key()] = entry;
+        }
+    }
+    return systemdTargetMap;
+}