Merge topic 'cmStringAlgorithms_move_functions'

959b97a27f Tests: testStringAlgorithms: Add cmTrimWhitespace, cmEscapeQuotes, cmTokenize
7fbcc16dcd cmStringAlgorithms: cmIsSpace, cmTrimWhitespace, cmEscapeQuotes, cmTokenize

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !3647
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
index a075a17..f130e05 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
@@ -8,6 +8,7 @@
 #include "cmCPackIFWRepository.h"
 #include "cmCPackLog.h" // IWYU pragma: keep
 #include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmXMLParser.h"
 #include "cmXMLWriter.h"
@@ -292,7 +293,7 @@
   {
     if (this->file) {
       std::string content(data, data + length);
-      content = cmSystemTools::TrimWhitespace(content);
+      content = cmTrimWhitespace(content);
       std::string source = this->basePath + "/" + content;
       std::string destination = this->path + "/" + content;
       if (!cmSystemTools::CopyFileIfDifferent(source, destination)) {
diff --git a/Source/CPack/WiX/cmCMakeToWixPath.cxx b/Source/CPack/WiX/cmCMakeToWixPath.cxx
index b3889cf..630a8f8 100644
--- a/Source/CPack/WiX/cmCMakeToWixPath.cxx
+++ b/Source/CPack/WiX/cmCMakeToWixPath.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCMakeToWixPath.h"
 
-#include "cmSystemTools.h"
+#include "cmStringAlgorithms.h"
 
 #include <string>
 #include <vector>
@@ -29,7 +29,7 @@
     return cygpath;
   }
 
-  return cmSystemTools::TrimWhitespace(winpath_chars.data());
+  return cmTrimWhitespace(winpath_chars.data());
 }
 #else
 std::string CMakeToWixPath(const std::string& path)
diff --git a/Source/CPack/WiX/cmWIXAccessControlList.cxx b/Source/CPack/WiX/cmWIXAccessControlList.cxx
index 563de02..b5e287d 100644
--- a/Source/CPack/WiX/cmWIXAccessControlList.cxx
+++ b/Source/CPack/WiX/cmWIXAccessControlList.cxx
@@ -4,6 +4,7 @@
 
 #include "cmCPackGenerator.h"
 
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 cmWIXAccessControlList::cmWIXAccessControlList(
@@ -48,8 +49,7 @@
     user = user_and_domain;
   }
 
-  std::vector<std::string> permissions =
-    cmSystemTools::tokenize(permission_string, ",");
+  std::vector<std::string> permissions = cmTokenize(permission_string, ",");
 
   this->SourceWriter.BeginElement("Permission");
   this->SourceWriter.AddAttribute("User", user);
@@ -57,8 +57,7 @@
     this->SourceWriter.AddAttribute("Domain", domain);
   }
   for (std::string const& permission : permissions) {
-    this->EmitBooleanAttribute(entry,
-                               cmSystemTools::TrimWhitespace(permission));
+    this->EmitBooleanAttribute(entry, cmTrimWhitespace(permission));
   }
   this->SourceWriter.EndElement("Permission");
 }
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index ca29967..5583520 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -5,6 +5,7 @@
 #include "cmCommandArgumentLexer.h"
 #include "cmMakefile.h"
 #include "cmState.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <iostream>
@@ -58,7 +59,7 @@
     std::string str;
     if (cmSystemTools::GetEnv(var, str)) {
       if (this->EscapeQuotes) {
-        return this->AddString(cmSystemTools::EscapeQuotes(str));
+        return this->AddString(cmEscapeQuotes(str));
       }
       return this->AddString(str);
     }
@@ -68,7 +69,7 @@
     if (const std::string* c =
           this->Makefile->GetState()->GetInitializedCacheValue(var)) {
       if (this->EscapeQuotes) {
-        return this->AddString(cmSystemTools::EscapeQuotes(*c));
+        return this->AddString(cmEscapeQuotes(*c));
       }
       return this->AddString(*c);
     }
