Selaa lähdekoodia

Refactor: Break up logic in cmSystemTools::ChangeRPath()

Kyle Edwards 4 vuotta sitten
vanhempi
sitoutus
966f7250df
1 muutettua tiedostoa jossa 108 lisäystä ja 70 poistoa
  1. 108 70
      Source/cmSystemTools.cxx

+ 108 - 70
Source/cmSystemTools.cxx

@@ -14,6 +14,7 @@
 
 #include "cmSystemTools.h"
 
+#include <cm/optional>
 #include <cmext/algorithm>
 
 #include <cm3p/uv.h>
@@ -65,6 +66,7 @@
 #include <cstdlib>
 #include <cstring>
 #include <ctime>
+#include <functional>
 #include <iostream>
 #include <sstream>
 #include <utility>
@@ -2524,6 +2526,7 @@ std::string::size_type cmSystemToolsFindRPath(cm::string_view const& have,
 #endif
 
 #if defined(CMake_USE_ELF_PARSER)
+namespace {
 struct cmSystemToolsRPathInfo
 {
   unsigned long Position;
@@ -2531,15 +2534,15 @@ struct cmSystemToolsRPathInfo
   std::string Name;
   std::string Value;
 };
-#endif
+
+using EmptyCallback = std::function<bool(std::string*, const cmELF&)>;
+using AdjustCallback = std::function<bool(
+  cm::optional<std::string>&, const std::string&, const char*, std::string*)>;
 
 // FIXME: Dispatch if multiple formats are supported.
-#if defined(CMake_USE_ELF_PARSER)
-bool cmSystemTools::ChangeRPath(std::string const& file,
-                                std::string const& oldRPath,
-                                std::string const& newRPath,
-                                bool removeEnvironmentRPath, std::string* emsg,
-                                bool* changed)
+bool AdjustRPath(std::string const& file, const EmptyCallback& emptyCallback,
+                 const AdjustCallback& adjustCallback, std::string* emsg,
+                 bool* changed)
 {
   if (changed) {
     *changed = false;
@@ -2566,17 +2569,7 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
       ++se_count;
     }
     if (se_count == 0) {
-      if (newRPath.empty()) {
-        // The new rpath is empty and there is no rpath anyway so it is
-        // okay.
-        return true;
-      }
-      if (emsg) {
-        *emsg =
-          cmStrCat("No valid ELF RPATH or RUNPATH entry exists in the file; ",
-                   elf.GetErrorMessage());
-      }
-      return false;
+      return emptyCallback(emsg, elf);
     }
 
     for (int i = 0; i < se_count; ++i) {
@@ -2586,68 +2579,38 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
         continue;
       }
 
-      // Make sure the current rpath contains the old rpath.
-      std::string::size_type pos =
-        cmSystemToolsFindRPath(se[i]->Value, oldRPath);
-      if (pos == std::string::npos) {
-        // If it contains the new rpath instead then it is okay.
-        if (cmSystemToolsFindRPath(se[i]->Value, newRPath) !=
-            std::string::npos) {
-          remove_rpath = false;
-          continue;
-        }
-        if (emsg) {
-          std::ostringstream e;
-          /* clang-format off */
-        e << "The current " << se_name[i] << " is:\n"
-          << "  " << se[i]->Value << "\n"
-          << "which does not contain:\n"
-          << "  " << oldRPath << "\n"
-          << "as was expected.";
-          /* clang-format on */
-          *emsg = e.str();
-        }
-        return false;
-      }
-
       // Store information about the entry in the file.
       rp[rp_count].Position = se[i]->Position;
       rp[rp_count].Size = se[i]->Size;
       rp[rp_count].Name = se_name[i];
 
-      std::string::size_type prefix_len = pos;
-
-      // If oldRPath was at the end of the file's RPath, and newRPath is empty,
-      // we should remove the unnecessary ':' at the end.
-      if (newRPath.empty() && pos > 0 && se[i]->Value[pos - 1] == ':' &&
-          pos + oldRPath.length() == se[i]->Value.length()) {
-        prefix_len--;
-      }
-
-      // Construct the new value which preserves the part of the path
-      // not being changed.
-      if (!removeEnvironmentRPath) {
-        rp[rp_count].Value = se[i]->Value.substr(0, prefix_len);
+      // Adjust the rpath.
+      cm::optional<std::string> outRPath;
+      if (!adjustCallback(outRPath, se[i]->Value, se_name[i], emsg)) {
+        return false;
       }
-      rp[rp_count].Value += newRPath;
-      rp[rp_count].Value += se[i]->Value.substr(pos + oldRPath.length());
 
-      if (!rp[rp_count].Value.empty()) {
-        remove_rpath = false;
-      }
+      if (outRPath) {
+        if (!outRPath->empty()) {
+          remove_rpath = false;
+        }
 
-      // Make sure there is enough room to store the new rpath and at
-      // least one null terminator.
-      if (rp[rp_count].Size < rp[rp_count].Value.length() + 1) {
-        if (emsg) {
-          *emsg = cmStrCat("The replacement path is too long for the ",
-                           se_name[i], " entry.");
+        // Make sure there is enough room to store the new rpath and at
+        // least one null terminator.
+        if (rp[rp_count].Size < outRPath->length() + 1) {
+          if (emsg) {
+            *emsg = cmStrCat("The replacement path is too long for the ",
+                             se_name[i], " entry.");
+          }
+          return false;
         }
-        return false;
-      }
 
-      // This entry is ready for update.
-      ++rp_count;
+        // This entry is ready for update.
+        rp[rp_count].Value = std::move(*outRPath);
+        ++rp_count;
+      } else {
+        remove_rpath = false;
+      }
     }
   }
 
@@ -2706,6 +2669,81 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
   }
   return true;
 }
+
+std::function<bool(std::string*, const cmELF&)> MakeEmptyCallback(
+  const std::string& newRPath)
+{
+  return [newRPath](std::string* emsg, const cmELF& elf) -> bool {
+    if (newRPath.empty()) {
+      // The new rpath is empty and there is no rpath anyway so it is
+      // okay.
+      return true;
+    }
+    if (emsg) {
+      *emsg =
+        cmStrCat("No valid ELF RPATH or RUNPATH entry exists in the file; ",
+                 elf.GetErrorMessage());
+    }
+    return false;
+  };
+};
+}
+
+bool cmSystemTools::ChangeRPath(std::string const& file,
+                                std::string const& oldRPath,
+                                std::string const& newRPath,
+                                bool removeEnvironmentRPath, std::string* emsg,
+                                bool* changed)
+{
+  auto adjustCallback = [oldRPath, newRPath, removeEnvironmentRPath](
+                          cm::optional<std::string>& outRPath,
+                          const std::string& inRPath, const char* se_name,
+                          std::string* emsg2) -> bool {
+    // Make sure the current rpath contains the old rpath.
+    std::string::size_type pos = cmSystemToolsFindRPath(inRPath, oldRPath);
+    if (pos == std::string::npos) {
+      // If it contains the new rpath instead then it is okay.
+      if (cmSystemToolsFindRPath(inRPath, newRPath) != std::string::npos) {
+        return true;
+      }
+      if (emsg2) {
+        std::ostringstream e;
+        /* clang-format off */
+        e << "The current " << se_name << " is:\n"
+          << "  " << inRPath << "\n"
+          << "which does not contain:\n"
+          << "  " << oldRPath << "\n"
+          << "as was expected.";
+        /* clang-format on */
+        *emsg2 = e.str();
+      }
+      return false;
+    }
+
+    std::string::size_type prefix_len = pos;
+
+    // If oldRPath was at the end of the file's RPath, and newRPath is empty,
+    // we should remove the unnecessary ':' at the end.
+    if (newRPath.empty() && pos > 0 && inRPath[pos - 1] == ':' &&
+        pos + oldRPath.length() == inRPath.length()) {
+      prefix_len--;
+    }
+
+    // Construct the new value which preserves the part of the path
+    // not being changed.
+    outRPath.emplace();
+    if (!removeEnvironmentRPath) {
+      *outRPath += inRPath.substr(0, prefix_len);
+    }
+    *outRPath += newRPath;
+    *outRPath += inRPath.substr(pos + oldRPath.length());
+
+    return true;
+  };
+
+  return AdjustRPath(file, MakeEmptyCallback(newRPath), adjustCallback, emsg,
+                     changed);
+}
 #elif defined(CMake_USE_XCOFF_PARSER)
 bool cmSystemTools::ChangeRPath(std::string const& file,
                                 std::string const& oldRPath,