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`.
This commit is contained in:
Alex Turbov 2024-07-01 20:29:20 +04:00 committed by Brad King
parent ce991188f3
commit 2e16b58b7c
2 changed files with 36 additions and 40 deletions

View File

@ -7,7 +7,6 @@
#include <cstddef> // IWYU pragma: keep
#include <cstdio>
#include <cstdlib>
#include <iterator>
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 <typename Range>
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 <typename Range>
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<std::string> 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);
}

View File

@ -7,6 +7,8 @@
#include <cctype>
#include <cstring>
#include <initializer_list>
#include <iterator>
#include <numeric>
#include <sstream>
#include <string>
#include <utility>
@ -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 <typename Range>
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