瀏覽代碼

Merge topic 'modernize_string_view_cmOutputConverter'

ec892a572b cmOutputConverter: Make shell escaping methods cm::string_view based
8573e20c43 cmOutputConverter: Let GetFortranFormat accept a cm::string_view
4911762358 cmOutputConverter: Return bool instead of int in utility functions
a929255dec cmOutputConverter: Let cmOutputConverterIsShellOperator accept cm::string_view
1b30b28c04 cmOutputConverter: Let cmOutputConverterIsShellOperator accept cm::string_view
6675f785be cmOutputConverter: Let EscapeForCMake accept a cm::string_view
09977c1816 cmSystemTool: Let TrimWhitespace accept a cm::string_view
2f19e53705 cmSystemTool: Let HelpFileName accept a cm::string_view
...

Acked-by: Kitware Robot <[email protected]>
Merge-request: !3615
Brad King 6 年之前
父節點
當前提交
f6df9c2565
共有 4 個文件被更改,包括 138 次插入126 次删除
  1. 90 85
      Source/cmOutputConverter.cxx
  2. 14 12
      Source/cmOutputConverter.h
  3. 29 24
      Source/cmSystemTools.cxx
  4. 5 5
      Source/cmSystemTools.h

+ 90 - 85
Source/cmOutputConverter.cxx

@@ -6,7 +6,6 @@
 #include <assert.h>
 #include <ctype.h>
 #include <set>
-#include <string.h>
 #include <vector>
 
 #include "cmState.h"
@@ -38,10 +37,10 @@ std::string cmOutputConverter::ConvertToOutputForExisting(
   return this->ConvertToOutputFormat(remote, format);
 }
 
