diff options
author | Kyle Edwards <kyle.edwards@kitware.com> | 2022-12-06 16:05:57 (GMT) |
---|---|---|
committer | Kyle Edwards <kyle.edwards@kitware.com> | 2022-12-06 18:54:42 (GMT) |
commit | 1cca051470c9f7959e58f3867cb89ffcd97b73a0 (patch) | |
tree | 4b497e0be229a3c948e6a3275cd1246573f1b36d /Source/cmStringAlgorithms.cxx | |
parent | aeac9b4660762e0067c7fc0a8763e381b76710b3 (diff) | |
download | CMake-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.cxx | 40 |
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; } |