summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2022-12-07 13:18:58 (GMT)
committerKitware Robot <kwrobot@kitware.com>2022-12-07 13:19:08 (GMT)
commit6bae244ad2a25a95a90dde1aa9047924b5acc530 (patch)
treec92d2962cf576ccc062b856f060ed2339c823754
parente544f2427da922bc3021b80ab2391da8ede526ec (diff)
parent1cca051470c9f7959e58f3867cb89ffcd97b73a0 (diff)
downloadCMake-6bae244ad2a25a95a90dde1aa9047924b5acc530.zip
CMake-6bae244ad2a25a95a90dde1aa9047924b5acc530.tar.gz
CMake-6bae244ad2a25a95a90dde1aa9047924b5acc530.tar.bz2
Merge topic 'cmstrcat-any-rvalue-arg'
1cca051470 cmStrCat(): allow any argument to be an rvalue string Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: buildbot <buildbot@kitware.com> Acked-by: Ben Boeckel <ben.boeckel@kitware.com> Merge-request: !7993
-rw-r--r--Source/cmStringAlgorithms.cxx40
-rw-r--r--Source/cmStringAlgorithms.h67
-rw-r--r--Tests/CMakeLib/testStringAlgorithms.cxx18
3 files changed, 75 insertions, 50 deletions
diff --git a/Source/cmStringAlgorithms.cxx b/Source/cmStringAlgorithms.cxx
index e559cfa..66bf383 100644
--- a/Source/cmStringAlgorithms.cxx
+++ b/Source/cmStringAlgorithms.cxx
@@ -203,25 +203,45 @@ cmAlphaNum::cmAlphaNum(double val)
MakeDigits(this->View_, this->Digits_, "%g", val);
}
-std::string cmCatViews(cm::optional<std::string>&& first,
- std::initializer_list<cm::string_view> views)
+std::string cmCatViews(
+ std::initializer_list<std::pair<cm::string_view, std::string*>> views)
{
std::size_t totalSize = 0;
- for (cm::string_view const& view : views) {
- totalSize += view.size();
+ std::string* rvalueString = nullptr;
+ std::size_t rvalueStringLength = 0;
+ std::size_t rvalueStringOffset = 0;
+ for (auto const& view : views) {
+ // Find the rvalue string with the largest capacity.
+ if (view.second &&
+ (!rvalueString ||
+ view.second->capacity() > rvalueString->capacity())) {
+ rvalueString = view.second;
+ rvalueStringLength = rvalueString->length();
+ rvalueStringOffset = totalSize;
+ }
+ totalSize += view.first.size();
}
std::string result;
std::string::size_type initialLen = 0;
- if (first) {
- totalSize += first->length();
- initialLen = first->length();
- result = std::move(*first);
+ if (rvalueString && rvalueString->capacity() >= totalSize) {
+ result = std::move(*rvalueString);
+ } else {
+ rvalueString = nullptr;
}
result.resize(totalSize);
+ if (rvalueString && rvalueStringOffset > 0) {
+ std::copy_backward(result.begin(), result.begin() + rvalueStringLength,
+ result.begin() + rvalueStringOffset +
+ rvalueStringLength);
+ }
std::string::iterator sit = result.begin() + initialLen;
- for (cm::string_view const& view : views) {
- sit = std::copy_n(view.data(), view.size(), sit);
+ for (auto const& view : views) {
+ if (rvalueString && view.second == rvalueString) {
+ sit += rvalueStringLength;
+ } else {
+ sit = std::copy_n(view.first.data(), view.first.size(), sit);
+ }
}
return result;
}
diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h
index bff2eda..9ea7491 100644
--- a/Source/cmStringAlgorithms.h
+++ b/Source/cmStringAlgorithms.h
@@ -12,7 +12,6 @@
#include <utility>
#include <vector>
-#include <cm/optional>
#include <cm/string_view>
#include "cmRange.h"
@@ -147,8 +146,8 @@ std::vector<std::string> cmExpandedLists(InputIt first, InputIt last)
}
/** Concatenate string pieces into a single string. */
-std::string cmCatViews(cm::optional<std::string>&& first,
- std::initializer_list<cm::string_view> views);
+std::string cmCatViews(
+ std::initializer_list<std::pair<cm::string_view, std::string*>> views);
/** Utility class for cmStrCat. */
class cmAlphaNum
@@ -162,6 +161,10 @@ public:
: View_(str)
{
}
+ cmAlphaNum(std::string&& str)
+ : RValueString_(&str)
+ {
+ }
cmAlphaNum(const char* str)
: View_(str)
{
@@ -184,45 +187,34 @@ public:
{
}
- cm::string_view View() const { return this->View_; }
+ cm::string_view View() const
+ {
+ if (this->RValueString_) {
+ return *this->RValueString_;
+ }
+ return this->View_;
+ }
+
+ std::string* RValueString() const { return this->RValueString_; }
private:
+ std::string* RValueString_ = nullptr;
cm::string_view View_;
char Digits_[32];
};
-template <typename A, typename B, typename... AV>
-class cmStrCatHelper
-{
-public:
- static std::string Compute(cmAlphaNum const& a, cmAlphaNum const& b,
- AV const&... args)
- {
- return cmCatViews(
- cm::nullopt,
- { a.View(), b.View(), static_cast<cmAlphaNum const&>(args).View()... });
- }
-};
-
-template <typename B, typename... AV>
-class cmStrCatHelper<std::string, B, AV...>
-{
-public:
- static std::string Compute(std::string&& a, cmAlphaNum const& b,
- AV const&... args)
- {
- return cmCatViews(
- std::move(a),
- { b.View(), static_cast<cmAlphaNum const&>(args).View()... });
- }
-};
-
/** Concatenate string pieces and numbers into a single string. */
template <typename A, typename B, typename... AV>
inline std::string cmStrCat(A&& a, B&& b, AV&&... args)
{
- return cmStrCatHelper<A, B, AV...>::Compute(
- std::forward<A>(a), std::forward<B>(b), std::forward<AV>(args)...);
+ static auto const makePair =
+ [](const cmAlphaNum& arg) -> std::pair<cm::string_view, std::string*> {
+ return { arg.View(), arg.RValueString() };
+ };
+
+ return cmCatViews({ makePair(std::forward<A>(a)),
+ makePair(std::forward<B>(b)),
+ makePair(std::forward<AV>(args))... });
}
/** Joins wrapped elements of a range with separator into a single string. */
@@ -233,10 +225,13 @@ std::string cmWrap(cm::string_view prefix, Range const& rng,
if (rng.empty()) {
return std::string();
}
- return cmCatViews(
- cm::nullopt,
- { prefix, cmJoin(rng, cmCatViews(cm::nullopt, { suffix, sep, prefix })),
- suffix });
+ return cmCatViews({ { prefix, nullptr },
+ { cmJoin(rng,
+ cmCatViews({ { suffix, nullptr },
+ { sep, nullptr },
+ { prefix, nullptr } })),
+ nullptr },
+ { suffix, nullptr } });
}
/** Joins wrapped elements of a range with separator into a single string. */
diff --git a/Tests/CMakeLib/testStringAlgorithms.cxx b/Tests/CMakeLib/testStringAlgorithms.cxx
index f73e62a..cb5f886 100644
--- a/Tests/CMakeLib/testStringAlgorithms.cxx
+++ b/Tests/CMakeLib/testStringAlgorithms.cxx
@@ -149,13 +149,23 @@ int testStringAlgorithms(int /*unused*/, char* /*unused*/ [])
{
std::string val;
std::string expect;
- val.reserve(120 * cmStrLen("cmStrCat move"));
+ val.reserve(50 * cmStrLen("cmStrCat move ") + 1);
auto data = val.data();
+ auto capacity = val.capacity();
+ bool moved = true;
for (int i = 0; i < 100; i++) {
- val = cmStrCat(std::move(val), "cmStrCat move");
- expect += "cmStrCat move";
+ if (i % 2 == 0) {
+ val = cmStrCat(std::move(val), "move ");
+ expect += "move ";
+ } else {
+ val = cmStrCat("cmStrCat ", std::move(val));
+ expect = "cmStrCat " + std::move(expect);
+ }
+ if (val.data() != data || val.capacity() != capacity) {
+ moved = false;
+ }
}
- assert_ok((val.data() == data), "cmStrCat move");
+ assert_ok(moved, "cmStrCat move");
assert_string(val, expect, "cmStrCat move");
}