summaryrefslogtreecommitdiffstats
path: root/Source/cmStringAlgorithms.cxx
diff options
context:
space:
mode:
authorKyle Edwards <kyle.edwards@kitware.com>2022-12-06 16:05:57 (GMT)
committerKyle Edwards <kyle.edwards@kitware.com>2022-12-06 18:54:42 (GMT)
commit1cca051470c9f7959e58f3867cb89ffcd97b73a0 (patch)
tree4b497e0be229a3c948e6a3275cd1246573f1b36d /Source/cmStringAlgorithms.cxx
parentaeac9b4660762e0067c7fc0a8763e381b76710b3 (diff)
downloadCMake-1cca051470c9f7959e58f3867cb89ffcd97b73a0.zip
CMake-1cca051470c9f7959e58f3867cb89ffcd97b73a0.tar.gz
CMake-1cca051470c9f7959e58f3867cb89ffcd97b73a0.tar.bz2
cmStrCat(): allow any argument to be an rvalue string
This will allow us to re-use any rvalue allocation that is available, not just from the first argument.
Diffstat (limited to 'Source/cmStringAlgorithms.cxx')
-rw-r--r--Source/cmStringAlgorithms.cxx40
1 files changed, 30 insertions, 10 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;
}