Refactor swutils to break down in to functions

Prior to this patch, this is one of the offenders in the bmcweb
codebase for complexity.  It does 4 levels of nested lambdas in a single
method, making it basically impossible to read.  As a side note, this
came up because of an unrelated refactoring, and clang-format seemed to
have just given up, and formatted this block in a nonsensical way.

Tested: Inspection only.  Don't have systems that use this code.

Change-Id: Ica5fa97bae6be2ba1d83d2ad01eeff85bdff6649
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/redfish-core/include/utils/sw_utils.hpp b/redfish-core/include/utils/sw_utils.hpp
index ad0994e..ef3163b 100644
--- a/redfish-core/include/utils/sw_utils.hpp
+++ b/redfish-core/include/utils/sw_utils.hpp
@@ -67,6 +67,207 @@
     }
 }
 
+inline void afterGetProperties(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& swId, bool runningImage,
+    const std::string& swVersionPurpose,
+    const std::string& activeVersionPropName, bool populateLinkToImages,
+    const boost::system::error_code& ec,
+    const dbus::utility::DBusPropertiesMap& propertiesList)
+{
+    if (ec)
+    {
+        BMCWEB_LOG_ERROR("error_code = {}", ec);
+        BMCWEB_LOG_ERROR("error msg = {}", ec.message());
+        // Have seen the code update app delete the
+        // D-Bus object, during code update, between
+        // the call to mapper and here. Just leave
+        // these properties off if resource not
+        // found.
+        if (ec.value() == EBADR)
+        {
+            return;
+        }
+        messages::internalError(asyncResp->res);
+        return;
+    }
+    // example propertiesList
+    // a{sv} 2 "Version" s
+    // "IBM-witherspoon-OP9-v2.0.10-2.22" "Purpose"
+    // s
+    // "xyz.openbmc_project.Software.Version.VersionPurpose.Host"
+    const std::string* version = nullptr;
+    const std::string* swInvPurpose = nullptr;
+
+    const bool success = sdbusplus::unpackPropertiesNoThrow(
+        dbus_utils::UnpackErrorPrinter(), propertiesList, "Purpose",
+        swInvPurpose, "Version", version);
+
+    if (!success)
+    {
+        messages::internalError(asyncResp->res);
+        return;
+    }
+
+    if (version == nullptr || version->empty())
+    {
+        messages::internalError(asyncResp->res);
+        return;
+    }
+    if (swInvPurpose == nullptr || *swInvPurpose != swVersionPurpose)
+    {
+        // Not purpose we're looking for
+        return;
+    }
+
+    BMCWEB_LOG_DEBUG("Image ID: {}", swId);
+    BMCWEB_LOG_DEBUG("Running image: {}", runningImage);
+    BMCWEB_LOG_DEBUG("Image purpose: {}", *swInvPurpose);
+
+    if (populateLinkToImages)
+    {
+        nlohmann::json& softwareImageMembers =
+            asyncResp->res.jsonValue["Links"]["SoftwareImages"];
+        // Firmware images are at
+        // /redfish/v1/UpdateService/FirmwareInventory/<Id>
+        // e.g. .../FirmwareInventory/82d3ec86
+        nlohmann::json::object_t member;
+        member["@odata.id"] = boost::urls::format(
+            "/redfish/v1/UpdateService/FirmwareInventory/{}", swId);
+        softwareImageMembers.emplace_back(std::move(member));
+        asyncResp->res.jsonValue["Links"]["SoftwareImages@odata.count"] =
+            softwareImageMembers.size();
+
+        if (runningImage)
+        {
+            nlohmann::json::object_t runningMember;
+            runningMember["@odata.id"] = boost::urls::format(
+                "/redfish/v1/UpdateService/FirmwareInventory/{}", swId);
+            // Create the link to the running image
+            asyncResp->res.jsonValue["Links"]["ActiveSoftwareImage"] =
+                std::move(runningMember);
+        }
+    }
+    if (!activeVersionPropName.empty() && runningImage)
+    {
+        asyncResp->res.jsonValue[activeVersionPropName] = *version;
+    }
+}
+
+inline void afterGetSubtree(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& swVersionPurpose,
+    const std::string& activeVersionPropName, bool populateLinkToImages,
+    const std::vector<std::string>& functionalSwIds,
+    const boost::system::error_code& ec,
+    const dbus::utility::MapperGetSubTreeResponse& subtree)
+{
+    if (ec)
+    {
+        BMCWEB_LOG_ERROR("error_code = {}", ec);
+        BMCWEB_LOG_ERROR("error msg = {}", ec.message());
+        messages::internalError(asyncResp->res);
+        return;
+    }
+
+    BMCWEB_LOG_DEBUG("Found {} images", subtree.size());
+
+    for (const std::pair<
+             std::string,
+             std::vector<std::pair<std::string, std::vector<std::string>>>>&
+             obj : subtree)
+    {
+        sdbusplus::message::object_path path(obj.first);
+        std::string swId = path.filename();
+        if (swId.empty())
+        {
+            messages::internalError(asyncResp->res);
+            BMCWEB_LOG_ERROR("Invalid software ID");
+
+            return;
+        }
+
+        bool runningImage = false;
+        // Look at Ids from
+        // /xyz/openbmc_project/software/functional
+        // to determine if this is
+        // a running image
+        if (std::ranges::find(functionalSwIds, swId) != functionalSwIds.end())
+        {
+            runningImage = true;
+        }
+
+        // Now grab its version
+        // info
+        sdbusplus::asio::getAllProperties(
+            *crow::connections::systemBus, obj.second[0].first, obj.first,
+            "xyz.openbmc_project.Software.Version",
+            [asyncResp, swId, runningImage, swVersionPurpose,
+             activeVersionPropName, populateLinkToImages](
+                const boost::system::error_code& ec3,
+                const dbus::utility::DBusPropertiesMap& propertiesList) {
+                afterGetProperties(asyncResp, swId, runningImage,
+                                   swVersionPurpose, activeVersionPropName,
+                                   populateLinkToImages, ec3, propertiesList);
+            });
+    }
+}
+
+inline void afterAssociatedEndpoints(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& swVersionPurpose,
+    const std::string& activeVersionPropName, bool populateLinkToImages,
+    const boost::system::error_code& ec,
+    const dbus::utility::MapperEndPoints& functionalSw)
+{
+    BMCWEB_LOG_DEBUG("populateSoftwareInformation enter");
+    if (ec)
+    {
+        BMCWEB_LOG_ERROR("error_code = {}", ec);
+        BMCWEB_LOG_ERROR("error msg = {}", ec.message());
+        // No functional software for this swVersionPurpose, so just
+        return;
+    }
+
+    if (functionalSw.empty())
+    {
+        // Could keep going and try to populate SoftwareImages
+        // but something is seriously wrong, so just fail
+        BMCWEB_LOG_ERROR("Zero functional software in system");
+        messages::internalError(asyncResp->res);
+        return;
+    }
+
+    std::vector<std::string> functionalSwIds;
+    // example functionalSw:
+    // v as 2 "/xyz/openbmc_project/software/ace821ef"
+    //        "/xyz/openbmc_project/software/230fb078"
+    for (const auto& sw : functionalSw)
+    {
+        sdbusplus::message::object_path path(sw);
+        std::string leaf = path.filename();
+        if (leaf.empty())
+        {
+            continue;
+        }
+
+        functionalSwIds.push_back(leaf);
+    }
+
+    constexpr std::array<std::string_view, 1> interfaces = {
+        "xyz.openbmc_project.Software.Version"};
+    dbus::utility::getSubTree(
+        "/xyz/openbmc_project/software", 0, interfaces,
+        [asyncResp, swVersionPurpose, activeVersionPropName,
+         populateLinkToImages, functionalSwIds](
+            const boost::system::error_code& ec2,
+            const dbus::utility::MapperGetSubTreeResponse& subtree) {
+            afterGetSubtree(asyncResp, swVersionPurpose, activeVersionPropName,
+                            populateLinkToImages, functionalSwIds, ec2,
+                            subtree);
+        });
+}
+
 /**
  * @brief Populate the running software version and image links
  *
@@ -99,193 +300,9 @@
          populateLinkToImages](
             const boost::system::error_code& ec,
             const dbus::utility::MapperEndPoints& functionalSw) {
-            BMCWEB_LOG_DEBUG("populateSoftwareInformation enter");
-            if (ec)
-            {
-                BMCWEB_LOG_ERROR("error_code = {}", ec);
-                BMCWEB_LOG_ERROR("error msg = {}", ec.message());
-                // No functional software for this swVersionPurpose, so just
-                // return
-                return;
-            }
-
-            if (functionalSw.empty())
-            {
-                // Could keep going and try to populate SoftwareImages but
-                // something is seriously wrong, so just fail
-                BMCWEB_LOG_ERROR("Zero functional software in system");
-                messages::internalError(asyncResp->res);
-                return;
-            }
-
-            std::vector<std::string> functionalSwIds;
-            // example functionalSw:
-            // v as 2 "/xyz/openbmc_project/software/ace821ef"
-            //        "/xyz/openbmc_project/software/230fb078"
-            for (const auto& sw : functionalSw)
-            {
-                sdbusplus::message::object_path path(sw);
-                std::string leaf = path.filename();
-                if (leaf.empty())
-                {
-                    continue;
-                }
-
-                functionalSwIds.push_back(leaf);
-            }
-
-            constexpr std::array<std::string_view, 1> interfaces = {
-                "xyz.openbmc_project.Software.Version"};
-            dbus::utility::getSubTree(
-                "/xyz/openbmc_project/software", 0, interfaces,
-                [asyncResp, swVersionPurpose, activeVersionPropName,
-                 populateLinkToImages, functionalSwIds](
-                    const boost::system::error_code& ec2,
-                    const dbus::utility::MapperGetSubTreeResponse& subtree) {
-                    if (ec2)
-                    {
-                        BMCWEB_LOG_ERROR("error_code = {}", ec2);
-                        BMCWEB_LOG_ERROR("error msg = {}", ec2.message());
-                        messages::internalError(asyncResp->res);
-                        return;
-                    }
-
-                    BMCWEB_LOG_DEBUG("Found {} images", subtree.size());
-
-                    for (const std::pair<
-                             std::string,
-                             std::vector<std::pair<
-                                 std::string, std::vector<std::string>>>>& obj :
-                         subtree)
-                    {
-                        sdbusplus::message::object_path path(obj.first);
-                        std::string swId = path.filename();
-                        if (swId.empty())
-                        {
-                            messages::internalError(asyncResp->res);
-                            BMCWEB_LOG_ERROR("Invalid software ID");
-
-                            return;
-                        }
-
-                        bool runningImage = false;
-                        // Look at Ids from
-                        // /xyz/openbmc_project/software/functional
-                        // to determine if this is a running image
-                        if (std::ranges::find(functionalSwIds, swId) !=
-                            functionalSwIds.end())
-                        {
-                            runningImage = true;
-                        }
-
-                        // Now grab its version info
-                        sdbusplus::asio::getAllProperties(
-                            *crow::connections::systemBus, obj.second[0].first,
-                            obj.first, "xyz.openbmc_project.Software.Version",
-                            [asyncResp, swId, runningImage, swVersionPurpose,
-                             activeVersionPropName, populateLinkToImages](
-                                const boost::system::error_code& ec3,
-                                const dbus::utility::DBusPropertiesMap&
-                                    propertiesList) {
-                                if (ec3)
-                                {
-                                    BMCWEB_LOG_ERROR("error_code = {}", ec3);
-                                    BMCWEB_LOG_ERROR("error msg = {}",
-                                                     ec3.message());
-                                    // Have seen the code update app delete the
-                                    // D-Bus object, during code update, between
-                                    // the call to mapper and here. Just leave
-                                    // these properties off if resource not
-                                    // found.
-                                    if (ec3.value() == EBADR)
-                                    {
-                                        return;
-                                    }
-                                    messages::internalError(asyncResp->res);
-                                    return;
-                                }
-                                // example propertiesList
-                                // a{sv} 2 "Version" s
-                                // "IBM-witherspoon-OP9-v2.0.10-2.22" "Purpose"
-                                // s
-                                // "xyz.openbmc_project.Software.Version.VersionPurpose.Host"
-                                const std::string* version = nullptr;
-                                const std::string* swInvPurpose = nullptr;
-
-                                const bool success =
-                                    sdbusplus::unpackPropertiesNoThrow(
-                                        dbus_utils::UnpackErrorPrinter(),
-                                        propertiesList, "Purpose", swInvPurpose,
-                                        "Version", version);
-
-                                if (!success)
-                                {
-                                    messages::internalError(asyncResp->res);
-                                    return;
-                                }
-
-                                if (version == nullptr || version->empty())
-                                {
-                                    messages::internalError(asyncResp->res);
-                                    return;
-                                }
-                                if (swInvPurpose == nullptr ||
-                                    *swInvPurpose != swVersionPurpose)
-                                {
-                                    // Not purpose we're looking for
-                                    return;
-                                }
-
-                                BMCWEB_LOG_DEBUG("Image ID: {}", swId);
-                                BMCWEB_LOG_DEBUG("Running image: {}",
-                                                 runningImage);
-                                BMCWEB_LOG_DEBUG("Image purpose: {}",
-                                                 *swInvPurpose);
-
-                                if (populateLinkToImages)
-                                {
-                                    nlohmann::json& softwareImageMembers =
-                                        asyncResp->res
-                                            .jsonValue["Links"]
-                                                      ["SoftwareImages"];
-                                    // Firmware images are at
-                                    // /redfish/v1/UpdateService/FirmwareInventory/<Id>
-                                    // e.g. .../FirmwareInventory/82d3ec86
-                                    nlohmann::json::object_t member;
-                                    member["@odata.id"] = boost::urls::format(
-                                        "/redfish/v1/UpdateService/FirmwareInventory/{}",
-                                        swId);
-                                    softwareImageMembers.emplace_back(
-                                        std::move(member));
-                                    asyncResp->res.jsonValue
-                                        ["Links"]
-                                        ["SoftwareImages@odata.count"] =
-                                        softwareImageMembers.size();
-
-                                    if (runningImage)
-                                    {
-                                        nlohmann::json::object_t runningMember;
-                                        runningMember["@odata.id"] =
-                                            boost::urls::format(
-                                                "/redfish/v1/UpdateService/FirmwareInventory/{}",
-                                                swId);
-                                        // Create the link to the running image
-                                        asyncResp->res
-                                            .jsonValue["Links"]
-                                                      ["ActiveSoftwareImage"] =
-                                            std::move(runningMember);
-                                    }
-                                }
-                                if (!activeVersionPropName.empty() &&
-                                    runningImage)
-                                {
-                                    asyncResp->res
-                                        .jsonValue[activeVersionPropName] =
-                                        *version;
-                                }
-                            });
-                    }
-                });
+            afterAssociatedEndpoints(asyncResp, swVersionPurpose,
+                                     activeVersionPropName,
+                                     populateLinkToImages, ec, functionalSw);
         });
 }