From b309f9449a03319cdf9208a89f7d37ea26e227a5 Mon Sep 17 00:00:00 2001
From: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
Date: Wed, 3 Feb 2010 16:50:11 +0100
Subject: [PATCH] directly link ProItems instead of using QList<ProItem*>

somewhat faster again
---
 src/shared/proparser/profileevaluator.cpp | 76 ++++++++++++-----------
 src/shared/proparser/proitems.cpp         |  5 +-
 src/shared/proparser/proitems.h           | 13 +++-
 src/shared/proparser/prowriter.cpp        |  4 +-
 4 files changed, 57 insertions(+), 41 deletions(-)

diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp
index 75a8d8ccf1e..71101e41b92 100644
--- a/src/shared/proparser/profileevaluator.cpp
+++ b/src/shared/proparser/profileevaluator.cpp
@@ -192,11 +192,23 @@ public:
 
     /////////////// 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(ProBlock *pro, const QString &content);
     bool readInternal(ProBlock *pro, const QString &content, ushort *buf);
 
-    ProBlock *currentBlock();
+    BlockCursor &currentBlock();
     void updateItem(ushort *uc, ushort *ptr);
     ProVariable *startVariable(ushort *uc, ushort *ptr);
     void finalizeVariable(ProVariable *var, ushort *uc, ushort *ptr);
@@ -205,8 +217,8 @@ public:
     void leaveScope();
     void finalizeBlock();
 
-    QStack<ProBlock *> m_blockstack;
-    ProBlock *m_block;
+    QStack<BlockCursor> m_blockstack;
+    BlockCursor m_block;
 
     /////////////// 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)
 {
     // Parser state
-    m_block = 0;
-    m_blockstack.clear();
-    m_blockstack.push(pro);
+    m_blockstack.push(BlockCursor(pro));
 
     // We rely on QStrings being null-terminated, so don't maintain a global end pointer.
     const ushort *cur = (const ushort *)in.unicode();
@@ -387,6 +397,8 @@ bool ProFileEvaluator::Private::readInternal(ProBlock *pro, const QString &in, u
                     ++m_lineNo;
                     goto freshLine;
                 }
+                m_block.reset();
+                m_blockstack.clear(); // FIXME: should actually check the state here
                 return true;
             }
             if (c != ' ' && c != '\t' && c != '\r')
@@ -560,9 +572,9 @@ bool ProFileEvaluator::Private::readInternal(ProBlock *pro, const QString &in, u
 
 void ProFileEvaluator::Private::finalizeBlock()
 {
-    if (m_blockstack.top()->blockKind() & ProBlock::SingleLine)
+    if (m_blockstack.top().block->blockKind() & ProBlock::SingleLine)
         leaveScope();
-    m_block = 0;
+    m_block.reset();
 }
 
 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));
 
-    ProBlock *block = m_blockstack.top();
-    block->appendItem(variable);
+    m_blockstack.top().append(variable);
 }
 
 void ProFileEvaluator::Private::insertOperator(const char op)
@@ -628,28 +639,27 @@ void ProFileEvaluator::Private::insertOperator(const char op)
             opkind = ProOperator::OrOperator;
     }
 
-    ProBlock * const block = currentBlock();
     ProOperator * const proOp = new ProOperator(opkind);
     proOp->setLineNumber(m_lineNo);
-    block->appendItem(proOp);
+    currentBlock().append(proOp);
 }
 
 void ProFileEvaluator::Private::enterScope(bool multiLine)
 {
-    ProBlock *parent = currentBlock();
+    BlockCursor &parent = currentBlock();
+
     ProBlock *block = new ProBlock();
     block->setLineNumber(m_lineNo);
-    parent->setBlockKind(ProBlock::ScopeKind);
-
-    parent->appendItem(block);
-
     if (multiLine)
         block->setBlockKind(ProBlock::ScopeContentsKind);
     else
         block->setBlockKind(ProBlock::ScopeContentsKind|ProBlock::SingleLine);
+    m_blockstack.push(BlockCursor(block));
 
-    m_blockstack.push(block);
-    m_block = 0;
+    parent.block->setBlockKind(ProBlock::ScopeKind);
+    parent.append(block);
+
+    m_block.reset();
 }
 
 void ProFileEvaluator::Private::leaveScope()
@@ -661,16 +671,14 @@ void ProFileEvaluator::Private::leaveScope()
     finalizeBlock();
 }
 
-ProBlock *ProFileEvaluator::Private::currentBlock()
+ProFileEvaluator::Private::BlockCursor &ProFileEvaluator::Private::currentBlock()
 {
-    if (m_block)
-        return m_block;
-
-    ProBlock *parent = m_blockstack.top();
-    m_block = new ProBlock();
-    m_block->setLineNumber(m_lineNo);
-    parent->appendItem(m_block);
-
+    if (!m_block.isValid()) {
+        ProBlock *blk = new ProBlock();
+        blk->setLineNumber(m_lineNo);
+        m_blockstack.top().append(blk);
+        m_block.set(blk);
+    }
     return m_block;
 }
 
@@ -681,7 +689,6 @@ void ProFileEvaluator::Private::updateItem(ushort *uc, ushort *ptr)
 
     QString proItem = QString((QChar*)uc, ptr - uc);
 
