1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#ifndef QDOM_P_H
4#define QDOM_P_H
5
6#include "qdom.h"
7
8#include <private/qglobal_p.h>
9#include <qhash.h>
10#include <qstring.h>
11#include <qlist.h>
12#include <qshareddata.h>
13
14QT_REQUIRE_CONFIG(dom);
15
16#include <QtCore/qxpfunctional.h>
17
18QT_BEGIN_NAMESPACE
19
20//
21// W A R N I N G
22// -------------
23//
24// This file is not part of the Qt API. It exists for the convenience of
25// qxml.cpp and qdom.cpp. This header file may change from version to version without
26// notice, or even be removed.
27//
28// We mean it.
29//
30
31/**************************************************************
32 *
33 * Private class declarations
34 *
35 **************************************************************/
36
37class QDomImplementationPrivate
38{
39public:
40 inline QDomImplementationPrivate() {}
41
42 QDomImplementationPrivate *clone();
43 QAtomicInt ref;
44 static QDomImplementation::InvalidDataPolicy invalidDataPolicy;
45};
46
47class QDomNodePrivate
48{
49public:
50 QDomNodePrivate(QDomDocumentPrivate *, QDomNodePrivate *parent = nullptr);
51 QDomNodePrivate(QDomNodePrivate *n, bool deep);
52 virtual ~QDomNodePrivate();
53
54 QString nodeName() const { return name; }
55 QString nodeValue() const { return value; }
56 virtual void setNodeValue(const QString &v) { value = v; }
57
58 QDomDocumentPrivate *ownerDocument();
59 void setOwnerDocument(QDomDocumentPrivate *doc);
60
61 virtual QDomNodePrivate *insertBefore(QDomNodePrivate *newChild, QDomNodePrivate *refChild);
62 virtual QDomNodePrivate *insertAfter(QDomNodePrivate *newChild, QDomNodePrivate *refChild);
63 virtual QDomNodePrivate *replaceChild(QDomNodePrivate *newChild, QDomNodePrivate *oldChild);
64 virtual QDomNodePrivate *removeChild(QDomNodePrivate *oldChild);
65 virtual QDomNodePrivate *appendChild(QDomNodePrivate *newChild);
66
67 QDomNodePrivate *namedItem(const QString &name);
68
69 virtual QDomNodePrivate *cloneNode(bool deep = true);
70 virtual void normalize();
71 virtual void clear();
72
73 inline QDomNodePrivate *parent() const { return hasParent ? ownerNode : nullptr; }
74 inline void setParent(QDomNodePrivate *p)
75 {
76 ownerNode = p;
77 hasParent = true;
78 }
79
80 void setNoParent()
81 {
82 ownerNode = hasParent ? (QDomNodePrivate *)ownerDocument() : nullptr;
83 hasParent = false;
84 }
85
86 // Dynamic cast
87 bool isAttr() const { return nodeType() == QDomNode::AttributeNode; }
88 bool isCDATASection() const { return nodeType() == QDomNode::CDATASectionNode; }
89 bool isDocumentFragment() const { return nodeType() == QDomNode::DocumentFragmentNode; }
90 bool isDocument() const { return nodeType() == QDomNode::DocumentNode; }
91 bool isDocumentType() const { return nodeType() == QDomNode::DocumentTypeNode; }
92 bool isElement() const { return nodeType() == QDomNode::ElementNode; }
93 bool isEntityReference() const { return nodeType() == QDomNode::EntityReferenceNode; }
94 bool isText() const
95 {
96 const QDomNode::NodeType nt = nodeType();
97 return (nt == QDomNode::TextNode) || (nt == QDomNode::CDATASectionNode);
98 }
99 bool isEntity() const { return nodeType() == QDomNode::EntityNode; }
100 bool isNotation() const { return nodeType() == QDomNode::NotationNode; }
101 bool isProcessingInstruction() const
102 {
103 return nodeType() == QDomNode::ProcessingInstructionNode;
104 }
105 bool isCharacterData() const
106 {
107 const QDomNode::NodeType nt = nodeType();
108 return (nt == QDomNode::CharacterDataNode) || (nt == QDomNode::TextNode)
109 || (nt == QDomNode::CommentNode);
110 }
111 bool isComment() const { return nodeType() == QDomNode::CommentNode; }
112
113 virtual QDomNode::NodeType nodeType() const { return QDomNode::BaseNode; }
114
115 void saveSubTree(const QDomNodePrivate *n, QTextStream &s, int depth, int indent) const;
116 virtual void save(QTextStream &, int, int) const {}
117 virtual void afterSave(QTextStream &, int, int) const {}
118
119 void setLocation(int lineNumber, int columnNumber);
120
121 // Variables
122 QAtomicInt ref;
123 QDomNodePrivate *prev;
124 QDomNodePrivate *next;
125 QDomNodePrivate *ownerNode; // either the node's parent or the node's owner document
126 QDomNodePrivate *first;
127 QDomNodePrivate *last;
128
129 QString name; // this is the local name if prefix != null
130 QString value;
131 QString prefix; // set this only for ElementNode and AttributeNode
132 QString namespaceURI; // set this only for ElementNode and AttributeNode
133 bool createdWithDom1Interface : 1;
134 bool hasParent : 1;
135
136 int lineNumber;
137 int columnNumber;
138};
139
140class QDomNodeListPrivate
141{
142public:
143 QDomNodeListPrivate(QDomNodePrivate *);
144 QDomNodeListPrivate(QDomNodePrivate *, const QString &);
145 QDomNodeListPrivate(QDomNodePrivate *, const QString &, const QString &);
146 ~QDomNodeListPrivate();
147
148 bool operator==(const QDomNodeListPrivate &) const noexcept;
149
150 void createList() const;
151 bool checkNode(QDomNodePrivate* p) const;
152 QDomNodePrivate *findNextInOrder(QDomNodePrivate* p) const;
153 QDomNodePrivate *findPrevInOrder(QDomNodePrivate* p) const;
154 void forEachNode(qxp::function_ref<void(QDomNodePrivate*)> yield) const;
155 bool maybeCreateList() const;
156 QDomNodePrivate *item(int index);
157 int length() const;
158 int noexceptLength() const noexcept;
159
160 QAtomicInt ref;
161 /*
162 This list contains the children of this node.
163 */
164 QDomNodePrivate *node_impl;
165 QString tagname;
166 QString nsURI;
167 mutable QList<QDomNodePrivate *> list;
168 mutable long timestamp;
169};
170
171class QDomNamedNodeMapPrivate
172{
173public:
174 QDomNamedNodeMapPrivate(QDomNodePrivate *);
175 ~QDomNamedNodeMapPrivate();
176
177 QDomNodePrivate *namedItem(const QString &name) const;
178 QDomNodePrivate *namedItemNS(const QString &nsURI, const QString &localName) const;
179 QDomNodePrivate *setNamedItem(QDomNodePrivate *arg);
180 QDomNodePrivate *setNamedItemNS(QDomNodePrivate *arg);
181 QDomNodePrivate *removeNamedItem(const QString &name);
182 QDomNodePrivate *item(int index) const;
183 int length() const;
184 bool contains(const QString &name) const;
185 bool containsNS(const QString &nsURI, const QString &localName) const;
186
187 /**
188 * Remove all children from the map.
189 */
190 void clearMap();
191 bool isReadOnly() { return readonly; }
192 void setReadOnly(bool r) { readonly = r; }
193 bool isAppendToParent() { return appendToParent; }
194 /**
195 * If true, then the node will redirect insert/remove calls
196 * to its parent by calling QDomNodePrivate::appendChild or removeChild.
197 * In addition the map won't increase or decrease the reference count
198 * of the nodes it contains.
199 *
200 * By default this value is false and the map will handle reference counting
201 * by itself.
202 */
203 void setAppendToParent(bool b) { appendToParent = b; }
204
205 /**
206 * Creates a copy of the map. It is a deep copy
207 * that means that all children are cloned.
208 */
209 QDomNamedNodeMapPrivate *clone(QDomNodePrivate *parent);
210
211 // Variables
212 QAtomicInt ref;
213 QMultiHash<QString, QDomNodePrivate *> map;
214 QDomNodePrivate *parent;
215 bool readonly;
216 bool appendToParent;
217};
218
219class QDomDocumentTypePrivate : public QDomNodePrivate
220{
221public:
222 QDomDocumentTypePrivate(QDomDocumentPrivate *, QDomNodePrivate *parent = nullptr);
223 QDomDocumentTypePrivate(QDomDocumentTypePrivate *n, bool deep);
224 ~QDomDocumentTypePrivate();
225 void init();
226
227 // Reimplemented from QDomNodePrivate
228 QDomNodePrivate *cloneNode(bool deep = true) override;
229 QDomNodePrivate *insertBefore(QDomNodePrivate *newChild, QDomNodePrivate *refChild) override;
230 QDomNodePrivate *insertAfter(QDomNodePrivate *newChild, QDomNodePrivate *refChild) override;
231 QDomNodePrivate *replaceChild(QDomNodePrivate *newChild, QDomNodePrivate *oldChild) override;
232 QDomNodePrivate *removeChild(QDomNodePrivate *oldChild) override;
233 QDomNodePrivate *appendChild(QDomNodePrivate *newChild) override;
234
235 QDomNode::NodeType nodeType() const override { return QDomNode::DocumentTypeNode; }
236
237 void save(QTextStream &s, int, int) const override;
238
239 // Variables
240 QDomNamedNodeMapPrivate *entities;
241 QDomNamedNodeMapPrivate *notations;
242 QString publicId;
243 QString systemId;
244 QString internalSubset;
245};
246
247class QDomDocumentFragmentPrivate : public QDomNodePrivate
248{
249public:
250 QDomDocumentFragmentPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent = nullptr);
251 QDomDocumentFragmentPrivate(QDomNodePrivate *n, bool deep);
252
253 // Reimplemented from QDomNodePrivate
254 virtual QDomNodePrivate *cloneNode(bool deep = true) override;
255 QDomNode::NodeType nodeType() const override { return QDomNode::DocumentFragmentNode; }
256};
257
258class QDomCharacterDataPrivate : public QDomNodePrivate
259{
260public:
261 QDomCharacterDataPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &data);
262 QDomCharacterDataPrivate(QDomCharacterDataPrivate *n, bool deep);
263
264 int dataLength() const;
265 QString substringData(unsigned long offset, unsigned long count) const;
266 void appendData(const QString &arg);
267 void insertData(unsigned long offset, const QString &arg);
268 void deleteData(unsigned long offset, unsigned long count);
269 void replaceData(unsigned long offset, unsigned long count, const QString &arg);
270
271 // Reimplemented from QDomNodePrivate
272 QDomNode::NodeType nodeType() const override { return QDomNode::CharacterDataNode; }
273 QDomNodePrivate *cloneNode(bool deep = true) override;
274};
275
276class QDomTextPrivate : public QDomCharacterDataPrivate
277{
278public:
279 QDomTextPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &val);
280 QDomTextPrivate(QDomTextPrivate *n, bool deep);
281
282 QDomTextPrivate *splitText(int offset);
283
284 // Reimplemented from QDomNodePrivate
285 QDomNodePrivate *cloneNode(bool deep = true) override;
286 QDomNode::NodeType nodeType() const override { return QDomNode::TextNode; }
287 virtual void save(QTextStream &s, int, int) const override;
288};
289
290class QDomAttrPrivate : public QDomNodePrivate
291{
292public:
293 QDomAttrPrivate(QDomDocumentPrivate *, QDomNodePrivate *, const QString &name);
294 QDomAttrPrivate(QDomDocumentPrivate *, QDomNodePrivate *, const QString &nsURI,
295 const QString &qName);
296 QDomAttrPrivate(QDomAttrPrivate *n, bool deep);
297
298 bool specified() const;
299
300 // Reimplemented from QDomNodePrivate
301 void setNodeValue(const QString &v) override;
302 QDomNodePrivate *cloneNode(bool deep = true) override;
303 QDomNode::NodeType nodeType() const override { return QDomNode::AttributeNode; }
304 virtual void save(QTextStream &s, int, int) const override;
305
306 // Variables
307 bool m_specified;
308};
309
310class QDomElementPrivate : public QDomNodePrivate
311{
312public:
313 QDomElementPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &name);
314 QDomElementPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &nsURI,
315 const QString &qName);
316 QDomElementPrivate(QDomElementPrivate *n, bool deep);
317 ~QDomElementPrivate();
318
319 QString attribute(const QString &name, const QString &defValue) const;
320 QString attributeNS(const QString &nsURI, const QString &localName,
321 const QString &defValue) const;
322 void setAttribute(const QString &name, const QString &value);
323 void setAttributeNS(const QString &nsURI, const QString &qName, const QString &newValue);
324 void removeAttribute(const QString &name);
325 QDomAttrPrivate *attributeNode(const QString &name);
326 QDomAttrPrivate *attributeNodeNS(const QString &nsURI, const QString &localName);
327 QDomAttrPrivate *setAttributeNode(QDomAttrPrivate *newAttr);
328 QDomAttrPrivate *setAttributeNodeNS(QDomAttrPrivate *newAttr);
329 QDomAttrPrivate *removeAttributeNode(QDomAttrPrivate *oldAttr);
330 bool hasAttribute(const QString &name);
331 bool hasAttributeNS(const QString &nsURI, const QString &localName);
332
333 QString text();
334
335 // Reimplemented from QDomNodePrivate
336 QDomNamedNodeMapPrivate *attributes() { return m_attr; }
337 bool hasAttributes() { return (m_attr->length() > 0); }
338 QDomNode::NodeType nodeType() const override { return QDomNode::ElementNode; }
339 QDomNodePrivate *cloneNode(bool deep = true) override;
340 virtual void save(QTextStream &s, int, int) const override;
341 virtual void afterSave(QTextStream &s, int, int) const override;
342
343 // Variables
344 QDomNamedNodeMapPrivate *m_attr;
345};
346
347class QDomCommentPrivate : public QDomCharacterDataPrivate
348{
349public:
350 QDomCommentPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &val);
351 QDomCommentPrivate(QDomCommentPrivate *n, bool deep);
352
353 // Reimplemented from QDomNodePrivate
354 QDomNodePrivate *cloneNode(bool deep = true) override;
355 QDomNode::NodeType nodeType() const override { return QDomNode::CommentNode; }
356 virtual void save(QTextStream &s, int, int) const override;
357};
358
359class QDomCDATASectionPrivate : public QDomTextPrivate
360{
361public:
362 QDomCDATASectionPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &val);
363 QDomCDATASectionPrivate(QDomCDATASectionPrivate *n, bool deep);
364
365 // Reimplemented from QDomNodePrivate
366 QDomNodePrivate *cloneNode(bool deep = true) override;
367 QDomNode::NodeType nodeType() const override { return QDomNode::CDATASectionNode; }
368 virtual void save(QTextStream &s, int, int) const override;
369};
370
371class QDomNotationPrivate : public QDomNodePrivate
372{
373public:
374 QDomNotationPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &name,
375 const QString &pub, const QString &sys);
376 QDomNotationPrivate(QDomNotationPrivate *n, bool deep);
377
378 // Reimplemented from QDomNodePrivate
379 QDomNodePrivate *cloneNode(bool deep = true) override;
380 QDomNode::NodeType nodeType() const override { return QDomNode::NotationNode; }
381 virtual void save(QTextStream &s, int, int) const override;
382
383 // Variables
384 QString m_sys;
385 QString m_pub;
386};
387
388class QDomEntityPrivate : public QDomNodePrivate
389{
390public:
391 QDomEntityPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &name,
392 const QString &pub, const QString &sys, const QString &notation);
393 QDomEntityPrivate(QDomEntityPrivate *n, bool deep);
394
395 // Reimplemented from QDomNodePrivate
396 QDomNodePrivate *cloneNode(bool deep = true) override;
397 QDomNode::NodeType nodeType() const override { return QDomNode::EntityNode; }
398 virtual void save(QTextStream &s, int, int) const override;
399
400 // Variables
401 QString m_sys;
402 QString m_pub;
403 QString m_notationName;
404};
405
406class QDomEntityReferencePrivate : public QDomNodePrivate
407{
408public:
409 QDomEntityReferencePrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &name);
410 QDomEntityReferencePrivate(QDomNodePrivate *n, bool deep);
411
412 // Reimplemented from QDomNodePrivate
413 QDomNodePrivate *cloneNode(bool deep = true) override;
414 QDomNode::NodeType nodeType() const override { return QDomNode::EntityReferenceNode; }
415 virtual void save(QTextStream &s, int, int) const override;
416};
417
418class QDomProcessingInstructionPrivate : public QDomNodePrivate
419{
420public:
421 QDomProcessingInstructionPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent,
422 const QString &target, const QString &data);
423 QDomProcessingInstructionPrivate(QDomProcessingInstructionPrivate *n, bool deep);
424
425 // Reimplemented from QDomNodePrivate
426 QDomNodePrivate *cloneNode(bool deep = true) override;
427 QDomNode::NodeType nodeType() const override { return QDomNode::ProcessingInstructionNode; }
428 virtual void save(QTextStream &s, int, int) const override;
429};
430
431class QDomDocumentPrivate : public QDomNodePrivate
432{
433public:
434 QDomDocumentPrivate();
435 QDomDocumentPrivate(const QString &name);
436 QDomDocumentPrivate(QDomDocumentTypePrivate *dt);
437 QDomDocumentPrivate(QDomDocumentPrivate *n, bool deep);
438 ~QDomDocumentPrivate();
439
440 QDomDocument::ParseResult setContent(QXmlStreamReader *reader,
441 QDomDocument::ParseOptions options);
442
443 // Attributes
444 QDomDocumentTypePrivate *doctype() { return type.data(); }
445 QDomImplementationPrivate *implementation() { return impl.data(); }
446 QDomElementPrivate *documentElement();
447
448 // Factories
449 QDomElementPrivate *createElement(const QString &tagName);
450 QDomElementPrivate *createElementNS(const QString &nsURI, const QString &qName);
451 QDomDocumentFragmentPrivate *createDocumentFragment();
452 QDomTextPrivate *createTextNode(const QString &data);
453 QDomCommentPrivate *createComment(const QString &data);
454 QDomCDATASectionPrivate *createCDATASection(const QString &data);
455 QDomProcessingInstructionPrivate *createProcessingInstruction(const QString &target,
456 const QString &data);
457 QDomAttrPrivate *createAttribute(const QString &name);
458 QDomAttrPrivate *createAttributeNS(const QString &nsURI, const QString &qName);
459 QDomEntityReferencePrivate *createEntityReference(const QString &name);
460
461 QDomNodePrivate *importNode(QDomNodePrivate *importedNode, bool deep);
462
463 // Reimplemented from QDomNodePrivate
464 QDomNodePrivate *cloneNode(bool deep = true) override;
465 QDomNode::NodeType nodeType() const override { return QDomNode::DocumentNode; }
466 void clear() override;
467
468 // Variables
469 QExplicitlySharedDataPointer<QDomImplementationPrivate> impl;
470 QExplicitlySharedDataPointer<QDomDocumentTypePrivate> type;
471
472 void saveDocument(QTextStream &stream, const int indent,
473 QDomNode::EncodingPolicy encUsed) const;
474
475 /* \internal
476 Counter for the QDomNodeListPrivate timestamps.
477
478 This is a cache optimization, that might in some cases be effective. The
479 dilemma is that QDomNode::childNodes() returns a list, but the
480 implementation stores the children in a linked list. Hence, in order to
481 get the children out through childNodes(), a list must be populated each
482 time, which is O(N).
483
484 DOM has the requirement of node references being live, see DOM Core
485 Level 3, 1.1.1 The DOM Structure Model, which means that changes to the
486 underlying documents must be reflected in node lists.
487
488 This mechanism, nodeListTime, is a caching optimization that reduces the
489 amount of times the node list is rebuilt, by only doing so when the
490 document actually changes. However, a change to anywhere in any document
491 invalidate all lists, since no dependency tracking is done.
492
493 It functions by that all modifying functions(insertBefore() and so on)
494 increment the count; each QDomNodeListPrivate copies nodeListTime on
495 construction, and compares its own value to nodeListTime in order to
496 determine whether it needs to rebuild.
497
498 This is reentrant. The nodeListTime may overflow, but that's ok since we
499 check for equalness, not whether nodeListTime is smaller than the list's
500 stored timestamp.
501 */
502 long nodeListTime;
503};
504
505QT_END_NAMESPACE
506
507#endif // QDOMHELPERS_P_H
508

source code of qtbase/src/xml/dom/qdom_p.h