Revamped code for VPD parser

The commit removes all the pre-existing code from the branch
and pushes the revamped code.

Major modification includes:
- Movement from multi exe to single daemon model.
- Multithreaded approach to parse FRU VPD.
- Better error handling.
- Refactored code for performance optimization.

Note: This code supports all the existing functionalities as it is.

Change-Id: I1ddce1f0725ac59020b72709689a1013643bda8b
Signed-off-by: Sunny Srivastava <sunnsr25@in.ibm.com>
diff --git a/vpd-manager/src/parser_factory.cpp b/vpd-manager/src/parser_factory.cpp
new file mode 100644
index 0000000..546e67b
--- /dev/null
+++ b/vpd-manager/src/parser_factory.cpp
@@ -0,0 +1,140 @@
+#include "parser_factory.hpp"
+
+#include "constants.hpp"
+#include "ddimm_parser.hpp"
+#include "exceptions.hpp"
+#include "ipz_parser.hpp"
+#include "isdimm_parser.hpp"
+#include "keyword_vpd_parser.hpp"
+
+namespace vpd
+{
+
+/**
+ * @brief Type of VPD formats.
+ */
+enum vpdType
+{
+    IPZ_VPD,                /**< IPZ VPD type */
+    KEYWORD_VPD,            /**< Keyword VPD type */
+    DDR4_DDIMM_MEMORY_VPD,  /**< DDR4 DDIMM Memory VPD type */
+    DDR5_DDIMM_MEMORY_VPD,  /**< DDR5 DDIMM Memory VPD type */
+    DDR4_ISDIMM_MEMORY_VPD, /**< DDR4 ISDIMM Memory VPD type */
+    DDR5_ISDIMM_MEMORY_VPD, /**< DDR5 ISDIMM Memory VPD type */
+    INVALID_VPD_FORMAT      /**< Invalid VPD type */
+};
+
+/**
+ * @brief API to get the type of VPD.
+ *
+ * @param[in] i_vpdVector - VPD file content
+ *
+ * @return Type of VPD data, "INVALID_VPD_FORMAT" in case of unknown type.
+ */
+static vpdType vpdTypeCheck(const types::BinaryVector& i_vpdVector)
+{
+    if (i_vpdVector[constants::IPZ_DATA_START] == constants::IPZ_DATA_START_TAG)
+    {
+        return vpdType::IPZ_VPD;
+    }
+    else if (i_vpdVector[constants::KW_VPD_DATA_START] ==
+             constants::KW_VPD_START_TAG)
+    {
+        return vpdType::KEYWORD_VPD;
+    }
+    else if (((i_vpdVector[constants::SPD_BYTE_3] &
+               constants::SPD_BYTE_BIT_0_3_MASK) ==
+              constants::SPD_MODULE_TYPE_DDIMM))
+    {
+        std::string l_is11SFormat;
+        if (i_vpdVector.size() > (constants::DDIMM_11S_BARCODE_START +
+                                  constants::DDIMM_11S_BARCODE_LEN))
+        {
+            // Read first 3 Bytes to check the 11S bar code format
+            for (uint8_t l_index = 0; l_index < constants::DDIMM_11S_FORMAT_LEN;
+                 l_index++)
+            {
+                l_is11SFormat +=
+                    i_vpdVector[constants::DDIMM_11S_BARCODE_START + l_index];
+            }
+        }
+
+        if (l_is11SFormat.compare(constants::DDIMM_11S_BARCODE_START_TAG) == 0)
+        {
+            // DDIMM memory VPD format
+            if ((i_vpdVector[constants::SPD_BYTE_2] &
+                 constants::SPD_BYTE_MASK) == constants::SPD_DRAM_TYPE_DDR5)
+            {
+                return vpdType::DDR5_DDIMM_MEMORY_VPD;
+            }
+
+            if ((i_vpdVector[constants::SPD_BYTE_2] &
+                 constants::SPD_BYTE_MASK) == constants::SPD_DRAM_TYPE_DDR4)
+            {
+                return vpdType::DDR4_DDIMM_MEMORY_VPD;
+            }
+        }
+
+        logging::logMessage("11S format is not found in the DDIMM VPD.");
+        return vpdType::INVALID_VPD_FORMAT;
+    }
+    else if ((i_vpdVector[constants::SPD_BYTE_2] & constants::SPD_BYTE_MASK) ==
+             constants::SPD_DRAM_TYPE_DDR5)
+    {
+        // ISDIMM memory VPD format
+        return vpdType::DDR5_ISDIMM_MEMORY_VPD;
+    }
+    else if ((i_vpdVector[constants::SPD_BYTE_2] & constants::SPD_BYTE_MASK) ==
+             constants::SPD_DRAM_TYPE_DDR4)
+    {
+        // ISDIMM memory VPD format
+        return vpdType::DDR4_ISDIMM_MEMORY_VPD;
+    }
+
+    return vpdType::INVALID_VPD_FORMAT;
+}
+
+std::shared_ptr<ParserInterface> ParserFactory::getParser(
+    const types::BinaryVector& i_vpdVector, const std::string& i_vpdFilePath,
+    size_t i_vpdStartOffset)
+{
+    if (i_vpdVector.empty())
+    {
+        throw std::runtime_error("Empty VPD vector passed to parser factory");
+    }
+
+    vpdType l_type = vpdTypeCheck(i_vpdVector);
+
+    switch (l_type)
+    {
+        case vpdType::IPZ_VPD:
+        {
+            return std::make_shared<IpzVpdParser>(i_vpdVector, i_vpdFilePath,
+                                                  i_vpdStartOffset);
+        }
+
+        case vpdType::KEYWORD_VPD:
+        {
+            return std::make_shared<KeywordVpdParser>(i_vpdVector);
+        }
+
+        case vpdType::DDR5_DDIMM_MEMORY_VPD:
+        case vpdType::DDR4_DDIMM_MEMORY_VPD:
+        {
+            return std::make_shared<DdimmVpdParser>(i_vpdVector);
+        }
+
+        case vpdType::DDR4_ISDIMM_MEMORY_VPD:
+        case vpdType::DDR5_ISDIMM_MEMORY_VPD:
+        {
+            // return shared pointer to class object.
+            logging::logMessage(
+                "ISDIMM parser selected for VPD path: " + i_vpdFilePath);
+            return std::make_shared<JedecSpdParser>(i_vpdVector);
+        }
+
+        default:
+            throw DataException("Unable to determine VPD format");
+    }
+}
+} // namespace vpd