Add RAS data parser handling for getting RAS data flags

In the future we will be supporting an additional 'flags'
type stored in the RAS data files for specific bits. This
adds the handling to the RAS data parser to get those flags.

Signed-off-by: Caleb Palmer <cnpalmer@us.ibm.com>
Change-Id: Ie7889135ae7a643fec287565143a8ee7edc33777
diff --git a/analyzer/ras-data/ras-data-parser.cpp b/analyzer/ras-data/ras-data-parser.cpp
index e8042ff..8ad510d 100644
--- a/analyzer/ras-data/ras-data-parser.cpp
+++ b/analyzer/ras-data/ras-data-parser.cpp
@@ -10,7 +10,6 @@
 
 namespace analyzer
 {
-
 //------------------------------------------------------------------------------
 
 std::shared_ptr<Resolution>
@@ -48,6 +47,91 @@
 
 //------------------------------------------------------------------------------
 
+bool RasDataParser::isFlagSet(const libhei::Signature& i_signature,
+                              const RasDataFlags i_flag)
+{
+    bool o_isFlagSet = false;
+
+    // List of all flag enums mapping to their corresponding string
+    std::map<RasDataFlags, std::string> flagMap = {
+        {SUE_SOURCE, "sue_source"},
+        {SUE_SEEN, "sue_seen"},
+        {CS_POSSIBLE, "cs_possible"},
+        {RECOVERED_ERROR, "recovered_error"},
+        {INFORMATIONAL_ONLY, "informational_only"},
+        {MNFG_INFORMATIONAL_ONLY, "mnfg_informational_only"},
+        {MASK_BUT_DONT_CLEAR, "mask_but_dont_clear"},
+        {CRC_RELATED_ERR, "crc_related_err"},
+        {CRC_ROOT_CAUSE, "crc_root_cause"},
+        {ODP_DATA_CORRUPT_SIDE_EFFECT, "odp_data_corrupt_side_effect"},
+        {ODP_DATA_CORRUPT_ROOT_CAUSE, "odp_data_corrupt_root_cause"},
+    };
+
+    // If the input flag does not exist in the map, that's a code bug.
+    assert(0 != flagMap.count(i_flag));
+
+    nlohmann::json data;
+    try
+    {
+        data = iv_dataFiles.at(i_signature.getChip().getType());
+    }
+    catch (const std::out_of_range& e)
+    {
+        trace::err("No RAS data defined for chip type: 0x%08x",
+                   i_signature.getChip().getType());
+        throw; // caught later downstream
+    }
+
+    // Get the signature keys. All are hex (lower case) with no prefix.
+    char buf[5];
+    sprintf(buf, "%04x", i_signature.getId());
+    std::string id{buf};
+
+    sprintf(buf, "%02x", i_signature.getBit());
+    std::string bit{buf};
+
+    // Get the list of flags in string format from the data.
+    if (data.at("signatures").at(id).at(bit).contains("flags"))
+    {
+        auto flags = data.at("signatures")
+                         .at(id)
+                         .at(bit)
+                         .at("flags")
+                         .get<std::vector<std::string>>();
+
+        // Check if the input flag exists
+        if (flags.end() !=
+            std::find(flags.begin(), flags.end(), flagMap[i_flag]))
+        {
+            o_isFlagSet = true;
+        }
+    }
+
+    // If the flag hasn't been found, check if it was defined as part of the
+    // action for this input signature.
+    if (!o_isFlagSet)
+    {
+        const auto action = parseSignature(data, i_signature);
+        for (const auto& a : data.at("actions").at(action))
+        {
+            auto type = a.at("type").get<std::string>();
+            if ("flag" == type)
+            {
+                auto name = a.at("name").get<std::string>();
+                if (name == flagMap[i_flag])
+                {
+                    o_isFlagSet = true;
+                    break;
+                }
+            }
+        }
+    }
+
+    return o_isFlagSet;
+}
+
+//------------------------------------------------------------------------------
+
 void RasDataParser::initDataFiles()
 {
     iv_dataFiles.clear(); // initially empty
@@ -332,6 +416,10 @@
 
             o_list->push(std::make_shared<PluginResolution>(name, inst));
         }
+        else if ("flag" == type)
+        {
+            // No action, flags will be handled with the isFlagSet function
+        }
         else
         {
             throw std::logic_error("Unsupported action type: " + type);
diff --git a/analyzer/ras-data/ras-data-parser.hpp b/analyzer/ras-data/ras-data-parser.hpp
index 60d9ab7..17908d4 100644
--- a/analyzer/ras-data/ras-data-parser.hpp
+++ b/analyzer/ras-data/ras-data-parser.hpp
@@ -8,7 +8,6 @@
 
 namespace analyzer
 {
-
 /**
  * @brief Manages the RAS data files and resolves service actions required for
  *        error signatures.
@@ -22,6 +21,22 @@
         initDataFiles();
     }
 
+    /** Define all RAS data flags that may be associated with a signature */
+    enum RasDataFlags
+    {
+        SUE_SOURCE,
+        SUE_SEEN,
+        CS_POSSIBLE,
+        RECOVERED_ERROR,
+        INFORMATIONAL_ONLY,
+        MNFG_INFORMATIONAL_ONLY,
+        MASK_BUT_DONT_CLEAR,
+        CRC_RELATED_ERR,
+        CRC_ROOT_CAUSE,
+        ODP_DATA_CORRUPT_SIDE_EFFECT,
+        ODP_DATA_CORRUPT_ROOT_CAUSE,
+    };
+
   private:
     /** @brief The RAS data files. */
     std::map<libhei::ChipType_t, nlohmann::json> iv_dataFiles;
@@ -35,6 +50,16 @@
     std::shared_ptr<Resolution>
         getResolution(const libhei::Signature& i_signature);
 
+    /**
+     * @brief Initializes the signature list within the input isolation data
+     *        with their appropriate flags based on the RAS data files.
+     * @param i_signature The target error signature.
+     * @param i_flag      The flag to check for
+     * @return True if the flag is set for the given signature, else false.
+     */
+    bool isFlagSet(const libhei::Signature& i_signature,
+                   const RasDataFlags i_flag);
+
   private:
     /**
      * @brief Parses all of the RAS data JSON files and validates them against