forked from qt-creator/qt-creator
optimize low-level pro reader code
avoid qstring functions. instead, use preallocated strings and pointers. now the majority of the parsing time is spent in qt (qfile and qtextcodec).
This commit is contained in:
@@ -140,7 +140,7 @@ public:
|
|||||||
ProBlock *currentBlock();
|
ProBlock *currentBlock();
|
||||||
void updateItem();
|
void updateItem();
|
||||||
bool parseLine(const QString &line);
|
bool parseLine(const QString &line);
|
||||||
void insertVariable(const QString &line, int *i);
|
void insertVariable(const ushort **pCur, const ushort *end);
|
||||||
void insertOperator(const char op);
|
void insertOperator(const char op);
|
||||||
void insertComment(const QString &comment);
|
void insertComment(const QString &comment);
|
||||||
void enterScope(bool multiLine);
|
void enterScope(bool multiLine);
|
||||||
@@ -153,11 +153,14 @@ public:
|
|||||||
ProItem *m_commentItem;
|
ProItem *m_commentItem;
|
||||||
QString m_proitem;
|
QString m_proitem;
|
||||||
QString m_pendingComment;
|
QString m_pendingComment;
|
||||||
|
ushort *m_proitemPtr;
|
||||||
bool m_syntaxError;
|
bool m_syntaxError;
|
||||||
bool m_contNextLine;
|
bool m_contNextLine;
|
||||||
bool m_inQuote;
|
bool m_inQuote;
|
||||||
int m_parens;
|
int m_parens;
|
||||||
|
|
||||||
|
enum StrState { NotStarted, Started, PutSpace };
|
||||||
|
|
||||||
/////////////// Evaluating pro file contents
|
/////////////// Evaluating pro file contents
|
||||||
|
|
||||||
// implementation of AbstractProItemVisitor
|
// implementation of AbstractProItemVisitor
|
||||||
@@ -304,32 +307,36 @@ bool ProFileEvaluator::Private::read(ProFile *pro, QTextStream *ts)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProFileEvaluator::Private::parseLine(const QString &line0)
|
bool ProFileEvaluator::Private::parseLine(const QString &line)
|
||||||
{
|
{
|
||||||
if (m_blockstack.isEmpty())
|
if (m_blockstack.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
const ushort *cur = (const ushort *)line.unicode(),
|
||||||
|
*end = cur + line.length();
|
||||||
int parens = m_parens;
|
int parens = m_parens;
|
||||||
bool inQuote = m_inQuote;
|
bool inQuote = m_inQuote;
|
||||||
bool escaped = false;
|
bool escaped = false;
|
||||||
QString line = line0.simplified();
|
|
||||||
|
|
||||||
for (int i = 0; !m_syntaxError && i < line.length(); ++i) {
|
m_proitem.reserve(line.length());
|
||||||
ushort c = line.at(i).unicode();
|
m_proitemPtr = (ushort *)m_proitem.unicode();
|
||||||
|
nextItem:
|
||||||
|
ushort *ptr = m_proitemPtr;
|
||||||
|
StrState sts = NotStarted;
|
||||||
|
while (cur < end) {
|
||||||
|
ushort c = *cur++;
|
||||||
if (c == '#') { // Yep - no escaping possible
|
if (c == '#') { // Yep - no escaping possible
|
||||||
insertComment(line.mid(i + 1));
|
m_proitemPtr = ptr;
|
||||||
escaped = m_contNextLine;
|
insertComment(line.right(end - cur).simplified());
|
||||||
break;
|
goto done;
|
||||||
}
|
}
|
||||||
if (!escaped) {
|
if (!escaped) {
|
||||||
if (c == '\\') {
|
if (c == '\\') {
|
||||||
escaped = true;
|
escaped = true;
|
||||||
m_proitem += c;
|
goto putch;
|
||||||
continue;
|
|
||||||
} else if (c == '"') {
|
} else if (c == '"') {
|
||||||
inQuote = !inQuote;
|
inQuote = !inQuote;
|
||||||
m_proitem += c;
|
goto putch;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
escaped = false;
|
escaped = false;
|
||||||
@@ -341,52 +348,70 @@ bool ProFileEvaluator::Private::parseLine(const QString &line0)
|
|||||||
--parens;
|
--parens;
|
||||||
} else if (!parens) {
|
} else if (!parens) {
|
||||||
if (m_block && (m_block->blockKind() & ProBlock::VariableKind)) {
|
if (m_block && (m_block->blockKind() & ProBlock::VariableKind)) {
|
||||||
if (c == ' ')
|
if (c == ' ' || c == '\t') {
|
||||||
|
m_proitemPtr = ptr;
|
||||||
updateItem();
|
updateItem();
|
||||||
else
|
goto nextItem;
|
||||||
m_proitem += c;
|
}
|
||||||
continue;
|
} else {
|
||||||
}
|
if (c == ':') {
|
||||||
if (c == ':') {
|
m_proitemPtr = ptr;
|
||||||
enterScope(false);
|
enterScope(false);
|
||||||
continue;
|
goto nextItem;
|
||||||
}
|
}
|
||||||
if (c == '{') {
|
if (c == '{') {
|
||||||
enterScope(true);
|
m_proitemPtr = ptr;
|
||||||
continue;
|
enterScope(true);
|
||||||
}
|
goto nextItem;
|
||||||
if (c == '}') {
|
}
|
||||||
leaveScope();
|
if (c == '}') {
|
||||||
continue;
|
m_proitemPtr = ptr;
|
||||||
}
|
leaveScope();
|
||||||
if (c == '=') {
|
if (m_syntaxError)
|
||||||
insertVariable(line, &i);
|
goto done1;
|
||||||
continue;
|
goto nextItem;
|
||||||
}
|
}
|
||||||
if (c == '|' || c == '!') {
|
if (c == '=') {
|
||||||
insertOperator(c);
|
m_proitemPtr = ptr;
|
||||||
continue;
|
insertVariable(&cur, end);
|
||||||
|
goto nextItem;
|
||||||
|
}
|
||||||
|
if (c == '|' || c == '!') {
|
||||||
|
m_proitemPtr = ptr;
|
||||||
|
insertOperator(c);
|
||||||
|
goto nextItem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_proitem += c;
|
if (c == ' ' || c == '\t') {
|
||||||
|
if (sts == Started)
|
||||||
|
sts = PutSpace;
|
||||||
|
} else {
|
||||||
|
putch:
|
||||||
|
if (sts == PutSpace)
|
||||||
|
*ptr++ = ' ';
|
||||||
|
*ptr++ = c;
|
||||||
|
sts = Started;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
m_proitemPtr = ptr;
|
||||||
|
done1:
|
||||||
|
m_contNextLine = escaped;
|
||||||
|
done:
|
||||||
m_inQuote = inQuote;
|
m_inQuote = inQuote;
|
||||||
m_parens = parens;
|
m_parens = parens;
|
||||||
m_contNextLine = escaped;
|
if (m_syntaxError)
|
||||||
if (escaped) {
|
|
||||||
m_proitem.chop(1);
|
|
||||||
updateItem();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
if (!m_syntaxError) {
|
|
||||||
updateItem();
|
|
||||||
finalizeBlock();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
|
if (escaped) {
|
||||||
|
--m_proitemPtr;
|
||||||
|
updateItem();
|
||||||
|
} else {
|
||||||
|
updateItem();
|
||||||
|
finalizeBlock();
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProFileEvaluator::Private::finalizeBlock()
|
void ProFileEvaluator::Private::finalizeBlock()
|
||||||
@@ -401,37 +426,44 @@ void ProFileEvaluator::Private::finalizeBlock()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProFileEvaluator::Private::insertVariable(const QString &line, int *i)
|
void ProFileEvaluator::Private::insertVariable(const ushort **pCur, const ushort *end)
|
||||||
{
|
{
|
||||||
ProVariable::VariableOperator opkind;
|
ProVariable::VariableOperator opkind;
|
||||||
|
ushort *uc = (ushort *)m_proitem.unicode();
|
||||||
|
ushort *ptr = m_proitemPtr;
|
||||||
|
|
||||||
if (m_proitem.isEmpty()) // Line starting with '=', like a conflict marker
|
if (ptr == uc) // Line starting with '=', like a conflict marker
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (m_proitem.at(m_proitem.length() - 1).unicode()) {
|
switch (*(ptr - 1)) {
|
||||||
case '+':
|
case '+':
|
||||||
m_proitem.chop(1);
|
--ptr;
|
||||||
opkind = ProVariable::AddOperator;
|
opkind = ProVariable::AddOperator;
|
||||||
break;
|
break;
|
||||||
case '-':
|
case '-':
|
||||||
m_proitem.chop(1);
|
--ptr;
|
||||||
opkind = ProVariable::RemoveOperator;
|
opkind = ProVariable::RemoveOperator;
|
||||||
break;
|
break;
|
||||||
case '*':
|
case '*':
|
||||||
m_proitem.chop(1);
|
--ptr;
|
||||||
opkind = ProVariable::UniqueAddOperator;
|
opkind = ProVariable::UniqueAddOperator;
|
||||||
break;
|
break;
|
||||||
case '~':
|
case '~':
|
||||||
m_proitem.chop(1);
|
--ptr;
|
||||||
opkind = ProVariable::ReplaceOperator;
|
opkind = ProVariable::ReplaceOperator;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
opkind = ProVariable::SetOperator;
|
opkind = ProVariable::SetOperator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (ptr != uc && *(ptr - 1) == ' ')
|
||||||
|
--ptr;
|
||||||
|
m_proitem.resize(ptr - uc);
|
||||||
|
QString proVar = m_proitem;
|
||||||
|
proVar.detach();
|
||||||
|
|
||||||
ProBlock *block = m_blockstack.top();
|
ProBlock *block = m_blockstack.top();
|
||||||
m_proitem = m_proitem.trimmed();
|
ProVariable *variable = new ProVariable(proVar, block);
|
||||||
ProVariable *variable = new ProVariable(m_proitem, block);
|
|
||||||
variable->setLineNumber(m_lineNo);
|
variable->setLineNumber(m_lineNo);
|
||||||
variable->setVariableOperator(opkind);
|
variable->setVariableOperator(opkind);
|
||||||
block->appendItem(variable);
|
block->appendItem(variable);
|
||||||
@@ -443,26 +475,31 @@ void ProFileEvaluator::Private::insertVariable(const QString &line, int *i)
|
|||||||
}
|
}
|
||||||
m_commentItem = variable;
|
m_commentItem = variable;
|
||||||
|
|
||||||
m_proitem.clear();
|
|
||||||
|
|
||||||
if (opkind == ProVariable::ReplaceOperator) {
|
if (opkind == ProVariable::ReplaceOperator) {
|
||||||
// skip util end of line or comment
|
// skip util end of line or comment
|
||||||
while (1) {
|
StrState sts = NotStarted;
|
||||||
++(*i);
|
ptr = uc;
|
||||||
|
const ushort *cur = *pCur;
|
||||||
// end of line?
|
while (cur < end) {
|
||||||
if (*i >= line.count())
|
ushort c = *cur;
|
||||||
|
if (c == '#') // comment?
|
||||||
break;
|
break;
|
||||||
|
++cur;
|
||||||
|
|
||||||
// comment?
|
if (c == ' ' || c == '\t') {
|
||||||
if (line.at(*i).unicode() == '#') {
|
if (sts == Started)
|
||||||
--(*i);
|
sts = PutSpace;
|
||||||
break;
|
} else {
|
||||||
|
if (sts == PutSpace)
|
||||||
|
*ptr++ = ' ';
|
||||||
|
*ptr++ = c;
|
||||||
|
sts = Started;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_proitem += line.at(*i);
|
|
||||||
}
|
}
|
||||||
m_proitem = m_proitem.trimmed();
|
*pCur = cur;
|
||||||
|
m_proitemPtr = ptr;
|
||||||
|
} else {
|
||||||
|
m_proitemPtr = uc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,22 +600,27 @@ ProBlock *ProFileEvaluator::Private::currentBlock()
|
|||||||
|
|
||||||
void ProFileEvaluator::Private::updateItem()
|
void ProFileEvaluator::Private::updateItem()
|
||||||
{
|
{
|
||||||
m_proitem = m_proitem.trimmed();
|
ushort *uc = (ushort *)m_proitem.unicode();
|
||||||
if (m_proitem.isEmpty())
|
ushort *ptr = m_proitemPtr;
|
||||||
|
|
||||||
|
if (ptr == uc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
m_proitem.resize(ptr - uc);
|
||||||
|
m_proitemPtr = uc;
|
||||||
|
QString proItem = m_proitem;
|
||||||
|
proItem.detach();
|
||||||
|
|
||||||
ProBlock *block = currentBlock();
|
ProBlock *block = currentBlock();
|
||||||
if (block->blockKind() & ProBlock::VariableKind) {
|
if (block->blockKind() & ProBlock::VariableKind) {
|
||||||
m_commentItem = new ProValue(m_proitem, static_cast<ProVariable*>(block));
|
m_commentItem = new ProValue(proItem, static_cast<ProVariable*>(block));
|
||||||
} else if (m_proitem.endsWith(QLatin1Char(')'))) {
|
} else if (proItem.endsWith(QLatin1Char(')'))) {
|
||||||
m_commentItem = new ProFunction(m_proitem);
|
m_commentItem = new ProFunction(proItem);
|
||||||
} else {
|
} else {
|
||||||
m_commentItem = new ProCondition(m_proitem);
|
m_commentItem = new ProCondition(proItem);
|
||||||
}
|
}
|
||||||
m_commentItem->setLineNumber(m_lineNo);
|
m_commentItem->setLineNumber(m_lineNo);
|
||||||
block->appendItem(m_commentItem);
|
block->appendItem(m_commentItem);
|
||||||
|
|
||||||
m_proitem.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user