util: add i2c->pcie map build method

Move method to util that handles creating a mapping between i2c-bus
numbers and their pci-e slot names.  It's done as a list of tuples.

Tested: Only ran unit-tests.
Change-Id: Ie09d193add63245eebcf3806255311232a7c4c9a
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/pcie_i2c.cpp b/pcie_i2c.cpp
index 88eb66c..6f93d01 100644
--- a/pcie_i2c.cpp
+++ b/pcie_i2c.cpp
@@ -21,9 +21,6 @@
 
 #include <cstdint>
 #include <cstring>
-#include <filesystem>
-#include <fstream>
-#include <regex>
 #include <sstream>
 #include <string>
 #include <system_error>
@@ -33,7 +30,6 @@
 {
 namespace ipmi
 {
-namespace fs = std::filesystem;
 
 namespace
 {
@@ -82,49 +78,7 @@
     }
 
     // If there are already entries in the vector, clear them.
-    if (!pcie_i2c_map.empty())
-        pcie_i2c_map.clear();
-
-    // Build a vector with i2c bus to pcie slot mapping.
-    // Iterate through all the devices under "/sys/bus/i2c/devices".
-    for (auto& i2c_dev : fs::directory_iterator("/sys/bus/i2c/devices"))
-    {
-        std::string i2c_dev_path = i2c_dev.path();
-        std::smatch i2c_dev_string_number;
-        std::regex e("(i2c-)(\\d+)");
-        // Check if the device has "i2c-" in its path.
-        if (std::regex_search(i2c_dev_path, i2c_dev_string_number, e))
-        {
-            // Check if the i2c device has "pcie-slot" file under "of-node" dir.
-            std::string pcie_slot_path = i2c_dev_path + "/of_node/pcie-slot";
-            std::string pcie_slot;
-            // Read the "pcie-slot" name from the "pcie-slot" file.
-            pcie_slot = readPropertyFile(pcie_slot_path);
-            if (pcie_slot.empty())
-            {
-                continue;
-            }
-            std::string pcie_slot_name;
-            std::string pcie_slot_full_path;
-            // Append the "pcie-slot" name to dts base.
-            pcie_slot_full_path.append("/proc/device-tree");
-            pcie_slot_full_path.append(pcie_slot);
-            // Read the "label" which contains the pcie slot name.
-            pcie_slot_full_path.append("/label");
-            pcie_slot_name = readPropertyFile(pcie_slot_full_path);
-            if (pcie_slot_name.empty())
-            {
-                continue;
-            }
-            // Get the i2c bus number from the i2c device path.
-            uint32_t i2c_bus_number = i2c_dev_string_number[2].matched
-                                          ? std::stoi(i2c_dev_string_number[2])
-                                          : 0;
-            // Store the i2c bus number and the pcie slot name in the vector.
-            pcie_i2c_map.push_back(
-                std::make_tuple(i2c_bus_number, pcie_slot_name));
-        }
-    }
+    pcie_i2c_map = buildPcieMap();
 
     struct PcieSlotCountReply reply;
     reply.subcommand = SysPcieSlotCount;
diff --git a/util.cpp b/util.cpp
index 34b0f9b..eebc84e 100644
--- a/util.cpp
+++ b/util.cpp
@@ -1,17 +1,22 @@
 #include "util.hpp"
 
+#include <cstdint>
 #include <cstdio>
+#include <filesystem>
 #include <fstream>
 #include <nlohmann/json.hpp>
 #include <phosphor-logging/elog-errors.hpp>
+#include <regex>
 #include <string>
+#include <tuple>
+#include <vector>
 #include <xyz/openbmc_project/Common/error.hpp>
 
 namespace google
 {
 namespace ipmi
 {
-
+namespace fs = std::filesystem;
 using namespace phosphor::logging;
 using InternalFailure =
     sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
@@ -67,5 +72,60 @@
     return "";
 }
 
+std::vector<std::tuple<std::uint32_t, std::string>> buildPcieMap()
+{
+    std::vector<std::tuple<std::uint32_t, std::string>> pcie_i2c_map;
+
+    // Build a vector with i2c bus to pcie slot mapping.
+    // Iterate through all the devices under "/sys/bus/i2c/devices".
+    for (const auto& i2c_dev : fs::directory_iterator("/sys/bus/i2c/devices"))
+    {
+        std::string i2c_dev_path = i2c_dev.path();
+        std::smatch i2c_dev_string_number;
+        std::regex e("(i2c-)(\\d+)");
+
+        // Check if the device has "i2c-" in its path.
+        if (std::regex_search(i2c_dev_path, i2c_dev_string_number, e))
+        {
+            // Check if the i2c device has "pcie-slot" file under "of-node" dir.
+            std::string pcie_slot_path = i2c_dev_path + "/of_node/pcie-slot";
+            std::string pcie_slot;
+
+            // Read the "pcie-slot" name from the "pcie-slot" file.
+            pcie_slot = readPropertyFile(pcie_slot_path);
+            if (pcie_slot.empty())
+            {
+                continue;
+            }
+            std::string pcie_slot_name;
+            std::string pcie_slot_full_path;
+
+            // Append the "pcie-slot" name to dts base.
+            pcie_slot_full_path.append("/proc/device-tree");
+            pcie_slot_full_path.append(pcie_slot);
+
+            // Read the "label" which contains the pcie slot name.
+            pcie_slot_full_path.append("/label");
+            pcie_slot_name = readPropertyFile(pcie_slot_full_path);
+
+            if (pcie_slot_name.empty())
+            {
+                continue;
+            }
+
+            // Get the i2c bus number from the i2c device path.
+            std::uint32_t i2c_bus_number =
+                i2c_dev_string_number[2].matched
+                    ? std::stoi(i2c_dev_string_number[2])
+                    : 0;
+            // Store the i2c bus number and the pcie slot name in the vector.
+            pcie_i2c_map.push_back(
+                std::make_tuple(i2c_bus_number, pcie_slot_name));
+        }
+    }
+
+    return pcie_i2c_map;
+}
+
 } // namespace ipmi
 } // namespace google
diff --git a/util.hpp b/util.hpp
index 760a1b2..d8c8bbd 100644
--- a/util.hpp
+++ b/util.hpp
@@ -1,7 +1,10 @@
 #pragma once
 
+#include <cstdint>
 #include <nlohmann/json.hpp>
 #include <string>
+#include <tuple>
+#include <vector>
 
 namespace google
 {
@@ -25,5 +28,12 @@
  */
 std::string readPropertyFile(const std::string& fileName);
 
+/**
+ * Build a map of the i2c bus numbers to their PCIe slot names.
+ *
+ * @return list of pairs of i2c bus with their corresponding slot names.
+ */
+std::vector<std::tuple<std::uint32_t, std::string>> buildPcieMap();
+
 } // namespace ipmi
 } // namespace google