pldm: Optimized parsing of PDR JSON files

Move the generateStateEffecterRepo method of parse JSON to
pdr_state_effecter.hpp.

Tested with JSON files:
 https://gist.github.com/lxwinspur/2c3fd68cdb35e06480c4a5f7890e3a06#file-effecter_pdr-json.

 pldmtool platform GetPDR -d 1
 Encode request successfully
 Request Message:
 08 01 80 02 51 01 00 00 00 00 00 00 00 01 80 00 00 00
 Success in creating the socket : RC = 3
 Success in connecting to socket : RC = 0
 Success in sending message type as pldm to mctp : RC = 0
 Write to socket successful : RC = 18
 Total length:18
 Loopback response message:
 08 01 80 02 51 01 00 00 00 00 00 00 00 01 80 00 00 00
 On first recv(),response == request : RC = 0
 Total length: 46
 Shutdown Socket successful :  RC = 0
 Response Message:
 08 01 00 02 51 00 02 00 00 00 00 00 00 00 01 1d 00 01 00 00 00 01 0b 00 00 13 00 00 00 01 00 21 00 00 00 00 00 00 00 00 00 01 c4 00 01 06
 Parsed Response Msg:
 nextRecordHandle: 2
 responseCount: 29
 recordHandle: 1
 PDRHeaderVersion: 1
 PDRType: 11
 recordChangeNumber: 0
 dataLength: 19
 PLDMTerminusHandle: 0
 effecterID: 1
 entityType: 33
 entityInstanceNumber: 0
 containerID: 0
 effecterSemanticID: 0
 effecterInit: 0
 effecterDescriptionPDR: false
 compositeEffecterCount: 1
 stateSetID: 196
 possibleStatesSize: 1
 possibleStates: 6

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I8428ed042fb0a90ecc448073f059f66360066306
diff --git a/libpldmresponder/pdr.cpp b/libpldmresponder/pdr.cpp
index 27a0bd3..44a07e6 100644
--- a/libpldmresponder/pdr.cpp
+++ b/libpldmresponder/pdr.cpp
@@ -1,6 +1,6 @@
 #include "pdr.hpp"
 
