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