summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-09-23 19:32:35 +0200
committerLars Knoll <lars.knoll@qt.io>2020-10-05 09:57:08 +0200
commit1b06c07115d7da4fb2af05d30647d822c3ccae7a (patch)
tree401b2f284c9d3f79fb7036aee9c77b4d4182a80a
parent0ad96eac3895e999aa71a68beaff25f5f2d612e6 (diff)
Don't store QTextHtmlParserNode by value in a QList
This is a performance bottleneck as the parse nodes are huge and we don't want to reallocate them all the time. Fixes: QTBUG-86354 Change-Id: Ia437acbb5b2c8af1723932d2cd96ba2ae48a871b Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
-rw-r--r--src/gui/text/qtexthtmlparser.cpp53
-rw-r--r--src/gui/text/qtexthtmlparser_p.h10
2 files changed, 34 insertions, 29 deletions
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index 9bfb0d0ec8..996980b764 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -518,7 +518,7 @@ void QTextHtmlParser::dumpHtml()
QTextHtmlParserNode *QTextHtmlParser::newNode(int parent)
{
- QTextHtmlParserNode *lastNode = &nodes.last();
+ QTextHtmlParserNode *lastNode = nodes.last();
QTextHtmlParserNode *newNode = nullptr;
bool reuseLastNode = true;
@@ -563,8 +563,8 @@ QTextHtmlParserNode *QTextHtmlParser::newNode(int parent)
newNode->text.clear();
newNode->id = Html_unknown;
} else {
- nodes.resize(nodes.size() + 1);
- newNode = &nodes.last();
+ nodes.append(new QTextHtmlParserNode);
+ newNode = nodes.last();
}
newNode->parent = parent;
@@ -573,8 +573,9 @@ QTextHtmlParserNode *QTextHtmlParser::newNode(int parent)
void QTextHtmlParser::parse(const QString &text, const QTextDocument *_resourceProvider)
{
+ qDeleteAll(nodes);
nodes.clear();
- nodes.resize(1);
+ nodes.append(new QTextHtmlParserNode);
txt = text;
pos = 0;
len = txt.length();
@@ -639,9 +640,9 @@ void QTextHtmlParser::parse()
if (c == QLatin1Char('<')) {
parseTag();
} else if (c == QLatin1Char('&')) {
- nodes.last().text += parseEntity();
+ nodes.last()->text += parseEntity();
} else {
- nodes.last().text += c;
+ nodes.last()->text += c;
}
}
}
@@ -654,8 +655,8 @@ void QTextHtmlParser::parseTag()
// handle comments and other exclamation mark declarations
if (hasPrefix(QLatin1Char('!'))) {
parseExclamationTag();
- if (nodes.last().wsm != QTextHtmlParserNode::WhiteSpacePre
- && nodes.last().wsm != QTextHtmlParserNode::WhiteSpacePreWrap
+ if (nodes.last()->wsm != QTextHtmlParserNode::WhiteSpacePre
+ && nodes.last()->wsm != QTextHtmlParserNode::WhiteSpacePreWrap
&& !textEditMode)
eatSpace();
return;
@@ -663,9 +664,9 @@ void QTextHtmlParser::parseTag()
// if close tag just close
if (hasPrefix(QLatin1Char('/'))) {
- if (nodes.last().id == Html_style) {
+ if (nodes.last()->id == Html_style) {
#ifndef QT_NO_CSSPARSER
- QCss::Parser parser(nodes.constLast().text);
+ QCss::Parser parser(nodes.constLast()->text);
QCss::StyleSheet sheet;
sheet.origin = QCss::StyleSheetOrigin_Author;
parser.parse(&sheet, Qt::CaseInsensitive);
@@ -773,7 +774,7 @@ void QTextHtmlParser::parseCloseTag()
|| at(p).wsm == QTextHtmlParserNode::WhiteSpacePreLine)
&& at(p).isBlock()) {
if (at(last()).text.endsWith(QLatin1Char('\n')))
- nodes[last()].text.chop(1);
+ nodes[last()]->text.chop(1);
}
newNode(at(p).parent);
@@ -892,7 +893,7 @@ QString QTextHtmlParser::parseWord()
// gives the new node the right parent
QTextHtmlParserNode *QTextHtmlParser::resolveParent()
{
- QTextHtmlParserNode *node = &nodes.last();
+ QTextHtmlParserNode *node = nodes.last();
int p = node->parent;
@@ -905,22 +906,22 @@ QTextHtmlParserNode *QTextHtmlParser::resolveParent()
n = at(n).parent;
if (!n) {
- nodes.insert(nodes.count() - 1, QTextHtmlParserNode());
- nodes.insert(nodes.count() - 1, QTextHtmlParserNode());
+ nodes.insert(nodes.count() - 1, new QTextHtmlParserNode);
+ nodes.insert(nodes.count() - 1, new QTextHtmlParserNode);
- QTextHtmlParserNode *table = &nodes[nodes.count() - 3];
+ QTextHtmlParserNode *table = nodes[nodes.count() - 3];
table->parent = p;
table->id = Html_table;
table->tag = QLatin1String("table");
table->children.append(nodes.count() - 2); // add row as child
- QTextHtmlParserNode *row = &nodes[nodes.count() - 2];
+ QTextHtmlParserNode *row = nodes[nodes.count() - 2];
row->parent = nodes.count() - 3; // table as parent
row->id = Html_tr;
row->tag = QLatin1String("tr");
p = nodes.count() - 2;
- node = &nodes.last(); // re-initialize pointer
+ node = nodes.last(); // re-initialize pointer
}
}
@@ -930,13 +931,13 @@ QTextHtmlParserNode *QTextHtmlParser::resolveParent()
n = at(n).parent;
if (!n) {
- nodes.insert(nodes.count() - 1, QTextHtmlParserNode());
- QTextHtmlParserNode *table = &nodes[nodes.count() - 2];
+ nodes.insert(nodes.count() - 1, new QTextHtmlParserNode);
+ QTextHtmlParserNode *table = nodes[nodes.count() - 2];
table->parent = p;
table->id = Html_table;
table->tag = QLatin1String("table");
p = nodes.count() - 2;
- node = &nodes.last(); // re-initialize pointer
+ node = nodes.last(); // re-initialize pointer
}
}
@@ -983,15 +984,15 @@ QTextHtmlParserNode *QTextHtmlParser::resolveParent()
node->parent = p;
// makes it easier to traverse the tree, later
- nodes[p].children.append(nodes.count() - 1);
+ nodes[p]->children.append(nodes.count() - 1);
return node;
}
// sets all properties on the new node
void QTextHtmlParser::resolveNode()
{
- QTextHtmlParserNode *node = &nodes.last();
- const QTextHtmlParserNode *parent = &nodes.at(node->parent);
+ QTextHtmlParserNode *node = nodes.last();
+ const QTextHtmlParserNode *parent = nodes.at(node->parent);
node->initializeProperties(parent, this);
}
@@ -1563,7 +1564,7 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes)
if (attributes.count() % 2 == 1)
return;
- QTextHtmlParserNode *node = &nodes.last();
+ QTextHtmlParserNode *node = nodes.last();
for (int i = 0; i < attributes.count(); i += 2) {
QString key = attributes.at(i);
@@ -2119,10 +2120,10 @@ QList<QCss::Declaration> QTextHtmlParser::declarationsForNode(int node) const
n.id = node;
const char *extraPseudo = nullptr;
- if (nodes.at(node).id == Html_a && nodes.at(node).hasHref)
+ if (nodes.at(node)->id == Html_a && nodes.at(node)->hasHref)
extraPseudo = "link";
// Ensure that our own style is taken into consideration
- decls = standardDeclarationForNode(nodes.at(node));
+ decls = standardDeclarationForNode(*nodes.at(node));
decls += selector.declarationsForNode(n, extraPseudo);
n = selector.parentNode(n);
while (!selector.isNullNode(n)) {
diff --git a/src/gui/text/qtexthtmlparser_p.h b/src/gui/text/qtexthtmlparser_p.h
index 4bfdab124b..2650c9cc3e 100644
--- a/src/gui/text/qtexthtmlparser_p.h
+++ b/src/gui/text/qtexthtmlparser_p.h
@@ -281,9 +281,13 @@ public:
MarginBottom,
MarginLeft
};
+ ~QTextHtmlParser()
+ {
+ qDeleteAll(nodes);
+ }
- inline const QTextHtmlParserNode &at(int i) const { return nodes.at(i); }
- inline QTextHtmlParserNode &operator[](int i) { return nodes[i]; }
+ inline const QTextHtmlParserNode &at(int i) const { return *nodes.at(i); }
+ inline QTextHtmlParserNode &operator[](int i) { return *nodes[i]; }
inline int count() const { return nodes.count(); }
inline int last() const { return nodes.count()-1; }
int depth(int i) const;
@@ -308,7 +312,7 @@ public:
static int lookupElement(const QString &element);
protected:
QTextHtmlParserNode *newNode(int parent);
- QList<QTextHtmlParserNode> nodes;
+ QList<QTextHtmlParserNode *> nodes;
QString txt;
int pos, len;