-#include "platform.hpp"
+#include "pdr_state_effecter.hpp"
 
 namespace pldm
 {
@@ -10,7 +10,6 @@
 
 namespace pdr
 {
-
 using namespace pldm::responder::pdr_utils;
 
 void getRepoByType(const Repo& inRepo, Repo& outRepo, Type pdrType)
diff --git a/libpldmresponder/pdr.hpp b/libpldmresponder/pdr.hpp
index 78925f7..a2a066f 100644
--- a/libpldmresponder/pdr.hpp
+++ b/libpldmresponder/pdr.hpp
@@ -1,13 +1,10 @@
 #pragma once
 
 #include "libpldmresponder/pdr_utils.hpp"
+#include "utils.hpp"
 
 #include <stdint.h>
 
-#include <string>
-
-#include "libpldm/pdr.h"
-
 using namespace pldm::responder::pdr_utils;
 
 namespace pldm
diff --git a/libpldmresponder/pdr_state_effecter.hpp b/libpldmresponder/pdr_state_effecter.hpp
new file mode 100644
index 0000000..25f3198
--- /dev/null
+++ b/libpldmresponder/pdr_state_effecter.hpp
@@ -0,0 +1,131 @@
+#pragma once
+
+#include "libpldmresponder/pdr_utils.hpp"
+
+#include "libpldm/platform.h"
+
+namespace pldm
+{
+
+namespace responder
+{
+
+namespace pdr_state_effecter
+{
+
+using Json = nlohmann::json;
+
+static const Json empty{};
+
+/** @brief Parse PDR JSON file and generate state effecter PDR structure
+ *
+ *  @param[in] json - the JSON Object with the state effecter PDR
+ *  @param[out] handler - the Parser of PLDM command handler
+ *  @param[out] repo - pdr::RepoInterface
+ *
+ */
+template <class Handler>
+void generateStateEffecterPDR(const Json& json, Handler& handler,
+                              pdr_utils::RepoInterface& repo)
+{
+    static const std::vector<Json> emptyList{};
+    auto entries = json.value("entries", emptyList);
+    for (const auto& e : entries)
+    {
+        size_t pdrSize = 0;
+        auto effecters = e.value("effecters", emptyList);
+        for (const auto& effecter : effecters)
+        {
+            auto set = effecter.value("set", empty);
+            auto statesSize = set.value("size", 0);
+            if (!statesSize)
+            {
+                std::cerr << "Malformed PDR JSON return "
+                             "pdrEntry;- no state set "
+                             "info, TYPE="
+                          << PLDM_STATE_EFFECTER_PDR << "\n";
+                throw InternalFailure();
+            }
+            pdrSize += sizeof(state_effecter_possible_states) -
+                       sizeof(bitfield8_t) + (sizeof(bitfield8_t) * statesSize);
+        }
+        pdrSize += sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t);
+
+        std::vector<uint8_t> entry{};
+        entry.resize(pdrSize);
+
+        pldm_state_effecter_pdr* pdr =
+            reinterpret_cast<pldm_state_effecter_pdr*>(entry.data());
+        pdr->hdr.record_handle = 0;
+        pdr->hdr.version = 1;
+        pdr->hdr.type = PLDM_STATE_EFFECTER_PDR;
+        pdr->hdr.record_change_num = 0;
+        pdr->hdr.length = pdrSize - sizeof(pldm_pdr_hdr);
+
+        pdr->terminus_handle = 0;
+        pdr->effecter_id = handler.getNextEffecterId();
+        pdr->entity_type = e.value("type", 0);
+        pdr->entity_instance = e.value("instance", 0);
+        pdr->container_id = e.value("container", 0);
+        pdr->effecter_semantic_id = 0;
+        pdr->effecter_init = PLDM_NO_INIT;
+        pdr->has_description_pdr = false;
+        pdr->composite_effecter_count = effecters.size();
+
+        DbusMappings dbusMappings{};
+        DbusValMaps dbusValMaps{};
+        uint8_t* start =
+            entry.data() + sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t);
+        for (const auto& effecter : effecters)
+        {
+            auto set = effecter.value("set", empty);
+            state_effecter_possible_states* possibleStates =
+                reinterpret_cast<state_effecter_possible_states*>(start);
+            possibleStates->state_set_id = set.value("id", 0);
+            possibleStates->possible_states_size = set.value("size", 0);
+
+            start += sizeof(possibleStates->state_set_id) +
+                     sizeof(possibleStates->possible_states_size);
+            static const std::vector<uint8_t> emptyStates{};
+            PossibleValues stateValues;
+            auto states = set.value("states", emptyStates);
+            for (const auto& state : states)
+            {
+                auto index = state / 8;
+                auto bit = state - (index * 8);
+                bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(start + index);
+                bf->byte |= 1 << bit;
+                stateValues.emplace_back(std::move(state));
+            }
+            start += possibleStates->possible_states_size;
+
+            auto dbusEntry = effecter.value("dbus", empty);
+            auto objectPath = dbusEntry.value("path", "");
+            auto interface = dbusEntry.value("interface", "");
+            auto propertyName = dbusEntry.value("property_name", "");
+            auto propertyType = dbusEntry.value("property_type", "");
+            pldm::utils::DBusMapping dbusMapping{objectPath, interface,
+                                                 propertyName, propertyType};
+            dbusMappings.emplace_back(std::move(dbusMapping));
+
+            Json propValues = dbusEntry["property_values"];
+            StatestoDbusVal dbusIdToValMap =
+                populateMapping(propertyType, propValues, stateValues);
+            if (!dbusIdToValMap.empty())
+            {
+                dbusValMaps.emplace_back(std::move(dbusIdToValMap));
+            }
+        }
+        handler.addDbusObjMaps(
+            pdr->effecter_id,
+            std::make_tuple(std::move(dbusMappings), std::move(dbusValMaps)));
+        PdrEntry pdrEntry{};
+        pdrEntry.data = entry.data();
+        pdrEntry.size = pdrSize;
+        repo.addRecord(pdrEntry);
+    }
+}
+
+} // namespace pdr_state_effecter
+} // namespace responder
+} // namespace pldm
diff --git a/libpldmresponder/pdr_utils.hpp b/libpldmresponder/pdr_utils.hpp
index 1f03863..6df5d94 100644
--- a/libpldmresponder/pdr_utils.hpp
+++ b/libpldmresponder/pdr_utils.hpp
@@ -51,6 +51,8 @@
 /** @brief Map of DBus property State to attribute value
  */
 using StatestoDbusVal = std::map<State, pldm::utils::PropertyValue>;
+using DbusMappings = std::vector<pldm::utils::DBusMapping>;
+using DbusValMaps = std::vector<StatestoDbusVal>;
 
 /** @brief Parse PDR JSON file and output Json object
  *
diff --git a/libpldmresponder/platform.cpp b/libpldmresponder/platform.cpp
index 45bd041..6aef73d 100644
--- a/libpldmresponder/platform.cpp
+++ b/libpldmresponder/platform.cpp
@@ -1,6 +1,7 @@
 
 #include "platform.hpp"
 
+#include "pdr_state_effecter.hpp"
 #include "utils.hpp"
 
 namespace pldm
@@ -15,130 +16,32 @@
 
 static const Json empty{};
 
-void Handler::addDbusObjMaps(uint16_t effecterId,
-                             std::tuple<DbusMappings, DbusValMaps> dbusObj)
+void Handler::addDbusObjMaps(
+    uint16_t effecterId,
+    std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj)
 {
     dbusObjMaps.emplace(effecterId, dbusObj);
 }
 
-const std::tuple<DbusMappings, DbusValMaps>&
+const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>&
     Handler::getDbusObjMaps(uint16_t effecterId) const
 {
     return dbusObjMaps.at(effecterId);
 }
 
-void Handler::generateStateEffecterRepo(const Json& json, Repo& repo)
-{
-    static const std::vector<Json> emptyList{};
-    auto entries = json.value("entries", emptyList);
-    for (const auto& e : entries)
-    {
-        size_t pdrSize = 0;
-        auto effecters = e.value("effecters", emptyList);
-        for (const auto& effecter : effecters)
-        {
-            auto set = effecter.value("set", empty);
-            auto statesSize = set.value("size", 0);
-            if (!statesSize)
-            {
-                std::cerr << "Malformed PDR JSON return "
-                             "pdrEntry;- no state set "
-                             "info, TYPE="
-                          << PLDM_STATE_EFFECTER_PDR << "\n";
-                throw InternalFailure();
-            }
-            pdrSize += sizeof(state_effecter_possible_states) -
-                       sizeof(bitfield8_t) + (sizeof(bitfield8_t) * statesSize);
-        }
-        pdrSize += sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t);
-
-        std::vector<uint8_t> entry{};
-        entry.resize(pdrSize);
-
-        pldm_state_effecter_pdr* pdr =
-            reinterpret_cast<pldm_state_effecter_pdr*>(entry.data());
-        pdr->hdr.record_handle = 0;
-        pdr->hdr.version = 1;
-        pdr->hdr.type = PLDM_STATE_EFFECTER_PDR;
-        pdr->hdr.record_change_num = 0;
-        pdr->hdr.length = pdrSize - sizeof(pldm_pdr_hdr);
-
-        pdr->terminus_handle = 0;
-        pdr->effecter_id = this->getNextEffecterId();
-        pdr->entity_type = e.value("type", 0);
-        pdr->entity_instance = e.value("instance", 0);
-        pdr->container_id = e.value("container", 0);
-        pdr->effecter_semantic_id = 0;
-        pdr->effecter_init = PLDM_NO_INIT;
-        pdr->has_description_pdr = false;
-        pdr->composite_effecter_count = effecters.size();
-
-        DbusMappings dbusMappings{};
-        DbusValMaps dbusValMaps{};
-        uint8_t* start =
-            entry.data() + sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t);
-        for (const auto& effecter : effecters)
-        {
-            auto set = effecter.value("set", empty);
-            state_effecter_possible_states* possibleStates =
-                reinterpret_cast<state_effecter_possible_states*>(start);
-            possibleStates->state_set_id = set.value("id", 0);
-            possibleStates->possible_states_size = set.value("size", 0);
-
-            start += sizeof(possibleStates->state_set_id) +
-                     sizeof(possibleStates->possible_states_size);
-            static const std::vector<uint8_t> emptyStates{};
-            PossibleValues stateValues;
-            auto states = set.value("states", emptyStates);
-            for (const auto& state : states)
-            {
-                auto index = state / 8;
-                auto bit = state - (index * 8);
-                bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(start + index);
-                bf->byte |= 1 << bit;
-                stateValues.emplace_back(std::move(state));
-            }
-            start += possibleStates->possible_states_size;
-
-            auto dbusEntry = effecter.value("dbus", empty);
-            auto objectPath = dbusEntry.value("path", "");
-            auto interface = dbusEntry.value("interface", "");
-            auto propertyName = dbusEntry.value("property_name", "");
-            auto propertyType = dbusEntry.value("property_type", "");
-            pldm::utils::DBusMapping dbusMapping{objectPath, interface,
-                                                 propertyName, propertyType};
-            dbusMappings.emplace_back(std::move(dbusMapping));
-
-            Json propValues = dbusEntry["property_values"];
-            StatestoDbusVal dbusIdToValMap =
-                populateMapping(propertyType, propValues, stateValues);
-            if (!dbusIdToValMap.empty())
-            {
-                dbusValMaps.emplace_back(std::move(dbusIdToValMap));
-            }
-        }
-
-        addDbusObjMaps(
-            pdr->effecter_id,
-            std::make_tuple(std::move(dbusMappings), std::move(dbusValMaps)));
-        PdrEntry pdrEntry{};
-        pdrEntry.data = entry.data();
-        pdrEntry.size = pdrSize;
-        repo.addRecord(pdrEntry);
-    }
-}
-
 void Handler::generate(const std::string& dir, Repo& repo)
 {
     // A map of PDR type to a lambda that handles creation of that PDR type.
     // The lambda essentially would parse the platform specific PDR JSONs to
     // generate the PDR structures. This function iterates through the map to
     // invoke all lambdas, so that all PDR types can be created.
-    const std::map<Type, std::function<void(const Json& json, Repo& repo)>>
-        generators = {
-            {PLDM_STATE_EFFECTER_PDR, [this](const auto& json, Repo& repo) {
-                 generateStateEffecterRepo(json, repo);
-             }}};
+
+    const std::map<Type, generatePDR> generateHandlers = {
+        {PLDM_STATE_EFFECTER_PDR,
+         [this](const auto& json, RepoInterface& repo) {
+             pdr_state_effecter::generateStateEffecterPDR<Handler>(json, *this,
+                                                                   repo);
+         }}};
 
     Type pdrType{};
     for (const auto& dirEntry : fs::directory_iterator(dir))
@@ -152,7 +55,7 @@
                 for (const auto& effecter : effecterPDRs)
                 {
                     pdrType = effecter.value("pdrType", 0);
-                    generators.at(pdrType)(effecter, repo);
+                    generateHandlers.at(pdrType)(effecter, repo);
                 }
             }
         }
diff --git a/libpldmresponder/platform.hpp b/libpldmresponder/platform.hpp
index 9c8860e..75a1ad3 100644
--- a/libpldmresponder/platform.hpp
+++ b/libpldmresponder/platform.hpp
@@ -24,10 +24,13 @@
 using namespace pldm::utils;
 using namespace pldm::responder::pdr_utils;
 
+using generatePDR =
+    std::function<void(const Json& json, pdr_utils::RepoInterface& repo)>;
+
 using EffecterId = uint16_t;
-using DbusMappings = std::vector<DBusMapping>;
-using DbusValMaps = std::vector<StatestoDbusVal>;
-using DbusObjMaps = std::map<EffecterId, std::tuple<DbusMappings, DbusValMaps>>;
+using DbusObjMaps =
+    std::map<EffecterId,
+             std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>>;
 
 class Handler : public CmdHandler
 {
@@ -60,17 +63,19 @@
      *  @param[in] dbusObj - list of D-Bus object structure and list of D-Bus
      *                       property value to attribute value
      */
-    void addDbusObjMaps(uint16_t effecterId,
-                        std::tuple<DbusMappings, DbusValMaps> dbusObj);
+    void addDbusObjMaps(
+        uint16_t effecterId,
+        std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj);
 
     /** @brief Retrieve an effecter id -> D-Bus objects mapping
      *
      *  @param[in] effecterId - effecter id
      *
-     *  @return std::tuple<DbusMappings, DbusValMaps> - list of D-Bus object
-     *          structure and list of D-Bus property value to attribute value
+     *  @return std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> -
+     *          list of D-Bus object structure and list of D-Bus property value
+     *          to attribute value
      */
-    const std::tuple<DbusMappings, DbusValMaps>&
+    const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>&
         getDbusObjMaps(uint16_t effecterId) const;
 
     uint16_t getNextEffecterId()