Implement config parsing

Add a configuration json parsing function to read the configuration file
from /usr/share/binaryblob/config.json for which system file and location
to serialize/deserialize the binarystore blobs. Add a simple unit test for
parsing configs as well.

Signed-off-by: Kun Yi <kunyi731@gmail.com>
Change-Id: Ie86d622e83991365bc202d659f5860ff01190311
diff --git a/main.cpp b/main.cpp
index 97b3aa9..b5964b8 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,7 +1,12 @@
 #include "handler.hpp"
+#include "parse_config.hpp"
+#include "sys_file.hpp"
 
 #include <blobs-ipmid/blobs.hpp>
+#include <exception>
+#include <fstream>
 #include <memory>
+#include <phosphor-logging/elog.hpp>
 
 #ifdef __cplusplus
 extern "C" {
@@ -17,7 +22,57 @@
 }
 #endif
 
+/* Configuration file path */
+constexpr auto blobConfigPath = "/usr/share/binaryblob/config.json";
+
 std::unique_ptr<blobs::GenericBlobInterface> createHandler()
 {
-    return std::make_unique<blobs::BinaryStoreBlobHandler>();
+    using namespace phosphor::logging;
+    using nlohmann::json;
+
+    std::ifstream input(blobConfigPath);
+    json j;
+
+    try
+    {
+        input >> j;
+    }
+    catch (const std::exception& e)
+    {
+        log<level::ERR>("Failed to parse config into json",
+                        entry("ERR=%s", e.what()));
+        return nullptr;
+    }
+
+    // Construct binary blobs from config and add to handler
+    auto handler = std::make_unique<blobs::BinaryStoreBlobHandler>();
+
+    for (const auto& element : j)
+    {
+        conf::BinaryBlobConfig config;
+        try
+        {
+            conf::parseFromConfigFile(element, config);
+        }
+        catch (const std::exception& e)
+        {
+            log<level::ERR>("Encountered error when parsing config file",
+                            entry("ERR=%s", e.what()));
+            return nullptr;
+        }
+
+        log<level::INFO>("Loading from config with",
+                         entry("BASE_ID=%s", config.blobBaseId.c_str()),
+                         entry("FILE=%s", config.sysFilePath.c_str()),
+                         entry("MAX_SIZE=%llx", static_cast<unsigned long long>(
+                                                    config.maxSizeBytes)));
+
+        auto file = std::make_unique<binstore::SysFileImpl>(config.sysFilePath,
+                                                            config.offsetBytes);
+
+        handler->addNewBinaryStore(binstore::BinaryStore::createFromConfig(
+            config.blobBaseId, std::move(file), config.maxSizeBytes));
+    }
+
+    return std::move(handler);
 }