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