ExpandListArguments: Optimize the parser

Optimize cmSystemTools::ExpandListArguments so as not to build a string
character-by-character. This avoids excess reallocations of the result
string.
This commit is contained in:
Ben Boeckel 2014-02-08 11:35:52 -05:00 committed by Ben Boeckel
parent c0bbefbfe7
commit 67253133f8
1 changed files with 18 additions and 33 deletions

View File

@ -1044,7 +1044,7 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
bool emptyArgs) bool emptyArgs)
{ {
// If argument is empty, it is an empty list. // If argument is empty, it is an empty list.
if(arg.length() == 0 && !emptyArgs) if(!emptyArgs && arg.empty())
{ {
return; return;
} }
@ -1054,10 +1054,11 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
newargs.push_back(arg); newargs.push_back(arg);
return; return;
} }
std::vector<char> newArgVec; std::string newArg;
const char *last = arg.c_str();
// Break the string at non-escaped semicolons not nested in []. // Break the string at non-escaped semicolons not nested in [].
int squareNesting = 0; int squareNesting = 0;
for(const char* c = arg.c_str(); *c; ++c) for(const char* c = last; *c; ++c)
{ {
switch(*c) switch(*c)
{ {
@ -1065,34 +1066,21 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
{ {
// We only want to allow escaping of semicolons. Other // We only want to allow escaping of semicolons. Other
// escapes should not be processed here. // escapes should not be processed here.
++c; const char* next = c + 1;
if(*c == ';') if(*next == ';')
{ {
newArgVec.push_back(*c); newArg.append(last, c - last);
} // Skip over the escape character
else last = c = next;
{
newArgVec.push_back('\\');
if(*c)
{
newArgVec.push_back(*c);
}
else
{
// Terminate the loop properly.
--c;
}
} }
} break; } break;
case '[': case '[':
{ {
++squareNesting; ++squareNesting;
newArgVec.push_back(*c);
} break; } break;
case ']': case ']':
{ {
--squareNesting; --squareNesting;
newArgVec.push_back(*c);
} break; } break;
case ';': case ';':
{ {
@ -1100,31 +1088,28 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
// brackets. // brackets.
if(squareNesting == 0) if(squareNesting == 0)
{ {
if ( newArgVec.size() || emptyArgs ) newArg.append(last, c - last);
// Skip over the semicolon
last = c + 1;
if ( !newArg.empty() || emptyArgs )
{ {
// Add the last argument if the string is not empty. // Add the last argument if the string is not empty.
newArgVec.push_back(0); newargs.push_back(newArg);
newargs.push_back(&*newArgVec.begin()); newArg = "";
newArgVec.clear();
} }
} }
else
{
newArgVec.push_back(*c);
}
} break; } break;
default: default:
{ {
// Just append this character. // Just append this character.
newArgVec.push_back(*c);
} break; } break;
} }
} }
if ( newArgVec.size() || emptyArgs ) newArg.append(last);
if ( !newArg.empty() || emptyArgs )
{ {
// Add the last argument if the string is not empty. // Add the last argument if the string is not empty.
newArgVec.push_back(0); newargs.push_back(newArg);
newargs.push_back(&*newArgVec.begin());
} }
} }