Commit ff42dec8 authored by Sebastian Holtermann's avatar Sebastian Holtermann

cmStringAlgorithms: Add cmExpandList functions

parent 0312b6d5
......@@ -72,6 +72,77 @@ std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep)
return tokens;
}
void cmExpandList(cm::string_view arg, std::vector<std::string>& argsOut,
bool emptyArgs)
{
// If argument is empty, it is an empty list.
if (!emptyArgs && arg.empty()) {
return;
}
// if there are no ; in the name then just copy the current string
if (arg.find(';') == cm::string_view::npos) {
argsOut.emplace_back(arg);
return;
}
std::string newArg;
// Break the string at non-escaped semicolons not nested in [].
int squareNesting = 0;
cm::string_view::iterator last = arg.begin();
cm::string_view::iterator const cend = arg.end();
for (cm::string_view::iterator c = last; c != cend; ++c) {
switch (*c) {
case '\\': {
// We only want to allow escaping of semicolons. Other
// escapes should not be processed here.
cm::string_view::iterator cnext = c + 1;
if ((cnext != cend) && *cnext == ';') {
newArg.append(last, c);
// Skip over the escape character
last = cnext;
c = cnext;
}
} break;
case '[': {
++squareNesting;
} break;
case ']': {
--squareNesting;
} break;
case ';': {
// Break the string here if we are not nested inside square
// brackets.
if (squareNesting == 0) {
newArg.append(last, c);
// Skip over the semicolon
last = c + 1;
if (!newArg.empty() || emptyArgs) {
// Add the last argument if the string is not empty.
argsOut.push_back(newArg);
Please register or sign in to reply
newArg.clear();
}
}
} break;
default: {
// Just append this character.
} break;
}
}
newArg.append(last, cend);
if (!newArg.empty() || emptyArgs) {
// Add the last argument if the string is not empty.
argsOut.push_back(std::move(newArg));
}
}
std::vector<std::string> cmExpandedList(cm::string_view arg, bool emptyArgs)
{
std::vector<std::string> argsOut;
cmExpandList(arg, argsOut, emptyArgs);
return argsOut;
}
namespace {
template <std::size_t N, typename T>
inline void MakeDigits(cm::string_view& view, char (&digits)[N],
......
......@@ -68,6 +68,48 @@ std::string cmJoin(Range const& rng, cm::string_view separator)
/** Extract tokens that are separated by any of the characters in @a sep. */
std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep);
/**
* Expand the ; separated string @a arg into multiple arguments.
* All found arguments are appended to @a argsOut.
*/
void cmExpandList(cm::string_view arg, std::vector<std::string>& argsOut,
bool emptyArgs = false);
/**
* Expand out any arguments in the string range [@a first, @a last) that have
* ; separated strings into multiple arguments. All found arguments are
* appended to @a argsOut.
*/
template <class InputIt>
void cmExpandLists(InputIt first, InputIt last,
std::vector<std::string>& argsOut)
{
for (; first != last; ++first) {
ExpandList(*first, argsOut);
}
}
/**
* Same as cmExpandList but a new vector is created containing
* the expanded arguments from the string @a arg.
*/
std::vector<std::string> cmExpandedList(cm::string_view arg,
bool emptyArgs = false);
/**
* Same as cmExpandList but a new vector is created containing the expanded
* versions of all arguments in the string range [@a first, @a last).
*/
template <class InputIt>
std::vector<std::string> cmExpandedLists(InputIt first, InputIt last)
{
std::vector<std::string> argsOut;
for (; first != last; ++first) {
cmExpandList(*first, argsOut);
}
return argsOut;
}
/** Concatenate string pieces into a single string. */
std::string cmCatViews(std::initializer_list<cm::string_view> views);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment