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/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);
                 }
             }
         }