-std::string cmOutputConverter::ConvertToOutputFormat(const std::string& source,
+std::string cmOutputConverter::ConvertToOutputFormat(cm::string_view source,
                                                      OutputFormat output) const
 {
-  std::string result = source;
+  std::string result(source);
   // Convert it to an output path.
   if (output == SHELL || output == WATCOMQUOTE) {
     result = this->ConvertDirectorySeparatorsForShell(source);
@@ -53,9 +52,9 @@ std::string cmOutputConverter::ConvertToOutputFormat(const std::string& source,
 }
 
 std::string cmOutputConverter::ConvertDirectorySeparatorsForShell(
-  const std::string& source) const
+  cm::string_view source) const
 {
-  std::string result = source;
+  std::string result(source);
   // For the MSYS shell convert drive letters to posix paths, so
   // that c:/some/path becomes /c/some/path.  This is needed to
   // avoid problems with the shell path translation.
@@ -71,21 +70,21 @@ std::string cmOutputConverter::ConvertDirectorySeparatorsForShell(
   return result;
 }
 
-static bool cmOutputConverterIsShellOperator(const std::string& str)
+static bool cmOutputConverterIsShellOperator(cm::string_view str)
 {
-  static std::set<std::string> const shellOperators{
+  static std::set<cm::string_view> const shellOperators{
     "<", ">", "<<", ">>", "|", "||", "&&", "&>", "1>", "2>", "2>&1", "1>&2"
   };
   return (shellOperators.count(str) != 0);
 }
 
-std::string cmOutputConverter::EscapeForShell(const std::string& str,
+std::string cmOutputConverter::EscapeForShell(cm::string_view str,
                                               bool makeVars, bool forEcho,
                                               bool useWatcomQuote) const
 {
   // Do not escape shell operators.
   if (cmOutputConverterIsShellOperator(str)) {
-    return str;
+    return std::string(str);
   }
 
   // Compute the flags for the target shell environment.
@@ -117,46 +116,44 @@ std::string cmOutputConverter::EscapeForShell(const std::string& str,
     flags |= Shell_Flag_IsUnix;
   }
 
-  return Shell__GetArgument(str.c_str(), flags);
+  return Shell__GetArgument(str, flags);
 }
 
-std::string cmOutputConverter::EscapeForCMake(const std::string& str)
+std::string cmOutputConverter::EscapeForCMake(cm::string_view str)
 {
   // Always double-quote the argument to take care of most escapes.
   std::string result = "\"";
-  for (const char* c = str.c_str(); *c; ++c) {
-    if (*c == '"') {
+  for (const char c : str) {
+    if (c == '"') {
       // Escape the double quote to avoid ending the argument.
       result += "\\\"";
-    } else if (*c == '$') {
+    } else if (c == '$') {
       // Escape the dollar to avoid expanding variables.
       result += "\\$";
-    } else if (*c == '\\') {
+    } else if (c == '\\') {
       // Escape the backslash to avoid other escapes.
       result += "\\\\";
     } else {
       // Other characters will be parsed correctly.
-      result += *c;
+      result += c;
     }
   }
   result += "\"";
   return result;
 }
 
-std::string cmOutputConverter::EscapeWindowsShellArgument(const char* arg,
+std::string cmOutputConverter::EscapeWindowsShellArgument(cm::string_view arg,
                                                           int shell_flags)
 {
   return Shell__GetArgument(arg, shell_flags);
 }
 
 cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
-  const char* value)
+  cm::string_view value)
 {
   FortranFormat format = FortranFormatNone;
-  if (value && *value) {
-    std::vector<std::string> fmt;
-    cmSystemTools::ExpandListArgument(value, fmt);
-    for (std::string const& fi : fmt) {
+  if (!value.empty()) {
+    for (std::string const& fi : cmSystemTools::ExpandedListArgument(value)) {
       if (fi == "FIXED") {
         format = FortranFormatFixed;
       }
@@ -168,6 +165,15 @@ cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
   return format;
 }
 
+cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
+  const char* value)
+{
+  if (!value) {
+    return FortranFormatNone;
+  }
+  return GetFortranFormat(cm::string_view(value));
+}
+
 void cmOutputConverter::SetLinkScriptShell(bool linkScriptShell)
 {
   this->LinkScriptShell = linkScriptShell;
@@ -213,12 +219,12 @@ use the caret character itself (^), use two in a row (^^).
 */
 
 /* Some helpers to identify character classes */
-static int Shell__CharIsWhitespace(char c)
+static bool Shell__CharIsWhitespace(char c)
 {
   return ((c == ' ') || (c == '\t'));
 }
 
-static int Shell__CharNeedsQuotesOnUnix(char c)
+static bool Shell__CharNeedsQuotesOnUnix(char c)
 {
   return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') ||
           (c == '&') || (c == '$') || (c == '(') || (c == ')') || (c == '~') ||
@@ -226,51 +232,52 @@ static int Shell__CharNeedsQuotesOnUnix(char c)
           (c == '\\'));
 }
 
-static int Shell__CharNeedsQuotesOnWindows(char c)
+static bool Shell__CharNeedsQuotesOnWindows(char c)
 {
   return ((c == '\'') || (c == '#') || (c == '&') || (c == '<') ||
           (c == '>') || (c == '|') || (c == '^'));
 }
 
-static int Shell__CharIsMakeVariableName(char c)
+static bool Shell__CharIsMakeVariableName(char c)
 {
   return c && (c == '_' || isalpha((static_cast<int>(c))));
 }
 
-int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
+bool cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
 {
   /* On Windows the built-in command shell echo never needs quotes.  */
   if (!(flags & Shell_Flag_IsUnix) && (flags & Shell_Flag_EchoWindows)) {
-    return 0;
+    return false;
   }
 
   /* On all platforms quotes are needed to preserve whitespace.  */
   if (Shell__CharIsWhitespace(c)) {
-    return 1;
+    return true;
   }
 
   if (flags & Shell_Flag_IsUnix) {
     /* On UNIX several special characters need quotes to preserve them.  */
     if (Shell__CharNeedsQuotesOnUnix(c)) {
-      return 1;
+      return true;
     }
   } else {
     /* On Windows several special characters need quotes to preserve them.  */
     if (Shell__CharNeedsQuotesOnWindows(c)) {
-      return 1;
+      return true;
     }
   }
-  return 0;
+  return false;
 }
 
-const char* cmOutputConverter::Shell__SkipMakeVariables(const char* c)
+cm::string_view::iterator cmOutputConverter::Shell__SkipMakeVariables(
+  cm::string_view::iterator c, cm::string_view::iterator end)
 {
-  while (*c == '$' && *(c + 1) == '(') {
-    const char* skip = c + 2;
-    while (Shell__CharIsMakeVariableName(*skip)) {
+  while ((c != end && (c + 1) != end) && (*c == '$' && *(c + 1) == '(')) {
+    cm::string_view::iterator skip = c + 2;
+    while ((skip != end) && Shell__CharIsMakeVariableName(*skip)) {
       ++skip;
     }
-    if (*skip == ')') {
+    if ((skip != end) && *skip == ')') {
       c = skip + 1;
     } else {
       break;
@@ -302,63 +309,60 @@ flag later when we understand applications of this better.
 */
 #define KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES 0
 
-int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int flags)
+bool cmOutputConverter::Shell__ArgumentNeedsQuotes(cm::string_view in,
+                                                   int flags)
 {
   /* The empty string needs quotes.  */
-  if (!*in) {
-    return 1;
+  if (in.empty()) {
+    return true;
   }
 
   /* Scan the string for characters that require quoting.  */
-  {
-    const char* c;
-    for (c = in; *c; ++c) {
-      /* Look for $(MAKEVAR) syntax if requested.  */
-      if (flags & Shell_Flag_AllowMakeVariables) {
+  for (cm::string_view::iterator cit = in.begin(), cend = in.end();
+       cit != cend; ++cit) {
+    /* Look for $(MAKEVAR) syntax if requested.  */
+    if (flags & Shell_Flag_AllowMakeVariables) {
 #if KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES
-        const char* skip = Shell__SkipMakeVariables(c);
-        if (skip != c) {
-          /* We need to quote make variable references to preserve the
-             string with contents substituted in its place.  */
-          return 1;
-        }
+      cm::string_view::iterator skip = Shell__SkipMakeVariables(cit, cend);
+      if (skip != cit) {
+        /* We need to quote make variable references to preserve the
+           string with contents substituted in its place.  */
+        return true;
+      }
 #else
-        /* Skip over the make variable references if any are present.  */
-        c = Shell__SkipMakeVariables(c);
+      /* Skip over the make variable references if any are present.  */
+      cit = Shell__SkipMakeVariables(cit, cend);
 
-        /* Stop if we have reached the end of the string.  */
-        if (!*c) {
-          break;
-        }
-#endif
+      /* Stop if we have reached the end of the string.  */
+      if (cit == cend) {
+        break;
       }
+#endif
+    }
 
-      /* Check whether this character needs quotes.  */
-      if (Shell__CharNeedsQuotes(*c, flags)) {
-        return 1;
-      }
+    /* Check whether this character needs quotes.  */
+    if (Shell__CharNeedsQuotes(*cit, flags)) {
+      return true;
     }
   }
 
   /* On Windows some single character arguments need quotes.  */
-  if (flags & Shell_Flag_IsUnix && *in && !*(in + 1)) {
-    char c = *in;
+  if (flags & Shell_Flag_IsUnix && in.size() == 1) {
+    char c = in[0];
     if ((c == '?') || (c == '&') || (c == '^') || (c == '|') || (c == '#')) {
-      return 1;
+      return true;
     }
   }
 
-  return 0;
+  return false;
 }
 
-std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
+std::string cmOutputConverter::Shell__GetArgument(cm::string_view in,
+                                                  int flags)
 {
   /* Output will be at least as long as input string.  */
   std::string out;
-  out.reserve(strlen(in));
-
-  /* String iterator.  */
-  const char* c;
+  out.reserve(in.size());
 
   /* Keep track of how many backslashes have been encountered in a row.  */
   int windows_backslashes = 0;
@@ -378,14 +382,15 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
   }
 
   /* Scan the string for characters that require escaping or quoting.  */
-  for (c = in; *c; ++c) {
+  for (cm::string_view::iterator cit = in.begin(), cend = in.end();
+       cit != cend; ++cit) {
     /* Look for $(MAKEVAR) syntax if requested.  */
     if (flags & Shell_Flag_AllowMakeVariables) {
-      const char* skip = Shell__SkipMakeVariables(c);
-      if (skip != c) {
+      cm::string_view::iterator skip = Shell__SkipMakeVariables(cit, cend);
+      if (skip != cit) {
         /* Copy to the end of the make variable references.  */
-        while (c != skip) {
-          out += *c++;
+        while (cit != skip) {
+          out += *cit++;
         }
 
         /* The make variable reference eliminates any escaping needed
@@ -393,7 +398,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
         windows_backslashes = 0;
 
         /* Stop if we have reached the end of the string.  */
-        if (!*c) {
+        if (cit == cend) {
           break;
         }
       }
@@ -403,7 +408,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
     if (flags & Shell_Flag_IsUnix) {
       /* On Unix a few special characters need escaping even inside a
          quoted argument.  */
-      if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') {
+      if (*cit == '\\' || *cit == '"' || *cit == '`' || *cit == '$') {
         /* This character needs a backslash to escape it.  */
         out += '\\';
       }
@@ -411,10 +416,10 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
       /* On Windows the built-in command shell echo never needs escaping.  */
     } else {
       /* On Windows only backslashes and double-quotes need escaping.  */
-      if (*c == '\\') {
+      if (*cit == '\\') {
         /* Found a backslash.  It may need to be escaped later.  */
         ++windows_backslashes;
-      } else if (*c == '"') {
+      } else if (*cit == '"') {
         /* Found a double-quote.  Escape all immediately preceding
            backslashes.  */
         while (windows_backslashes > 0) {
@@ -432,7 +437,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
     }
 
     /* Check whether this character needs escaping for a make tool.  */
-    if (*c == '$') {
+    if (*cit == '$') {
       if (flags & Shell_Flag_Make) {
         /* In Makefiles a dollar is written $$.  The make tool will
            replace it with just $ before passing it to the shell.  */
@@ -449,7 +454,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
         /* Otherwise a dollar is written just $. */
         out += '$';
       }
-    } else if (*c == '#') {
+    } else if (*cit == '#') {
       if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) {
         /* In Watcom WMake makefiles a pound is written $#.  The make
            tool will replace it with just # before passing it to the
@@ -459,7 +464,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
         /* Otherwise a pound is written just #. */
         out += '#';
       }
-    } else if (*c == '%') {
+    } else if (*cit == '%') {
       if ((flags & Shell_Flag_VSIDE) ||
           ((flags & Shell_Flag_Make) &&
            ((flags & Shell_Flag_MinGWMake) || (flags & Shell_Flag_NMake)))) {
@@ -469,7 +474,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
         /* Otherwise a percent is written just %. */
         out += '%';
       }
-    } else if (*c == ';') {
+    } else if (*cit == ';') {
       if (flags & Shell_Flag_VSIDE) {
         /* In a VS IDE a semicolon is written ";".  If this is written
            in an un-quoted argument it starts a quoted segment,
@@ -483,7 +488,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
       }
     } else {
       /* Store this character.  */
-      out += *c;
+      out += *cit;
     }
   }
 

+ 14 - 12
Source/cmOutputConverter.h

@@ -5,9 +5,10 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include <string>
-
 #include "cmStateSnapshot.h"
+#include "cm_string_view.hxx"
+
+#include <string>
 
 class cmState;
 
@@ -22,10 +23,9 @@ public:
     WATCOMQUOTE,
     RESPONSE
   };
-  std::string ConvertToOutputFormat(const std::string& source,
+  std::string ConvertToOutputFormat(cm::string_view source,
                                     OutputFormat output) const;
-  std::string ConvertDirectorySeparatorsForShell(
-    const std::string& source) const;
+  std::string ConvertDirectorySeparatorsForShell(cm::string_view source) const;
 
   //! for existing files convert to output path and short path if spaces
   std::string ConvertToOutputForExisting(const std::string& remote,
@@ -72,15 +72,15 @@ public:
     Shell_Flag_IsUnix = (1 << 8)
   };
 
-  std::string EscapeForShell(const std::string& str, bool makeVars = false,
+  std::string EscapeForShell(cm::string_view str, bool makeVars = false,
                              bool forEcho = false,
                              bool useWatcomQuote = false) const;
 
-  static std::string EscapeForCMake(const std::string& str);
+  static std::string EscapeForCMake(cm::string_view str);
 
   /** Compute an escaped version of the given argument for use in a
       windows shell.  */
-  static std::string EscapeWindowsShellArgument(const char* arg,
+  static std::string EscapeWindowsShellArgument(cm::string_view arg,
                                                 int shell_flags);
 
   enum FortranFormat
@@ -89,15 +89,17 @@ public:
     FortranFormatFixed,
     FortranFormatFree
   };
+  static FortranFormat GetFortranFormat(cm::string_view value);
   static FortranFormat GetFortranFormat(const char* value);
 
 private:
   cmState* GetState() const;
 
-  static int Shell__CharNeedsQuotes(char c, int flags);
-  static const char* Shell__SkipMakeVariables(const char* c);
-  static int Shell__ArgumentNeedsQuotes(const char* in, int flags);
-  static std::string Shell__GetArgument(const char* in, int flags);
+  static bool Shell__CharNeedsQuotes(char c, int flags);
+  static cm::string_view::iterator Shell__SkipMakeVariables(
+    cm::string_view::iterator begin, cm::string_view::iterator end);
+  static bool Shell__ArgumentNeedsQuotes(cm::string_view in, int flags);
+  static std::string Shell__GetArgument(cm::string_view in, int flags);
 
 private:
   cmStateSnapshot StateSnapshot;

+ 29 - 24
Source/cmSystemTools.cxx

@@ -176,36 +176,37 @@ void cmSystemTools::ExpandRegistryValues(std::string& source,
 }
 #endif
 
-std::string cmSystemTools::EscapeQuotes(const std::string& str)
+std::string cmSystemTools::EscapeQuotes(cm::string_view str)
 {
   std::string result;
   result.reserve(str.size());
-  for (const char* ch = str.c_str(); *ch != '\0'; ++ch) {
-    if (*ch == '"') {
+  for (const char ch : str) {
+    if (ch == '"') {
       result += '\\';
     }
-    result += *ch;
+    result += ch;
   }
   return result;
 }
 
-std::string cmSystemTools::HelpFileName(std::string name)
+std::string cmSystemTools::HelpFileName(cm::string_view str)
 {
+  std::string name(str);
   cmSystemTools::ReplaceString(name, "<", "");
   cmSystemTools::ReplaceString(name, ">", "");
   return name;
 }
 
-std::string cmSystemTools::TrimWhitespace(const std::string& s)
+std::string cmSystemTools::TrimWhitespace(cm::string_view str)
 {
-  std::string::const_iterator start = s.begin();
-  while (start != s.end() && cm_isspace(*start)) {
+  auto start = str.begin();
+  while (start != str.end() && cm_isspace(*start)) {
     ++start;
   }
-  if (start == s.end()) {
-    return "";
+  if (start == str.end()) {
+    return std::string();
   }
-  std::string::const_iterator stop = s.end() - 1;
+  auto stop = str.end() - 1;
   while (cm_isspace(*stop)) {
     --stop;
   }
@@ -1121,7 +1122,7 @@ void cmSystemTools::GlobDirs(const std::string& path,
   }
 }
 
-void cmSystemTools::ExpandListArgument(const std::string& arg,
+void cmSystemTools::ExpandListArgument(cm::string_view arg,
                                        std::vector<std::string>& argsOut,
                                        bool emptyArgs)
 {
@@ -1129,25 +1130,29 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
   if (!emptyArgs && arg.empty()) {
     return;
   }
+
   // if there are no ; in the name then just copy the current string
-  if (arg.find(';') == std::string::npos) {
-    argsOut.push_back(arg);
+  if (arg.find(';') == cm::string_view::npos) {
+    argsOut.emplace_back(arg);
     return;
   }
+
   std::string newArg;
-  const char* last = arg.c_str();
   // Break the string at non-escaped semicolons not nested in [].
   int squareNesting = 0;
-  for (const char* c = last; *c; ++c) {
+  cm::string_view::iterator last = arg.begin();
+  cm::string_view::iterator const cend = arg.end();
+  for (cm::string_view::iterator c = last; c != cend; ++c) {
     switch (*c) {
       case '\\': {
         // We only want to allow escaping of semicolons.  Other
         // escapes should not be processed here.
-        const char* next = c + 1;
-        if (*next == ';') {
-          newArg.append(last, c - last);
+        cm::string_view::iterator cnext = c + 1;
+        if ((cnext != cend) && *cnext == ';') {
+          newArg.append(last, c);
           // Skip over the escape character
-          last = c = next;
+          last = cnext;
+          c = cnext;
         }
       } break;
       case '[': {
@@ -1160,7 +1165,7 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
         // Break the string here if we are not nested inside square
         // brackets.
         if (squareNesting == 0) {
-          newArg.append(last, c - last);
+          newArg.append(last, c);
           // Skip over the semicolon
           last = c + 1;
           if (!newArg.empty() || emptyArgs) {
@@ -1175,15 +1180,15 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
       } break;
     }
   }
-  newArg.append(last);
+  newArg.append(last, cend);
   if (!newArg.empty() || emptyArgs) {
     // Add the last argument if the string is not empty.
-    argsOut.push_back(newArg);
+    argsOut.push_back(std::move(newArg));
   }
 }
 
 std::vector<std::string> cmSystemTools::ExpandedListArgument(
-  const std::string& arg, bool emptyArgs)
+  cm::string_view arg, bool emptyArgs)
 {
   std::vector<std::string> argsOut;
   ExpandListArgument(arg, argsOut, emptyArgs);

+ 5 - 5
Source/cmSystemTools.h

@@ -32,7 +32,7 @@ public:
    * Expand the ; separated string @a arg into multiple arguments.
    * All found arguments are appended to @a argsOut.
    */
-  static void ExpandListArgument(const std::string& arg,
+  static void ExpandListArgument(cm::string_view arg,
                                  std::vector<std::string>& argsOut,
                                  bool emptyArgs = false);
 
@@ -54,7 +54,7 @@ public:
    * Same as ExpandListArgument but a new vector is created containing
    * the expanded arguments from the string @a arg.
    */
-  static std::vector<std::string> ExpandedListArgument(const std::string& arg,
+  static std::vector<std::string> ExpandedListArgument(cm::string_view arg,
                                                        bool emptyArgs = false);
 
   /**
@@ -78,15 +78,15 @@ public:
                                    KeyWOW64 view = KeyWOW64_Default);
 
   //! Escape quotes in a string.
-  static std::string EscapeQuotes(const std::string& str);
+  static std::string EscapeQuotes(cm::string_view str);
 
   /** Map help document name to file name.  */
-  static std::string HelpFileName(std::string);
+  static std::string HelpFileName(cm::string_view);
 
   /**
    * Returns a string that has whitespace removed from the start and the end.
    */
-  static std::string TrimWhitespace(const std::string& s);
+  static std::string TrimWhitespace(cm::string_view str);
 
   using MessageCallback = std::function<void(const std::string&, const char*)>;
   /**