Browse Source

cmSystemTools: Add ExpandedListArgument and ExpandedLists methods

Changes
-------

In `cmSystemTools` this
- renames the method `ExpandList` to `ExpandLists` and makes it iterator based

and adds the methods
- `std::vector<std::string> ExpandedLists(InputIt first, InputIt last)`
- `std::vector<std::string> ExpandedListArgument(const std::string& arg,
                                                       bool emptyArgs)`

Both return the  `std::vector<std::string>` instead of taking a return vector
reference like `cmSystemTools::ExpandLists` and
`cmSystemTools::ExpandListArgument`.

Motivation
----------

Since C++17 return value optimization is mandatory, so returning a
`std:vector<std::string>` from a function should be (at least) as fast as
passing a return vector reference to the function.

The new methods can replace `cmSystemTools::ExpandLists` and
`cmSystemTools::ExpandListArgument` in many cases, which leads to
shorter and simpler syntax.

E.g. the commonly used pattern
```
  if (const char* value = X->GetProperty("A_KEY_STRING")) {
    std::vector<std::string> valuesList;
    cmSystemTools::ExpandListArgument(value, valuesList);
    for (std::string const& i : valuesList) {
      doSomething(i);
    }
  }
```
becomes
```
  if (const char* value = X->GetProperty("A_KEY_STRING")) {
    for (std::string const& i :
      cmSystemTools::ExpandedListArgument(value)) {
      doSomething(i);
    }
  }
```
Sebastian Holtermann 6 years ago
parent
commit
cdff7f4e2a
4 changed files with 58 additions and 29 deletions
  1. 4 6
      Source/cmGlobalXCodeGenerator.cxx
  2. 4 6
      Source/cmRemoveCommand.cxx
  3. 12 12
      Source/cmSystemTools.cxx
  4. 38 5
      Source/cmSystemTools.h

+ 4 - 6
Source/cmGlobalXCodeGenerator.cxx

@@ -2485,12 +2485,10 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget(
 std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target,
                                                       cmGeneratorTarget* gtgt)
 {
-  std::string configTypes =
-    this->CurrentMakefile->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES");
-  std::vector<std::string> configVectorIn;
-  std::vector<std::string> configVector;
-  configVectorIn.push_back(configTypes);
-  cmSystemTools::ExpandList(configVectorIn, configVector);
+  std::vector<std::string> const configVector =
+    cmSystemTools::ExpandedListArgument(
+      this->CurrentMakefile->GetRequiredDefinition(
+        "CMAKE_CONFIGURATION_TYPES"));
   cmXCodeObject* configlist =
     this->CreateObject(cmXCodeObject::XCConfigurationList);
   cmXCodeObject* buildConfigurations =

+ 4 - 6
Source/cmRemoveCommand.cxx

@@ -25,15 +25,13 @@ bool cmRemoveCommand::InitialPass(std::vector<std::string> const& args,
   }
 
   // expand the variable
-  std::vector<std::string> varArgsExpanded;
-  cmSystemTools::ExpandListArgument(cacheValue, varArgsExpanded);
+  std::vector<std::string> const varArgsExpanded =
+    cmSystemTools::ExpandedListArgument(cacheValue);
 
   // expand the args
   // check for REMOVE(VAR v1 v2 ... vn)
-  std::vector<std::string> argsExpanded;
-  std::vector<std::string> temp;
-  temp.insert(temp.end(), args.begin() + 1, args.end());
-  cmSystemTools::ExpandList(temp, argsExpanded);
+  std::vector<std::string> const argsExpanded =
+    cmSystemTools::ExpandedLists(args.begin() + 1, args.end());
 
   // now create the new value
   std::string value;

+ 12 - 12
Source/cmSystemTools.cxx

@@ -1208,16 +1208,8 @@ void cmSystemTools::GlobDirs(const std::string& path,
   }
 }
 
-void cmSystemTools::ExpandList(std::vector<std::string> const& arguments,
-                               std::vector<std::string>& newargs)
-{
-  for (std::string const& arg : arguments) {
-    cmSystemTools::ExpandListArgument(arg, newargs);
-  }
-}
-
 void cmSystemTools::ExpandListArgument(const std::string& arg,
-                                       std::vector<std::string>& newargs,
+                                       std::vector<std::string>& argsOut,
                                        bool emptyArgs)
 {
   // If argument is empty, it is an empty list.
@@ -1226,7 +1218,7 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
   }
   // if there are no ; in the name then just copy the current string
   if (arg.find(';') == std::string::npos) {
-    newargs.push_back(arg);
+    argsOut.push_back(arg);
     return;
   }
   std::string newArg;
@@ -1260,7 +1252,7 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
           last = c + 1;
           if (!newArg.empty() || emptyArgs) {
             // Add the last argument if the string is not empty.
-            newargs.push_back(newArg);
+            argsOut.push_back(newArg);
             newArg.clear();
           }
         }
@@ -1273,10 +1265,18 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
   newArg.append(last);
   if (!newArg.empty() || emptyArgs) {
     // Add the last argument if the string is not empty.
-    newargs.push_back(newArg);
+    argsOut.push_back(newArg);
   }
 }
 
+std::vector<std::string> cmSystemTools::ExpandedListArgument(
+  const std::string& arg, bool emptyArgs)
+{
+  std::vector<std::string> argsOut;
+  ExpandListArgument(arg, argsOut, emptyArgs);
+  return argsOut;
+}
+
 bool cmSystemTools::SimpleGlob(const std::string& glob,
                                std::vector<std::string>& files,
                                int type /* = 0 */)

+ 38 - 5
Source/cmSystemTools.h

@@ -29,16 +29,49 @@ public:
   typedef cmsys::SystemTools Superclass;
   typedef cmProcessOutput::Encoding Encoding;
 
-  /** Expand out any arguments in the vector that have ; separated
-   *  strings into multiple arguments.  A new vector is created
-   *  containing the expanded versions of all arguments in argsIn.
+  /**
+   * Expand the ; separated string @a arg into multiple arguments.
+   * All found arguments are appended to @a argsOut.
    */
-  static void ExpandList(std::vector<std::string> const& argsIn,
-                         std::vector<std::string>& argsOut);
   static void ExpandListArgument(const std::string& arg,
                                  std::vector<std::string>& argsOut,
                                  bool emptyArgs = false);
 
+  /**
+   * Expand out any arguments in the string range [@a first, @a last) that have
+   * ; separated strings into multiple arguments.  All found arguments are
+   * appended to @a argsOut.
+   */
+  template <class InputIt>
+  static void ExpandLists(InputIt first, InputIt last,
+                          std::vector<std::string>& argsOut)
+  {
+    for (; first != last; ++first) {
+      cmSystemTools::ExpandListArgument(*first, argsOut);
+    }
+  }
+
+  /**
+   * 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,
+                                                       bool emptyArgs = false);
+
+  /**
+   * Same as ExpandList but a new vector is created containing the expanded
+   * versions of all arguments in the string range [@a first, @a last).
+   */
+  template <class InputIt>
+  static std::vector<std::string> ExpandedLists(InputIt first, InputIt last)
+  {
+    std::vector<std::string> argsOut;
+    for (; first != last; ++first) {
+      cmSystemTools::ExpandListArgument(*first, argsOut);
+    }
+    return argsOut;
+  }
+
   /**
    * Look for and replace registry values in a string
    */