summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Chevrier <marc.chevrier@gmail.com>2023-08-03 17:02:25 (GMT)
committerMarc Chevrier <marc.chevrier@gmail.com>2023-08-04 07:52:08 (GMT)
commit7f9f96151ab4b17598c2f449d887dbe2a123a54a (patch)
tree05eff7315f9e1212ad6f01f62b03ee1754eec31b
parent6e4822a035d1af77b9a86e36cdd213c3d2fce54c (diff)
downloadCMake-7f9f96151ab4b17598c2f449d887dbe2a123a54a.zip
CMake-7f9f96151ab4b17598c2f449d887dbe2a123a54a.tar.gz
CMake-7f9f96151ab4b17598c2f449d887dbe2a123a54a.tar.bz2
cmList: Fix performance regression in append/prepend
Fixes: #25147
-rw-r--r--Source/cmList.cxx21
-rw-r--r--Source/cmList.h57
-rw-r--r--Tests/CMakeLib/testList.cxx8
3 files changed, 57 insertions, 29 deletions
diff --git a/Source/cmList.cxx b/Source/cmList.cxx
index 022fcd2..28d4791 100644
--- a/Source/cmList.cxx
+++ b/Source/cmList.cxx
@@ -802,32 +802,35 @@ cmList& cmList::transform(TransformAction action,
return *this;
}
-std::string cmList::join(cm::string_view glue) const
-{
- return cmJoin(this->Values, glue);
-}
-
-std::string& cmList::append(std::string& list, cm::string_view value)
+std::string& cmList::append(std::string& list, std::string&& value)
{
if (list.empty()) {
- list = std::string(value);
+ list = std::move(value);
} else {
list += cmStrCat(cmList::element_separator, value);
}
return list;
}
+std::string& cmList::append(std::string& list, cm::string_view value)
+{
+ return cmList::append(list, std::string{ value });
+}
-std::string& cmList::prepend(std::string& list, cm::string_view value)
+std::string& cmList::prepend(std::string& list, std::string&& value)
{
if (list.empty()) {
- list = std::string(value);
+ list = std::move(value);
} else {
list.insert(0, cmStrCat(value, cmList::element_separator));
}
return list;
}
+std::string& cmList::prepend(std::string& list, cm::string_view value)
+{
+ return cmList::prepend(list, std::string{ value });
+}
cmList::size_type cmList::ComputeIndex(index_type pos, bool boundCheck) const
{
diff --git a/Source/cmList.h b/Source/cmList.h
index eba0400..798b984 100644
--- a/Source/cmList.h
+++ b/Source/cmList.h
@@ -10,7 +10,6 @@
#include <initializer_list>
#include <iterator>
#include <memory>
-#include <numeric>
#include <stdexcept>
#include <string>
#include <utility>
@@ -936,7 +935,10 @@ public:
std::vector<std::string> const& args,
std::unique_ptr<TransformSelector> = {});
- std::string join(cm::string_view glue) const;
+ std::string join(cm::string_view glue) const
+ {
+ return cmList::Join(this->Values, glue);
+ }
void swap(cmList& other) noexcept { this->Values.swap(other.Values); }
@@ -1080,6 +1082,7 @@ public:
// but without any intermediate expansion. So the operation is simply a
// string concatenation with special handling for the CMake list item
// separator
+ static std::string& append(std::string& list, std::string&& value);
static std::string& append(std::string& list, cm::string_view value);
template <typename InputIterator>
static std::string& append(std::string& list, InputIterator first,
@@ -1089,15 +1092,11 @@ public:
return list;
}
- return cmList::append(list,
- cm::string_view{ std::accumulate(
- std::next(first), last, *first,
- [](std::string a, const std::string& b) {
- return std::move(a) +
- std::string(cmList::element_separator) + b;
- }) });
+ return cmList::append(
+ list, cmList::Join(first, last, cmList::element_separator));
}
+ static std::string& prepend(std::string& list, std::string&& value);
static std::string& prepend(std::string& list, cm::string_view value);
template <typename InputIterator>
static std::string& prepend(std::string& list, InputIterator first,
@@ -1107,13 +1106,8 @@ public:
return list;
}
- return cmList::prepend(list,
- cm::string_view{ std::accumulate(
- std::next(first), last, *first,
- [](std::string a, const std::string& b) {
- return std::move(a) +
- std::string(cmList::element_separator) + b;
- }) });
+ return cmList::prepend(
+ list, cmList::Join(first, last, cmList::element_separator));
}
// Non-members
@@ -1185,6 +1179,37 @@ private:
return container.begin() + delta;
}
+ static std::string const& ToString(std::string const& s) { return s; }
+ static std::string ToString(cm::string_view s) { return std::string{ s }; }
+
+ template <typename Range>
+ static std::string Join(Range const& r, cm::string_view glue)
+ {
+ if (cm::size(r) == 0) {
+ return std::string{};
+ }
+
+ return cmList::Join(std::begin(r), std::end(r), glue);
+ }
+ template <typename InputIterator>
+ static std::string Join(InputIterator first, InputIterator last,
+ cm::string_view glue)
+ {
+ if (first == last) {
+ return std::string{};
+ }
+
+ const auto sep = std::string{ glue };
+
+ std::string joined = cmList::ToString(*first);
+ for (auto it = std::next(first); it != last; ++it) {
+ joined += sep;
+ joined += cmList::ToString(*it);
+ }
+
+ return joined;
+ }
+
container_type Values;
};
diff --git a/Tests/CMakeLib/testList.cxx b/Tests/CMakeLib/testList.cxx
index f6ec720..6d6c218 100644
--- a/Tests/CMakeLib/testList.cxx
+++ b/Tests/CMakeLib/testList.cxx
@@ -859,7 +859,7 @@ bool testStaticModifiers()
}
{
std::string list{ "a;b;c" };
- cmList::append(list, "");
+ cmList::append(list, ""_s);
if (list != "a;b;c;") {
result = false;
@@ -894,7 +894,7 @@ bool testStaticModifiers()
}
{
std::string list{ "a;b;c" };
- cmList::prepend(list, "d;e");
+ cmList::prepend(list, "d;e"_s);
if (list != "d;e;a;b;c") {
result = false;
@@ -902,7 +902,7 @@ bool testStaticModifiers()
}
{
std::string list;
- cmList::prepend(list, "d;e");
+ cmList::prepend(list, "d;e"_s);
if (list != "d;e") {
result = false;
@@ -910,7 +910,7 @@ bool testStaticModifiers()
}
{
std::string list{ "a;b;c" };
- cmList::prepend(list, "");
+ cmList::prepend(list, ""_s);
if (list != ";a;b;c") {
result = false;