directly link ProItems instead of using QList<ProItem*>

somewhat faster again
This commit is contained in:
Oswald Buddenhagen
2010-02-03 16:50:11 +01:00
parent 9341f7da4e
commit b309f9449a
4 changed files with 57 additions and 41 deletions

View File

@@ -192,11 +192,23 @@ public:
/////////////// Reading pro file /////////////// Reading pro file
struct BlockCursor {
BlockCursor() : cursor(0) {}
BlockCursor(ProBlock *blk) : block(blk), cursor(blk->itemsRef()) {}
~BlockCursor() { if (cursor) *cursor = 0; }
void set(ProBlock *blk) { if (cursor) *cursor = 0; block = blk; cursor = blk->itemsRef(); }
void reset() { if (cursor) { *cursor = 0; cursor = 0; } }
void append(ProItem *item) { *cursor = item; cursor = item->nextRef(); }
bool isValid() const { return cursor != 0; }
ProBlock *block;
ProItem **cursor;
};
bool read(ProFile *pro); bool read(ProFile *pro);
bool read(ProBlock *pro, const QString &content); bool read(ProBlock *pro, const QString &content);
bool readInternal(ProBlock *pro, const QString &content, ushort *buf); bool readInternal(ProBlock *pro, const QString &content, ushort *buf);
ProBlock *currentBlock(); BlockCursor &currentBlock();
void updateItem(ushort *uc, ushort *ptr); void updateItem(ushort *uc, ushort *ptr);
ProVariable *startVariable(ushort *uc, ushort *ptr); ProVariable *startVariable(ushort *uc, ushort *ptr);
void finalizeVariable(ProVariable *var, ushort *uc, ushort *ptr); void finalizeVariable(ProVariable *var, ushort *uc, ushort *ptr);
@@ -205,8 +217,8 @@ public:
void leaveScope(); void leaveScope();
void finalizeBlock(); void finalizeBlock();
QStack<ProBlock *> m_blockstack; QStack<BlockCursor> m_blockstack;
ProBlock *m_block; BlockCursor m_block;
/////////////// Evaluating pro file contents /////////////// Evaluating pro file contents
@@ -355,9 +367,7 @@ bool ProFileEvaluator::Private::read(ProBlock *pro, const QString &content)
bool ProFileEvaluator::Private::readInternal(ProBlock *pro, const QString &in, ushort *buf) bool ProFileEvaluator::Private::readInternal(ProBlock *pro, const QString &in, ushort *buf)
{ {
// Parser state // Parser state
m_block = 0; m_blockstack.push(BlockCursor(pro));
m_blockstack.clear();
m_blockstack.push(pro);
// We rely on QStrings being null-terminated, so don't maintain a global end pointer. // We rely on QStrings being null-terminated, so don't maintain a global end pointer.
const ushort *cur = (const ushort *)in.unicode(); const ushort *cur = (const ushort *)in.unicode();
@@ -387,6 +397,8 @@ bool ProFileEvaluator::Private::readInternal(ProBlock *pro, const QString &in, u
++m_lineNo; ++m_lineNo;
goto freshLine; goto freshLine;
} }
m_block.reset();
m_blockstack.clear(); // FIXME: should actually check the state here
return true; return true;
} }
if (c != ' ' && c != '\t' && c != '\r') if (c != ' ' && c != '\t' && c != '\r')
@@ -560,9 +572,9 @@ bool ProFileEvaluator::Private::readInternal(ProBlock *pro, const QString &in, u
void ProFileEvaluator::Private::finalizeBlock() void ProFileEvaluator::Private::finalizeBlock()
{ {
if (m_blockstack.top()->blockKind() & ProBlock::SingleLine) if (m_blockstack.top().block->blockKind() & ProBlock::SingleLine)
leaveScope(); leaveScope();
m_block = 0; m_block.reset();
} }
ProVariable *ProFileEvaluator::Private::startVariable(ushort *uc, ushort *ptr) ProVariable *ProFileEvaluator::Private::startVariable(ushort *uc, ushort *ptr)
@@ -610,8 +622,7 @@ void ProFileEvaluator::Private::finalizeVariable(ProVariable *variable, ushort *
{ {
variable->setValue(QString((QChar*)uc, ptr - uc)); variable->setValue(QString((QChar*)uc, ptr - uc));
ProBlock *block = m_blockstack.top(); m_blockstack.top().append(variable);
block->appendItem(variable);
} }
void ProFileEvaluator::Private::insertOperator(const char op) void ProFileEvaluator::Private::insertOperator(const char op)
@@ -628,28 +639,27 @@ void ProFileEvaluator::Private::insertOperator(const char op)
opkind = ProOperator::OrOperator; opkind = ProOperator::OrOperator;
} }
ProBlock * const block = currentBlock();
ProOperator * const proOp = new ProOperator(opkind); ProOperator * const proOp = new ProOperator(opkind);
proOp->setLineNumber(m_lineNo); proOp->setLineNumber(m_lineNo);
block->appendItem(proOp); currentBlock().append(proOp);
} }
void ProFileEvaluator::Private::enterScope(bool multiLine) void ProFileEvaluator::Private::enterScope(bool multiLine)
{ {
ProBlock *parent = currentBlock(); BlockCursor &parent = currentBlock();
ProBlock *block = new ProBlock(); ProBlock *block = new ProBlock();
block->setLineNumber(m_lineNo); block->setLineNumber(m_lineNo);
parent->setBlockKind(ProBlock::ScopeKind);
parent->appendItem(block);
if (multiLine) if (multiLine)
block->setBlockKind(ProBlock::ScopeContentsKind); block->setBlockKind(ProBlock::ScopeContentsKind);
else else
block->setBlockKind(ProBlock::ScopeContentsKind|ProBlock::SingleLine); block->setBlockKind(ProBlock::ScopeContentsKind|ProBlock::SingleLine);
m_blockstack.push(BlockCursor(block));
m_blockstack.push(block); parent.block->setBlockKind(ProBlock::ScopeKind);
m_block = 0; parent.append(block);
m_block.reset();
} }
void ProFileEvaluator::Private::leaveScope() void ProFileEvaluator::Private::leaveScope()
@@ -661,16 +671,14 @@ void ProFileEvaluator::Private::leaveScope()
finalizeBlock(); finalizeBlock();
} }
ProBlock *ProFileEvaluator::Private::currentBlock() ProFileEvaluator::Private::BlockCursor &ProFileEvaluator::Private::currentBlock()
{ {
if (m_block) if (!m_block.isValid()) {
return m_block; ProBlock *blk = new ProBlock();
blk->setLineNumber(m_lineNo);
ProBlock *parent = m_blockstack.top(); m_blockstack.top().append(blk);
m_block = new ProBlock(); m_block.set(blk);
m_block->setLineNumber(m_lineNo); }
parent->appendItem(m_block);
return m_block; return m_block;
} }
@@ -681,7 +689,6 @@ void ProFileEvaluator::Private::updateItem(ushort *uc, ushort *ptr)
QString proItem = QString((QChar*)uc, ptr - uc); QString proItem = QString((QChar*)uc, ptr - uc);
ProBlock *block = currentBlock();
ProItem *item; ProItem *item;
if (proItem.endsWith(QLatin1Char(')'))) { if (proItem.endsWith(QLatin1Char(')'))) {
item = new ProFunction(proItem); item = new ProFunction(proItem);
@@ -689,7 +696,7 @@ void ProFileEvaluator::Private::updateItem(ushort *uc, ushort *ptr)
item = new ProCondition(proItem); item = new ProCondition(proItem);
} }
item->setLineNumber(m_lineNo); item->setLineNumber(m_lineNo);
block->appendItem(item); currentBlock().append(item);
} }
//////// Evaluator tools ///////// //////// Evaluator tools /////////
@@ -866,15 +873,14 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitProBlock(ProBlock *block)
} }
} }
ProItem::ProItemReturn rt = ProItem::ReturnTrue; ProItem::ProItemReturn rt = ProItem::ReturnTrue;
QList<ProItem *> items = block->items(); for (ProItem *item = block->items(); item; item = item->next()) {
for (int i = 0; i < items.count(); ++i) { rt = visitProItem(item);
rt = visitProItem(items.at(i));
if (rt != ProItem::ReturnTrue && rt != ProItem::ReturnFalse) { if (rt != ProItem::ReturnTrue && rt != ProItem::ReturnFalse) {
if (rt == ProItem::ReturnLoop) { if (rt == ProItem::ReturnLoop) {
rt = ProItem::ReturnTrue; rt = ProItem::ReturnTrue;
while (visitProLoopIteration()) while (visitProLoopIteration())
for (int j = i; ++j < items.count(); ) { for (ProItem *lItem = item; (lItem = lItem->next()); ) {
rt = visitProItem(items.at(j)); rt = visitProItem(lItem);
if (rt != ProItem::ReturnTrue && rt != ProItem::ReturnFalse) { if (rt != ProItem::ReturnTrue && rt != ProItem::ReturnFalse) {
if (rt == ProItem::ReturnNext) { if (rt == ProItem::ReturnNext) {
rt = ProItem::ReturnTrue; rt = ProItem::ReturnTrue;

View File

@@ -36,17 +36,20 @@ QT_BEGIN_NAMESPACE
ProBlock::ProBlock() ProBlock::ProBlock()
: ProItem(BlockKind) : ProItem(BlockKind)
{ {
m_proitems = 0;
m_blockKind = 0; m_blockKind = 0;
m_refCount = 1; m_refCount = 1;
} }
ProBlock::~ProBlock() ProBlock::~ProBlock()
{ {
foreach (ProItem *itm, m_proitems) for (ProItem *itm, *nitm = m_proitems; (itm = nitm); ) {
nitm = itm->m_next;
if (itm->kind() == BlockKind) if (itm->kind() == BlockKind)
static_cast<ProBlock *>(itm)->deref(); static_cast<ProBlock *>(itm)->deref();
else else
delete itm; delete itm;
}
} }
ProFile::ProFile(const QString &fileName) ProFile::ProFile(const QString &fileName)

View File

@@ -63,9 +63,15 @@ public:
int lineNumber() const { return m_lineNumber; } int lineNumber() const { return m_lineNumber; }
void setLineNumber(int lineNumber) { m_lineNumber = lineNumber; } void setLineNumber(int lineNumber) { m_lineNumber = lineNumber; }
ProItem *next() const { return m_next; }
ProItem **nextRef() { return &m_next; }
private: private:
ProItem *m_next;
ProItemKind m_kind; ProItemKind m_kind;
int m_lineNumber; int m_lineNumber;
friend class ProBlock; // C++ is braindead ...
}; };
class ProBlock : public ProItem class ProBlock : public ProItem
@@ -83,16 +89,17 @@ public:
ProBlock(); ProBlock();
~ProBlock(); ~ProBlock();
void appendItem(ProItem *proitem) { m_proitems << proitem; }
QList<ProItem *> items() const { return m_proitems; }
void setBlockKind(int blockKind) { m_blockKind = blockKind; } void setBlockKind(int blockKind) { m_blockKind = blockKind; }
int blockKind() const { return m_blockKind; } int blockKind() const { return m_blockKind; }
ProItem *items() const { return m_proitems; }
ProItem **itemsRef() { return &m_proitems; }
void ref() { ++m_refCount; } void ref() { ++m_refCount; }
void deref() { if (!--m_refCount) delete this; } void deref() { if (!--m_refCount) delete this; }
private: private:
QList<ProItem *> m_proitems; ProItem *m_proitems;
int m_blockKind; int m_blockKind;
int m_refCount; int m_refCount;
}; };

View File

@@ -40,7 +40,7 @@ void ProWriter::addFiles(ProFile *profile, QStringList *lines,
const QStringList &vars) const QStringList &vars)
{ {
// Check if variable item exists as child of root item // Check if variable item exists as child of root item
foreach (ProItem *item, profile->items()) { for (ProItem *item = profile->items(); item; item = item->next()) {
if (item->kind() == ProItem::VariableKind) { if (item->kind() == ProItem::VariableKind) {
ProVariable *proVar = static_cast<ProVariable*>(item); ProVariable *proVar = static_cast<ProVariable*>(item);
if (vars.contains(proVar->variable()) if (vars.contains(proVar->variable())
@@ -87,7 +87,7 @@ void ProWriter::addFiles(ProFile *profile, QStringList *lines,
static void findProVariables(ProBlock *block, const QStringList &vars, static void findProVariables(ProBlock *block, const QStringList &vars,
QList<ProVariable *> *proVars) QList<ProVariable *> *proVars)
{ {
foreach (ProItem *item, block->items()) { for (ProItem *item = block->items(); item; item = item->next()) {
if (item->kind() == ProItem::BlockKind) { if (item->kind() == ProItem::BlockKind) {
findProVariables(static_cast<ProBlock*>(item), vars, proVars); findProVariables(static_cast<ProBlock*>(item), vars, proVars);
} else if (item->kind() == ProItem::VariableKind) { } else if (item->kind() == ProItem::VariableKind) {