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>
This commit is contained in:
parent
0ad96eac38
commit
1b06c07115
@ -518,7 +518,7 @@ void QTextHtmlParser::dumpHtml()
|
|||||||
|
|
||||||
QTextHtmlParserNode *QTextHtmlParser::newNode(int parent)
|
QTextHtmlParserNode *QTextHtmlParser::newNode(int parent)
|
||||||
{
|
{
|
||||||
QTextHtmlParserNode *lastNode = &nodes.last();
|
QTextHtmlParserNode *lastNode = nodes.last();
|
||||||
QTextHtmlParserNode *newNode = nullptr;
|
QTextHtmlParserNode *newNode = nullptr;
|
||||||
|
|
||||||
bool reuseLastNode = true;
|
bool reuseLastNode = true;
|
||||||
@ -563,8 +563,8 @@ QTextHtmlParserNode *QTextHtmlParser::newNode(int parent)
|
|||||||
newNode->text.clear();
|
newNode->text.clear();
|
||||||
newNode->id = Html_unknown;
|
newNode->id = Html_unknown;
|
||||||
} else {
|
} else {
|
||||||
nodes.resize(nodes.size() + 1);
|
nodes.append(new QTextHtmlParserNode);
|
||||||
newNode = &nodes.last();
|
newNode = nodes.last();
|
||||||
}
|
}
|
||||||
|
|
||||||
newNode->parent = parent;
|
newNode->parent = parent;
|
||||||
@ -573,8 +573,9 @@ QTextHtmlParserNode *QTextHtmlParser::newNode(int parent)
|
|||||||
|
|
||||||
void QTextHtmlParser::parse(const QString &text, const QTextDocument *_resourceProvider)
|
void QTextHtmlParser::parse(const QString &text, const QTextDocument *_resourceProvider)
|
||||||
{
|
{
|
||||||
|
qDeleteAll(nodes);
|
||||||
nodes.clear();
|
nodes.clear();
|
||||||
nodes.resize(1);
|
nodes.append(new QTextHtmlParserNode);
|
||||||
txt = text;
|
txt = text;
|
||||||
pos = 0;
|
pos = 0;
|
||||||
len = txt.length();
|
len = txt.length();
|
||||||
@ -639,9 +640,9 @@ void QTextHtmlParser::parse()
|
|||||||
if (c == QLatin1Char('<')) {
|
if (c == QLatin1Char('<')) {
|
||||||
parseTag();
|
parseTag();
|
||||||
} else if (c == QLatin1Char('&')) {
|
} else if (c == QLatin1Char('&')) {
|
||||||
nodes.last().text += parseEntity();
|
nodes.last()->text += parseEntity();
|
||||||
} else {
|
} else {
|
||||||
nodes.last().text += c;
|
nodes.last()->text += c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -654,8 +655,8 @@ void QTextHtmlParser::parseTag()
|
|||||||
// handle comments and other exclamation mark declarations
|
// handle comments and other exclamation mark declarations
|
||||||
if (hasPrefix(QLatin1Char('!'))) {
|
if (hasPrefix(QLatin1Char('!'))) {
|
||||||
parseExclamationTag();
|
parseExclamationTag();
|
||||||
if (nodes.last().wsm != QTextHtmlParserNode::WhiteSpacePre
|
if (nodes.last()->wsm != QTextHtmlParserNode::WhiteSpacePre
|
||||||
&& nodes.last().wsm != QTextHtmlParserNode::WhiteSpacePreWrap
|
&& nodes.last()->wsm != QTextHtmlParserNode::WhiteSpacePreWrap
|
||||||
&& !textEditMode)
|
&& !textEditMode)
|
||||||
eatSpace();
|
eatSpace();
|
||||||
return;
|
return;
|
||||||
@ -663,9 +664,9 @@ void QTextHtmlParser::parseTag()
|
|||||||
|
|
||||||
// if close tag just close
|
// if close tag just close
|
||||||
if (hasPrefix(QLatin1Char('/'))) {
|
if (hasPrefix(QLatin1Char('/'))) {
|
||||||
if (nodes.last().id == Html_style) {
|
if (nodes.last()->id == Html_style) {
|
||||||
#ifndef QT_NO_CSSPARSER
|
#ifndef QT_NO_CSSPARSER
|
||||||
QCss::Parser parser(nodes.constLast().text);
|
QCss::Parser parser(nodes.constLast()->text);
|
||||||
QCss::StyleSheet sheet;
|
QCss::StyleSheet sheet;
|
||||||
sheet.origin = QCss::StyleSheetOrigin_Author;
|
sheet.origin = QCss::StyleSheetOrigin_Author;
|
||||||
parser.parse(&sheet, Qt::CaseInsensitive);
|
parser.parse(&sheet, Qt::CaseInsensitive);
|
||||||
@ -773,7 +774,7 @@ void QTextHtmlParser::parseCloseTag()
|
|||||||
|| at(p).wsm == QTextHtmlParserNode::WhiteSpacePreLine)
|
|| at(p).wsm == QTextHtmlParserNode::WhiteSpacePreLine)
|
||||||
&& at(p).isBlock()) {
|
&& at(p).isBlock()) {
|
||||||
if (at(last()).text.endsWith(QLatin1Char('\n')))
|
if (at(last()).text.endsWith(QLatin1Char('\n')))
|
||||||
nodes[last()].text.chop(1);
|
nodes[last()]->text.chop(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
newNode(at(p).parent);
|
newNode(at(p).parent);
|
||||||
@ -892,7 +893,7 @@ QString QTextHtmlParser::parseWord()
|
|||||||
// gives the new node the right parent
|
// gives the new node the right parent
|
||||||
QTextHtmlParserNode *QTextHtmlParser::resolveParent()
|
QTextHtmlParserNode *QTextHtmlParser::resolveParent()
|
||||||
{
|
{
|
||||||
QTextHtmlParserNode *node = &nodes.last();
|
QTextHtmlParserNode *node = nodes.last();
|
||||||
|
|
||||||
int p = node->parent;
|
int p = node->parent;
|
||||||
|
|
||||||
@ -905,22 +906,22 @@ QTextHtmlParserNode *QTextHtmlParser::resolveParent()
|
|||||||
n = at(n).parent;
|
n = at(n).parent;
|
||||||
|
|
||||||
if (!n) {
|
if (!n) {
|
||||||
nodes.insert(nodes.count() - 1, QTextHtmlParserNode());
|
nodes.insert(nodes.count() - 1, new QTextHtmlParserNode);
|
||||||
nodes.insert(nodes.count() - 1, QTextHtmlParserNode());
|
nodes.insert(nodes.count() - 1, new QTextHtmlParserNode);
|
||||||
|
|
||||||
QTextHtmlParserNode *table = &nodes[nodes.count() - 3];
|
QTextHtmlParserNode *table = nodes[nodes.count() - 3];
|
||||||
table->parent = p;
|
table->parent = p;
|
||||||
table->id = Html_table;
|
table->id = Html_table;
|
||||||
table->tag = QLatin1String("table");
|
table->tag = QLatin1String("table");
|
||||||
table->children.append(nodes.count() - 2); // add row as child
|
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->parent = nodes.count() - 3; // table as parent
|
||||||
row->id = Html_tr;
|
row->id = Html_tr;
|
||||||
row->tag = QLatin1String("tr");
|
row->tag = QLatin1String("tr");
|
||||||
|
|
||||||
p = nodes.count() - 2;
|
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;
|
n = at(n).parent;
|
||||||
|
|
||||||
if (!n) {
|
if (!n) {
|
||||||
nodes.insert(nodes.count() - 1, QTextHtmlParserNode());
|
nodes.insert(nodes.count() - 1, new QTextHtmlParserNode);
|
||||||
QTextHtmlParserNode *table = &nodes[nodes.count() - 2];
|
QTextHtmlParserNode *table = nodes[nodes.count() - 2];
|
||||||
table->parent = p;
|
table->parent = p;
|
||||||
table->id = Html_table;
|
table->id = Html_table;
|
||||||
table->tag = QLatin1String("table");
|
table->tag = QLatin1String("table");
|
||||||
p = nodes.count() - 2;
|
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;
|
node->parent = p;
|
||||||
|
|
||||||
// makes it easier to traverse the tree, later
|
// makes it easier to traverse the tree, later
|
||||||
nodes[p].children.append(nodes.count() - 1);
|
nodes[p]->children.append(nodes.count() - 1);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets all properties on the new node
|
// sets all properties on the new node
|
||||||
void QTextHtmlParser::resolveNode()
|
void QTextHtmlParser::resolveNode()
|
||||||
{
|
{
|
||||||
QTextHtmlParserNode *node = &nodes.last();
|
QTextHtmlParserNode *node = nodes.last();
|
||||||
const QTextHtmlParserNode *parent = &nodes.at(node->parent);
|
const QTextHtmlParserNode *parent = nodes.at(node->parent);
|
||||||
node->initializeProperties(parent, this);
|
node->initializeProperties(parent, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1563,7 +1564,7 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes)
|
|||||||
if (attributes.count() % 2 == 1)
|
if (attributes.count() % 2 == 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QTextHtmlParserNode *node = &nodes.last();
|
QTextHtmlParserNode *node = nodes.last();
|
||||||
|
|
||||||
for (int i = 0; i < attributes.count(); i += 2) {
|
for (int i = 0; i < attributes.count(); i += 2) {
|
||||||
QString key = attributes.at(i);
|
QString key = attributes.at(i);
|
||||||
@ -2119,10 +2120,10 @@ QList<QCss::Declaration> QTextHtmlParser::declarationsForNode(int node) const
|
|||||||
n.id = node;
|
n.id = node;
|
||||||
|
|
||||||
const char *extraPseudo = nullptr;
|
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";
|
extraPseudo = "link";
|
||||||
// Ensure that our own style is taken into consideration
|
// Ensure that our own style is taken into consideration
|
||||||
decls = standardDeclarationForNode(nodes.at(node));
|
decls = standardDeclarationForNode(*nodes.at(node));
|
||||||
decls += selector.declarationsForNode(n, extraPseudo);
|
decls += selector.declarationsForNode(n, extraPseudo);
|
||||||
n = selector.parentNode(n);
|
n = selector.parentNode(n);
|
||||||
while (!selector.isNullNode(n)) {
|
while (!selector.isNullNode(n)) {
|
||||||
|
@ -281,9 +281,13 @@ public:
|
|||||||
MarginBottom,
|
MarginBottom,
|
||||||
MarginLeft
|
MarginLeft
|
||||||
};
|
};
|
||||||
|
~QTextHtmlParser()
|
||||||
|
{
|
||||||
|
qDeleteAll(nodes);
|
||||||
|
}
|
||||||
|
|
||||||
inline const QTextHtmlParserNode &at(int i) const { return nodes.at(i); }
|
inline const QTextHtmlParserNode &at(int i) const { return *nodes.at(i); }
|
||||||
inline QTextHtmlParserNode &operator[](int i) { return nodes[i]; }
|
inline QTextHtmlParserNode &operator[](int i) { return *nodes[i]; }
|
||||||
inline int count() const { return nodes.count(); }
|
inline int count() const { return nodes.count(); }
|
||||||
inline int last() const { return nodes.count()-1; }
|
inline int last() const { return nodes.count()-1; }
|
||||||
int depth(int i) const;
|
int depth(int i) const;
|
||||||
@ -308,7 +312,7 @@ public:
|
|||||||
static int lookupElement(const QString &element);
|
static int lookupElement(const QString &element);
|
||||||
protected:
|
protected:
|
||||||
QTextHtmlParserNode *newNode(int parent);
|
QTextHtmlParserNode *newNode(int parent);
|
||||||
QList<QTextHtmlParserNode> nodes;
|
QList<QTextHtmlParserNode *> nodes;
|
||||||
QString txt;
|
QString txt;
|
||||||
int pos, len;
|
int pos, len;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user