@@ -99,7 +100,7 @@
     }
   }
   if (this->EscapeQuotes && value) {
-    return this->AddString(cmSystemTools::EscapeQuotes(value));
+    return this->AddString(cmEscapeQuotes(value));
   }
   return this->AddString(value ? value : "");
 }
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index d2a4148..e286ed7 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -238,7 +238,7 @@
     } else if (doing == DoingLinkOptions) {
       linkOptions.push_back(argv[i]);
     } else if (doing == DoingLinkLibraries) {
-      libsToLink += "\"" + cmSystemTools::TrimWhitespace(argv[i]) + "\" ";
+      libsToLink += "\"" + cmTrimWhitespace(argv[i]) + "\" ";
       if (cmTarget* tgt = this->Makefile->FindTargetToUse(argv[i])) {
         switch (tgt->GetType()) {
           case cmStateEnums::SHARED_LIBRARY:
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index 172897c..e4b7670 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -21,6 +21,7 @@
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTargetDepend.h"
@@ -1270,11 +1271,11 @@
   lg->GetTargetFlags(&linkLineComputer, this->Config, linkLibs,
                      linkLanguageFlags, linkFlags, frameworkPath, linkPath,
                      this->GT);
-  linkLanguageFlags = cmSystemTools::TrimWhitespace(linkLanguageFlags);
-  linkFlags = cmSystemTools::TrimWhitespace(linkFlags);
-  frameworkPath = cmSystemTools::TrimWhitespace(frameworkPath);
-  linkPath = cmSystemTools::TrimWhitespace(linkPath);
-  linkLibs = cmSystemTools::TrimWhitespace(linkLibs);
+  linkLanguageFlags = cmTrimWhitespace(linkLanguageFlags);
+  linkFlags = cmTrimWhitespace(linkFlags);
+  frameworkPath = cmTrimWhitespace(frameworkPath);
+  linkPath = cmTrimWhitespace(linkPath);
+  linkLibs = cmTrimWhitespace(linkLibs);
 
   if (!linkLanguageFlags.empty()) {
     linkFragments.append(
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index d9e5e71..03fc5ae 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -3410,8 +3410,7 @@
       cmSystemTools::ParseUnixCommandLine(
         value.c_str() + LINKER_SHELL.length(), linkerOptions);
     } else {
-      linkerOptions =
-        cmSystemTools::tokenize(value.substr(LINKER.length()), ",");
+      linkerOptions = cmTokenize(value.substr(LINKER.length()), ",");
     }
 
     if (linkerOptions.empty() ||
diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx
index fc82535..c948b2a 100644
--- a/Source/cmGetFilenameComponentCommand.cxx
+++ b/Source/cmGetFilenameComponentCommand.cxx
@@ -4,6 +4,7 @@
 
 #include "cmMakefile.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -64,7 +65,7 @@
     // First assume the path to the program was specified with no
     // arguments and with no quoting or escaping for spaces.
     // Only bother doing this if there is non-whitespace.
-    if (!cmSystemTools::TrimWhitespace(filename).empty()) {
+    if (!cmTrimWhitespace(filename).empty()) {
       result = cmSystemTools::FindProgram(filename);
     }
 
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 0b68966..9914d15 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -383,7 +383,7 @@
   }
 
   // Do not add a variable if the value is empty.
-  std::string val = cmSystemTools::TrimWhitespace(value);
+  std::string val = cmTrimWhitespace(value);
   if (val.empty()) {
     return;
   }
@@ -528,7 +528,7 @@
       cmSystemTools::SetFatalErrorOccured();
       return false;
     }
-    this->NinjaVersion = cmSystemTools::TrimWhitespace(version);
+    this->NinjaVersion = cmTrimWhitespace(version);
     this->CheckNinjaFeatures();
   }
   return true;
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 4a3cadd..720b6c5 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -325,7 +325,7 @@
 bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset(
   std::string const& ts, cmMakefile* mf)
 {
-  std::vector<std::string> const fields = cmSystemTools::tokenize(ts, ",");
+  std::vector<std::string> const fields = cmTokenize(ts, ",");
   std::vector<std::string>::const_iterator fi = fields.begin();
   if (fi == fields.end()) {
     return true;
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index bead0e3..ca80d3b 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -518,9 +518,9 @@
           const std::string::size_type posEqual = itPair.find('=');
           if (posEqual != std::string::npos) {
             const std::string key =
-              cmSystemTools::TrimWhitespace(itPair.substr(0, posEqual));
+              cmTrimWhitespace(itPair.substr(0, posEqual));
             const std::string value =
-              cmSystemTools::TrimWhitespace(itPair.substr(posEqual + 1));
+              cmTrimWhitespace(itPair.substr(posEqual + 1));
             fout << "\t\t" << key << " = " << value << "\n";
             if (key == "SolutionGuid") {
               addGuid = false;
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 8f4ae62..f675c8e 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -2945,8 +2945,7 @@
   if (it != this->TargetGroup.end()) {
     tgroup = it->second;
   } else {
-    std::vector<std::string> tgt_folders =
-      cmSystemTools::tokenize(target, "/");
+    std::vector<std::string> tgt_folders = cmTokenize(target, "/");
     std::string curr_tgt_folder;
     for (std::vector<std::string>::size_type i = 0; i < tgt_folders.size();
          i++) {
@@ -2980,8 +2979,7 @@
   if (sg->GetFullName() != sg->GetName()) {
     std::string curr_folder = target;
     curr_folder += "/";
-    for (auto const& folder :
-         cmSystemTools::tokenize(sg->GetFullName(), "\\")) {
+    for (auto const& folder : cmTokenize(sg->GetFullName(), "\\")) {
       curr_folder += folder;
       std::map<std::string, cmXCodeObject*>::iterator i_folder =
         this->GroupNameMap.find(curr_folder);
diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx
index 2423faf..953333c 100644
--- a/Source/cmJsonObjects.cxx
+++ b/Source/cmJsonObjects.cxx
@@ -20,6 +20,7 @@
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTest.h"
@@ -541,19 +542,19 @@
     lg->GetTargetFlags(&linkLineComputer, config, linkLibs, linkLanguageFlags,
                        linkFlags, frameworkPath, linkPath, target);
 
-    linkLibs = cmSystemTools::TrimWhitespace(linkLibs);
-    linkFlags = cmSystemTools::TrimWhitespace(linkFlags);
-    linkLanguageFlags = cmSystemTools::TrimWhitespace(linkLanguageFlags);
-    frameworkPath = cmSystemTools::TrimWhitespace(frameworkPath);
-    linkPath = cmSystemTools::TrimWhitespace(linkPath);
+    linkLibs = cmTrimWhitespace(linkLibs);
+    linkFlags = cmTrimWhitespace(linkFlags);
+    linkLanguageFlags = cmTrimWhitespace(linkLanguageFlags);
+    frameworkPath = cmTrimWhitespace(frameworkPath);
+    linkPath = cmTrimWhitespace(linkPath);
 
-    if (!cmSystemTools::TrimWhitespace(linkLibs).empty()) {
+    if (!cmTrimWhitespace(linkLibs).empty()) {
       result[kLINK_LIBRARIES_KEY] = linkLibs;
     }
-    if (!cmSystemTools::TrimWhitespace(linkFlags).empty()) {
+    if (!cmTrimWhitespace(linkFlags).empty()) {
       result[kLINK_FLAGS_KEY] = linkFlags;
     }
-    if (!cmSystemTools::TrimWhitespace(linkLanguageFlags).empty()) {
+    if (!cmTrimWhitespace(linkLanguageFlags).empty()) {
       result[kLINK_LANGUAGE_FLAGS_KEY] = linkLanguageFlags;
     }
     if (!frameworkPath.empty()) {
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index 8c14596..1f748ca 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -855,7 +855,7 @@
                   { "STRIP", 0,
                     [&command](const std::string& s) -> std::string {
                       if (command.Selector->InSelection(s)) {
-                        return cmSystemTools::TrimWhitespace(s);
+                        return cmTrimWhitespace(s);
                       }
 
                       return s;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 015453a..86a002f 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -2175,8 +2175,7 @@
   if (delimiter == nullptr) {
     delimiter = "\\";
   }
-  return this->GetOrCreateSourceGroup(
-    cmSystemTools::tokenize(name, delimiter));
+  return this->GetOrCreateSourceGroup(cmTokenize(name, delimiter));
 }
 
 /**
@@ -2668,7 +2667,7 @@
       if (const char* val = this->GetDefinition(var)) {
         // Store the value in the output escaping as requested.
         if (escapeQuotes) {
-          source.append(cmSystemTools::EscapeQuotes(val));
+          source.append(cmEscapeQuotes(val));
         } else {
           source.append(val);
         }
@@ -2832,7 +2831,7 @@
           // Get the string we're meant to append to.
           if (value) {
             if (escapeQuotes) {
-              varresult = cmSystemTools::EscapeQuotes(value);
+              varresult = cmEscapeQuotes(value);
             } else {
               varresult = value;
             }
@@ -2958,7 +2957,7 @@
             }
 
             if (escapeQuotes) {
-              varresult = cmSystemTools::EscapeQuotes(varresult);
+              varresult = cmEscapeQuotes(varresult);
             }
             // Skip over the variable.
             result.append(last, in - last);
diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx
index ffdd0ce..0f69c84 100644
--- a/Source/cmSourceGroupCommand.cxx
+++ b/Source/cmSourceGroupCommand.cxx
@@ -21,7 +21,7 @@
 
 std::vector<std::string> tokenizePath(const std::string& path)
 {
-  return cmSystemTools::tokenize(path, "\\/");
+  return cmTokenize(path, "\\/");
 }
 
 std::string getFullFilePath(const std::string& currentPath,
diff --git a/Source/cmStringAlgorithms.cxx b/Source/cmStringAlgorithms.cxx
index 5deb9b0..5867a44 100644
--- a/Source/cmStringAlgorithms.cxx
+++ b/Source/cmStringAlgorithms.cxx
@@ -5,6 +5,59 @@
 #include <algorithm>
 #include <cstdio>
 
+std::string cmTrimWhitespace(cm::string_view str)
+{
+  auto start = str.begin();
+  while (start != str.end() && cmIsSpace(*start)) {
+    ++start;
+  }
+  if (start == str.end()) {
+    return std::string();
+  }
+  auto stop = str.end() - 1;
+  while (cmIsSpace(*stop)) {
+    --stop;
+  }
+  return std::string(start, stop + 1);
+}
+
+std::string cmEscapeQuotes(cm::string_view str)
+{
+  std::string result;
+  result.reserve(str.size());
+  for (const char ch : str) {
+    if (ch == '"') {
+      result += '\\';
+    }
+    result += ch;
+  }
+  return result;
+}
+
+std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep)
+{
+  std::vector<std::string> tokens;
+  cm::string_view::size_type tokend = 0;
+
+  do {
+    cm::string_view::size_type tokstart = str.find_first_not_of(sep, tokend);
+    if (tokstart == cm::string_view::npos) {
+      break; // no more tokens
+    }
+    tokend = str.find_first_of(sep, tokstart);
+    if (tokend == cm::string_view::npos) {
+      tokens.emplace_back(str.substr(tokstart));
+    } else {
+      tokens.emplace_back(str.substr(tokstart, tokend - tokstart));
+    }
+  } while (tokend != cm::string_view::npos);
+
+  if (tokens.empty()) {
+    tokens.emplace_back();
+  }
+  return tokens;
+}
+
 namespace {
 template <std::size_t N, typename T>
 inline void MakeDigits(cm::string_view& view, char (&digits)[N],
diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h
index cdb494f..1898649 100644
--- a/Source/cmStringAlgorithms.h
+++ b/Source/cmStringAlgorithms.h
@@ -7,6 +7,7 @@
 
 #include "cmRange.h"
 #include "cm_string_view.hxx"
+#include <cctype>
 #include <initializer_list>
 #include <sstream>
 #include <string.h>
@@ -31,6 +32,18 @@
   std::string const Test_;
 };
 
+/** Returns true if the character @a ch is a whitespace character.  **/
+inline bool cmIsSpace(char ch)
+{
+  return ((ch & 0x80) == 0) && std::isspace(ch);
+}
+
+/** Returns a string that has whitespace removed from the start and the end. */
+std::string cmTrimWhitespace(cm::string_view str);
+
+/** Escape quotes in a string.  */
+std::string cmEscapeQuotes(cm::string_view str);
+
 /** Joins elements of a range with separator into a single string.  */
 template <typename Range>
 std::string cmJoin(Range const& rng, cm::string_view separator)
@@ -49,6 +62,9 @@
   return os.str();
 }
 
+/** Extract tokens that are separated by any of the characters in @a sep.  */
+std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep);
+
 /** Concatenate string pieces into a single string.  */
 std::string cmCatViews(std::initializer_list<cm::string_view> views);
 
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 5f4e1fc..aed787e 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -84,11 +84,6 @@
 
 } // namespace
 
-static bool cm_isspace(char c)
-{
-  return ((c & 0x80) == 0) && isspace(c);
-}
-
 #if !defined(HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE)
 // For GetEnvironmentVariables
 #  if defined(_WIN32)
@@ -177,19 +172,6 @@
 }
 #endif
 
-std::string cmSystemTools::EscapeQuotes(cm::string_view str)
-{
-  std::string result;
-  result.reserve(str.size());
-  for (const char ch : str) {
-    if (ch == '"') {
-      result += '\\';
-    }
-    result += ch;
-  }
-  return result;
-}
-
 std::string cmSystemTools::HelpFileName(cm::string_view str)
 {
   std::string name(str);
@@ -198,22 +180,6 @@
   return name;
 }
 
-std::string cmSystemTools::TrimWhitespace(cm::string_view str)
-{
-  auto start = str.begin();
-  while (start != str.end() && cm_isspace(*start)) {
-    ++start;
-  }
-  if (start == str.end()) {
-    return std::string();
-  }
-  auto stop = str.end() - 1;
-  while (cm_isspace(*stop)) {
-    --stop;
-  }
-  return std::string(start, stop + 1);
-}
-
 void cmSystemTools::Error(const std::string& m)
 {
   std::string message = "CMake Error: " + m;
@@ -396,7 +362,7 @@
     } else {
       arg.append(backslashes, '\\');
       backslashes = 0;
-      if (cm_isspace(*c)) {
+      if (cmIsSpace(*c)) {
         if (in_quotes) {
           arg.append(1, *c);
         } else if (in_argument) {
@@ -2882,31 +2848,6 @@
   return false;
 }
 
-std::vector<std::string> cmSystemTools::tokenize(const std::string& str,
-                                                 const std::string& sep)
-{
-  std::vector<std::string> tokens;
-  std::string::size_type tokend = 0;
-
-  do {
-    std::string::size_type tokstart = str.find_first_not_of(sep, tokend);
-    if (tokstart == std::string::npos) {
-      break; // no more tokens
-    }
-    tokend = str.find_first_of(sep, tokstart);
-    if (tokend == std::string::npos) {
-      tokens.push_back(str.substr(tokstart));
-    } else {
-      tokens.push_back(str.substr(tokstart, tokend - tokstart));
-    }
-  } while (tokend != std::string::npos);
-
-  if (tokens.empty()) {
-    tokens.emplace_back();
-  }
-  return tokens;
-}
-
 bool cmSystemTools::StringToLong(const char* str, long* value)
 {
   errno = 0;
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index ac1aa80..d3fcb64 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -77,17 +77,9 @@
   static void ExpandRegistryValues(std::string& source,
                                    KeyWOW64 view = KeyWOW64_Default);
 
-  //! Escape quotes in a string.
-  static std::string EscapeQuotes(cm::string_view str);
-
   /** Map help document name to file name.  */
   static std::string HelpFileName(cm::string_view);
 
-  /**
-   * Returns a string that has whitespace removed from the start and the end.
-   */
-  static std::string TrimWhitespace(cm::string_view str);
-
   using MessageCallback = std::function<void(const std::string&, const char*)>;
   /**
    *  Set the function used by GUIs to display error messages
@@ -508,10 +500,6 @@
   /** Remove a directory; repeat a few times in case of locked files.  */
   static bool RepeatedRemoveDirectory(const std::string& dir);
 
-  /** Tokenize a string */
-  static std::vector<std::string> tokenize(const std::string& str,
-                                           const std::string& sep);
-
   /** Convert string to long. Expected that the whole string is an integer */
   static bool StringToLong(const char* str, long* value);
   static bool StringToULong(const char* str, unsigned long* value);
diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx
index c78361e..20f5e2f 100644
--- a/Source/cmVSSetupHelper.cxx
+++ b/Source/cmVSSetupHelper.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmVSSetupHelper.h"
 
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmsys/Encoding.hxx"
 #include "cmsys/FStream.hxx"
@@ -195,7 +196,7 @@
     if (!fin || !cmSystemTools::GetLineFromStream(fin, vcToolsVersion)) {
       return false;
     }
-    vcToolsVersion = cmSystemTools::TrimWhitespace(vcToolsVersion);
+    vcToolsVersion = cmTrimWhitespace(vcToolsVersion);
     std::string const vcToolsDir = vcRoot + "/VC/Tools/MSVC/" + vcToolsVersion;
     if (!cmSystemTools::FileIsDirectory(vcToolsDir)) {
       return false;
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index e1b0c70..6c28996 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -193,7 +193,7 @@
     std::string arch_name = arch[0];
     std::vector<std::string> codes;
     if (!code.empty()) {
-      codes = cmSystemTools::tokenize(code[0], ",");
+      codes = cmTokenize(code[0], ",");
     }
     if (codes.empty()) {
       codes.push_back(arch_name);
@@ -220,7 +220,7 @@
     cmSystemTools::ReplaceString(entry, "]", "");
     cmSystemTools::ReplaceString(entry, "\"", "");
 
-    std::vector<std::string> codes = cmSystemTools::tokenize(entry, ",");
+    std::vector<std::string> codes = cmTokenize(entry, ",");
     if (codes.size() >= 2) {
       auto gencode_arch = cm::cbegin(codes);
       for (auto ci = gencode_arch + 1; ci != cm::cend(codes); ++ci) {
diff --git a/Source/cmVisualStudioSlnParser.cxx b/Source/cmVisualStudioSlnParser.cxx
index 3e7e142..9eaee11 100644
--- a/Source/cmVisualStudioSlnParser.cxx
+++ b/Source/cmVisualStudioSlnParser.cxx
@@ -463,7 +463,7 @@
   if (!this->ParseBOM(input, line, state))
     return false;
   do {
-    line = cmSystemTools::TrimWhitespace(line);
+    line = cmTrimWhitespace(line);
     if (line.empty())
       continue;
     ParsedLine parsedLine;
@@ -579,9 +579,9 @@
     return true;
   }
   const std::string& key = line.substr(0, idxEqualSign);
-  parsedLine.SetTag(cmSystemTools::TrimWhitespace(key));
+  parsedLine.SetTag(cmTrimWhitespace(key));
   const std::string& value = line.substr(idxEqualSign + 1);
-  parsedLine.AddValue(cmSystemTools::TrimWhitespace(value));
+  parsedLine.AddValue(cmTrimWhitespace(value));
   return true;
 }
 
@@ -590,18 +590,17 @@
 {
   size_t idxLeftParen = fullTag.find('(');
   if (idxLeftParen == fullTag.npos) {
-    parsedLine.SetTag(cmSystemTools::TrimWhitespace(fullTag));
+    parsedLine.SetTag(cmTrimWhitespace(fullTag));
     return true;
   }
-  parsedLine.SetTag(
-    cmSystemTools::TrimWhitespace(fullTag.substr(0, idxLeftParen)));
+  parsedLine.SetTag(cmTrimWhitespace(fullTag.substr(0, idxLeftParen)));
   size_t idxRightParen = fullTag.rfind(')');
   if (idxRightParen == fullTag.npos) {
     this->LastResult.SetError(ResultErrorInputStructure,
                               state.GetCurrentLine());
     return false;
   }
-  const std::string& arg = cmSystemTools::TrimWhitespace(
+  const std::string& arg = cmTrimWhitespace(
     fullTag.substr(idxLeftParen + 1, idxRightParen - idxLeftParen - 1));
   if (arg.front() == '"') {
     if (arg.back() != '"') {
@@ -618,7 +617,7 @@
 bool cmVisualStudioSlnParser::ParseValue(const std::string& value,
                                          ParsedLine& parsedLine)
 {
-  const std::string& trimmed = cmSystemTools::TrimWhitespace(value);
+  const std::string& trimmed = cmTrimWhitespace(value);
   if (trimmed.empty())
     parsedLine.AddValue(trimmed);
   else if (trimmed.front() == '"' && trimmed.back() == '"')
diff --git a/Tests/CMakeLib/testStringAlgorithms.cxx b/Tests/CMakeLib/testStringAlgorithms.cxx
index 95616ff..55d2a8f 100644
--- a/Tests/CMakeLib/testStringAlgorithms.cxx
+++ b/Tests/CMakeLib/testStringAlgorithms.cxx
@@ -38,6 +38,28 @@
   };
 
   // ----------------------------------------------------------------------
+  // Test cmTrimWhitespace
+  {
+    std::string base = "base";
+    std::string spaces = "  \f\f\n\n\r\r\t\t\v\v";
+    assert_string(cmTrimWhitespace(spaces + base), base,
+                  "cmTrimWhitespace front");
+    assert_string(cmTrimWhitespace(base + spaces), base,
+                  "cmTrimWhitespace back");
+    assert_string(cmTrimWhitespace(spaces + base + spaces), base,
+                  "cmTrimWhitespace front and back");
+  }
+
+  // ----------------------------------------------------------------------
+  // Test cmEscapeQuotes
+  {
+    assert_string(cmEscapeQuotes("plain"), "plain", "cmEscapeQuotes plain");
+    std::string base = "\"base\"\"";
+    std::string result = "\\\"base\\\"\\\"";
+    assert_string(cmEscapeQuotes(base), result, "cmEscapeQuotes escaped");
+  }
+
+  // ----------------------------------------------------------------------
   // Test cmJoin
   {
     typedef std::string ST;
@@ -52,6 +74,21 @@
   }
 
   // ----------------------------------------------------------------------
+  // Test cmTokenize
+  {
+    typedef std::vector<std::string> VT;
+    assert_ok(cmTokenize("", ";") == VT{ "" }, "cmTokenize empty");
+    assert_ok(cmTokenize(";", ";") == VT{ "" }, "cmTokenize sep");
+    assert_ok(cmTokenize("abc", ";") == VT{ "abc" }, "cmTokenize item");
+    assert_ok(cmTokenize("abc;", ";") == VT{ "abc" }, "cmTokenize item sep");
+    assert_ok(cmTokenize(";abc", ";") == VT{ "abc" }, "cmTokenize sep item");
+    assert_ok(cmTokenize("abc;;efg", ";") == VT{ "abc", "efg" },
+              "cmTokenize item sep sep item");
+    assert_ok(cmTokenize("a1;a2;a3;a4", ";") == VT{ "a1", "a2", "a3", "a4" },
+              "cmTokenize multiple items");
+  }
+
+  // ----------------------------------------------------------------------
   // Test cmStrCat
   {
     int ni = -1100;