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/include/ipz_parser.hpp b/vpd-manager/include/ipz_parser.hpp
new file mode 100644
index 0000000..2d50ddd
--- /dev/null
+++ b/vpd-manager/include/ipz_parser.hpp
@@ -0,0 +1,273 @@
+#pragma once
+
+#include "logger.hpp"
+#include "parser_interface.hpp"
+#include "types.hpp"
+
+#include <fstream>
+#include <string_view>
+
+namespace vpd
+{
+/**
+ * @brief Concrete class to implement IPZ VPD parsing.
+ *
+ * The class inherits ParserInterface interface class and overrides the parser
+ * functionality to implement parsing logic for IPZ VPD format.
+ */
+class IpzVpdParser : public ParserInterface
+{
+  public:
+    // Deleted APIs
+    IpzVpdParser() = delete;
+    IpzVpdParser(const IpzVpdParser&) = delete;
+    IpzVpdParser& operator=(const IpzVpdParser&) = delete;
+    IpzVpdParser(IpzVpdParser&&) = delete;
+    IpzVpdParser& operator=(IpzVpdParser&&) = delete;
+
+    /**
+     * @brief Constructor.
+     *
+     * @param[in] vpdVector - VPD data.
+     * @param[in] vpdFilePath - Path to VPD EEPROM.
+     * @param[in] vpdStartOffset - Offset from where VPD starts in the file.
+     * Defaulted to 0.
+     */
+    IpzVpdParser(const types::BinaryVector& vpdVector,
+                 const std::string& vpdFilePath, size_t vpdStartOffset = 0) :
+        m_vpdVector(vpdVector), m_vpdFilePath(vpdFilePath),
+        m_vpdStartOffset(vpdStartOffset)
+    {
+        try
+        {
+            m_vpdFileStream.exceptions(
+                std::ifstream::badbit | std::ifstream::failbit);
+            m_vpdFileStream.open(vpdFilePath, std::ios::in | std::ios::out |
+                                                  std::ios::binary);
+        }
+        catch (const std::fstream::failure& e)
+        {
+            logging::logMessage(e.what());
+        }
+    }
+
+    /**
+     * @brief Defaul destructor.
+     */
+    ~IpzVpdParser() = default;
+
+    /**
+     * @brief API to parse IPZ VPD file.
+     *
+     * Note: Caller needs to check validity of the map returned. Throws
+     * exception in certain situation, needs to be handled accordingly.
+     *
+     * @return parsed VPD data.
+     */
+    virtual types::VPDMapVariant parse() override;
+
+    /**
+     * @brief API to check validity of VPD header.
+     *
+     * Note: The API throws exception in case of any failure or malformed VDP.
+     *
+     * @param[in] itrToVPD - Iterator to the beginning of VPD file.
+     * Don't change the parameter to reference as movement of passsed iterator
+     * to an offset is not required after header check.
+     */
+    void checkHeader(types::BinaryVector::const_iterator itrToVPD);
+
+    /**
+     * @brief API to read keyword's value from hardware
+     *
+     * @param[in] i_paramsToReadData - Data required to perform read
+     *
+     * @throw
+     * sdbusplus::xyz::openbmc_project::Common::Device::Error::ReadFailure.
+     *
+     * @return On success return the value read. On failure throw exception.
+     */
+    types::DbusVariantType
+        readKeywordFromHardware(const types::ReadVpdParams i_paramsToReadData);
+
+    /**
+     * @brief API to write keyword's value on hardware.
+     *
+     * @param[in] i_paramsToWriteData - Data required to perform write.
+     *
+     * @throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument.
+     * @throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed.
+     * @throw DataException
+     * @throw EccException
+     *
+     *
+     * @return On success returns number of bytes written on hardware, On
+     * failure throws exception.
+     */
+    int writeKeywordOnHardware(const types::WriteVpdParams i_paramsToWriteData);
+
+  private:
+    /**
+     * @brief Check ECC of VPD header.
+     *
+     * @return true/false based on check result.
+     */
+    bool vhdrEccCheck();
+
+    /**
+     * @brief Check ECC of VTOC.
+     *
+     * @return true/false based on check result.
+     */
+    bool vtocEccCheck();
+
+    /**
+     * @brief Check ECC of a record.
+     *
+     * Note: Throws exception in case of failure. Caller need to handle as
+     * required.
+     *
+     * @param[in] iterator - Iterator to the record.
+     * @return success/failre
+     */
+    bool recordEccCheck(types::BinaryVector::const_iterator iterator);
+
+    /**
+     * @brief API to read VTOC record.
+     *
+     * The API reads VTOC record and returns the length of PT keyword.
+     *
+     * Note: Throws exception in case of any error. Caller need to handle as
+     * required.
+     *
+     * @param[in] itrToVPD - Iterator to begining of VPD data.
+     * @return Length of PT keyword.
+     */
+    auto readTOC(types::BinaryVector::const_iterator& itrToVPD);
+
+    /**
+     * @brief API to read PT record.
+     *
+     * Note: Throws exception in case ECC check fails.
+     *
+     * @param[in] itrToPT - Iterator to PT record in VPD vector.
+     * @param[in] ptLength - length of the PT record.
+     * @return List of record's offset.
+     */
+    types::RecordOffsetList readPT(types::BinaryVector::const_iterator& itrToPT,
+                                   auto ptLength);
+
+    /**
+     * @brief API to read keyword data based on its encoding type.
+     *
+     * @param[in] kwdName - Name of the keyword.
+     * @param[in] kwdDataLength - Length of keyword data.
+     * @param[in] itrToKwdData - Iterator to start of keyword data.
+     * @return keyword data, empty otherwise.
+     */
+    std::string readKwData(std::string_view kwdName, std::size_t kwdDataLength,
+                           types::BinaryVector::const_iterator itrToKwdData);
+
+    /**
+     * @brief API to read keyword and its value under a record.
+     *
+     * @param[in] iterator - pointer to the start of keywords under the record.
+     * @return keyword-value map of keywords under that record.
+     */
+    types::IPZVpdMap::mapped_type
+        readKeywords(types::BinaryVector::const_iterator& itrToKwds);
+
+    /**
+     * @brief API to process a record.
+     *
+     * @param[in] recordOffset - Offset of the record in VPD.
+     */
+    void processRecord(auto recordOffset);
+
+    /**
+     * @brief Get keyword's value from record
+     *
+     * @param[in] i_record - Record's name
+     * @param[in] i_keyword - Keyword's name
+     * @param[in] i_recordDataOffset - Record's offset value
+     *
+     * @throw std::runtime_error
+     *
+     * @return On success return bytes read, on failure throws error.
+     */
+    types::BinaryVector getKeywordValueFromRecord(
+        const types::Record& i_recordName, const types::Keyword& i_keywordName,
+        const types::RecordOffset& i_recordDataOffset);
+
+    /**
+     * @brief Get record's details from VTOC's PT keyword value
+     *
+     * This API parses through VTOC's PT keyword value and returns the given
+     * record's offset, record's length, ECC offset and ECC length.
+     *
+     * @param[in] i_record - Record's name.
+     * @param[in] i_vtocOffset - Offset to VTOC record
+     *
+     * @return On success return record's details, on failure return empty
+     * buffer.
+     */
+    types::RecordData
+        getRecordDetailsFromVTOC(const types::Record& l_recordName,
+                                 const types::RecordOffset& i_vtocOffset);
+
+    /**
+     * @brief API to update record's ECC
+     *
+     * This API is required to update the record's ECC based on the record's
+     * current data.
+     *
+     * @param[in] i_recordDataOffset - Record's data offset
+     * @param[in] i_recordDataLength - Record's data length
+     * @param[in] i_recordECCOffset - Record's ECC offset
+     * @param[in] i_recordECCLength - Record's ECC length
+     * @param[in,out] io_vpdVector - FRU VPD in vector to update record's ECC.
+     *
+     * @throw EccException
+     */
+    void updateRecordECC(const auto& i_recordDataOffset,
+                         const auto& i_recordDataLength,
+                         const auto& i_recordECCOffset,
+                         size_t i_recordECCLength,
+                         types::BinaryVector& io_vpdVector);
+
+    /**
+     * @brief API to set record's keyword's value on hardware.
+     *
+     * @param[in] i_recordName - Record name.
+     * @param[in] i_keywordName - Keyword name.
+     * @param[in] i_keywordData - Keyword data.
+     * @param[in] i_recordDataOffset - Offset to record's data.
+     * @param[in,out] io_vpdVector - FRU VPD in vector to read and write
+     * keyword's value.
+     *
+     * @throw DataException
+     *
+     * @return On success returns number of bytes set. On failure returns -1.
+     */
+    int setKeywordValueInRecord(const types::Record& i_recordName,
+                                const types::Keyword& i_keywordName,
+                                const types::BinaryVector& i_keywordData,
+                                const types::RecordOffset& i_recordDataOffset,
+                                types::BinaryVector& io_vpdVector);
+
+    // Holds VPD data.
+    const types::BinaryVector& m_vpdVector;
+
+    // stores parsed VPD data.
+    types::IPZVpdMap m_parsedVPDMap{};
+
+    // Holds the VPD file path
+    const std::string& m_vpdFilePath;
+
+    // Stream to the VPD file. Required to correct ECC
+    std::fstream m_vpdFileStream;
+
+    // VPD start offset. Required for ECC correction.
+    size_t m_vpdStartOffset = 0;
+};
+} // namespace vpd