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/keyword_vpd_parser.cpp b/vpd-manager/src/keyword_vpd_parser.cpp
new file mode 100644
index 0000000..9997f94
--- /dev/null
+++ b/vpd-manager/src/keyword_vpd_parser.cpp
@@ -0,0 +1,136 @@
+#include "keyword_vpd_parser.hpp"
+
+#include "constants.hpp"
+#include "exceptions.hpp"
+#include "logger.hpp"
+
+#include <iostream>
+#include <numeric>
+#include <string>
+
+namespace vpd
+{
+
+types::VPDMapVariant KeywordVpdParser::parse()
+{
+    if (m_keywordVpdVector.empty())
+    {
+        throw(DataException("Vector for Keyword format VPD is empty"));
+    }
+    m_vpdIterator = m_keywordVpdVector.begin();
+
+    if (*m_vpdIterator != constants::KW_VPD_START_TAG)
+    {
+        throw(DataException("Invalid Large resource type Identifier String"));
+    }
+
+    checkNextBytesValidity(sizeof(constants::KW_VPD_START_TAG));
+    std::advance(m_vpdIterator, sizeof(constants::KW_VPD_START_TAG));
+
+    uint16_t l_dataSize = getKwDataSize();
+
+    checkNextBytesValidity(constants::TWO_BYTES + l_dataSize);
+    std::advance(m_vpdIterator, constants::TWO_BYTES + l_dataSize);
+
+    // Check for invalid vendor defined large resource type
+    if (*m_vpdIterator != constants::KW_VPD_PAIR_START_TAG)
+    {
+        if (*m_vpdIterator != constants::ALT_KW_VPD_PAIR_START_TAG)
+        {
+            throw(DataException("Invalid Keyword Vpd Start Tag"));
+        }
+    }
+    types::BinaryVector::const_iterator l_checkSumStart = m_vpdIterator;
+    auto l_kwValMap = populateVpdMap();
+
+    // Do these validations before returning parsed data.
+    // Check for small resource type end tag
+    if (*m_vpdIterator != constants::KW_VAL_PAIR_END_TAG)
+    {
+        throw(DataException("Invalid Small resource type End"));
+    }
+
+    types::BinaryVector::const_iterator l_checkSumEnd = m_vpdIterator;
+    validateChecksum(l_checkSumStart, l_checkSumEnd);
+
+    checkNextBytesValidity(constants::TWO_BYTES);
+    std::advance(m_vpdIterator, constants::TWO_BYTES);
+
+    // Check VPD end Tag.
+    if (*m_vpdIterator != constants::KW_VPD_END_TAG)
+    {
+        throw(DataException("Invalid Small resource type."));
+    }
+
+    return l_kwValMap;
+}
+
+types::KeywordVpdMap KeywordVpdParser::populateVpdMap()
+{
+    checkNextBytesValidity(constants::ONE_BYTE);
+    std::advance(m_vpdIterator, constants::ONE_BYTE);
+
+    auto l_totalSize = getKwDataSize();
+    if (l_totalSize == 0)
+    {
+        throw(DataException("Data size is 0, badly formed keyword VPD"));
+    }
+
+    checkNextBytesValidity(constants::TWO_BYTES);
+    std::advance(m_vpdIterator, constants::TWO_BYTES);
+
+    types::KeywordVpdMap l_kwValMap;
+
+    // Parse the keyword-value and store the pairs in map
+    while (l_totalSize > 0)
+    {
+        checkNextBytesValidity(constants::TWO_BYTES);
+        std::string l_keywordName(m_vpdIterator,
+                                  m_vpdIterator + constants::TWO_BYTES);
+        std::advance(m_vpdIterator, constants::TWO_BYTES);
+
+        size_t l_kwSize = *m_vpdIterator;
+        checkNextBytesValidity(constants::ONE_BYTE + l_kwSize);
+        m_vpdIterator++;
+        std::vector<uint8_t> l_valueBytes(m_vpdIterator,
+                                          m_vpdIterator + l_kwSize);
+        std::advance(m_vpdIterator, l_kwSize);
+
+        l_kwValMap.emplace(
+            std::make_pair(std::move(l_keywordName), std::move(l_valueBytes)));
+
+        l_totalSize -= constants::TWO_BYTES + constants::ONE_BYTE + l_kwSize;
+    }
+
+    return l_kwValMap;
+}
+
+void KeywordVpdParser::validateChecksum(
+    types::BinaryVector::const_iterator i_checkSumStart,
+    types::BinaryVector::const_iterator i_checkSumEnd)
+{
+    uint8_t l_checkSumCalculated = 0;
+
+    // Checksum calculation
+    l_checkSumCalculated =
+        std::accumulate(i_checkSumStart, i_checkSumEnd, l_checkSumCalculated);
+    l_checkSumCalculated = ~l_checkSumCalculated + 1;
+    uint8_t l_checksumVpdValue = *(m_vpdIterator + constants::ONE_BYTE);
+
+    if (l_checkSumCalculated != l_checksumVpdValue)
+    {
+        throw(DataException("Invalid Checksum"));
+    }
+}
+
+void KeywordVpdParser::checkNextBytesValidity(uint8_t i_numberOfBytes)
+{
+    if ((std::distance(m_keywordVpdVector.begin(),
+                       m_vpdIterator + i_numberOfBytes)) >
+        std::distance(m_keywordVpdVector.begin(), m_keywordVpdVector.end()))
+    {
+        throw(DataException("Truncated VPD data"));
+    }
+}
+
+} // namespace vpd