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