optimize assembly of arguments for built-in functions

this function class just joins each string list argument into a
single string. so instead of first building a list and joining it
right afterwards, create a single string in the first place.
This commit is contained in:
Oswald Buddenhagen
2010-04-27 22:00:11 +02:00
parent 25e6890c93
commit 2fd83af82f

View File

@@ -258,7 +258,7 @@ public:
static QStringList split_value_list(const QString &vals); static QStringList split_value_list(const QString &vals);
bool isActiveConfig(const QString &config, bool regex = false); bool isActiveConfig(const QString &config, bool regex = false);
QStringList expandVariableReferences(const QString &value, int *pos = 0); QStringList expandVariableReferences(const QString &value, int *pos = 0, bool joined = false);
QStringList evaluateExpandFunction(const QString &function, const QString &arguments); QStringList evaluateExpandFunction(const QString &function, const QString &arguments);
QString format(const char *format) const; QString format(const char *format) const;
void logMessage(const QString &msg) const; void logMessage(const QString &msg) const;
@@ -1268,7 +1268,7 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitProLoop(ProLoop *loop)
int index = 0; int index = 0;
QString variable; QString variable;
QStringList oldVarVal; QStringList oldVarVal;
QString it_list = expandVariableReferences(loop->expression()).join(statics.field_sep); QString it_list = expandVariableReferences(loop->expression(), 0, true).first();
if (loop->variable().isEmpty()) { if (loop->variable().isEmpty()) {
if (it_list != statics.strever) { if (it_list != statics.strever) {
logMessage(format("Invalid loop expression.")); logMessage(format("Invalid loop expression."));
@@ -1351,12 +1351,11 @@ void ProFileEvaluator::Private::visitProVariable(ProVariable *var)
{ {
m_lineNo = var->lineNumber(); m_lineNo = var->lineNumber();
const QString &varName = var->variable(); const QString &varName = var->variable();
QStringList varVal = expandVariableReferences(var->value());
if (var->variableOperator() == ProVariable::ReplaceOperator) { // ~= if (var->variableOperator() == ProVariable::ReplaceOperator) { // ~=
// DEFINES ~= s/a/b/?[gqi] // DEFINES ~= s/a/b/?[gqi]
QString val = varVal.join(statics.field_sep); QString val = expandVariableReferences(var->value(), 0, true).first();
if (val.length() < 4 || val.at(0) != QLatin1Char('s')) { if (val.length() < 4 || val.at(0) != QLatin1Char('s')) {
logMessage(format("the ~= operator can handle only the s/// function.")); logMessage(format("the ~= operator can handle only the s/// function."));
return; return;
@@ -1388,6 +1387,7 @@ void ProFileEvaluator::Private::visitProVariable(ProVariable *var)
replaceInList(&m_filevaluemap[currentProFile()][varName], regexp, replace, global); replaceInList(&m_filevaluemap[currentProFile()][varName], regexp, replace, global);
} }
} else { } else {
QStringList varVal = expandVariableReferences(var->value());
switch (var->variableOperator()) { switch (var->variableOperator()) {
default: // ReplaceOperator - cannot happen default: // ReplaceOperator - cannot happen
case ProVariable::SetOperator: // = case ProVariable::SetOperator: // =
@@ -1796,7 +1796,7 @@ static void appendString(const QString &string,
} }
static void flushCurrent(QStringList *ret, static void flushCurrent(QStringList *ret,
QString *current, QChar **ptr, QString *pending) QString *current, QChar **ptr, QString *pending, bool joined)
{ {
QChar *uc = (QChar*)current->constData(); QChar *uc = (QChar*)current->constData();
int len = *ptr - uc; int len = *ptr - uc;
@@ -1806,12 +1806,14 @@ static void flushCurrent(QStringList *ret,
} else if (!pending->isEmpty()) { } else if (!pending->isEmpty()) {
ret->append(*pending); ret->append(*pending);
pending->clear(); pending->clear();
} else if (joined) {
ret->append(QString());
} }
} }
static inline void flushFinal(QStringList *ret, static inline void flushFinal(QStringList *ret,
const QString &current, const QChar *ptr, const QString &pending, const QString &current, const QChar *ptr, const QString &pending,
const QString &str, bool replaced) const QString &str, bool replaced, bool joined)
{ {
int len = ptr - current.data(); int len = ptr - current.data();
if (len) { if (len) {
@@ -1821,10 +1823,13 @@ static inline void flushFinal(QStringList *ret,
ret->append(QString(current.data(), len)); ret->append(QString(current.data(), len));
} else if (!pending.isEmpty()) { } else if (!pending.isEmpty()) {
ret->append(pending); ret->append(pending);
} else if (joined) {
ret->append(QString());
} }
} }
QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &str, int *pos) QStringList ProFileEvaluator::Private::expandVariableReferences(
const QString &str, int *pos, bool joined)
{ {
QStringList ret; QStringList ret;
// if (ok) // if (ok)
@@ -1855,6 +1860,7 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &s
QString var, args; QString var, args;
bool replaced = false; bool replaced = false;
bool putSpace = false;
QString current; // Buffer for successively assembled string segments QString current; // Buffer for successively assembled string segments
current.resize(str.size()); current.resize(str.size());
QChar *ptr = current.data(); QChar *ptr = current.data();
@@ -1946,13 +1952,18 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &s
replacement = values(map(var)); replacement = values(map(var));
} }
if (!replacement.isEmpty()) { if (!replacement.isEmpty()) {
if (quote) { if (quote || joined) {
if (putSpace) {
putSpace = false;
if (!replacement.at(0).isEmpty()) // Bizarre, indeed
appendChar(' ', &current, &ptr, &pending);
}
appendString(replacement.join(statics.field_sep), appendString(replacement.join(statics.field_sep),
&current, &ptr, &pending); &current, &ptr, &pending);
} else { } else {
appendString(replacement.at(0), &current, &ptr, &pending); appendString(replacement.at(0), &current, &ptr, &pending);
if (replacement.size() > 1) { if (replacement.size() > 1) {
flushCurrent(&ret, &current, &ptr, &pending); flushCurrent(&ret, &current, &ptr, &pending, false);
int j = 1; int j = 1;
if (replacement.size() > 2) { if (replacement.size() > 2) {
// FIXME: ret.reserve(ret.size() + replacement.size() - 2); // FIXME: ret.reserve(ret.size() + replacement.size() - 2);
@@ -1983,7 +1994,10 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &s
quote = unicode; quote = unicode;
continue; continue;
} else if (unicode == SPACE || unicode == TAB) { } else if (unicode == SPACE || unicode == TAB) {
flushCurrent(&ret, &current, &ptr, &pending); if (!joined)
flushCurrent(&ret, &current, &ptr, &pending, false);
else if ((ptr - (QChar*)current.constData()) || !pending.isEmpty())
putSpace = true;
continue; continue;
} else if (pos) { } else if (pos) {
if (unicode == LPAREN) { if (unicode == LPAREN) {
@@ -1991,17 +2005,26 @@ QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &s
} else if (unicode == RPAREN) { } else if (unicode == RPAREN) {
--parens; --parens;
} else if (!parens && unicode == COMMA) { } else if (!parens && unicode == COMMA) {
if (!joined) {
*pos = i + 1; *pos = i + 1;
flushFinal(&ret, current, ptr, pending, str, replaced); flushFinal(&ret, current, ptr, pending, str, replaced, false);
return ret; return ret;
} }
flushCurrent(&ret, &current, &ptr, &pending, true);
putSpace = false;
continue;
} }
} }
}
if (putSpace) {
putSpace = false;
appendChar(' ', &current, &ptr, &pending);
}
appendChar(unicode, &current, &ptr, &pending); appendChar(unicode, &current, &ptr, &pending);
} }
if (pos) if (pos)
*pos = str_len; *pos = str_len;
flushFinal(&ret, current, ptr, pending, str, replaced); flushFinal(&ret, current, ptr, pending, str, replaced, joined);
return ret; return ret;
} }
@@ -2100,14 +2123,12 @@ QStringList ProFileEvaluator::Private::evaluateFunction(
QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &func, const QString &arguments) QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &func, const QString &arguments)
{ {
QList<QStringList> args_list = prepareFunctionArgs(arguments);
if (ProFunctionDef *funcPtr = m_functionDefs.replaceFunctions.value(func, 0)) if (ProFunctionDef *funcPtr = m_functionDefs.replaceFunctions.value(func, 0))
return evaluateFunction(funcPtr, args_list, 0); return evaluateFunction(funcPtr, prepareFunctionArgs(arguments), 0);
QStringList args; //why don't the builtin functions just use args_list? --Sam //why don't the builtin functions just use args_list? --Sam
foreach (const QStringList &arg, args_list) int pos = 0;
args += arg.join(statics.field_sep); QStringList args = expandVariableReferences(arguments, &pos, true);
ExpandFunc func_t = ExpandFunc(statics.expands.value(func.toLower())); ExpandFunc func_t = ExpandFunc(statics.expands.value(func.toLower()));
@@ -2469,11 +2490,9 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun
ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction( ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
const QString &function, const QString &arguments) const QString &function, const QString &arguments)
{ {
QList<QStringList> args_list = prepareFunctionArgs(arguments);
if (ProFunctionDef *funcPtr = m_functionDefs.testFunctions.value(function, 0)) { if (ProFunctionDef *funcPtr = m_functionDefs.testFunctions.value(function, 0)) {
bool ok; bool ok;
QStringList ret = evaluateFunction(funcPtr, args_list, &ok); QStringList ret = evaluateFunction(funcPtr, prepareFunctionArgs(arguments), &ok);
if (ok) { if (ok) {
if (ret.isEmpty()) { if (ret.isEmpty()) {
return ProItem::ReturnTrue; return ProItem::ReturnTrue;
@@ -2498,9 +2517,9 @@ ProItem::ProItemReturn ProFileEvaluator::Private::evaluateConditionalFunction(
return ProItem::ReturnFalse; return ProItem::ReturnFalse;
} }
QStringList args; //why don't the builtin functions just use args_list? --Sam //why don't the builtin functions just use args_list? --Sam
foreach (const QStringList &arg, args_list) int pos = 0;
args += arg.join(statics.field_sep); QStringList args = expandVariableReferences(arguments, &pos, true);
TestFunc func_t = (TestFunc)statics.functions.value(function); TestFunc func_t = (TestFunc)statics.functions.value(function);