From 2e16b58b7c72525f78b8aa1eebb7ccd9a0a24512 Mon Sep 17 00:00:00 2001 From: Alex Turbov Date: Mon, 1 Jul 2024 20:29:20 +0400 Subject: cmStringAlgorithms: Move generic strings join function to public API Move `cmJoinImpl` from `cmStringAlgorithms.cxx` to the `cmStringAlgorithms.h` as `cmJoinStrings`. Two existing overloads are not suitable for reverse iterators due to the hardcoded type of the first parameter. The signature is similar to the generic (template) `cmJoin`. With `enable_if` "magic", `cmJoinString` could be renamed to `cmJoin` in the future. Also, replace `getJoinedLength` with `std::accumulate`. --- Source/cmStringAlgorithms.cxx | 42 ++---------------------------------------- Source/cmStringAlgorithms.h | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 40 deletions(-) diff --git a/Source/cmStringAlgorithms.cxx b/Source/cmStringAlgorithms.cxx index e352d8d..332bd8d 100644 --- a/Source/cmStringAlgorithms.cxx +++ b/Source/cmStringAlgorithms.cxx @@ -7,7 +7,6 @@ #include // IWYU pragma: keep #include #include -#include std::string cmTrimWhitespace(cm::string_view str) { @@ -239,51 +238,14 @@ bool cmStrToULongLong(std::string const& str, unsigned long long* value) return cmStrToULongLong(str.c_str(), value); } -template -std::size_t getJoinedLength(Range const& rng, cm::string_view separator) -{ - std::size_t rangeLength{}; - for (auto const& item : rng) { - rangeLength += item.size(); - } - - auto const separatorsLength = (rng.size() - 1) * separator.size(); - - return rangeLength + separatorsLength; -} - -template -std::string cmJoinImpl(Range const& rng, cm::string_view separator, - cm::string_view initial) -{ - if (rng.empty()) { - return { std::begin(initial), std::end(initial) }; - } - - std::string result; - result.reserve(initial.size() + getJoinedLength(rng, separator)); - result.append(std::begin(initial), std::end(initial)); - - auto begin = std::begin(rng); - auto end = std::end(rng); - result += *begin; - - for (++begin; begin != end; ++begin) { - result.append(std::begin(separator), std::end(separator)); - result += *begin; - } - - return result; -} - std::string cmJoin(std::vector const& rng, cm::string_view separator, cm::string_view initial) { - return cmJoinImpl(rng, separator, initial); + return cmJoinStrings(rng, separator, initial); } std::string cmJoin(cmStringRange const& rng, cm::string_view separator, cm::string_view initial) { - return cmJoinImpl(rng, separator, initial); + return cmJoinStrings(rng, separator, initial); } diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h index 55a1e46..3d7f9b0 100644 --- a/Source/cmStringAlgorithms.h +++ b/Source/cmStringAlgorithms.h @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include #include @@ -77,6 +79,38 @@ std::string cmJoin(Range const& rng, cm::string_view separator) return os.str(); } +/** Generic function to join strings range with separator + * and initial leading string into a single string. + */ +template +std::string cmJoinStrings(Range const& rng, cm::string_view separator, + cm::string_view initial) +{ + if (rng.empty()) { + return { std::begin(initial), std::end(initial) }; + } + + std::string result; + result.reserve( + std::accumulate(std::begin(rng), std::end(rng), + initial.size() + (rng.size() - 1) * separator.size(), + [](std::size_t sum, const std::string& item) { + return sum + item.size(); + })); + result.append(std::begin(initial), std::end(initial)); + + auto begin = std::begin(rng); + auto end = std::end(rng); + result += *begin; + + for (++begin; begin != end; ++begin) { + result.append(std::begin(separator), std::end(separator)); + result += *begin; + } + + return result; +} + /** * Faster overloads for std::string ranges. * If @a initial is provided, it prepends the resulted string without -- cgit v0.12