-    ProBlock *block = currentBlock();
     ProItem *item;
     if (proItem.endsWith(QLatin1Char(')'))) {
         item = new ProFunction(proItem);
@@ -689,7 +696,7 @@ void ProFileEvaluator::Private::updateItem(ushort *uc, ushort *ptr)
         item = new ProCondition(proItem);
     }
     item->setLineNumber(m_lineNo);
-    block->appendItem(item);
+    currentBlock().append(item);
 }
 
 //////// Evaluator tools /////////
@@ -866,15 +873,14 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitProBlock(ProBlock *block)
         }
     }
     ProItem::ProItemReturn rt = ProItem::ReturnTrue;
-    QList<ProItem *> items = block->items();
-    for (int i = 0; i < items.count(); ++i) {
-        rt = visitProItem(items.at(i));
+    for (ProItem *item = block->items(); item; item = item->next()) {
+        rt = visitProItem(item);
         if (rt != ProItem::ReturnTrue && rt != ProItem::ReturnFalse) {
             if (rt == ProItem::ReturnLoop) {
                 rt = ProItem::ReturnTrue;
                 while (visitProLoopIteration())
-                    for (int j = i; ++j < items.count(); ) {
-                        rt = visitProItem(items.at(j));
+                    for (ProItem *lItem = item; (lItem = lItem->next()); ) {
+                        rt = visitProItem(lItem);
                         if (rt != ProItem::ReturnTrue && rt != ProItem::ReturnFalse) {
                             if (rt == ProItem::ReturnNext) {
                                 rt = ProItem::ReturnTrue;
diff --git a/src/shared/proparser/proitems.cpp b/src/shared/proparser/proitems.cpp
index 236ed5070ac..e1301cbb1d6 100644
--- a/src/shared/proparser/proitems.cpp
+++ b/src/shared/proparser/proitems.cpp
@@ -36,17 +36,20 @@ QT_BEGIN_NAMESPACE
 ProBlock::ProBlock()
     : ProItem(BlockKind)
 {
+    m_proitems = 0;
     m_blockKind = 0;
     m_refCount = 1;
 }
 
 ProBlock::~ProBlock()
 {
-    foreach (ProItem *itm, m_proitems)
+    for (ProItem *itm, *nitm = m_proitems; (itm = nitm); ) {
+        nitm = itm->m_next;
         if (itm->kind() == BlockKind)
             static_cast<ProBlock *>(itm)->deref();
         else
             delete itm;
+    }
 }
 
 ProFile::ProFile(const QString &fileName)
diff --git a/src/shared/proparser/proitems.h b/src/shared/proparser/proitems.h
index b55933dce2b..46d085f066f 100644
--- a/src/shared/proparser/proitems.h
+++ b/src/shared/proparser/proitems.h
@@ -63,9 +63,15 @@ public:
     int lineNumber() const { return m_lineNumber; }
     void setLineNumber(int lineNumber) { m_lineNumber = lineNumber; }
 
+    ProItem *next() const { return m_next; }
+    ProItem **nextRef() { return &m_next; }
+
 private:
+    ProItem *m_next;
     ProItemKind m_kind;
     int m_lineNumber;
+
+    friend class ProBlock; // C++ is braindead ...
 };
 
 class ProBlock : public ProItem
@@ -83,16 +89,17 @@ public:
     ProBlock();
     ~ProBlock();
 
-    void appendItem(ProItem *proitem) { m_proitems << proitem; }
-    QList<ProItem *> items() const { return m_proitems; }
     void setBlockKind(int blockKind) { m_blockKind = blockKind; }
     int blockKind() const { return m_blockKind; }
 
+    ProItem *items() const { return m_proitems; }
+    ProItem **itemsRef() { return &m_proitems; }
+
     void ref() { ++m_refCount; }
     void deref() { if (!--m_refCount) delete this; }
 
 private:
-    QList<ProItem *> m_proitems;
+    ProItem *m_proitems;
     int m_blockKind;
     int m_refCount;
 };
diff --git a/src/shared/proparser/prowriter.cpp b/src/shared/proparser/prowriter.cpp
index 3c8942600c3..9a5e797f698 100644
--- a/src/shared/proparser/prowriter.cpp
+++ b/src/shared/proparser/prowriter.cpp
@@ -40,7 +40,7 @@ void ProWriter::addFiles(ProFile *profile, QStringList *lines,
                          const QStringList &vars)
 {
     // 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) {
             ProVariable *proVar = static_cast<ProVariable*>(item);
             if (vars.contains(proVar->variable())
@@ -87,7 +87,7 @@ void ProWriter::addFiles(ProFile *profile, QStringList *lines,
 static void findProVariables(ProBlock *block, const QStringList &vars,
                              QList<ProVariable *> *proVars)
 {
-    foreach (ProItem *item, block->items()) {
+    for (ProItem *item = block->items(); item; item = item->next()) {
         if (item->kind() == ProItem::BlockKind) {
             findProVariables(static_cast<ProBlock*>(item), vars, proVars);
         } else if (item->kind() == ProItem::VariableKind) {
-- 
GitLab