From 8586077baae74c90056704c022aad8357788fa38 Mon Sep 17 00:00:00 2001
From: Sebastian Holtermann <sebholt@xwmw.org>
Date: Mon, 26 Aug 2019 14:47:45 +0200
Subject: Autogen: Modernize cmQtAutoGen methods using cm::string_view

---
 Source/cmQtAutoGen.cxx | 104 +++++++++++++++++++------------------------------
 Source/cmQtAutoGen.h   |  10 +++--
 2 files changed, 45 insertions(+), 69 deletions(-)

diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index 9d29e5c..dc7424e 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -12,6 +12,7 @@
 
 #include <algorithm>
 #include <array>
+#include <initializer_list>
 #include <sstream>
 #include <utility>
 
@@ -21,7 +22,7 @@
 /// @arg valueOpts list of options that accept a value
 void MergeOptions(std::vector<std::string>& baseOpts,
                   std::vector<std::string> const& newOpts,
-                  std::vector<std::string> const& valueOpts, bool isQt5)
+                  std::initializer_list<cm::string_view> valueOpts, bool isQt5)
 {
   typedef std::vector<std::string>::iterator Iter;
   typedef std::vector<std::string>::const_iterator CIter;
@@ -117,60 +118,42 @@ std::string const& cmQtAutoGen::GeneratorNameUpper(GenT genType)
 
 std::string cmQtAutoGen::Tools(bool moc, bool uic, bool rcc)
 {
-  std::string res;
-  std::vector<std::string> lst;
+  std::array<cm::string_view, 3> lst;
+  decltype(lst)::size_type num = 0;
   if (moc) {
-    lst.emplace_back("AUTOMOC");
+    lst.at(num++) = "AUTOMOC";
   }
   if (uic) {
-    lst.emplace_back("AUTOUIC");
+    lst.at(num++) = "AUTOUIC";
   }
   if (rcc) {
-    lst.emplace_back("AUTORCC");
+    lst.at(num++) = "AUTORCC";
   }
-  switch (lst.size()) {
+  switch (num) {
     case 1:
-      res += lst.at(0);
-      break;
+      return std::string(lst[0]);
     case 2:
-      res += lst.at(0);
-      res += " and ";
-      res += lst.at(1);
-      break;
+      return cmStrCat(lst[0], " and ", lst[1]);
     case 3:
-      res += lst.at(0);
-      res += ", ";
-      res += lst.at(1);
-      res += " and ";
-      res += lst.at(2);
-      break;
+      return cmStrCat(lst[0], ", ", lst[1], " and ", lst[2]);
     default:
       break;
   }
-  return res;
+  return std::string();
 }
 
-std::string cmQtAutoGen::Quoted(std::string const& text)
+std::string cmQtAutoGen::Quoted(cm::string_view text)
 {
-  const std::array<std::pair<const char*, const char*>, 9> replaces = {
-    { { "\\", "\\\\" },
-      { "\"", "\\\"" },
-      { "\a", "\\a" },
-      { "\b", "\\b" },
-      { "\f", "\\f" },
-      { "\n", "\\n" },
-      { "\r", "\\r" },
-      { "\t", "\\t" },
-      { "\v", "\\v" } }
-  };
+  static std::initializer_list<std::pair<const char*, const char*>> const
+    replacements = { { "\\", "\\\\" }, { "\"", "\\\"" }, { "\a", "\\a" },
+                     { "\b", "\\b" },  { "\f", "\\f" },  { "\n", "\\n" },
+                     { "\r", "\\r" },  { "\t", "\\t" },  { "\v", "\\v" } };
 
-  std::string res = text;
-  for (auto const& pair : replaces) {
+  std::string res(text);
+  for (auto const& pair : replacements) {
     cmSystemTools::ReplaceString(res, pair.first, pair.second);
   }
-  res = '"' + res;
-  res += '"';
-  return res;
+  return cmStrCat('"', res, '"');
 }
 
 std::string cmQtAutoGen::QuotedCommand(std::vector<std::string> const& command)
@@ -191,37 +174,31 @@ std::string cmQtAutoGen::QuotedCommand(std::vector<std::string> const& command)
   return res;
 }
 
-std::string cmQtAutoGen::SubDirPrefix(std::string const& filename)
+std::string cmQtAutoGen::SubDirPrefix(cm::string_view filename)
 {
-  std::string::size_type slash_pos = filename.rfind('/');
-  if (slash_pos == std::string::npos) {
+  auto slashPos = filename.rfind('/');
+  if (slashPos == cm::string_view::npos) {
     return std::string();
   }
-  return filename.substr(0, slash_pos + 1);
+  return std::string(filename.substr(0, slashPos + 1));
 }
 
-std::string cmQtAutoGen::AppendFilenameSuffix(std::string const& filename,
-                                              std::string const& suffix)
+std::string cmQtAutoGen::AppendFilenameSuffix(cm::string_view filename,
+                                              cm::string_view suffix)
 {
-  std::string res;
-  auto pos = filename.rfind('.');
-  if (pos != std::string::npos) {
-    const auto it_dot = filename.begin() + pos;
-    res.assign(filename.begin(), it_dot);
-    res.append(suffix);
-    res.append(it_dot, filename.end());
-  } else {
-    res = filename;
-    res.append(suffix);
+  auto dotPos = filename.rfind('.');
+  if (dotPos == cm::string_view::npos) {
+    return cmStrCat(filename, suffix);
   }
-  return res;
+  return cmStrCat(filename.substr(0, dotPos), suffix,
+                  filename.substr(dotPos, filename.size() - dotPos));
 }
 
 void cmQtAutoGen::UicMergeOptions(std::vector<std::string>& baseOpts,
                                   std::vector<std::string> const& newOpts,
                                   bool isQt5)
 {
-  static std::vector<std::string> const valueOpts = {
+  static std::initializer_list<cm::string_view> const valueOpts = {
     "tr",      "translate", "postfix", "generator",
     "include", // Since Qt 5.3
     "g"
@@ -233,9 +210,9 @@ void cmQtAutoGen::RccMergeOptions(std::vector<std::string>& baseOpts,
                                   std::vector<std::string> const& newOpts,
                                   bool isQt5)
 {
-  static std::vector<std::string> const valueOpts = { "name", "root",
-                                                      "compress",
-                                                      "threshold" };
+  static std::initializer_list<cm::string_view> const valueOpts = {
+    "name", "root", "compress", "threshold"
+  };
   MergeOptions(baseOpts, newOpts, valueOpts, isQt5);
 }
 
@@ -349,9 +326,8 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile,
 
       // Log command
       if (verbose) {
-        std::string msg =
-          cmStrCat("Running command:\n", QuotedCommand(cmd), '\n');
-        cmSystemTools::Stdout(msg);
+        cmSystemTools::Stdout(
+          cmStrCat("Running command:\n", QuotedCommand(cmd), '\n'));
       }
 
       result = cmSystemTools::RunSingleCommand(
@@ -362,12 +338,10 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile,
       error =
         cmStrCat("The rcc list process failed for ", Quoted(qrcFile), '\n');
       if (!rccStdOut.empty()) {
-        error += rccStdOut;
-        error += "\n";
+        error += cmStrCat(rccStdOut, '\n');
       }
       if (!rccStdErr.empty()) {
-        error += rccStdErr;
-        error += "\n";
+        error += cmStrCat(rccStdErr, '\n');
       }
       return false;
     }
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index 619fff1..03468ec 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -5,6 +5,8 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include "cm_string_view.hxx"
+
 #include <memory>
 #include <string>
 #include <vector>
@@ -74,16 +76,16 @@ public:
   static std::string Tools(bool moc, bool uic, bool rcc);
 
   /// @brief Returns the string escaped and enclosed in quotes
-  static std::string Quoted(std::string const& text);
+  static std::string Quoted(cm::string_view text);
 
   static std::string QuotedCommand(std::vector<std::string> const& command);
 
   /// @brief Returns the parent directory of the file with a "/" suffix
-  static std::string SubDirPrefix(std::string const& filename);
+  static std::string SubDirPrefix(cm::string_view filename);
 
   /// @brief Appends the suffix to the filename before the last dot
-  static std::string AppendFilenameSuffix(std::string const& filename,
-                                          std::string const& suffix);
+  static std::string AppendFilenameSuffix(cm::string_view filename,
+                                          cm::string_view suffix);
 
   /// @brief Merges newOpts into baseOpts
   static void UicMergeOptions(std::vector<std::string>& baseOpts,
-- 
cgit v0.12


From c797148e8573614a66465cd4ca6ed4bf5e8a5584 Mon Sep 17 00:00:00 2001
From: Sebastian Holtermann <sebholt@xwmw.org>
Date: Mon, 26 Aug 2019 15:31:55 +0200
Subject: Autogen: Use cm::string_view for AUTO{MOC,UIC,RCC} generator names

- Store `AUTO{MOC,UIC,RCC}` generator name as `cm::string_view`
- Use `std::initializer_list` instead of `std::array`
---
 Source/cmQtAutoGen.cxx            | 34 +++++++++++--------------------
 Source/cmQtAutoGen.h              |  4 ++--
 Source/cmQtAutoGenInitializer.cxx | 43 +++++++++++++++++++++++----------------
 Source/cmQtAutoGenInitializer.h   |  4 ++--
 Source/cmQtAutoGenerator.cxx      |  6 +++---
 5 files changed, 44 insertions(+), 47 deletions(-)

diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index dc7424e..d890f8e 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -76,44 +76,34 @@ void MergeOptions(std::vector<std::string>& baseOpts,
 unsigned int const cmQtAutoGen::ParallelMax = 64;
 std::string const cmQtAutoGen::ListSep = "<<<S>>>";
 
-std::string const& cmQtAutoGen::GeneratorName(GenT genType)
+cm::string_view cmQtAutoGen::GeneratorName(GenT genType)
 {
-  static const std::string AutoGen("AutoGen");
-  static const std::string AutoMoc("AutoMoc");
-  static const std::string AutoUic("AutoUic");
-  static const std::string AutoRcc("AutoRcc");
-
   switch (genType) {
     case GenT::GEN:
-      return AutoGen;
+      return "AutoGen";
     case GenT::MOC:
-      return AutoMoc;
+      return "AutoMoc";
     case GenT::UIC:
-      return AutoUic;
+      return "AutoUic";
     case GenT::RCC:
-      return AutoRcc;
+      return "AutoRcc";
   }
-  return AutoGen;
+  return "AutoGen";
 }
 
-std::string const& cmQtAutoGen::GeneratorNameUpper(GenT genType)
+cm::string_view cmQtAutoGen::GeneratorNameUpper(GenT genType)
 {
-  static const std::string AUTOGEN("AUTOGEN");
-  static const std::string AUTOMOC("AUTOMOC");
-  static const std::string AUTOUIC("AUTOUIC");
-  static const std::string AUTORCC("AUTORCC");
-
   switch (genType) {
     case GenT::GEN:
-      return AUTOGEN;
+      return "AUTOGEN";
     case GenT::MOC:
-      return AUTOMOC;
+      return "AUTOMOC";
     case GenT::UIC:
-      return AUTOUIC;
+      return "AUTOUIC";
     case GenT::RCC:
-      return AUTORCC;
+      return "AUTORCC";
   }
-  return AUTOGEN;
+  return "AUTOGEN";
 }
 
 std::string cmQtAutoGen::Tools(bool moc, bool uic, bool rcc)
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index 03468ec..939ceb3 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -68,9 +68,9 @@ public:
 
 public:
   /// @brief Returns the generator name
-  static std::string const& GeneratorName(GenT genType);
+  static cm::string_view GeneratorName(GenT genType);
   /// @brief Returns the generator name in upper case
-  static std::string const& GeneratorNameUpper(GenT genType);
+  static cm::string_view GeneratorNameUpper(GenT genType);
 
   /// @brief Returns a string with the requested tool names
   static std::string Tools(bool moc, bool uic, bool rcc);
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index c355a5f..6b9011b 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -29,8 +29,8 @@
 #include "cmsys/SystemInformation.hxx"
 
 #include <algorithm>
-#include <array>
 #include <deque>
+#include <initializer_list>
 #include <map>
 #include <set>
 #include <string>
@@ -696,7 +696,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
     std::vector<MUFileHandle> extraHeaders;
     extraHeaders.reserve(this->AutogenTarget.Sources.size() * 2);
     // Header search suffixes and extensions
-    std::array<std::string, 2> const suffixes{ { "", "_p" } };
+    static std::initializer_list<cm::string_view> const suffixes{ "", "_p" };
     auto const& exts = cm->GetHeaderExtensions();
     // Scan through sources
     for (auto const& pair : this->AutogenTarget.Sources) {
@@ -708,7 +708,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
           cmStrCat(cmQtAutoGen::SubDirPrefix(srcPath),
                    cmSystemTools::GetFilenameWithoutLastExtension(srcPath));
         for (auto const& suffix : suffixes) {
-          std::string const suffixedPath = basePath + suffix;
+          std::string const suffixedPath = cmStrCat(basePath, suffix);
           for (auto const& ext : exts) {
             std::string fullPath = cmStrCat(suffixedPath, '.', ext);
 
@@ -1454,7 +1454,7 @@ bool cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename,
 }
 
 bool cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName,
-                                              std::string const& genNameUpper)
+                                              cm::string_view genNameUpper)
 {
   cmMakefile* makefile = this->Target->Target->GetMakefile();
   cmSourceGroup* sourceGroup = nullptr;
@@ -1464,13 +1464,14 @@ bool cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName,
     std::string groupName;
     {
       // Prefer generator specific source group name
-      std::array<std::string, 2> props{ { genNameUpper + "_SOURCE_GROUP",
-                                          "AUTOGEN_SOURCE_GROUP" } };
-      for (std::string& prop : props) {
+      std::initializer_list<std::string> const props{
+        cmStrCat(genNameUpper, "_SOURCE_GROUP"), "AUTOGEN_SOURCE_GROUP"
+      };
+      for (std::string const& prop : props) {
         const char* propName = makefile->GetState()->GetGlobalProperty(prop);
         if ((propName != nullptr) && (*propName != '\0')) {
           groupName = propName;
-          property = std::move(prop);
+          property = prop;
           break;
         }
       }
@@ -1512,11 +1513,16 @@ static std::vector<cmQtAutoGen::IntegerVersion> GetKnownQtVersions(
   cmGeneratorTarget const* target)
 {
   // Qt version variable prefixes
-  static std::array<std::string, 3> const prefixes{ { "Qt6Core", "Qt5Core",
-                                                      "QT" } };
+  static std::initializer_list<
+    std::pair<cm::string_view, cm::string_view>> const keys{
+    { "Qt6Core_VERSION_MAJOR", "Qt6Core_VERSION_MINOR" },
+    { "Qt5Core_VERSION_MAJOR", "Qt5Core_VERSION_MINOR" },
+    { "QT_VERSION_MAJOR", "QT_VERSION_MINOR" },
+  };
 
   std::vector<cmQtAutoGen::IntegerVersion> result;
-  result.reserve(prefixes.size() * 2);
+  result.reserve(keys.size() * 2);
+
   // Adds a version to the result (nullptr safe)
   auto addVersion = [&result](const char* major, const char* minor) {
     cmQtAutoGen::IntegerVersion ver(CharPtrToUInt(major),
@@ -1525,18 +1531,19 @@ static std::vector<cmQtAutoGen::IntegerVersion> GetKnownQtVersions(
       result.emplace_back(ver);
     }
   };
+
   cmMakefile* makefile = target->Target->GetMakefile();
 
   // Read versions from variables
-  for (const std::string& prefix : prefixes) {
-    addVersion(makefile->GetDefinition(prefix + "_VERSION_MAJOR"),
-               makefile->GetDefinition(prefix + "_VERSION_MINOR"));
+  for (auto const& keyPair : keys) {
+    addVersion(makefile->GetDefinition(std::string(keyPair.first)),
+               makefile->GetDefinition(std::string(keyPair.second)));
   }
 
   // Read versions from directory properties
-  for (const std::string& prefix : prefixes) {
-    addVersion(makefile->GetProperty(prefix + "_VERSION_MAJOR"),
-               makefile->GetProperty(prefix + "_VERSION_MINOR"));
+  for (auto const& keyPair : keys) {
+    addVersion(makefile->GetProperty(std::string(keyPair.first)),
+               makefile->GetProperty(std::string(keyPair.second)));
   }
 
   return result;
@@ -1580,7 +1587,7 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
 
   // Custom executable
   {
-    std::string const prop = genVars.GenNameUpper + "_EXECUTABLE";
+    std::string const prop = cmStrCat(genVars.GenNameUpper, "_EXECUTABLE");
     std::string const val = this->Target->Target->GetSafeProperty(prop);
     if (!val.empty()) {
       // Evaluate generator expression
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
index 7d72cad..65666a6 100644
--- a/Source/cmQtAutoGenInitializer.h
+++ b/Source/cmQtAutoGenInitializer.h
@@ -63,7 +63,7 @@ public:
     bool Enabled = false;
     // Generator type/name
     GenT Gen;
-    std::string const& GenNameUpper;
+    cm::string_view GenNameUpper;
     // Executable
     std::string ExecutableTargetName;
     cmGeneratorTarget* ExecutableTarget = nullptr;
@@ -145,7 +145,7 @@ private:
   bool AddGeneratedSource(std::string const& filename, GenVarsT const& genVars,
                           bool prepend = false);
   bool AddToSourceGroup(std::string const& fileName,
-                        std::string const& genNameUpper);
+                        cm::string_view genNameUpper);
   void AddCleanFile(std::string const& fileName);
 
   bool GetQtExecutable(GenVarsT& genVars, const std::string& executable,
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index 90361a9..2820ef4 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -86,7 +86,7 @@ void cmQtAutoGenerator::Logger::Warning(GenT genType,
     msg += " warning: ";
   } else {
     // Multi line message
-    msg += HeadLine(GeneratorName(genType) + " warning");
+    msg += HeadLine(cmStrCat(GeneratorName(genType), " warning"));
   }
   // Message
   msg += message;
@@ -110,7 +110,7 @@ void cmQtAutoGenerator::Logger::WarningFile(GenT genType,
 void cmQtAutoGenerator::Logger::Error(GenT genType,
                                       std::string const& message) const
 {
-  std::string msg = HeadLine(GeneratorName(genType) + " error");
+  std::string msg = HeadLine(cmStrCat(GeneratorName(genType), " error"));
   // Message
   msg += message;
   if (msg.back() != '\n') {
@@ -136,7 +136,7 @@ void cmQtAutoGenerator::Logger::ErrorCommand(
 {
   std::string msg;
   msg.push_back('\n');
-  msg += HeadLine(GeneratorName(genType) + " subprocess error");
+  msg += HeadLine(cmStrCat(GeneratorName(genType), " subprocess error"));
   msg += message;
   if (msg.back() != '\n') {
     msg.push_back('\n');
-- 
cgit v0.12


From 7a78d1541568343898160d8e934047b84a6c98b3 Mon Sep 17 00:00:00 2001
From: Sebastian Holtermann <sebholt@xwmw.org>
Date: Mon, 26 Aug 2019 16:23:17 +0200
Subject: Autogen: Let cmQtAutoGenerator::Logger methods accept cm::string_view

---
 Source/cmQtAutoGenerator.cxx | 77 +++++++++++++++-----------------------------
 Source/cmQtAutoGenerator.h   | 19 +++++------
 2 files changed, 36 insertions(+), 60 deletions(-)

diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index 2820ef4..3bcc1c9 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -58,18 +58,16 @@ void cmQtAutoGenerator::Logger::SetColorOutput(bool value)
   ColorOutput_ = value;
 }
 
-std::string cmQtAutoGenerator::Logger::HeadLine(std::string const& title)
+std::string cmQtAutoGenerator::Logger::HeadLine(cm::string_view title)
 {
-  return cmStrCat(title, "\n", std::string(title.size(), '-'), "\n");
+  return cmStrCat(title, '\n', std::string(title.size(), '-'), '\n');
 }
 
 void cmQtAutoGenerator::Logger::Info(GenT genType,
-                                     std::string const& message) const
+                                     cm::string_view message) const
 {
-  std::string msg = cmStrCat(GeneratorName(genType), ": ", message);
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
+  std::string msg = cmStrCat(GeneratorName(genType), ": ", message,
+                             cmHasSuffix(message, '\n') ? "" : "\n");
   {
     std::lock_guard<std::mutex> lock(Mutex_);
     cmSystemTools::Stdout(msg);
@@ -77,23 +75,18 @@ void cmQtAutoGenerator::Logger::Info(GenT genType,
 }
 
 void cmQtAutoGenerator::Logger::Warning(GenT genType,
-                                        std::string const& message) const
+                                        cm::string_view message) const
 {
   std::string msg;
   if (message.find('\n') == std::string::npos) {
     // Single line message
-    msg += GeneratorName(genType);
-    msg += " warning: ";
+    msg = cmStrCat(GeneratorName(genType), " warning: ", message,
+                   cmHasSuffix(message, '\n') ? "\n" : "\n\n");
   } else {
     // Multi line message
-    msg += HeadLine(cmStrCat(GeneratorName(genType), " warning"));
-  }
-  // Message
-  msg += message;
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
+    msg = cmStrCat(HeadLine(cmStrCat(GeneratorName(genType), " warning")),
+                   message, cmHasSuffix(message, '\n') ? "\n" : "\n\n");
   }
-  msg.push_back('\n');
   {
     std::lock_guard<std::mutex> lock(Mutex_);
     cmSystemTools::Stdout(msg);
@@ -101,22 +94,18 @@ void cmQtAutoGenerator::Logger::Warning(GenT genType,
 }
 
 void cmQtAutoGenerator::Logger::WarningFile(GenT genType,
-                                            std::string const& filename,
-                                            std::string const& message) const
+                                            cm::string_view filename,
+                                            cm::string_view message) const
 {
-  Warning(genType, cmStrCat("  ", Quoted(filename), "\n", message));
+  Warning(genType, cmStrCat("  ", Quoted(filename), '\n', message));
 }
 
 void cmQtAutoGenerator::Logger::Error(GenT genType,
-                                      std::string const& message) const
+                                      cm::string_view message) const
 {
-  std::string msg = HeadLine(cmStrCat(GeneratorName(genType), " error"));
-  // Message
-  msg += message;
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  msg.push_back('\n');
+  std::string msg =
+    cmStrCat(HeadLine(cmStrCat(GeneratorName(genType), " error")), message,
+             cmHasSuffix(message, '\n') ? "\n" : "\n\n");
   {
     std::lock_guard<std::mutex> lock(Mutex_);
     cmSystemTools::Stderr(msg);
@@ -124,36 +113,22 @@ void cmQtAutoGenerator::Logger::Error(GenT genType,
 }
 
 void cmQtAutoGenerator::Logger::ErrorFile(GenT genType,
-                                          std::string const& filename,
-                                          std::string const& message) const
+                                          cm::string_view filename,
+                                          cm::string_view message) const
 {
   Error(genType, cmStrCat("  ", Quoted(filename), '\n', message));
 }
 
 void cmQtAutoGenerator::Logger::ErrorCommand(
-  GenT genType, std::string const& message,
+  GenT genType, cm::string_view message,
   std::vector<std::string> const& command, std::string const& output) const
 {
-  std::string msg;
-  msg.push_back('\n');
-  msg += HeadLine(cmStrCat(GeneratorName(genType), " subprocess error"));
-  msg += message;
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  msg.push_back('\n');
-  msg += HeadLine("Command");
-  msg += QuotedCommand(command);
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  msg.push_back('\n');
-  msg += HeadLine("Output");
-  msg += output;
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  msg.push_back('\n');
+  std::string msg = cmStrCat(
+    '\n', HeadLine(cmStrCat(GeneratorName(genType), " subprocess error")),
+    message, cmHasSuffix(message, '\n') ? "\n" : "\n\n");
+  msg += cmStrCat(HeadLine("Command"), QuotedCommand(command), "\n\n");
+  msg += cmStrCat(HeadLine("Output"), output,
+                  cmHasSuffix(output, '\n') ? "\n" : "\n\n");
   {
     std::lock_guard<std::mutex> lock(Mutex_);
     cmSystemTools::Stderr(msg);
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
index ff4c4c9..4b8b0b7 100644
--- a/Source/cmQtAutoGenerator.h
+++ b/Source/cmQtAutoGenerator.h
@@ -7,6 +7,7 @@
 
 #include "cmFileTime.h"
 #include "cmQtAutoGen.h"
+#include "cm_string_view.hxx"
 
 #include <mutex>
 #include <string>
@@ -41,21 +42,21 @@ public:
     bool ColorOutput() const { return this->ColorOutput_; }
     void SetColorOutput(bool value);
     // -- Log info
-    void Info(GenT genType, std::string const& message) const;
+    void Info(GenT genType, cm::string_view message) const;
     // -- Log warning
-    void Warning(GenT genType, std::string const& message) const;
-    void WarningFile(GenT genType, std::string const& filename,
-                     std::string const& message) const;
+    void Warning(GenT genType, cm::string_view message) const;
+    void WarningFile(GenT genType, cm::string_view filename,
+                     cm::string_view message) const;
     // -- Log error
-    void Error(GenT genType, std::string const& message) const;
-    void ErrorFile(GenT genType, std::string const& filename,
-                   std::string const& message) const;
-    void ErrorCommand(GenT genType, std::string const& message,
+    void Error(GenT genType, cm::string_view message) const;
+    void ErrorFile(GenT genType, cm::string_view filename,
+                   cm::string_view message) const;
+    void ErrorCommand(GenT genType, cm::string_view message,
                       std::vector<std::string> const& command,
                       std::string const& output) const;
 
   private:
-    static std::string HeadLine(std::string const& title);
+    static std::string HeadLine(cm::string_view title);
 
   private:
     mutable std::mutex Mutex_;
-- 
cgit v0.12


From da6c4b12736b0d73987d0a8a0bd06a5bbac7193b Mon Sep 17 00:00:00 2001
From: Sebastian Holtermann <sebholt@xwmw.org>
Date: Mon, 26 Aug 2019 17:04:06 +0200
Subject: Autogen: cmQtAutoGenInitializer string concatenation cleanups

---
 Source/cmQtAutoGenInitializer.cxx | 95 ++++++++++++++++++---------------------
 1 file changed, 43 insertions(+), 52 deletions(-)

diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 6b9011b..bd96c08 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -396,13 +396,13 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
 
     // CMAKE_AUTOMOC_RELAXED_MODE deprecation warning
     if (this->Moc.Enabled) {
-      if (cmIsOn(makefile->GetDefinition("CMAKE_AUTOMOC_RELAXED_MODE"))) {
-        std::string msg =
+      if (makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE")) {
+        makefile->IssueMessage(
+          MessageType::AUTHOR_WARNING,
           cmStrCat("AUTOMOC: CMAKE_AUTOMOC_RELAXED_MODE is "
                    "deprecated an will be removed in the future.  Consider "
                    "disabling it and converting the target ",
-                   this->Target->GetName(), " to regular mode.");
-        makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg);
+                   this->Target->GetName(), " to regular mode."));
       }
     }
   }
@@ -814,33 +814,31 @@ bool cmQtAutoGenInitializer::InitScanFiles()
         this->AutogenTarget.DependFiles.insert(muf->RealPath);
       }
     } else if (this->CMP0071Warn) {
-      std::string msg =
-        cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0071), '\n');
-      std::string property;
+      cm::string_view property;
       if (this->Moc.Enabled && this->Uic.Enabled) {
-        property = kw.SKIP_AUTOGEN;
+        property = "SKIP_AUTOGEN";
       } else if (this->Moc.Enabled) {
-        property = kw.SKIP_AUTOMOC;
+        property = "SKIP_AUTOMOC";
       } else if (this->Uic.Enabled) {
-        property = kw.SKIP_AUTOUIC;
+        property = "SKIP_AUTOUIC";
       }
-      msg += "For compatibility, CMake is excluding the GENERATED source "
-             "file(s):\n";
+      std::string files;
       for (MUFile* muf : this->AutogenTarget.FilesGenerated) {
-        msg += "  ";
-        msg += Quoted(muf->RealPath);
-        msg += '\n';
+        files += cmStrCat("  ", Quoted(muf->RealPath), '\n');
       }
-      msg += "from processing by ";
-      msg += cmQtAutoGen::Tools(this->Moc.Enabled, this->Uic.Enabled, false);
-      msg += ". If any of the files should be processed, set CMP0071 to NEW. "
-             "If any of the files should not be processed, "
-             "explicitly exclude them by setting the source file property ";
-      msg += property;
-      msg += ":\n  set_property(SOURCE file.h PROPERTY ";
-      msg += property;
-      msg += " ON)\n";
-      makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg);
+      makefile->IssueMessage(
+        MessageType::AUTHOR_WARNING,
+        cmStrCat(
+          cmPolicies::GetPolicyWarning(cmPolicies::CMP0071), '\n',
+          "For compatibility, CMake is excluding the GENERATED source "
+          "file(s):\n",
+          files, "from processing by ",
+          cmQtAutoGen::Tools(this->Moc.Enabled, this->Uic.Enabled, false),
+          ".  If any of the files should be processed, set CMP0071 to NEW.  "
+          "If any of the files should not be processed, "
+          "explicitly exclude them by setting the source file property ",
+          property, ":\n  set_property(SOURCE file.h PROPERTY ", property,
+          " ON)\n"));
     }
   }
 
@@ -867,20 +865,16 @@ bool cmQtAutoGenInitializer::InitScanFiles()
       for (Qrc& qrc : this->Rcc.Qrcs) {
         qrc.PathChecksum = fpathCheckSum.getPart(qrc.QrcFile);
         // RCC output file name
-        qrc.RccFile = cmStrCat(this->Dir.Build + "/", qrc.PathChecksum,
-                               "/qrc_", qrc.QrcName, ".cpp");
+        qrc.RccFile = cmStrCat(this->Dir.Build, '/', qrc.PathChecksum, "/qrc_",
+                               qrc.QrcName, ".cpp");
         {
-          std::string base = cmStrCat(this->Dir.Info, "/RCC", qrc.QrcName);
-          if (!qrc.Unique) {
-            base += qrc.PathChecksum;
-          }
-
+          cm::string_view const baseSuffix =
+            qrc.Unique ? cm::string_view() : cm::string_view(qrc.PathChecksum);
+          std::string const base =
+            cmStrCat(this->Dir.Info, "/RCC", qrc.QrcName, baseSuffix);
           qrc.LockFile = cmStrCat(base, ".lock");
-
           qrc.InfoFile = cmStrCat(base, "Info.cmake");
-
           qrc.SettingsFile = cmStrCat(base, "Settings.txt");
-
           if (this->MultiConfig) {
             for (std::string const& cfg : this->ConfigsList) {
               qrc.ConfigSettingsFile[cfg] =
@@ -900,7 +894,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
         // Replace '-' with '_'. The former is not valid for symbol names.
         std::replace(name.begin(), name.end(), '-', '_');
         if (!qrc.Unique) {
-          name += cmStrCat("_", qrc.PathChecksum);
+          name += cmStrCat('_', qrc.PathChecksum);
         }
         std::vector<std::string> nameOpts;
         nameOpts.emplace_back("-name");
@@ -1131,8 +1125,7 @@ bool cmQtAutoGenInitializer::InitRccTargets()
       {
         ccName = cmStrCat(this->Target->GetName(), "_arcc_", qrc.QrcName);
         if (!qrc.Unique) {
-          ccName += "_";
-          ccName += qrc.PathChecksum;
+          ccName += cmStrCat('_', qrc.PathChecksum);
         }
 
         cmTarget* autoRccTarget = makefile->AddUtilityCommand(
@@ -1274,7 +1267,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
         if (muf->MocIt || muf->UicIt) {
           headers.emplace_back(muf->RealPath);
           headersFlags.emplace_back(
-            cmStrCat(muf->MocIt ? "M" : "m", muf->UicIt ? "U" : "u"));
+            cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u'));
         }
       }
     }
@@ -1283,19 +1276,17 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
       cmFilePathChecksum const fpathCheckSum(makefile);
       std::unordered_set<std::string> emitted;
       for (std::string const& hdr : headers) {
-        std::string basePath =
+        std::string const basePath =
           cmStrCat(fpathCheckSum.getPart(hdr), "/moc_",
                    cmSystemTools::GetFilenameWithoutLastExtension(hdr));
-        for (int ii = 1; ii != 1024; ++ii) {
-          std::string path = basePath;
-          if (ii > 1) {
-            path += cmStrCat("_", ii);
-          }
-          path += ".cpp";
+        std::string suffix;
+        for (int ii = 0; ii != 1024; ++ii) {
+          std::string path = cmStrCat(basePath, suffix, ".cpp");
           if (emitted.emplace(path).second) {
             headersBuildPaths.emplace_back(std::move(path));
             break;
           }
+          suffix = cmStrCat('_', ii + 1);
         }
       }
     }
@@ -1329,7 +1320,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
         if (muf->MocIt || muf->UicIt) {
           sources.emplace_back(muf->RealPath);
           sourcesFlags.emplace_back(
-            cmStrCat(muf->MocIt ? "M" : "m", muf->UicIt ? "U" : "u"));
+            cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u'));
         }
       }
     }
@@ -1614,15 +1605,15 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
   // Find executable target
   {
     // Find executable target name
-    std::string targetName;
+    cm::string_view prefix;
     if (this->QtVersion.Major == 4) {
-      targetName = "Qt4::";
+      prefix = "Qt4::";
     } else if (this->QtVersion.Major == 5) {
-      targetName = "Qt5::";
+      prefix = "Qt5::";
     } else if (this->QtVersion.Major == 6) {
-      targetName = "Qt6::";
+      prefix = "Qt6::";
     }
-    targetName += executable;
+    std::string const targetName = cmStrCat(prefix, executable);
 
     // Find target
     cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
-- 
cgit v0.12


From 10dc684508ca0055f1558a40f27777a6bba6bc1c Mon Sep 17 00:00:00 2001
From: Sebastian Holtermann <sebholt@xwmw.org>
Date: Mon, 26 Aug 2019 17:16:54 +0200
Subject: Autogen: cmQtAutoRcc string concatenation cleanups

---
 Source/cmQtAutoRcc.cxx | 97 +++++++++++++++++++-------------------------------
 1 file changed, 37 insertions(+), 60 deletions(-)

diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx
index cc1a290..1cceaf1 100644
--- a/Source/cmQtAutoRcc.cxx
+++ b/Source/cmQtAutoRcc.cxx
@@ -1,9 +1,6 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmQtAutoRcc.h"
-#include "cmQtAutoGen.h"
-
-#include <sstream>
 
 #include "cmAlgorithms.h"
 #include "cmCryptoHash.h"
@@ -11,10 +8,10 @@
 #include "cmFileLockResult.h"
 #include "cmMakefile.h"
 #include "cmProcessOutput.h"
+#include "cmQtAutoGen.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
-
-// -- Class methods
+#include "cm_string_view.hxx"
 
 cmQtAutoRcc::cmQtAutoRcc() = default;
 
@@ -23,36 +20,27 @@ cmQtAutoRcc::~cmQtAutoRcc() = default;
 bool cmQtAutoRcc::Init(cmMakefile* makefile)
 {
   // -- Utility lambdas
-  auto InfoGet = [makefile](std::string const& key) {
-    return makefile->GetSafeDefinition(key);
+  auto InfoGet = [makefile](cm::string_view key) {
+    return makefile->GetSafeDefinition(std::string(key));
   };
   auto InfoGetList =
-    [makefile](std::string const& key) -> std::vector<std::string> {
-    std::vector<std::string> list =
-      cmExpandedList(makefile->GetSafeDefinition(key));
-    return list;
+    [makefile](cm::string_view key) -> std::vector<std::string> {
+    return cmExpandedList(makefile->GetSafeDefinition(std::string(key)));
   };
-  auto InfoGetConfig = [makefile,
-                        this](std::string const& key) -> std::string {
-    const char* valueConf = nullptr;
-    {
-      std::string keyConf = cmStrCat(key, '_', InfoConfig());
-      valueConf = makefile->GetDefinition(keyConf);
-    }
-    if (valueConf == nullptr) {
-      return makefile->GetSafeDefinition(key);
+  auto InfoGetConfig = [makefile, this](cm::string_view key) -> std::string {
+    if (const char* valueConf =
+          makefile->GetDefinition(cmStrCat(key, '_', InfoConfig()))) {
+      return std::string(valueConf);
     }
-    return std::string(valueConf);
+    return makefile->GetSafeDefinition(std::string(key));
   };
   auto InfoGetConfigList =
-    [&InfoGetConfig](std::string const& key) -> std::vector<std::string> {
-    std::vector<std::string> list = cmExpandedList(InfoGetConfig(key));
-    return list;
+    [&InfoGetConfig](cm::string_view key) -> std::vector<std::string> {
+    return cmExpandedList(InfoGetConfig(key));
   };
-  auto LogInfoError = [this](std::string const& msg) -> bool {
-    std::ostringstream err;
-    err << "In " << Quoted(this->InfoFile()) << ":\n" << msg;
-    this->Log().Error(GenT::RCC, err.str());
+  auto LogInfoError = [this](cm::string_view msg) -> bool {
+    this->Log().Error(GenT::RCC,
+                      cmStrCat("In ", Quoted(this->InfoFile()), ":\n", msg));
     return false;
   };
 
@@ -79,9 +67,8 @@ bool cmQtAutoRcc::Init(cmMakefile* makefile)
   // - Rcc executable
   RccExecutable_ = InfoGet("ARCC_RCC_EXECUTABLE");
   if (!RccExecutableTime_.Load(RccExecutable_)) {
-    std::string error = cmStrCat("The rcc executable ", Quoted(RccExecutable_),
-                                 " does not exist.");
-    return LogInfoError(error);
+    return LogInfoError(cmStrCat("The rcc executable ", Quoted(RccExecutable_),
+                                 " does not exist."));
   }
   RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS");
 
@@ -169,10 +156,8 @@ bool cmQtAutoRcc::Process()
 
 std::string cmQtAutoRcc::MultiConfigOutput() const
 {
-  static std::string const suffix = "_CMAKE_";
-  std::string res = cmStrCat(RccPathChecksum_, '/',
-                             AppendFilenameSuffix(RccFileName_, suffix));
-  return res;
+  return cmStrCat(RccPathChecksum_, '/',
+                  AppendFilenameSuffix(RccFileName_, "_CMAKE_"));
 }
 
 bool cmQtAutoRcc::SettingsFileRead()
@@ -272,10 +257,9 @@ bool cmQtAutoRcc::TestQrcRccFiles(bool& generate)
 {
   // Test if the rcc input file exists
   if (!QrcFileTime_.Load(QrcFile_)) {
-    std::string error;
-    error =
-      cmStrCat("The resources file ", Quoted(QrcFile_), " does not exist");
-    Log().ErrorFile(GenT::RCC, QrcFile_, error);
+    Log().ErrorFile(
+      GenT::RCC, QrcFile_,
+      cmStrCat("The resources file ", Quoted(QrcFile_), " does not exist"));
     return false;
   }
 
@@ -342,10 +326,9 @@ bool cmQtAutoRcc::TestResources(bool& generate)
     // Check if the resource file exists
     cmFileTime fileTime;
     if (!fileTime.Load(resFile)) {
-      std::string error;
-      error = cmStrCat("Could not find the resource file\n  ", Quoted(resFile),
-                       '\n');
-      Log().ErrorFile(GenT::RCC, QrcFile_, error);
+      Log().ErrorFile(GenT::RCC, QrcFile_,
+                      cmStrCat("Could not find the resource file\n  ",
+                               Quoted(resFile), '\n'));
       return false;
     }
     // Check if the resource file is newer than the rcc output file
@@ -367,10 +350,9 @@ bool cmQtAutoRcc::TestInfoFile()
   // Test if the rcc output file is older than the info file
   if (RccFileTime_.Older(InfoFileTime())) {
     if (Log().Verbose()) {
-      std::string reason =
-        cmStrCat("Touching ", Quoted(RccFileOutput_),
-                 " because it is older than ", Quoted(InfoFile()));
-      Log().Info(GenT::RCC, reason);
+      Log().Info(GenT::RCC,
+                 cmStrCat("Touching ", Quoted(RccFileOutput_),
+                          " because it is older than ", Quoted(InfoFile())));
     }
     // Touch build file
     if (!cmSystemTools::Touch(RccFileOutput_, false)) {
@@ -402,13 +384,9 @@ bool cmQtAutoRcc::GenerateRcc()
 
   // Log reason and command
   if (Log().Verbose()) {
-    std::string msg = Reason;
-    if (!msg.empty() && (msg.back() != '\n')) {
-      msg += '\n';
-    }
-    msg += QuotedCommand(cmd);
-    msg += '\n';
-    Log().Info(GenT::RCC, msg);
+    Log().Info(GenT::RCC,
+               cmStrCat(Reason, cmHasSuffix(Reason, '\n') ? "" : "\n",
+                        QuotedCommand(cmd), '\n'));
   }
 
   std::string rccStdOut;
@@ -419,12 +397,11 @@ bool cmQtAutoRcc::GenerateRcc()
     cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
   if (!result || (retVal != 0)) {
     // rcc process failed
-    {
-      std::string err =
-        cmStrCat("The rcc process failed to compile\n  ", Quoted(QrcFile_),
-                 "\ninto\n  ", Quoted(RccFileOutput_));
-      Log().ErrorCommand(GenT::RCC, err, cmd, rccStdOut + rccStdErr);
-    }
+    Log().ErrorCommand(GenT::RCC,
+                       cmStrCat("The rcc process failed to compile\n  ",
+                                Quoted(QrcFile_), "\ninto\n  ",
+                                Quoted(RccFileOutput_)),
+                       cmd, rccStdOut + rccStdErr);
     cmSystemTools::RemoveFile(RccFileOutput_);
     return false;
   }
-- 
cgit v0.12


From 619a92eacd689d867343c05fff568bf1dc9467b7 Mon Sep 17 00:00:00 2001
From: Sebastian Holtermann <sebholt@xwmw.org>
Date: Mon, 26 Aug 2019 17:25:44 +0200
Subject: Autogen: cmQtAutoRcc settings hash computation optimizations

---
 Source/cmQtAutoRcc.cxx | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx
index 1cceaf1..e931346 100644
--- a/Source/cmQtAutoRcc.cxx
+++ b/Source/cmQtAutoRcc.cxx
@@ -13,6 +13,8 @@
 #include "cmSystemTools.h"
 #include "cm_string_view.hxx"
 
+#include <algorithm>
+
 cmQtAutoRcc::cmQtAutoRcc() = default;
 
 cmQtAutoRcc::~cmQtAutoRcc() = default;
@@ -164,15 +166,19 @@ bool cmQtAutoRcc::SettingsFileRead()
 {
   // Compose current settings strings
   {
-    cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
-    std::string const sep(" ~~~ ");
-    {
-      std::string str =
-        cmStrCat(RccExecutable_, sep, cmJoin(RccListOptions_, ";"), sep,
-                 QrcFile_, sep, RccPathChecksum_, sep, RccFileName_, sep,
-                 cmJoin(Options_, ";"), sep, cmJoin(Inputs_, ";"), sep);
-      SettingsString_ = crypt.HashString(str);
-    }
+    cmCryptoHash cryptoHash(cmCryptoHash::AlgoSHA256);
+    auto cha = [&cryptoHash](cm::string_view value) {
+      cryptoHash.Append(value);
+      cryptoHash.Append(";");
+    };
+    cha(RccExecutable_);
+    std::for_each(RccListOptions_.begin(), RccListOptions_.end(), cha);
+    cha(QrcFile_);
+    cha(RccPathChecksum_);
+    cha(RccFileName_);
+    std::for_each(Options_.begin(), Options_.end(), cha);
+    std::for_each(Inputs_.begin(), Inputs_.end(), cha);
+    SettingsString_ = cryptoHash.FinalizeHex();
   }
 
   // Make sure the settings file exists
-- 
cgit v0.12


From b66cd3fe63d381ed2d26191fe440b59bf01fc67b Mon Sep 17 00:00:00 2001
From: Sebastian Holtermann <sebholt@xwmw.org>
Date: Mon, 26 Aug 2019 18:30:57 +0200
Subject: Autogen: cmQtAutoMocUic string concatenation cleanups

---
 Source/cmQtAutoMocUic.cxx | 475 +++++++++++++++++++++-------------------------
 Source/cmQtAutoMocUic.h   |  15 +-
 2 files changed, 225 insertions(+), 265 deletions(-)

diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index df190a1..d4d9e56 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -3,10 +3,9 @@
 #include "cmQtAutoMocUic.h"
 
 #include <algorithm>
-#include <array>
+#include <initializer_list>
 #include <list>
 #include <set>
-#include <sstream>
 #include <utility>
 
 #include "cm_memory.hxx"
@@ -233,22 +232,21 @@ bool cmQtAutoMocUic::UicSettingsT::skipped(std::string const& fileName) const
 }
 
 void cmQtAutoMocUic::JobT::LogError(GenT genType,
-                                    std::string const& message) const
+                                    cm::string_view message) const
 {
   Gen()->AbortError();
   Gen()->Log().Error(genType, message);
 }
 
-void cmQtAutoMocUic::JobT::LogFileError(GenT genType,
-                                        std::string const& filename,
-                                        std::string const& message) const
+void cmQtAutoMocUic::JobT::LogFileError(GenT genType, cm::string_view filename,
+                                        cm::string_view message) const
 {
   Gen()->AbortError();
   Gen()->Log().ErrorFile(genType, filename, message);
 }
 
 void cmQtAutoMocUic::JobT::LogCommandError(
-  GenT genType, std::string const& message,
+  GenT genType, cm::string_view message,
   std::vector<std::string> const& command, std::string const& output) const
 {
   Gen()->AbortError();
@@ -262,16 +260,14 @@ bool cmQtAutoMocUic::JobT::RunProcess(GenT genType,
 {
   // Log command
   if (Log().Verbose()) {
-    std::string msg;
-    if ((infoMessage != nullptr) && !infoMessage->empty()) {
-      msg = *infoMessage;
-      if (msg.back() != '\n') {
-        msg += '\n';
-      }
+    cm::string_view info;
+    if (infoMessage != nullptr) {
+      info = *infoMessage;
     }
-    msg += QuotedCommand(command);
-    msg += '\n';
-    Log().Info(genType, msg);
+    Log().Info(genType,
+               cmStrCat(info,
+                        info.empty() || cmHasSuffix(info, '\n') ? "" : "\n",
+                        QuotedCommand(command), '\n'));
   }
   return cmWorkerPool::JobT::RunProcess(result, command,
                                         BaseConst().AutogenBuildDir);
@@ -302,10 +298,11 @@ void cmQtAutoMocUic::JobMocPredefsT::Process()
       }
       // Execute command
       if (!RunProcess(GenT::MOC, result, cmd, reason.get())) {
-        std::string msg =
-          cmStrCat("The content generation command for ",
-                   Quoted(predefsFileRel), " failed.\n", result.ErrorMessage);
-        LogCommandError(GenT::MOC, msg, cmd, result.StdOut);
+        LogCommandError(GenT::MOC,
+                        cmStrCat("The content generation command for ",
+                                 Quoted(predefsFileRel), " failed.\n",
+                                 result.ErrorMessage),
+                        cmd, result.StdOut);
         return;
       }
     }
@@ -313,9 +310,8 @@ void cmQtAutoMocUic::JobMocPredefsT::Process()
     // (Re)write predefs file only on demand
     if (cmQtAutoGenerator::FileDiffers(predefsFileAbs, result.StdOut)) {
       if (!cmQtAutoGenerator::FileWrite(predefsFileAbs, result.StdOut)) {
-        std::string msg =
-          cmStrCat("Writing ", Quoted(predefsFileRel), " failed.");
-        LogFileError(GenT::MOC, predefsFileAbs, msg);
+        LogFileError(GenT::MOC, predefsFileAbs,
+                     cmStrCat("Writing ", Quoted(predefsFileRel), " failed."));
         return;
       }
     } else {
@@ -324,9 +320,9 @@ void cmQtAutoMocUic::JobMocPredefsT::Process()
         Log().Info(GenT::MOC, "Touching " + Quoted(predefsFileRel));
       }
       if (!cmSystemTools::Touch(predefsFileAbs, false)) {
-        std::string msg =
-          cmStrCat("Touching ", Quoted(predefsFileAbs), " failed.");
-        LogFileError(GenT::MOC, predefsFileAbs, msg);
+        LogFileError(
+          GenT::MOC, predefsFileAbs,
+          cmStrCat("Touching ", Quoted(predefsFileAbs), " failed."));
         return;
       }
     }
@@ -654,14 +650,12 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource(
   // Check if this source needs to be moc processed but doesn't.
   if (!sourceIncludesDotMoc && !parseData.Macro.empty() &&
       !(relaxedMode && sourceIncludesMocUnderscore)) {
-    {
-      std::string emsg =
-        cmStrCat("The file contains a ", Quoted(parseData.Macro),
-                 " macro, but does not include ", Quoted(sourceBase + ".moc"),
-                 "!\nConsider to\n  - add #include \"", sourceBase,
-                 ".moc\"\n  - enable SKIP_AUTOMOC for this file");
-      LogFileError(GenT::MOC, sourceFile.FileName, emsg);
-    }
+    LogFileError(GenT::MOC, sourceFile.FileName,
+                 cmStrCat("The file contains a ", Quoted(parseData.Macro),
+                          " macro, but does not include ",
+                          Quoted(sourceBase + ".moc"),
+                          "!\nConsider to\n  - add #include \"", sourceBase,
+                          ".moc\"\n  - enable SKIP_AUTOMOC for this file"));
     return false;
   }
 
@@ -670,14 +664,12 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource(
     std::string const headerBase = incKey.Dir + incKey.Base;
     SourceFileHandleT header = MocFindIncludedHeader(sourceDir, headerBase);
     if (!header) {
-      {
-        std::string msg =
-          cmStrCat("The file includes the moc file ", Quoted(incKey.Key),
-                   ",\nbut the header could not be found "
-                   "in the following locations\n",
-                   MocMessageTestHeaders(headerBase));
-        LogFileError(GenT::MOC, sourceFile.FileName, msg);
-      }
+      LogFileError(GenT::MOC, sourceFile.FileName,
+                   cmStrCat("The file includes the moc file ",
+                            Quoted(incKey.Key),
+                            ",\nbut the header could not be found "
+                            "in the following locations\n",
+                            MocMessageTestHeaders(headerBase)));
       return false;
     }
     // The include might be handled differently in relaxed mode
@@ -688,18 +680,19 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource(
       // be generated from <BASE>.cpp instead of <BASE>.h, because otherwise
       // it won't build. But warn, since this is not how it is supposed to be
       // used. This is for KDE4 compatibility.
-      {
-        // Issue a warning
-        std::string msg = cmStrCat(
-          "The file contains a ", Quoted(parseData.Macro),
-          " macro, but does not include ", Quoted(sourceBase + ".moc"),
-          ".\nInstead it includes ", Quoted(incKey.Key),
-          ".\nRunning moc on the source\n  ", Quoted(sourceFile.FileName),
-          "!\nBetter include ", Quoted(sourceBase + ".moc"),
-          " for compatibility with regular mode.\n",
-          "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n");
-        Log().WarningFile(GenT::MOC, sourceFile.FileName, msg);
-      }
+
+      // Issue a warning
+      Log().WarningFile(
+        GenT::MOC, sourceFile.FileName,
+        cmStrCat("The file contains a ", Quoted(parseData.Macro),
+                 " macro, but does not include ", Quoted(sourceBase + ".moc"),
+                 ".\nInstead it includes ", Quoted(incKey.Key),
+                 ".\nRunning moc on the source\n  ",
+                 Quoted(sourceFile.FileName), "!\nBetter include ",
+                 Quoted(sourceBase + ".moc"),
+                 " for compatibility with regular mode.\n",
+                 "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
+
       // Create mapping
       if (!MocRegisterIncluded(incKey.Key, source, source, false)) {
         return false;
@@ -735,13 +728,13 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource(
       std::string const headerBase = incKey.Dir + incKey.Base;
       SourceFileHandleT header = MocFindIncludedHeader(sourceDir, headerBase);
       if (!header) {
-        std::string msg =
+        LogFileError(
+          GenT::MOC, sourceFile.FileName,
           cmStrCat("The file includes the moc file ", Quoted(incKey.Key),
                    ",\nwhich seems to be the moc file from a different source "
                    "file.\nCMAKE_AUTOMOC_RELAXED_MODE: Also a matching header"
                    "could not be found in the following locations\n",
-                   MocMessageTestHeaders(headerBase));
-        LogFileError(GenT::MOC, sourceFile.FileName, msg);
+                   MocMessageTestHeaders(headerBase)));
         return false;
       }
       // Check if header is skipped
@@ -750,23 +743,25 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource(
       }
       // Issue a warning
       if (ownMoc && parseData.Macro.empty()) {
-        std::string msg = cmStrCat(
-          "The file includes the moc file ", Quoted(incKey.Key),
-          ", but does not contain a\n", MocConst().MacrosString(),
-          " macro.\nRunning moc on the header\n  ", Quoted(header->FileName),
-          "!\nBetter include ", Quoted("moc_" + incKey.Base + ".cpp"),
-          " for a compatibility with regular mode.\n",
-          "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n");
-        Log().WarningFile(GenT::MOC, sourceFile.FileName, msg);
+        Log().WarningFile(
+          GenT::MOC, sourceFile.FileName,
+          cmStrCat("The file includes the moc file ", Quoted(incKey.Key),
+                   ", but does not contain a\n", MocConst().MacrosString(),
+                   " macro.\nRunning moc on the header\n  ",
+                   Quoted(header->FileName), "!\nBetter include ",
+                   Quoted("moc_" + incKey.Base + ".cpp"),
+                   " for a compatibility with regular mode.\n",
+                   "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
       } else {
-        std::string msg = cmStrCat(
-          "The file includes the moc file ", Quoted(incKey.Key),
-          " instead of ", Quoted("moc_" + incKey.Base + ".cpp"),
-          ".\nRunning moc on the header\n  ", Quoted(header->FileName),
-          "!\nBetter include ", Quoted("moc_" + incKey.Base + ".cpp"),
-          " for compatibility with regular mode.\n",
-          "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n");
-        Log().WarningFile(GenT::MOC, sourceFile.FileName, msg);
+        Log().WarningFile(
+          GenT::MOC, sourceFile.FileName,
+          cmStrCat("The file includes the moc file ", Quoted(incKey.Key),
+                   " instead of ", Quoted("moc_" + incKey.Base + ".cpp"),
+                   ".\nRunning moc on the header\n  ",
+                   Quoted(header->FileName), "!\nBetter include ",
+                   Quoted("moc_" + incKey.Base + ".cpp"),
+                   " for compatibility with regular mode.\n",
+                   "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
       }
       // Create mapping
       if (!MocRegisterIncluded(incKey.Key, source, std::move(header), true)) {
@@ -780,20 +775,22 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource(
       bool const ownMoc = (incKey.Base == sourceBase);
       if (!ownMoc) {
         // Don't allow <BASE>.moc include other than own in regular mode
-        std::string msg = cmStrCat(
-          "The file includes the moc file ", Quoted(incKey.Key),
-          ",\nwhich seems to be the moc file from a different "
-          "source file.\nThis is not supported.  Include ",
-          Quoted(sourceBase + ".moc"), " to run moc on this source file.");
-        LogFileError(GenT::MOC, sourceFile.FileName, msg);
+        LogFileError(
+          GenT::MOC, sourceFile.FileName,
+          cmStrCat("The file includes the moc file ", Quoted(incKey.Key),
+                   ",\nwhich seems to be the moc file from a different "
+                   "source file.\nThis is not supported.  Include ",
+                   Quoted(sourceBase + ".moc"),
+                   " to run moc on this source file."));
         return false;
       }
       // Accept but issue a warning if moc isn't required
       if (parseData.Macro.empty()) {
-        std::string msg = cmStrCat(
-          "The file includes the moc file ", Quoted(incKey.Key),
-          ", but does not contain a ", MocConst().MacrosString(), " macro.");
-        Log().WarningFile(GenT::MOC, sourceFile.FileName, msg);
+        Log().WarningFile(GenT::MOC, sourceFile.FileName,
+                          cmStrCat("The file includes the moc file ",
+                                   Quoted(incKey.Key),
+                                   ", but does not contain a ",
+                                   MocConst().MacrosString(), " macro."));
       }
       // Create mapping
       if (!MocRegisterIncluded(incKey.Key, source, source, false)) {
@@ -864,19 +861,16 @@ cmQtAutoMocUic::SourceFileHandleT cmQtAutoMocUic::JobEvaluateT::MocFindHeader(
 }
 
 std::string cmQtAutoMocUic::JobEvaluateT::MocMessageTestHeaders(
-  std::string const& fileBase) const
+  cm::string_view fileBase) const
 {
-  std::ostringstream res;
-  {
-    std::string exts =
-      cmStrCat(".{", cmJoin(BaseConst().HeaderExtensions, ","),
-               '}'); // Compose result string
-    res << "  " << fileBase << exts << '\n';
-    for (std::string const& path : MocConst().IncludePaths) {
-      res << "  " << path << '/' << fileBase << exts << '\n';
-    }
+  std::string const exts =
+    cmStrCat(".{", cmJoin(BaseConst().HeaderExtensions, ","), '}');
+  // Compose result string
+  std::string res = cmStrCat("  ", fileBase, exts, '\n');
+  for (std::string const& path : MocConst().IncludePaths) {
+    res += cmStrCat("  ", path, '/', fileBase, exts, '\n');
   }
-  return res.str();
+  return res;
 }
 
 bool cmQtAutoMocUic::JobEvaluateT::MocRegisterIncluded(
@@ -888,26 +882,24 @@ bool cmQtAutoMocUic::JobEvaluateT::MocRegisterIncluded(
   if (handle) {
     // Check if the output file would be generated from different source files
     if (handle->SourceFile != sourceFileHandle) {
-      std::string msg = cmStrCat("The source files\n  ",
-                                 Quoted(includerFileHandle->FileName), '\n');
+      std::string files =
+        cmStrCat("  ", Quoted(includerFileHandle->FileName), '\n');
       for (auto const& item : handle->IncluderFiles) {
-        msg += "  ";
-        msg += Quoted(item->FileName);
-        msg += '\n';
-      }
-      msg += "contain the same include string ";
-      msg += Quoted(includeString);
-      msg += ", but\nthe moc file would be generated from different "
-             "source files\n  ";
-      msg += Quoted(sourceFileHandle->FileName);
-      msg += " and\n  ";
-      msg += Quoted(handle->SourceFile->FileName);
-      msg += ".\nConsider to\n"
-             "  - not include the \"moc_<NAME>.cpp\" file\n"
-             "  - add a directory prefix to a \"<NAME>.moc\" include "
-             "(e.g \"sub/<NAME>.moc\")\n"
-             "  - rename the source file(s)\n";
-      LogError(GenT::MOC, msg);
+        files += cmStrCat("  ", Quoted(item->FileName), '\n');
+      }
+      LogError(
+        GenT::MOC,
+        cmStrCat("The source files\n", files,
+                 "contain the same include string ", Quoted(includeString),
+                 ", but\nthe moc file would be generated from different "
+                 "source files\n  ",
+                 Quoted(sourceFileHandle->FileName), " and\n  ",
+                 Quoted(handle->SourceFile->FileName),
+                 ".\nConsider to\n"
+                 "  - not include the \"moc_<NAME>.cpp\" file\n"
+                 "  - add a directory prefix to a \"<NAME>.moc\" include "
+                 "(e.g \"sub/<NAME>.moc\")\n"
+                 "  - rename the source file(s)\n"));
       return false;
     }
 
@@ -921,7 +913,7 @@ bool cmQtAutoMocUic::JobEvaluateT::MocRegisterIncluded(
   handle->IncludeString = includeString;
   handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
   handle->SourceFile = std::move(sourceFileHandle);
-  handle->OutputFile += Gen()->AbsoluteIncludePath(includeString);
+  handle->OutputFile = Gen()->AbsoluteIncludePath(includeString);
 
   // Register mapping in sources/headers map
   MocRegisterMapping(handle, sourceIsHeader);
@@ -993,26 +985,25 @@ bool cmQtAutoMocUic::JobEvaluateT::UicRegisterMapping(
     MappingHandleT const& handle = it->second;
     if (handle->SourceFile != uiFileHandle) {
       // The output file already gets generated - from a different .ui file!
-      std::string msg = cmStrCat("The source files\n  ",
-                                 Quoted(includerFileHandle->FileName), '\n');
+      std::string files =
+        cmStrCat("  ", Quoted(includerFileHandle->FileName), '\n');
       for (auto const& item : handle->IncluderFiles) {
-        msg += "  ";
-        msg += Quoted(item->FileName);
-        msg += '\n';
-      }
-      msg += "contain the same include string ";
-      msg += Quoted(includeString);
-      msg += ", but\nthe uic file would be generated from different "
-             "user interface files\n  ";
-      msg += Quoted(uiFileHandle->FileName);
-      msg += " and\n  ";
-      msg += Quoted(handle->SourceFile->FileName);
-      msg += ".\nConsider to\n"
-             "  - add a directory prefix to a \"ui_<NAME>.h\" include "
-             "(e.g \"sub/ui_<NAME>.h\")\n"
-             "  - rename the <NAME>.ui file(s) and adjust the \"ui_<NAME>.h\" "
-             "include(s)\n";
-      LogError(GenT::UIC, msg);
+        files += cmStrCat("  ", Quoted(item->FileName), '\n');
+      }
+      LogError(
+        GenT::UIC,
+        cmStrCat(
+          "The source files\n", files, "contain the same include string ",
+          Quoted(includeString),
+          ", but\nthe uic file would be generated from different "
+          "user interface files\n  ",
+          Quoted(uiFileHandle->FileName), " and\n  ",
+          Quoted(handle->SourceFile->FileName),
+          ".\nConsider to\n"
+          "  - add a directory prefix to a \"ui_<NAME>.h\" include "
+          "(e.g \"sub/ui_<NAME>.h\")\n"
+          "  - rename the <NAME>.ui file(s) and adjust the \"ui_<NAME>.h\" "
+          "include(s)\n"));
       return false;
     }
     // Add includer file to existing mapping
@@ -1023,7 +1014,7 @@ bool cmQtAutoMocUic::JobEvaluateT::UicRegisterMapping(
     handle->IncludeString = includeString;
     handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
     handle->SourceFile = std::move(uiFileHandle);
-    handle->OutputFile += Gen()->AbsoluteIncludePath(includeString);
+    handle->OutputFile = Gen()->AbsoluteIncludePath(includeString);
     // Register mapping
     Includes.emplace(includeString, std::move(handle));
   }
@@ -1080,16 +1071,15 @@ cmQtAutoMocUic::JobEvaluateT::UicFindIncludedUi(
 
   // Log error
   {
-    std::string msg =
-      cmStrCat("The file includes the uic file ", Quoted(incKey.Key),
-               ",\nbut the user interface file ", Quoted(searchFileName),
-               "\ncould not be found in the following locations\n");
+    std::string files;
     for (std::string const& testFile : testFiles) {
-      msg += "  ";
-      msg += Quoted(testFile);
-      msg += '\n';
+      files += cmStrCat("  ", Quoted(testFile), '\n');
     }
-    LogFileError(GenT::UIC, sourceFile, msg);
+    LogFileError(
+      GenT::UIC, sourceFile,
+      cmStrCat("The file includes the uic file ", Quoted(incKey.Key),
+               ",\nbut the user interface file ", Quoted(searchFileName),
+               "\ncould not be found in the following locations\n", files));
   }
 
   return SourceFileHandleT();
@@ -1257,9 +1247,7 @@ cmQtAutoMocUic::JobGenerateT::MocFindDependency(
   }
   // Search in include directories
   for (std::string const& includePath : MocConst().IncludePaths) {
-    ResPair res{ includePath, {} };
-    res.first += '/';
-    res.first += includeString;
+    ResPair res{ cmStrCat(includePath, '/', includeString), {} };
     if (res.second.Load(res.first)) {
       return res;
     }
@@ -1366,21 +1354,19 @@ void cmQtAutoMocUic::JobMocT::Process()
     }
   } else {
     // Moc command failed
-    std::string msg =
-      cmStrCat("The moc process failed to compile\n  ", Quoted(sourceFile),
-               "\ninto\n  ", Quoted(outputFile));
-    if (Mapping->IncluderFiles.empty()) {
-      msg += ".\n";
-    } else {
-      msg += "\nincluded by\n";
+    std::string includers;
+    if (!Mapping->IncluderFiles.empty()) {
+      includers = "included by\n";
       for (auto const& item : Mapping->IncluderFiles) {
-        msg += "  ";
-        msg += Quoted(item->FileName);
-        msg += '\n';
+        includers += cmStrCat("  ", Quoted(item->FileName), '\n');
       }
     }
-    msg += result.ErrorMessage;
-    LogCommandError(GenT::MOC, msg, cmd, result.StdOut);
+    LogCommandError(GenT::MOC,
+                    cmStrCat("The moc process failed to compile\n  ",
+                             Quoted(sourceFile), "\ninto\n  ",
+                             Quoted(outputFile), '\n', includers,
+                             result.ErrorMessage),
+                    cmd, result.StdOut);
   }
 }
 
@@ -1414,16 +1400,16 @@ void cmQtAutoMocUic::JobUicT::Process()
     }
   } else {
     // Uic command failed
-    std::string msg =
-      cmStrCat("The uic process failed to compile\n  ", Quoted(sourceFile),
-               "\ninto\n  ", Quoted(outputFile), "\nincluded by\n");
+    std::string includers;
     for (auto const& item : Mapping->IncluderFiles) {
-      msg += "  ";
-      msg += Quoted(item->FileName);
-      msg += '\n';
+      includers += cmStrCat("  ", Quoted(item->FileName), '\n');
     }
-    msg += result.ErrorMessage;
-    LogCommandError(GenT::UIC, msg, cmd, result.StdOut);
+    LogCommandError(GenT::UIC,
+                    cmStrCat("The uic process failed to compile\n  ",
+                             Quoted(sourceFile), "\ninto\n  ",
+                             Quoted(outputFile), "\nincluded by\n", includers,
+                             result.ErrorMessage),
+                    cmd, result.StdOut);
   }
 }
 
@@ -1436,19 +1422,14 @@ void cmQtAutoMocUic::JobMocsCompilationT::Process()
   if (MocEval().CompFiles.empty()) {
     // Placeholder content
     content += "// No files found that require moc or the moc files are "
-               "included\n";
-    content += "enum some_compilers { need_more_than_nothing };\n";
+               "included\n"
+               "enum some_compilers { need_more_than_nothing };\n";
   } else {
     // Valid content
-    char const clampB = BaseConst().MultiConfig ? '<' : '"';
-    char const clampE = BaseConst().MultiConfig ? '>' : '"';
-    for (std::string const& mocfile : MocEval().CompFiles) {
-      content += "#include ";
-      content += clampB;
-      content += mocfile;
-      content += clampE;
-      content += '\n';
-    }
+    const bool mc = BaseConst().MultiConfig;
+    cm::string_view const wrapFront = mc ? "#include <" : "#include \"";
+    cm::string_view const wrapBack = mc ? ">\n" : "\"\n";
+    content += cmWrap(wrapFront, MocEval().CompFiles, wrapBack, "");
   }
 
   std::string const& compAbs = MocConst().CompFileAbs;
@@ -1484,22 +1465,21 @@ cmQtAutoMocUic::~cmQtAutoMocUic() = default;
 bool cmQtAutoMocUic::Init(cmMakefile* makefile)
 {
   // Utility lambdas
-  auto InfoGet = [makefile](const char* key) {
-    return makefile->GetSafeDefinition(key);
+  auto InfoGet = [makefile](cm::string_view key) {
+    return makefile->GetSafeDefinition(std::string(key));
   };
-  auto InfoGetBool = [makefile](const char* key) {
-    return makefile->IsOn(key);
+  auto InfoGetBool = [makefile](cm::string_view key) {
+    return makefile->IsOn(std::string(key));
   };
-  auto InfoGetList = [makefile](const char* key) -> std::vector<std::string> {
-    std::vector<std::string> list =
-      cmExpandedList(makefile->GetSafeDefinition(key));
-    return list;
+  auto InfoGetList =
+    [makefile](cm::string_view key) -> std::vector<std::string> {
+    return cmExpandedList(makefile->GetSafeDefinition(std::string(key)));
   };
   auto InfoGetLists =
-    [makefile](const char* key) -> std::vector<std::vector<std::string>> {
+    [makefile](cm::string_view key) -> std::vector<std::vector<std::string>> {
     std::vector<std::vector<std::string>> lists;
     {
-      std::string const value = makefile->GetSafeDefinition(key);
+      std::string const value = makefile->GetSafeDefinition(std::string(key));
       std::string::size_type pos = 0;
       while (pos < value.size()) {
         std::string::size_type next = value.find(ListSep, pos);
@@ -1517,38 +1497,30 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
     }
     return lists;
   };
-  auto InfoGetConfig = [makefile, this](const char* key) -> std::string {
-    const char* valueConf = nullptr;
-    {
-      std::string keyConf = cmStrCat(key, '_', InfoConfig());
-      valueConf = makefile->GetDefinition(keyConf);
+  auto InfoGetConfig = [makefile, this](cm::string_view key) -> std::string {
+    if (const char* valueConf =
+          makefile->GetDefinition(cmStrCat(key, '_', InfoConfig()))) {
+      return std::string(valueConf);
     }
-    if (valueConf == nullptr) {
-      return makefile->GetSafeDefinition(key);
-    }
-    return std::string(valueConf);
+    return makefile->GetSafeDefinition(std::string(key));
   };
   auto InfoGetConfigList =
-    [&InfoGetConfig](const char* key) -> std::vector<std::string> {
-    std::vector<std::string> list = cmExpandedList(InfoGetConfig(key));
-    return list;
+    [&InfoGetConfig](cm::string_view key) -> std::vector<std::string> {
+    return cmExpandedList(InfoGetConfig(key));
   };
-  auto LogInfoError = [this](std::string const& msg) -> bool {
-    std::ostringstream err;
-    err << "In " << Quoted(this->InfoFile()) << ":\n" << msg;
-    this->Log().Error(GenT::GEN, err.str());
+  auto LogInfoError = [this](cm::string_view msg) -> bool {
+    this->Log().Error(GenT::GEN,
+                      cmStrCat("In ", Quoted(this->InfoFile()), ":\n", msg));
     return false;
   };
-  auto MatchSizes = [&LogInfoError](const char* keyA, const char* keyB,
+  auto MatchSizes = [&LogInfoError](cm::string_view keyA, cm::string_view keyB,
                                     std::size_t sizeA,
                                     std::size_t sizeB) -> bool {
     if (sizeA == sizeB) {
       return true;
     }
-    std::ostringstream err;
-    err << "Lists sizes mismatch " << keyA << '(' << sizeA << ") " << keyB
-        << '(' << sizeB << ')';
-    return LogInfoError(err.str());
+    return LogInfoError(cmStrCat("Lists sizes mismatch ", keyA, '(', sizeA,
+                                 ") ", keyB, '(', sizeB, ')'));
   };
 
   // -- Read info file
@@ -1590,10 +1562,9 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
     return LogInfoError("CMake executable file name missing.");
   }
   if (!BaseConst_.CMakeExecutableTime.Load(BaseConst_.CMakeExecutable)) {
-    std::string error =
-      cmStrCat("The CMake executable ", Quoted(BaseConst_.CMakeExecutable),
-               " does not exist.");
-    return LogInfoError(error);
+    return LogInfoError(cmStrCat("The CMake executable ",
+                                 Quoted(BaseConst_.CMakeExecutable),
+                                 " does not exist."));
   }
   BaseConst_.ParseCacheFile = InfoGetConfig("AM_PARSE_CACHE_FILE");
   if (BaseConst_.ParseCacheFile.empty()) {
@@ -1620,10 +1591,9 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
     MocConst_.Enabled = true;
     // Load the executable file time
     if (!MocConst_.ExecutableTime.Load(MocConst_.Executable)) {
-      std::string error =
-        cmStrCat("The moc executable ", Quoted(MocConst_.Executable),
-                 " does not exist.");
-      return LogInfoError(error);
+      return LogInfoError(cmStrCat("The moc executable ",
+                                   Quoted(MocConst_.Executable),
+                                   " does not exist."));
     }
     for (std::string& sfl : InfoGetList("AM_MOC_SKIP")) {
       MocConst_.SkipList.insert(std::move(sfl));
@@ -1639,12 +1609,11 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
     {
       auto addFilter = [this, &LogInfoError](std::string const& key,
                                              std::string const& exp) -> bool {
-        auto filterErr = [&LogInfoError, &key, &exp](const char* err) -> bool {
-          std::ostringstream ferr;
-          ferr << "AUTOMOC_DEPEND_FILTERS: " << err << '\n';
-          ferr << "  Key: " << Quoted(key) << '\n';
-          ferr << "  Exp: " << Quoted(exp) << '\n';
-          return LogInfoError(ferr.str());
+        auto filterErr = [&LogInfoError, &key,
+                          &exp](cm::string_view err) -> bool {
+          return LogInfoError(cmStrCat("AUTOMOC_DEPEND_FILTERS: ", err, '\n',
+                                       "  Key: ", Quoted(key), '\n',
+                                       "  Exp: ", Quoted(exp), '\n'));
         };
         if (key.empty()) {
           return filterErr("Key is empty");
@@ -1688,10 +1657,9 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
     UicConst_.Enabled = true;
     // Load the executable file time
     if (!UicConst_.ExecutableTime.Load(UicConst_.Executable)) {
-      std::string error =
-        cmStrCat("The uic executable ", Quoted(UicConst_.Executable),
-                 " does not exist.");
-      return LogInfoError(error);
+      return LogInfoError(cmStrCat("The uic executable ",
+                                   Quoted(UicConst_.Executable),
+                                   " does not exist."));
     }
     for (std::string& sfl : InfoGetList("AM_UIC_SKIP")) {
       UicConst_.SkipList.insert(std::move(sfl));
@@ -1699,8 +1667,8 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
     UicConst_.SearchPaths = InfoGetList("AM_UIC_SEARCH_PATHS");
     UicConst_.TargetOptions = InfoGetConfigList("AM_UIC_TARGET_OPTIONS");
     {
-      const char* keyFiles = "AM_UIC_OPTIONS_FILES";
-      const char* keyOpts = "AM_UIC_OPTIONS_OPTIONS";
+      cm::string_view const keyFiles = "AM_UIC_OPTIONS_FILES";
+      cm::string_view const keyOpts = "AM_UIC_OPTIONS_OPTIONS";
       auto sources = InfoGetList(keyFiles);
       auto options = InfoGetLists(keyOpts);
       if (!MatchSizes(keyFiles, keyOpts, sources.size(), options.size())) {
@@ -1742,8 +1710,8 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
     // Headers
     {
       // Get file lists
-      const char* keyFiles = "AM_HEADERS";
-      const char* keyFlags = "AM_HEADERS_FLAGS";
+      cm::string_view const keyFiles = "AM_HEADERS";
+      cm::string_view const keyFlags = "AM_HEADERS_FLAGS";
       std::vector<std::string> files = InfoGetList(keyFiles);
       std::vector<std::string> flags = InfoGetList(keyFlags);
       std::vector<std::string> builds;
@@ -1751,7 +1719,7 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
         return false;
       }
       if (MocConst().Enabled) {
-        const char* keyPaths = "AM_HEADERS_BUILD_PATHS";
+        cm::string_view const keyPaths = "AM_HEADERS_BUILD_PATHS";
         builds = InfoGetList(keyPaths);
         if (!MatchSizes(keyFiles, keyPaths, files.size(), builds.size())) {
           return false;
@@ -1778,8 +1746,8 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
 
     // Sources
     {
-      const char* keyFiles = "AM_SOURCES";
-      const char* keyFlags = "AM_SOURCES_FLAGS";
+      cm::string_view const keyFiles = "AM_SOURCES";
+      cm::string_view const keyFlags = "AM_SOURCES_FLAGS";
       std::vector<std::string> files = InfoGetList(keyFiles);
       std::vector<std::string> flags = InfoGetList(keyFlags);
       if (!MatchSizes(keyFiles, keyFlags, files.size(), flags.size())) {
@@ -1807,12 +1775,12 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
 
     // Moc predefs file
     if (!MocConst_.PredefsCmd.empty()) {
-      MocConst_.PredefsFileRel = "moc_predefs";
       if (BaseConst_.MultiConfig) {
-        MocConst_.PredefsFileRel += '_';
-        MocConst_.PredefsFileRel += InfoConfig();
+        MocConst_.PredefsFileRel =
+          cmStrCat("moc_predefs_", InfoConfig(), ".h");
+      } else {
+        MocConst_.PredefsFileRel = "moc_predefs.h";
       }
-      MocConst_.PredefsFileRel += ".h";
       MocConst_.PredefsFileAbs = AbsoluteBuildPath(MocConst().PredefsFileRel);
     }
 
@@ -1825,14 +1793,14 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile)
       MocConst_.IncludePaths.reserve(includes.size());
       // Append project directories only
       {
-        std::array<std::string const*, 2> const movePaths = {
-          { &BaseConst().ProjectBinaryDir, &BaseConst().ProjectSourceDir }
+        std::initializer_list<cm::string_view> const movePaths = {
+          BaseConst().ProjectBinaryDir, BaseConst().ProjectSourceDir
         };
-        for (std::string const* ppath : movePaths) {
+        for (cm::string_view const& ppath : movePaths) {
           std::list<std::string>::iterator it = includes.begin();
           while (it != includes.end()) {
             std::string const& path = *it;
-            if (cmHasPrefix(path, *ppath)) {
+            if (cmHasPrefix(path, ppath)) {
               MocConst_.IncludePaths.push_back(path);
               it = includes.erase(it);
             } else {
@@ -2027,13 +1995,10 @@ bool cmQtAutoMocUic::SettingsFileWrite()
     // Compose settings file content
     std::string content;
     {
-      auto SettingAppend = [&content](const char* key,
-                                      std::string const& value) {
+      auto SettingAppend = [&content](cm::string_view key,
+                                      cm::string_view value) {
         if (!value.empty()) {
-          content += key;
-          content += ':';
-          content += value;
-          content += '\n';
+          content += cmStrCat(key, ':', value, '\n');
         }
       };
       SettingAppend("moc", SettingsStringMoc_);
@@ -2054,7 +2019,7 @@ bool cmQtAutoMocUic::SettingsFileWrite()
 
 void cmQtAutoMocUic::ParseCacheRead()
 {
-  const char* reason = nullptr;
+  cm::string_view reason;
   // Don't read the cache if it is invalid
   if (!BaseEval().ParseCacheTime.Load(BaseConst().ParseCacheFile)) {
     reason = "Refreshing parse cache because it doesn't exist.";
@@ -2066,7 +2031,7 @@ void cmQtAutoMocUic::ParseCacheRead()
       "Refreshing parse cache because it is older than the CMake executable.";
   }
 
-  if (reason != nullptr) {
+  if (!reason.empty()) {
     // Don't read but refresh the complete parse cache
     if (Log().Verbose()) {
       Log().Info(GenT::GEN, reason);
@@ -2115,19 +2080,13 @@ void cmQtAutoMocUic::Abort(bool error)
 }
 
 std::string cmQtAutoMocUic::AbsoluteBuildPath(
-  std::string const& relativePath) const
+  cm::string_view relativePath) const
 {
-  std::string res(BaseConst().AutogenBuildDir);
-  res += '/';
-  res += relativePath;
-  return res;
+  return cmStrCat(BaseConst().AutogenBuildDir, '/', relativePath);
 }
 
 std::string cmQtAutoMocUic::AbsoluteIncludePath(
-  std::string const& relativePath) const
+  cm::string_view relativePath) const
 {
-  std::string res(BaseConst().AutogenIncludeDir);
-  res += '/';
-  res += relativePath;
-  return res;
+  return cmStrCat(BaseConst().AutogenIncludeDir, '/', relativePath);
 }
diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h
index dc18328..e4c0d66 100644
--- a/Source/cmQtAutoMocUic.h
+++ b/Source/cmQtAutoMocUic.h
@@ -9,6 +9,7 @@
 #include "cmQtAutoGen.h"
 #include "cmQtAutoGenerator.h"
 #include "cmWorkerPool.h"
+#include "cm_string_view.hxx"
 #include "cmsys/RegularExpression.hxx"
 
 #include <atomic>
@@ -333,10 +334,10 @@ public:
     UicEvalT& UicEval() const { return Gen()->UicEval(); }
 
     // -- Error logging with automatic abort
-    void LogError(GenT genType, std::string const& message) const;
-    void LogFileError(GenT genType, std::string const& filename,
-                      std::string const& message) const;
-    void LogCommandError(GenT genType, std::string const& message,
+    void LogError(GenT genType, cm::string_view message) const;
+    void LogFileError(GenT genType, cm::string_view filename,
+                      cm::string_view message) const;
+    void LogCommandError(GenT genType, cm::string_view message,
                          std::vector<std::string> const& command,
                          std::string const& output) const;
 
@@ -429,7 +430,7 @@ public:
     SourceFileHandleT MocFindIncludedHeader(
       std::string const& includerDir, std::string const& includeBase) const;
     SourceFileHandleT MocFindHeader(std::string const& basePath) const;
-    std::string MocMessageTestHeaders(std::string const& fileBase) const;
+    std::string MocMessageTestHeaders(cm::string_view fileBase) const;
     bool MocRegisterIncluded(std::string const& includeString,
                              SourceFileHandleT includerFileHandle,
                              SourceFileHandleT sourceFileHandle,
@@ -531,8 +532,8 @@ public:
   void AbortSuccess() { Abort(false); }
 
   // -- Utility
-  std::string AbsoluteBuildPath(std::string const& relativePath) const;
-  std::string AbsoluteIncludePath(std::string const& relativePath) const;
+  std::string AbsoluteBuildPath(cm::string_view relativePath) const;
+  std::string AbsoluteIncludePath(cm::string_view relativePath) const;
   template <class JOBTYPE>
   void CreateParseJobs(SourceFileMapT const& sourceMap);
 
-- 
cgit v0.12


From 32b15d320f9afd858a5966744dda5568cd396798 Mon Sep 17 00:00:00 2001
From: Sebastian Holtermann <sebholt@xwmw.org>
Date: Mon, 26 Aug 2019 18:36:18 +0200
Subject: Autogen: cmQtAutoMocUic settings hash computation optimizations

---
 Source/cmQtAutoMocUic.cxx | 24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index d4d9e56..133bae5 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -1912,22 +1912,19 @@ void cmQtAutoMocUic::SettingsFileRead()
   // Compose current settings strings
   {
     cmCryptoHash cryptoHash(cmCryptoHash::AlgoSHA256);
-    std::string const sep(";");
-    auto cha = [&cryptoHash, &sep](std::string const& value) {
+    auto cha = [&cryptoHash](cm::string_view value) {
       cryptoHash.Append(value);
-      cryptoHash.Append(sep);
+      cryptoHash.Append(";");
     };
 
     if (MocConst_.Enabled) {
       cryptoHash.Initialize();
       cha(MocConst().Executable);
-      for (auto const& value : MocConst().AllOptions) {
-        cha(value);
-      }
+      std::for_each(MocConst().AllOptions.begin(), MocConst().AllOptions.end(),
+                    cha);
       cha(BaseConst().IncludeProjectDirsBefore ? "TRUE" : "FALSE");
-      for (auto const& value : MocConst().PredefsCmd) {
-        cha(value);
-      }
+      std::for_each(MocConst().PredefsCmd.begin(), MocConst().PredefsCmd.end(),
+                    cha);
       for (auto const& filter : MocConst().DependFilters) {
         cha(filter.Key);
       }
@@ -1940,14 +1937,11 @@ void cmQtAutoMocUic::SettingsFileRead()
     if (UicConst().Enabled) {
       cryptoHash.Initialize();
       cha(UicConst().Executable);
-      for (auto const& value : UicConst().TargetOptions) {
-        cha(value);
-      }
+      std::for_each(UicConst().TargetOptions.begin(),
+                    UicConst().TargetOptions.end(), cha);
       for (const auto& item : UicConst().Options) {
         cha(item.first);
-        for (auto const& svalue : item.second) {
-          cha(svalue);
-        }
+        std::for_each(item.second.begin(), item.second.end(), cha);
       }
       SettingsStringUic_ = cryptoHash.FinalizeHex();
     }
-- 
cgit v0.12