summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Boeckel <mathstuf@gmail.com>2014-02-08 16:35:52 (GMT)
committerBen Boeckel <ben.boeckel@kitware.com>2014-02-21 21:56:06 (GMT)
commit67253133f8ca99034a1eabe326a51c74f5e95c87 (patch)
treea9a7c66b27f8635418cc124a3c2e384cca3d2a6d
parentc0bbefbfe7209e849c04f57e79908401ba825fe0 (diff)
downloadCMake-67253133f8ca99034a1eabe326a51c74f5e95c87.zip
CMake-67253133f8ca99034a1eabe326a51c74f5e95c87.tar.gz
CMake-67253133f8ca99034a1eabe326a51c74f5e95c87.tar.bz2
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.
-rw-r--r--Source/cmSystemTools.cxx51
1 files changed, 18 insertions, 33 deletions
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index ff05975..7cc63bb 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1044,7 +1044,7 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
bool emptyArgs)
{
// If argument is empty, it is an empty list.
- if(arg.length() == 0 && !emptyArgs)
+ if(!emptyArgs && arg.empty())
{
return;
}
@@ -1054,10 +1054,11 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
newargs.push_back(arg);
return;
}
- std::vector<char> newArgVec;
+ std::string newArg;
+ const char *last = arg.c_str();
// Break the string at non-escaped semicolons not nested in [].
int squareNesting = 0;
- for(const char* c = arg.c_str(); *c; ++c)
+ for(const char* c = last; *c; ++c)
{
switch(*c)
{
@@ -1065,34 +1066,21 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
{
// We only want to allow escaping of semicolons. Other
// escapes should not be processed here.
- ++c;
- if(*c == ';')
- {
- newArgVec.push_back(*c);
- }
- else
+ const char* next = c + 1;
+ if(*next == ';')
{
- newArgVec.push_back('\\');
- if(*c)
- {
- newArgVec.push_back(*c);
- }
- else
- {
- // Terminate the loop properly.
- --c;
- }
+ newArg.append(last, c - last);
+ // Skip over the escape character
+ last = c = next;
}
} break;
case '[':
{
++squareNesting;
- newArgVec.push_back(*c);
} break;
case ']':
{
--squareNesting;
- newArgVec.push_back(*c);
} break;
case ';':
{
@@ -1100,31 +1088,28 @@ void cmSystemTools::ExpandListArgument(const std::string& arg,
// brackets.
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.
- newArgVec.push_back(0);
- newargs.push_back(&*newArgVec.begin());
- newArgVec.clear();
+ newargs.push_back(newArg);
+ newArg = "";
}
}
- else
- {
- newArgVec.push_back(*c);
- }
} break;
default:
{
// Just append this character.
- newArgVec.push_back(*c);
} break;
}
}
- if ( newArgVec.size() || emptyArgs )
+ newArg.append(last);
+ if ( !newArg.empty() || emptyArgs )
{
// Add the last argument if the string is not empty.
- newArgVec.push_back(0);
- newargs.push_back(&*newArgVec.begin());
+ newargs.push_back(newArg);
}
}