1 /*
2 Original code by Lee Thomason (www.grinninglizard.com)
3 
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any
6 damages arising from the use of this software.
7 
8 Permission is granted to anyone to use this software for any
9 purpose, including commercial applications, and to alter it and
10 redistribute it freely, subject to the following restrictions:
11 
12 1. The origin of this software must not be misrepresented; you must
13 not claim that you wrote the original software. If you use this
14 software in a product, an acknowledgment in the product documentation
15 would be appreciated but is not required.
16 
17 2. Altered source versions must be plainly marked as such, and
18 must not be misrepresented as being the original software.
19 
20 3. This notice may not be removed or altered from any source
21 distribution.
22 */
23 
24 #ifndef TINYXML2_INCLUDED
25 #define TINYXML2_INCLUDED
26 
27 #include <cctype>
28 #include <climits>
29 #include <cstdio>
30 #include <cstring>
31 //#include <cstdarg>
32 #include <stdarg.h>
33 /*
34    TODO: intern strings instead of allocation.
35 */
36 /*
37     gcc: g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
38 */
39 
40 #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
41     #ifndef DEBUG
42         #define DEBUG
43     #endif
44 #endif
45 
46 
47 #if defined(DEBUG)
48         #if defined(_MSC_VER)
49                 #define TIXMLASSERT( x )           if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
50         #elif defined (ANDROID_NDK)
51                 #include <android/log.h>
52                 #define TIXMLASSERT( x )           if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
53         #else
54                 #include <assert.h>
55                 #define TIXMLASSERT                assert
56         #endif
57 #else
58         #define TIXMLASSERT( x )           {}
59 #endif
60 
61 
62 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
63     // Microsoft visual studio, version 2005 and higher.
64     /*int _snprintf_s(
65        char *buffer,
66        size_t sizeOfBuffer,
67        size_t count,
68        const char *format [,
69           argument] ...
70     );*/
TIXML_SNPRINTF(char * buffer,size_t size,const char * format,...)71     inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) {
72         va_list va;
73         va_start( va, format );
74         int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
75         va_end( va );
76         return result;
77     }
78     #define TIXML_SSCANF   sscanf_s
79 #else
80     // GCC version 3 and higher
81     //#warning( "Using sn* functions." )
82     #define TIXML_SNPRINTF snprintf
83     #define TIXML_SSCANF   sscanf
84 #endif
85 
86 static const int TIXML2_MAJOR_VERSION = 1;
87 static const int TIXML2_MINOR_VERSION = 0;
88 static const int TIXML2_PATCH_VERSION = 6;
89 
90 namespace tinyxml2
91 {
92 class XMLDocument;
93 class XMLElement;
94 class XMLAttribute;
95 class XMLComment;
96 class XMLNode;
97 class XMLText;
98 class XMLDeclaration;
99 class XMLUnknown;
100 
101 class XMLPrinter;
102 
103 /*
104     A class that wraps strings. Normally stores the start and end
105     pointers into the XML file itself, and will apply normalization
106     and entity translation if actually read. Can also store (and memory
107     manage) a traditional char[]
108 */
109 class StrPair
110 {
111 public:
112     enum {
113         NEEDS_ENTITY_PROCESSING            = 0x01,
114         NEEDS_NEWLINE_NORMALIZATION        = 0x02,
115 
116         TEXT_ELEMENT        = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
117         TEXT_ELEMENT_LEAVE_ENTITIES        = NEEDS_NEWLINE_NORMALIZATION,
118         ATTRIBUTE_NAME        = 0,
119         ATTRIBUTE_VALUE        = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
120         ATTRIBUTE_VALUE_LEAVE_ENTITIES        = NEEDS_NEWLINE_NORMALIZATION,
121         COMMENT                = NEEDS_NEWLINE_NORMALIZATION
122     };
123 
StrPair()124     StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
125     ~StrPair();
126 
Set(char * _start,char * _end,int _flags)127     void Set( char* _start, char* _end, int _flags ) {
128         Reset();
129         this->start = _start; this->end = _end; this->flags = _flags | NEEDS_FLUSH;
130     }
131     const char* GetStr();
Empty()132     bool Empty() const { return start == end; }
133 
SetInternedStr(const char * str)134     void SetInternedStr( const char* str ) { Reset(); this->start = const_cast<char*>(str); }
135     void SetStr( const char* str, int flags=0 );
136 
137     char* ParseText( char* in, const char* endTag, int strFlags );
138     char* ParseName( char* in );
139 
140 
141 private:
142     void Reset();
143 
144     enum {
145         NEEDS_FLUSH = 0x100,
146         NEEDS_DELETE = 0x200
147     };
148 
149     // After parsing, if *end != 0, it can be set to zero.
150     int flags;
151     char* start;
152     char* end;
153 };
154 
155 
156 /*
157     A dynamic array of Plain Old Data. Doesn't support constructors, etc.
158     Has a small initial memory pool, so that low or no usage will not
159     cause a call to new/delete
160 */
161 template <class T, int INIT>
162 class DynArray
163 {
164 public:
165     DynArray< T, INIT >()
166     {
167         mem = pool;
168         allocated = INIT;
169         size = 0;
170     }
~DynArray()171     ~DynArray()
172     {
173         if ( mem != pool ) {
174             delete [] mem;
175         }
176     }
Push(T t)177     void Push( T t )
178     {
179         EnsureCapacity( size+1 );
180         mem[size++] = t;
181     }
182 
PushArr(int count)183     T* PushArr( int count )
184     {
185         EnsureCapacity( size+count );
186         T* ret = &mem[size];
187         size += count;
188         return ret;
189     }
Pop()190     T Pop() {
191         return mem[--size];
192     }
PopArr(int count)193     void PopArr( int count )
194     {
195         TIXMLASSERT( size >= count );
196         size -= count;
197     }
198 
Empty()199     bool Empty() const                    { return size == 0; }
200     T& operator[](int i)                { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
201     const T& operator[](int i) const    { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
Size()202     int Size() const                    { return size; }
Capacity()203     int Capacity() const                { return allocated; }
Mem()204     const T* Mem() const                { return mem; }
Mem()205     T* Mem()                            { return mem; }
206 
207 
208 private:
EnsureCapacity(int cap)209     void EnsureCapacity( int cap ) {
210         if ( cap > allocated ) {
211             int newAllocated = cap * 2;
212             T* newMem = new T[newAllocated];
213             memcpy( newMem, mem, sizeof(T)*size );    // warning: not using constructors, only works for PODs
214             if ( mem != pool ) delete [] mem;
215             mem = newMem;
216             allocated = newAllocated;
217         }
218     }
219 
220     T* mem;
221     T pool[INIT];
222     int allocated;        // objects allocated
223     int size;            // number objects in use
224 };
225 
226 
227 /*
228     Parent virtual class of a pool for fast allocation
229     and deallocation of objects.
230 */
231 class MemPool
232 {
233 public:
MemPool()234     MemPool() {}
~MemPool()235     virtual ~MemPool() {}
236 
237     virtual int ItemSize() const = 0;
238     virtual void* Alloc() = 0;
239     virtual void Free( void* ) = 0;
240 };
241 
242 
243 /*
244     Template child class to create pools of the correct type.
245 */
246 template< int SIZE >
247 class MemPoolT : public MemPool
248 {
249 public:
MemPoolT()250     MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0)    {}
~MemPoolT()251     ~MemPoolT() {
252         // Delete the blocks.
253         for( int i=0; i<blockPtrs.Size(); ++i ) {
254             delete blockPtrs[i];
255         }
256     }
257 
ItemSize()258     virtual int ItemSize() const    { return SIZE; }
CurrentAllocs()259     int CurrentAllocs() const        { return currentAllocs; }
260 
Alloc()261     virtual void* Alloc() {
262         if ( !root ) {
263             // Need a new block.
264             Block* block = new Block();
265             blockPtrs.Push( block );
266 
267             for( int i=0; i<COUNT-1; ++i ) {
268                 block->chunk[i].next = &block->chunk[i+1];
269             }
270             block->chunk[COUNT-1].next = 0;
271             root = block->chunk;
272         }
273         void* result = root;
274         root = root->next;
275 
276         ++currentAllocs;
277         if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
278         nAllocs++;
279         return result;
280     }
Free(void * mem)281     virtual void Free( void* mem ) {
282         if ( !mem ) return;
283         --currentAllocs;
284         Chunk* chunk = (Chunk*)mem;
285         memset( chunk, 0xfe, sizeof(Chunk) );
286         chunk->next = root;
287         root = chunk;
288     }
Trace(const char * name)289     void Trace( const char* name ) {
290         printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
291                  name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
292     }
293 
294 private:
295     enum { COUNT = 1024/SIZE };
296     union Chunk {
297         Chunk* next;
298         char mem[SIZE];
299     };
300     struct Block {
301         Chunk chunk[COUNT];
302     };
303     DynArray< Block*, 10 > blockPtrs;
304     Chunk* root;
305 
306     int currentAllocs;
307     int nAllocs;
308     int maxAllocs;
309 };
310 
311 
312 
313 /**
314     Implements the interface to the "Visitor pattern" (see the Accept() method.)
315     If you call the Accept() method, it requires being passed a XMLVisitor
316     class to handle callbacks. For nodes that contain other nodes (Document, Element)
317     you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
318     are simply called with Visit().
319 
320     If you return 'true' from a Visit method, recursive parsing will continue. If you return
321     false, <b>no children of this node or its sibilings</b> will be visited.
322 
323     All flavors of Visit methods have a default implementation that returns 'true' (continue
324     visiting). You need to only override methods that are interesting to you.
325 
326     Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
327 
328     You should never change the document from a callback.
329 
330     @sa XMLNode::Accept()
331 */
332 class XMLVisitor
333 {
334 public:
~XMLVisitor()335     virtual ~XMLVisitor() {}
336 
337     /// Visit a document.
VisitEnter(const XMLDocument &)338     virtual bool VisitEnter( const XMLDocument& /*doc*/ )            { return true; }
339     /// Visit a document.
VisitExit(const XMLDocument &)340     virtual bool VisitExit( const XMLDocument& /*doc*/ )            { return true; }
341 
342     /// Visit an element.
VisitEnter(const XMLElement &,const XMLAttribute *)343     virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )    { return true; }
344     /// Visit an element.
VisitExit(const XMLElement &)345     virtual bool VisitExit( const XMLElement& /*element*/ )            { return true; }
346 
347     /// Visit a declaration.
Visit(const XMLDeclaration &)348     virtual bool Visit( const XMLDeclaration& /*declaration*/ )        { return true; }
349     /// Visit a text node.
Visit(const XMLText &)350     virtual bool Visit( const XMLText& /*text*/ )                    { return true; }
351     /// Visit a comment node.
Visit(const XMLComment &)352     virtual bool Visit( const XMLComment& /*comment*/ )                { return true; }
353     /// Visit an unknown node.
Visit(const XMLUnknown &)354     virtual bool Visit( const XMLUnknown& /*unknown*/ )                { return true; }
355 };
356 
357 
358 /*
359     Utility functionality.
360 */
361 class XMLUtil
362 {
363 public:
364     // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
365     // correct, but simple, and usually works.
SkipWhiteSpace(const char * p)366     static const char* SkipWhiteSpace( const char* p )    { while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) { ++p; } return p; }
SkipWhiteSpace(char * p)367     static char* SkipWhiteSpace( char* p )                { while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) )        { ++p; } return p; }
368 
369     inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {
370         int n = 0;
371         if ( p == q ) {
372             return true;
373         }
374         while( *p && *q && *p == *q && n<nChar ) {
375             ++p; ++q; ++n;
376         }
377         if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
378             return true;
379         }
380         return false;
381     }
IsUTF8Continuation(const char p)382     inline static int IsUTF8Continuation( const char p ) { return p & 0x80; }
IsAlphaNum(unsigned char anyByte)383     inline static int IsAlphaNum( unsigned char anyByte )    { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
IsAlpha(unsigned char anyByte)384     inline static int IsAlpha( unsigned char anyByte )        { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
385 
386     static const char* ReadBOM( const char* p, bool* hasBOM );
387     // p is the starting location,
388     // the UTF-8 value of the entity will be placed in value, and length filled in.
389     static const char* GetCharacterRef( const char* p, char* value, int* length );
390     static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
391 
392     // converts primitive types to strings
393     static void ToStr( int v, char* buffer, int bufferSize );
394     static void ToStr( unsigned v, char* buffer, int bufferSize );
395     static void ToStr( bool v, char* buffer, int bufferSize );
396     static void ToStr( float v, char* buffer, int bufferSize );
397     static void ToStr( double v, char* buffer, int bufferSize );
398 
399     // converts strings to primitive types
400     static bool    ToInt( const char* str, int* value );
401     static bool ToUnsigned( const char* str, unsigned* value );
402     static bool    ToBool( const char* str, bool* value );
403     static bool    ToFloat( const char* str, float* value );
404     static bool ToDouble( const char* str, double* value );
405 };
406 
407 
408 /** XMLNode is a base class for every object that is in the
409     XML Document Object Model (DOM), except XMLAttributes.
410     Nodes have siblings, a parent, and children which can
411     be navigated. A node is always in a XMLDocument.
412     The type of a XMLNode can be queried, and it can
413     be cast to its more defined type.
414 
415     A XMLDocument allocates memory for all its Nodes.
416     When the XMLDocument gets deleted, all its Nodes
417     will also be deleted.
418 
419     @verbatim
420     A Document can contain:    Element    (container or leaf)
421                             Comment (leaf)
422                             Unknown (leaf)
423                             Declaration( leaf )
424 
425     An Element can contain:    Element (container or leaf)
426                             Text    (leaf)
427                             Attributes (not on tree)
428                             Comment (leaf)
429                             Unknown (leaf)
430 
431     @endverbatim
432 */
433 class XMLNode
434 {
435     friend class XMLDocument;
436     friend class XMLElement;
437 public:
438 
439     /// Get the XMLDocument that owns this XMLNode.
GetDocument()440     const XMLDocument* GetDocument() const    { return document; }
441     /// Get the XMLDocument that owns this XMLNode.
GetDocument()442     XMLDocument* GetDocument()                { return document; }
443 
ToElement()444     virtual XMLElement*        ToElement()        { return 0; }    ///< Safely cast to an Element, or null.
ToText()445     virtual XMLText*        ToText()        { return 0; }    ///< Safely cast to Text, or null.
ToComment()446     virtual XMLComment*        ToComment()        { return 0; }    ///< Safely cast to a Comment, or null.
ToDocument()447     virtual XMLDocument*    ToDocument()    { return 0; }    ///< Safely cast to a Document, or null.
ToDeclaration()448     virtual XMLDeclaration*    ToDeclaration()    { return 0; }    ///< Safely cast to a Declaration, or null.
ToUnknown()449     virtual XMLUnknown*        ToUnknown()        { return 0; }    ///< Safely cast to an Unknown, or null.
450 
ToElement()451     virtual const XMLElement*        ToElement() const        { return 0; }
ToText()452     virtual const XMLText*            ToText() const            { return 0; }
ToComment()453     virtual const XMLComment*        ToComment() const        { return 0; }
ToDocument()454     virtual const XMLDocument*        ToDocument() const        { return 0; }
ToDeclaration()455     virtual const XMLDeclaration*    ToDeclaration() const    { return 0; }
ToUnknown()456     virtual const XMLUnknown*        ToUnknown() const        { return 0; }
457 
458     /** The meaning of 'value' changes for the specific type.
459         @verbatim
460         Document:    empty
461         Element:    name of the element
462         Comment:    the comment text
463         Unknown:    the tag contents
464         Text:        the text string
465         @endverbatim
466     */
Value()467     const char* Value() const            { return value.GetStr(); }
468     /** Set the Value of an XML node.
469         @sa Value()
470     */
471     void SetValue( const char* val, bool staticMem=false );
472 
473     /// Get the parent of this node on the DOM.
Parent()474     const XMLNode*    Parent() const            { return parent; }
Parent()475     XMLNode* Parent()                        { return parent; }
476 
477     /// Returns true if this node has no children.
NoChildren()478     bool NoChildren() const                    { return !firstChild; }
479 
480     /// Get the first child node, or null if none exists.
FirstChild()481     const XMLNode*  FirstChild() const        { return firstChild; }
FirstChild()482     XMLNode*        FirstChild()            { return firstChild; }
483     /** Get the first child element, or optionally the first child
484         element with the specified name.
485     */
486     const XMLElement* FirstChildElement( const char* value=0 ) const;
487     XMLElement* FirstChildElement( const char* _value=0 )    { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( _value )); }
488 
489     /// Get the last child node, or null if none exists.
LastChild()490     const XMLNode*    LastChild() const                        { return lastChild; }
LastChild()491     XMLNode*        LastChild()                                { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
492 
493     /** Get the last child element or optionally the last child
494         element with the specified name.
495     */
496     const XMLElement* LastChildElement( const char* value=0 ) const;
497     XMLElement* LastChildElement( const char* _value=0 )    { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(_value) ); }
498 
499     /// Get the previous (left) sibling node of this node.
PreviousSibling()500     const XMLNode*    PreviousSibling() const                    { return prev; }
PreviousSibling()501     XMLNode*    PreviousSibling()                            { return prev; }
502 
503     /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
504     const XMLElement*    PreviousSiblingElement( const char* value=0 ) const ;
505     XMLElement*    PreviousSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( _value ) ); }
506 
507     /// Get the next (right) sibling node of this node.
NextSibling()508     const XMLNode*    NextSibling() const                        { return next; }
NextSibling()509     XMLNode*    NextSibling()                                { return next; }
510 
511     /// Get the next (right) sibling element of this node, with an opitionally supplied name.
512     const XMLElement*    NextSiblingElement( const char* value=0 ) const;
513      XMLElement*    NextSiblingElement( const char* _value=0 )    { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( _value ) ); }
514 
515     /**
516         Add a child node as the last (right) child.
517     */
518     XMLNode* InsertEndChild( XMLNode* addThis );
519 
LinkEndChild(XMLNode * addThis)520     XMLNode* LinkEndChild( XMLNode* addThis )    { return InsertEndChild( addThis ); }
521     /**
522         Add a child node as the first (left) child.
523     */
524     XMLNode* InsertFirstChild( XMLNode* addThis );
525     /**
526         Add a node after the specified child node.
527     */
528     XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
529 
530     /**
531         Delete all the children of this node.
532     */
533     void DeleteChildren();
534 
535     /**
536         Delete a child of this node.
537     */
538     void DeleteChild( XMLNode* node );
539 
540     /**
541         Make a copy of this node, but not its children.
542         You may pass in a Document pointer that will be
543         the owner of the new Node. If the 'document' is
544         null, then the node returned will be allocated
545         from the current Document. (this->GetDocument())
546 
547         Note: if called on a XMLDocument, this will return null.
548     */
549     virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
550 
551     /**
552         Test if 2 nodes are the same, but don't test children.
553         The 2 nodes do not need to be in the same Document.
554 
555         Note: if called on a XMLDocument, this will return false.
556     */
557     virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
558 
559     /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
560         XML tree will be conditionally visited and the host will be called back
561         via the TiXmlVisitor interface.
562 
563         This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
564         the XML for the callbacks, so the performance of TinyXML is unchanged by using this
565         interface versus any other.)
566 
567         The interface has been based on ideas from:
568 
569         - http://www.saxproject.org/
570         - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
571 
572         Which are both good references for "visiting".
573 
574         An example of using Accept():
575         @verbatim
576         TiXmlPrinter printer;
577         tinyxmlDoc.Accept( &printer );
578         const char* xmlcstr = printer.CStr();
579         @endverbatim
580     */
581     virtual bool Accept( XMLVisitor* visitor ) const = 0;
582 
583     // internal
584     virtual char* ParseDeep( char*, StrPair* );
585 
586 protected:
587     XMLNode( XMLDocument* );
588     virtual ~XMLNode();
589     XMLNode( const XMLNode& );    // not supported
590     XMLNode& operator=( const XMLNode& );    // not supported
591 
592     XMLDocument*    document;
593     XMLNode*        parent;
594     mutable StrPair    value;
595 
596     XMLNode*        firstChild;
597     XMLNode*        lastChild;
598 
599     XMLNode*        prev;
600     XMLNode*        next;
601 
602 private:
603     MemPool*        memPool;
604     void Unlink( XMLNode* child );
605 };
606 
607 
608 /** XML text.
609 
610     Note that a text node can have child element nodes, for example:
611     @verbatim
612     <root>This is <b>bold</b></root>
613     @endverbatim
614 
615     A text node can have 2 ways to output the next. "normal" output
616     and CDATA. It will default to the mode it was parsed from the XML file and
617     you generally want to leave it alone, but you can change the output mode with
618     SetCDATA() and query it with CDATA().
619 */
620 class XMLText : public XMLNode
621 {
622     friend class XMLBase;
623     friend class XMLDocument;
624 public:
625     virtual bool Accept( XMLVisitor* visitor ) const;
626 
ToText()627     virtual XMLText*    ToText()            { return this; }
ToText()628     virtual const XMLText*    ToText() const    { return this; }
629 
630     /// Declare whether this should be CDATA or standard text.
SetCData(bool _isCData)631     void SetCData( bool _isCData )            { this->isCData = _isCData; }
632     /// Returns true if this is a CDATA text element.
CData()633     bool CData() const                        { return isCData; }
634 
635     char* ParseDeep( char*, StrPair* endTag );
636     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
637     virtual bool ShallowEqual( const XMLNode* compare ) const;
638 
639 
640 protected:
XMLText(XMLDocument * doc)641     XMLText( XMLDocument* doc )    : XMLNode( doc ), isCData( false )    {}
~XMLText()642     virtual ~XMLText()                                                {}
643     XMLText( const XMLText& );    // not supported
644     XMLText& operator=( const XMLText& );    // not supported
645 
646 private:
647     bool isCData;
648 };
649 
650 
651 /** An XML Comment. */
652 class XMLComment : public XMLNode
653 {
654     friend class XMLDocument;
655 public:
ToComment()656     virtual XMLComment*    ToComment()                    { return this; }
ToComment()657     virtual const XMLComment* ToComment() const        { return this; }
658 
659     virtual bool Accept( XMLVisitor* visitor ) const;
660 
661     char* ParseDeep( char*, StrPair* endTag );
662     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
663     virtual bool ShallowEqual( const XMLNode* compare ) const;
664 
665 protected:
666     XMLComment( XMLDocument* doc );
667     virtual ~XMLComment();
668     XMLComment( const XMLComment& );    // not supported
669     XMLComment& operator=( const XMLComment& );    // not supported
670 
671 private:
672 };
673 
674 
675 /** In correct XML the declaration is the first entry in the file.
676     @verbatim
677         <?xml version="1.0" standalone="yes"?>
678     @endverbatim
679 
680     TinyXML2 will happily read or write files without a declaration,
681     however.
682 
683     The text of the declaration isn't interpreted. It is parsed
684     and written as a string.
685 */
686 class XMLDeclaration : public XMLNode
687 {
688     friend class XMLDocument;
689 public:
ToDeclaration()690     virtual XMLDeclaration*    ToDeclaration()                    { return this; }
ToDeclaration()691     virtual const XMLDeclaration* ToDeclaration() const        { return this; }
692 
693     virtual bool Accept( XMLVisitor* visitor ) const;
694 
695     char* ParseDeep( char*, StrPair* endTag );
696     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
697     virtual bool ShallowEqual( const XMLNode* compare ) const;
698 
699 protected:
700     XMLDeclaration( XMLDocument* doc );
701     virtual ~XMLDeclaration();
702     XMLDeclaration( const XMLDeclaration& );    // not supported
703     XMLDeclaration& operator=( const XMLDeclaration& );    // not supported
704 };
705 
706 
707 /** Any tag that tinyXml doesn't recognize is saved as an
708     unknown. It is a tag of text, but should not be modified.
709     It will be written back to the XML, unchanged, when the file
710     is saved.
711 
712     DTD tags get thrown into TiXmlUnknowns.
713 */
714 class XMLUnknown : public XMLNode
715 {
716     friend class XMLDocument;
717 public:
ToUnknown()718     virtual XMLUnknown*    ToUnknown()                    { return this; }
ToUnknown()719     virtual const XMLUnknown* ToUnknown() const        { return this; }
720 
721     virtual bool Accept( XMLVisitor* visitor ) const;
722 
723     char* ParseDeep( char*, StrPair* endTag );
724     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
725     virtual bool ShallowEqual( const XMLNode* compare ) const;
726 
727 protected:
728     XMLUnknown( XMLDocument* doc );
729     virtual ~XMLUnknown();
730     XMLUnknown( const XMLUnknown& );    // not supported
731     XMLUnknown& operator=( const XMLUnknown& );    // not supported
732 };
733 
734 
735 enum {
736     XML_NO_ERROR = 0,
737     XML_SUCCESS = 0,
738 
739     XML_NO_ATTRIBUTE,
740     XML_WRONG_ATTRIBUTE_TYPE,
741 
742     XML_ERROR_FILE_NOT_FOUND,
743     XML_ERROR_FILE_COULD_NOT_BE_OPENED,
744     XML_ERROR_FILE_READ_ERROR,
745     XML_ERROR_ELEMENT_MISMATCH,
746     XML_ERROR_PARSING_ELEMENT,
747     XML_ERROR_PARSING_ATTRIBUTE,
748     XML_ERROR_IDENTIFYING_TAG,
749     XML_ERROR_PARSING_TEXT,
750     XML_ERROR_PARSING_CDATA,
751     XML_ERROR_PARSING_COMMENT,
752     XML_ERROR_PARSING_DECLARATION,
753     XML_ERROR_PARSING_UNKNOWN,
754     XML_ERROR_EMPTY_DOCUMENT,
755     XML_ERROR_MISMATCHED_ELEMENT,
756     XML_ERROR_PARSING,
757 
758     XML_CAN_NOT_CONVERT_TEXT,
759     XML_NO_TEXT_NODE
760 };
761 
762 
763 /** An attribute is a name-value pair. Elements have an arbitrary
764     number of attributes, each with a unique name.
765 
766     @note The attributes are not XMLNodes. You may only query the
767     Next() attribute in a list.
768 */
769 class XMLAttribute
770 {
771     friend class XMLElement;
772 public:
Name()773     const char* Name() const { return name.GetStr(); }            ///< The name of the attribute.
Value()774     const char* Value() const { return value.GetStr(); }        ///< The value of the attribute.
Next()775     const XMLAttribute* Next() const { return next; }            ///< The next attribute in the list.
776 
777     /** IntAttribute interprets the attribute as an integer, and returns the value.
778         If the value isn't an integer, 0 will be returned. There is no error checking;
779         use QueryIntAttribute() if you need error checking.
780     */
IntValue()781     int         IntValue() const                { int i=0;        QueryIntValue( &i );        return i; }
782     /// Query as an unsigned integer. See IntAttribute()
UnsignedValue()783     unsigned UnsignedValue() const            { unsigned i=0; QueryUnsignedValue( &i );    return i; }
784     /// Query as a boolean. See IntAttribute()
BoolValue()785     bool     BoolValue() const                { bool b=false; QueryBoolValue( &b );        return b; }
786     /// Query as a double. See IntAttribute()
DoubleValue()787     double      DoubleValue() const            { double d=0;    QueryDoubleValue( &d );        return d; }
788     /// Query as a float. See IntAttribute()
FloatValue()789     float     FloatValue() const                { float f=0;    QueryFloatValue( &f );        return f; }
790 
791     /** QueryIntAttribute interprets the attribute as an integer, and returns the value
792         in the provided paremeter. The function will return XML_NO_ERROR on success,
793         and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
794     */
795     int QueryIntValue( int* value ) const;
796     /// See QueryIntAttribute
797     int QueryUnsignedValue( unsigned int* value ) const;
798     /// See QueryIntAttribute
799     int QueryBoolValue( bool* value ) const;
800     /// See QueryIntAttribute
801     int QueryDoubleValue( double* value ) const;
802     /// See QueryIntAttribute
803     int QueryFloatValue( float* value ) const;
804 
805     /// Set the attribute to a string value.
806     void SetAttribute( const char* value );
807     /// Set the attribute to value.
808     void SetAttribute( int value );
809     /// Set the attribute to value.
810     void SetAttribute( unsigned value );
811     /// Set the attribute to value.
812     void SetAttribute( bool value );
813     /// Set the attribute to value.
814     void SetAttribute( double value );
815     /// Set the attribute to value.
816     void SetAttribute( float value );
817 
818 private:
819     enum { BUF_SIZE = 200 };
820 
XMLAttribute()821     XMLAttribute() : next( 0 ) {}
~XMLAttribute()822     virtual ~XMLAttribute()    {}
823     XMLAttribute( const XMLAttribute& );    // not supported
824     void operator=( const XMLAttribute& );    // not supported
825     void SetName( const char* name );
826 
827     char* ParseDeep( char* p, bool processEntities );
828 
829     mutable StrPair name;
830     mutable StrPair value;
831     XMLAttribute* next;
832     MemPool* memPool;
833 };
834 
835 
836 /** The element is a container class. It has a value, the element name,
837     and can contain other elements, text, comments, and unknowns.
838     Elements also contain an arbitrary number of attributes.
839 */
840 class XMLElement : public XMLNode
841 {
842     friend class XMLBase;
843     friend class XMLDocument;
844 public:
845     /// Get the name of an element (which is the Value() of the node.)
Name()846     const char* Name() const        { return Value(); }
847     /// Set the name of the element.
848     void SetName( const char* str, bool staticMem=false )    { SetValue( str, staticMem ); }
849 
ToElement()850     virtual XMLElement* ToElement()                { return this; }
ToElement()851     virtual const XMLElement* ToElement() const { return this; }
852     virtual bool Accept( XMLVisitor* visitor ) const;
853 
854     /** Given an attribute name, Attribute() returns the value
855         for the attribute of that name, or null if none
856         exists. For example:
857 
858         @verbatim
859         const char* value = ele->Attribute( "foo" );
860         @endverbatim
861 
862         The 'value' parameter is normally null. However, if specified,
863         the attribute will only be returned if the 'name' and 'value'
864         match. This allow you to write code:
865 
866         @verbatim
867         if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
868         @endverbatim
869 
870         rather than:
871         @verbatim
872         if ( ele->Attribute( "foo" ) ) {
873             if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
874         }
875         @endverbatim
876     */
877     const char* Attribute( const char* name, const char* value=0 ) const;
878 
879     /** Given an attribute name, IntAttribute() returns the value
880         of the attribute interpreted as an integer. 0 will be
881         returned if there is an error. For a method with error
882         checking, see QueryIntAttribute()
883     */
IntAttribute(const char * name)884     int         IntAttribute( const char* name ) const        { int i=0;        QueryIntAttribute( name, &i );        return i; }
885     /// See IntAttribute()
UnsignedAttribute(const char * name)886     unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; }
887     /// See IntAttribute()
BoolAttribute(const char * name)888     bool     BoolAttribute( const char* name ) const    { bool b=false; QueryBoolAttribute( name, &b );        return b; }
889     /// See IntAttribute()
DoubleAttribute(const char * name)890     double      DoubleAttribute( const char* name ) const    { double d=0;    QueryDoubleAttribute( name, &d );    return d; }
891     /// See IntAttribute()
FloatAttribute(const char * name)892     float     FloatAttribute( const char* name ) const    { float f=0;    QueryFloatAttribute( name, &f );    return f; }
893 
894     /** Given an attribute name, QueryIntAttribute() returns
895         XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
896         can't be performed, or XML_NO_ATTRIBUTE if the attribute
897         doesn't exist. If successful, the result of the conversion
898         will be written to 'value'. If not successful, nothing will
899         be written to 'value'. This allows you to provide default
900         value:
901 
902         @verbatim
903         int value = 10;
904         QueryIntAttribute( "foo", &value );        // if "foo" isn't found, value will still be 10
905         @endverbatim
906     */
QueryIntAttribute(const char * name,int * _value)907     int QueryIntAttribute( const char* name, int* _value ) const                { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryIntValue( _value ); }
908     /// See QueryIntAttribute()
QueryUnsignedAttribute(const char * name,unsigned int * _value)909     int QueryUnsignedAttribute( const char* name, unsigned int* _value ) const    { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryUnsignedValue( _value ); }
910     /// See QueryIntAttribute()
QueryBoolAttribute(const char * name,bool * _value)911     int QueryBoolAttribute( const char* name, bool* _value ) const                { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryBoolValue( _value ); }
912     /// See QueryIntAttribute()
QueryDoubleAttribute(const char * name,double * _value)913     int QueryDoubleAttribute( const char* name, double* _value ) const            { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryDoubleValue( _value ); }
914     /// See QueryIntAttribute()
QueryFloatAttribute(const char * name,float * _value)915     int QueryFloatAttribute( const char* name, float* _value ) const            { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryFloatValue( _value ); }
916 
917     /// Sets the named attribute to value.
SetAttribute(const char * name,const char * _value)918     void SetAttribute( const char* name, const char* _value )    { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
919     /// Sets the named attribute to value.
SetAttribute(const char * name,int _value)920     void SetAttribute( const char* name, int _value )            { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
921     /// Sets the named attribute to value.
SetAttribute(const char * name,unsigned _value)922     void SetAttribute( const char* name, unsigned _value )        { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
923     /// Sets the named attribute to value.
SetAttribute(const char * name,bool _value)924     void SetAttribute( const char* name, bool _value )            { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
925     /// Sets the named attribute to value.
SetAttribute(const char * name,double _value)926     void SetAttribute( const char* name, double _value )        { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
927 
928     /**
929         Delete an attribute.
930     */
931     void DeleteAttribute( const char* name );
932 
933     /// Return the first attribute in the list.
FirstAttribute()934     const XMLAttribute* FirstAttribute() const { return rootAttribute; }
935     /// Query a specific attribute in the list.
936     const XMLAttribute* FindAttribute( const char* name ) const;
937 
938     /** Convenience function for easy access to the text inside an element. Although easy
939         and concise, GetText() is limited compared to getting the TiXmlText child
940         and accessing it directly.
941 
942         If the first child of 'this' is a TiXmlText, the GetText()
943         returns the character string of the Text node, else null is returned.
944 
945         This is a convenient method for getting the text of simple contained text:
946         @verbatim
947         <foo>This is text</foo>
948             const char* str = fooElement->GetText();
949         @endverbatim
950 
951         'str' will be a pointer to "This is text".
952 
953         Note that this function can be misleading. If the element foo was created from
954         this XML:
955         @verbatim
956             <foo><b>This is text</b></foo>
957         @endverbatim
958 
959         then the value of str would be null. The first child node isn't a text node, it is
960         another element. From this XML:
961         @verbatim
962             <foo>This is <b>text</b></foo>
963         @endverbatim
964         GetText() will return "This is ".
965     */
966     const char* GetText() const;
967 
968     /**
969         Convenience method to query the value of a child text node. This is probably best
970         shown by example. Given you have a document is this form:
971         @verbatim
972             <point>
973                 <x>1</x>
974                 <y>1.4</y>
975             </point>
976         @endverbatim
977 
978         The QueryIntText() and similar functions provide a safe and easier way to get to the
979         "value" of x and y.
980 
981         @verbatim
982             int x = 0;
983             float y = 0;    // types of x and y are contrived for example
984             const XMLElement* xElement = pointElement->FirstChildElement( "x" );
985             const XMLElement* yElement = pointElement->FirstChildElement( "y" );
986             xElement->QueryIntText( &x );
987             yElement->QueryFloatText( &y );
988         @endverbatim
989 
990         @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
991                  to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
992 
993     */
994     int QueryIntText( int* _value ) const;
995     /// See QueryIntText()
996     int QueryUnsignedText( unsigned* _value ) const;
997     /// See QueryIntText()
998     int QueryBoolText( bool* _value ) const;
999     /// See QueryIntText()
1000     int QueryDoubleText( double* _value ) const;
1001     /// See QueryIntText()
1002     int QueryFloatText( float* _value ) const;
1003 
1004     // internal:
1005     enum {
1006         OPEN,        // <foo>
1007         CLOSED,        // <foo/>
1008         CLOSING        // </foo>
1009     };
ClosingType()1010     int ClosingType() const { return closingType; }
1011     char* ParseDeep( char* p, StrPair* endTag );
1012     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1013     virtual bool ShallowEqual( const XMLNode* compare ) const;
1014 
1015 private:
1016     XMLElement( XMLDocument* doc );
1017     virtual ~XMLElement();
1018     XMLElement( const XMLElement& );    // not supported
1019     void operator=( const XMLElement& );    // not supported
1020 
1021     XMLAttribute* FindAttribute( const char* name );
1022     XMLAttribute* FindOrCreateAttribute( const char* name );
1023     //void LinkAttribute( XMLAttribute* attrib );
1024     char* ParseAttributes( char* p );
1025 
1026     int closingType;
1027     // The attribute list is ordered; there is no 'lastAttribute'
1028     // because the list needs to be scanned for dupes before adding
1029     // a new attribute.
1030     XMLAttribute* rootAttribute;
1031 };
1032 
1033 
1034 /** A Document binds together all the functionality.
1035     It can be saved, loaded, and printed to the screen.
1036     All Nodes are connected and allocated to a Document.
1037     If the Document is deleted, all its Nodes are also deleted.
1038 */
1039 class XMLDocument : public XMLNode
1040 {
1041     friend class XMLElement;
1042 public:
1043     /// constructor
1044     XMLDocument( bool processEntities = true );
1045     ~XMLDocument();
1046 
ToDocument()1047     virtual XMLDocument* ToDocument()                { return this; }
ToDocument()1048     virtual const XMLDocument* ToDocument() const    { return this; }
1049 
1050     /**
1051         Parse an XML file from a character string.
1052         Returns XML_NO_ERROR (0) on success, or
1053         an errorID.
1054     */
1055     int Parse( const char* xml );
1056 
1057     /**
1058         Load an XML file from disk.
1059         Returns XML_NO_ERROR (0) on success, or
1060         an errorID.
1061     */
1062     int LoadFile( const char* filename );
1063 
1064     /**
1065         Load an XML file from disk. You are responsible
1066         for providing and closing the FILE*.
1067 
1068         Returns XML_NO_ERROR (0) on success, or
1069         an errorID.
1070     */
1071     int LoadFile( FILE* );
1072 
1073     /**
1074         Save the XML file to disk.
1075         Returns XML_NO_ERROR (0) on success, or
1076         an errorID.
1077     */
1078     int SaveFile( const char* filename );
1079 
1080     /**
1081         Save the XML file to disk. You are responsible
1082         for providing and closing the FILE*.
1083 
1084         Returns XML_NO_ERROR (0) on success, or
1085         an errorID.
1086     */
1087     int SaveFile( FILE* );
1088 
ProcessEntities()1089     bool ProcessEntities() const                        { return processEntities; }
1090 
1091     /**
1092         Returns true if this document has a leading Byte Order Mark of UTF8.
1093     */
HasBOM()1094     bool HasBOM() const { return writeBOM; }
1095     /** Sets whether to write the BOM when writing the file.
1096     */
SetBOM(bool useBOM)1097     void SetBOM( bool useBOM ) { writeBOM = useBOM; }
1098 
1099     /** Return the root element of DOM. Equivalent to FirstChildElement().
1100         To get the first node, use FirstChild().
1101     */
RootElement()1102     XMLElement* RootElement()                { return FirstChildElement(); }
RootElement()1103     const XMLElement* RootElement() const    { return FirstChildElement(); }
1104 
1105     /** Print the Document. If the Printer is not provided, it will
1106         print to stdout. If you provide Printer, this can print to a file:
1107         @verbatim
1108         XMLPrinter printer( fp );
1109         doc.Print( &printer );
1110         @endverbatim
1111 
1112         Or you can use a printer to print to memory:
1113         @verbatim
1114         XMLPrinter printer;
1115         doc->Print( &printer );
1116         // printer.CStr() has a const char* to the XML
1117         @endverbatim
1118     */
1119     void Print( XMLPrinter* streamer=0 );
1120     virtual bool Accept( XMLVisitor* visitor ) const;
1121 
1122     /**
1123         Create a new Element associated with
1124         this Document. The memory for the Element
1125         is managed by the Document.
1126     */
1127     XMLElement* NewElement( const char* name );
1128     /**
1129         Create a new Comment associated with
1130         this Document. The memory for the Comment
1131         is managed by the Document.
1132     */
1133     XMLComment* NewComment( const char* comment );
1134     /**
1135         Create a new Text associated with
1136         this Document. The memory for the Text
1137         is managed by the Document.
1138     */
1139     XMLText* NewText( const char* text );
1140     /**
1141         Create a new Declaration associated with
1142         this Document. The memory for the object
1143         is managed by the Document.
1144 
1145         If the 'text' param is null, the standard
1146         declaration is used.:
1147         @verbatim
1148             <?xml version="1.0" encoding="UTF-8"?>
1149         @endverbatim
1150     */
1151     XMLDeclaration* NewDeclaration( const char* text=0 );
1152     /**
1153         Create a new Unknown associated with
1154         this Document. The memory for the object
1155         is managed by the Document.
1156     */
1157     XMLUnknown* NewUnknown( const char* text );
1158 
1159     /**
1160         Delete a node associated with this document.
1161         It will be unlinked from the DOM.
1162     */
DeleteNode(XMLNode * node)1163     void DeleteNode( XMLNode* node )    { node->parent->DeleteChild( node ); }
1164 
1165     void SetError( int error, const char* str1, const char* str2 );
1166 
1167     /// Return true if there was an error parsing the document.
Error()1168     bool Error() const { return errorID != XML_NO_ERROR; }
1169     /// Return the errorID.
ErrorID()1170     int  ErrorID() const { return errorID; }
1171     /// Return a possibly helpful diagnostic location or string.
GetErrorStr1()1172     const char* GetErrorStr1() const { return errorStr1; }
1173     /// Return a possibly helpful secondary diagnostic location or string.
GetErrorStr2()1174     const char* GetErrorStr2() const { return errorStr2; }
1175     /// If there is an error, print it to stdout.
1176     void PrintError() const;
1177 
1178     // internal
1179     char* Identify( char* p, XMLNode** node );
1180 
ShallowClone(XMLDocument *)1181     virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const    { return 0; }
ShallowEqual(const XMLNode *)1182     virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const    { return false; }
1183 
1184 private:
1185     XMLDocument( const XMLDocument& );    // not supported
1186     void operator=( const XMLDocument& );    // not supported
1187     void InitDocument();
1188 
1189     bool writeBOM;
1190     bool processEntities;
1191     int errorID;
1192     const char* errorStr1;
1193     const char* errorStr2;
1194     char* charBuffer;
1195 
1196     MemPoolT< sizeof(XMLElement) >    elementPool;
1197     MemPoolT< sizeof(XMLAttribute) > attributePool;
1198     MemPoolT< sizeof(XMLText) >        textPool;
1199     MemPoolT< sizeof(XMLComment) >    commentPool;
1200 };
1201 
1202 
1203 /**
1204     A XMLHandle is a class that wraps a node pointer with null checks; this is
1205     an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
1206     DOM structure. It is a separate utility class.
1207 
1208     Take an example:
1209     @verbatim
1210     <Document>
1211         <Element attributeA = "valueA">
1212             <Child attributeB = "value1" />
1213             <Child attributeB = "value2" />
1214         </Element>
1215     </Document>
1216     @endverbatim
1217 
1218     Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
1219     easy to write a *lot* of code that looks like:
1220 
1221     @verbatim
1222     XMLElement* root = document.FirstChildElement( "Document" );
1223     if ( root )
1224     {
1225         XMLElement* element = root->FirstChildElement( "Element" );
1226         if ( element )
1227         {
1228             XMLElement* child = element->FirstChildElement( "Child" );
1229             if ( child )
1230             {
1231                 XMLElement* child2 = child->NextSiblingElement( "Child" );
1232                 if ( child2 )
1233                 {
1234                     // Finally do something useful.
1235     @endverbatim
1236 
1237     And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
1238     of such code. A XMLHandle checks for null pointers so it is perfectly safe
1239     and correct to use:
1240 
1241     @verbatim
1242     XMLHandle docHandle( &document );
1243     XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
1244     if ( child2 )
1245     {
1246         // do something useful
1247     @endverbatim
1248 
1249     Which is MUCH more concise and useful.
1250 
1251     It is also safe to copy handles - internally they are nothing more than node pointers.
1252     @verbatim
1253     XMLHandle handleCopy = handle;
1254     @endverbatim
1255 
1256     See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
1257 */
1258 class XMLHandle
1259 {
1260 public:
1261     /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
XMLHandle(XMLNode * _node)1262     XMLHandle( XMLNode* _node )                                                { node = _node; }
1263     /// Create a handle from a node.
XMLHandle(XMLNode & _node)1264     XMLHandle( XMLNode& _node )                                                { node = &_node; }
1265     /// Copy constructor
XMLHandle(const XMLHandle & ref)1266     XMLHandle( const XMLHandle& ref )                                        { node = ref.node; }
1267     /// Assignment
1268     XMLHandle& operator=( const XMLHandle& ref )                            { node = ref.node; return *this; }
1269 
1270     /// Get the first child of this handle.
FirstChild()1271     XMLHandle FirstChild()                                                     { return XMLHandle( node ? node->FirstChild() : 0 ); }
1272     /// Get the first child element of this handle.
1273     XMLHandle FirstChildElement( const char* value=0 )                        { return XMLHandle( node ? node->FirstChildElement( value ) : 0 ); }
1274     /// Get the last child of this handle.
LastChild()1275     XMLHandle LastChild()                                                    { return XMLHandle( node ? node->LastChild() : 0 ); }
1276     /// Get the last child element of this handle.
1277     XMLHandle LastChildElement( const char* _value=0 )                        { return XMLHandle( node ? node->LastChildElement( _value ) : 0 ); }
1278     /// Get the previous sibling of this handle.
PreviousSibling()1279     XMLHandle PreviousSibling()                                                { return XMLHandle( node ? node->PreviousSibling() : 0 ); }
1280     /// Get the previous sibling element of this handle.
1281     XMLHandle PreviousSiblingElement( const char* _value=0 )                { return XMLHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
1282     /// Get the next sibling of this handle.
NextSibling()1283     XMLHandle NextSibling()                                                    { return XMLHandle( node ? node->NextSibling() : 0 ); }
1284     /// Get the next sibling element of this handle.
1285     XMLHandle NextSiblingElement( const char* _value=0 )                    { return XMLHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
1286 
1287     /// Safe cast to XMLNode. This can return null.
ToNode()1288     XMLNode* ToNode()                            { return node; }
1289     /// Safe cast to XMLElement. This can return null.
ToElement()1290     XMLElement* ToElement()                     { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
1291     /// Safe cast to XMLText. This can return null.
ToText()1292     XMLText* ToText()                             { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
1293     /// Safe cast to XMLUnknown. This can return null.
ToUnknown()1294     XMLUnknown* ToUnknown()                     { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
1295     /// Safe cast to XMLDeclaration. This can return null.
ToDeclaration()1296     XMLDeclaration* ToDeclaration()             { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
1297 
1298 private:
1299     XMLNode* node;
1300 };
1301 
1302 
1303 /**
1304     A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1305     same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
1306 */
1307 class XMLConstHandle
1308 {
1309 public:
XMLConstHandle(const XMLNode * _node)1310     XMLConstHandle( const XMLNode* _node )                                            { node = _node; }
XMLConstHandle(const XMLNode & _node)1311     XMLConstHandle( const XMLNode& _node )                                            { node = &_node; }
XMLConstHandle(const XMLConstHandle & ref)1312     XMLConstHandle( const XMLConstHandle& ref )                                        { node = ref.node; }
1313 
1314     XMLConstHandle& operator=( const XMLConstHandle& ref )                            { node = ref.node; return *this; }
1315 
FirstChild()1316     const XMLConstHandle FirstChild() const                                            { return XMLConstHandle( node ? node->FirstChild() : 0 ); }
1317     const XMLConstHandle FirstChildElement( const char* value=0 ) const                { return XMLConstHandle( node ? node->FirstChildElement( value ) : 0 ); }
LastChild()1318     const XMLConstHandle LastChild()    const                                        { return XMLConstHandle( node ? node->LastChild() : 0 ); }
1319     const XMLConstHandle LastChildElement( const char* _value=0 ) const                { return XMLConstHandle( node ? node->LastChildElement( _value ) : 0 ); }
PreviousSibling()1320     const XMLConstHandle PreviousSibling() const                                    { return XMLConstHandle( node ? node->PreviousSibling() : 0 ); }
1321     const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const        { return XMLConstHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
NextSibling()1322     const XMLConstHandle NextSibling() const                                        { return XMLConstHandle( node ? node->NextSibling() : 0 ); }
1323     const XMLConstHandle NextSiblingElement( const char* _value=0 ) const            { return XMLConstHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
1324 
1325 
ToNode()1326     const XMLNode* ToNode() const                { return node; }
ToElement()1327     const XMLElement* ToElement() const            { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
ToText()1328     const XMLText* ToText() const                { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
ToUnknown()1329     const XMLUnknown* ToUnknown() const            { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
ToDeclaration()1330     const XMLDeclaration* ToDeclaration() const    { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
1331 
1332 private:
1333     const XMLNode* node;
1334 };
1335 
1336 
1337 /**
1338     Printing functionality. The XMLPrinter gives you more
1339     options than the XMLDocument::Print() method.
1340 
1341     It can:
1342     -# Print to memory.
1343     -# Print to a file you provide.
1344     -# Print XML without a XMLDocument.
1345 
1346     Print to Memory
1347 
1348     @verbatim
1349     XMLPrinter printer;
1350     doc->Print( &printer );
1351     SomeFunction( printer.CStr() );
1352     @endverbatim
1353 
1354     Print to a File
1355 
1356     You provide the file pointer.
1357     @verbatim
1358     XMLPrinter printer( fp );
1359     doc.Print( &printer );
1360     @endverbatim
1361 
1362     Print without a XMLDocument
1363 
1364     When loading, an XML parser is very useful. However, sometimes
1365     when saving, it just gets in the way. The code is often set up
1366     for streaming, and constructing the DOM is just overhead.
1367 
1368     The Printer supports the streaming case. The following code
1369     prints out a trivially simple XML file without ever creating
1370     an XML document.
1371 
1372     @verbatim
1373     XMLPrinter printer( fp );
1374     printer.OpenElement( "foo" );
1375     printer.PushAttribute( "foo", "bar" );
1376     printer.CloseElement();
1377     @endverbatim
1378 */
1379 class XMLPrinter : public XMLVisitor
1380 {
1381 public:
1382     /** Construct the printer. If the FILE* is specified,
1383         this will print to the FILE. Else it will print
1384         to memory, and the result is available in CStr().
1385         If 'compact' is set to true, then output is created
1386         with only required whitespace and newlines.
1387     */
1388     XMLPrinter( FILE* file=0, bool compact = false );
~XMLPrinter()1389     ~XMLPrinter()    {}
1390 
1391     /** If streaming, write the BOM and declaration. */
1392     void PushHeader( bool writeBOM, bool writeDeclaration );
1393     /** If streaming, start writing an element.
1394         The element must be closed with CloseElement()
1395     */
1396     void OpenElement( const char* name );
1397     /// If streaming, add an attribute to an open element.
1398     void PushAttribute( const char* name, const char* value );
1399     void PushAttribute( const char* name, int value );
1400     void PushAttribute( const char* name, unsigned value );
1401     void PushAttribute( const char* name, bool value );
1402     void PushAttribute( const char* name, double value );
1403     /// If streaming, close the Element.
1404     void CloseElement();
1405 
1406     /// Add a text node.
1407     void PushText( const char* text, bool cdata=false );
1408     /// Add a text node from an integer.
1409     void PushText( int value );
1410     /// Add a text node from an unsigned.
1411     void PushText( unsigned value );
1412     /// Add a text node from a bool.
1413     void PushText( bool value );
1414     /// Add a text node from a float.
1415     void PushText( float value );
1416     /// Add a text node from a double.
1417     void PushText( double value );
1418 
1419     /// Add a comment
1420     void PushComment( const char* comment );
1421 
1422     void PushDeclaration( const char* value );
1423     void PushUnknown( const char* value );
1424 
1425     virtual bool VisitEnter( const XMLDocument& /*doc*/ );
VisitExit(const XMLDocument &)1426     virtual bool VisitExit( const XMLDocument& /*doc*/ )            { return true; }
1427 
1428     virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1429     virtual bool VisitExit( const XMLElement& element );
1430 
1431     virtual bool Visit( const XMLText& text );
1432     virtual bool Visit( const XMLComment& comment );
1433     virtual bool Visit( const XMLDeclaration& declaration );
1434     virtual bool Visit( const XMLUnknown& unknown );
1435 
1436     /**
1437         If in print to memory mode, return a pointer to
1438         the XML file in memory.
1439     */
CStr()1440     const char* CStr() const { return buffer.Mem(); }
1441     /**
1442            If in print to memory mode, return the size
1443         of the XML file in memory. (Note the size returned
1444         includes the terminating null.)
1445       */
CStrSize()1446       int CStrSize() const { return buffer.Size(); }
1447 
1448 private:
1449     void SealElement();
1450     void PrintSpace( int depth );
1451     void PrintString( const char*, bool restrictedEntitySet );    // prints out, after detecting entities.
1452     void Print( const char* format, ... );
1453 
1454     bool elementJustOpened;
1455     bool firstElement;
1456     FILE* fp;
1457     int depth;
1458     int textDepth;
1459     bool processEntities;
1460     bool compactMode;
1461 
1462     enum {
1463         ENTITY_RANGE = 64,
1464         BUF_SIZE = 200
1465     };
1466     bool entityFlag[ENTITY_RANGE];
1467     bool restrictedEntityFlag[ENTITY_RANGE];
1468 
1469     DynArray< const char*, 10 > stack;
1470     DynArray< char, 20 > buffer;
1471 #ifdef _MSC_VER
1472     DynArray< char, 20 > accumulator;
1473 #endif
1474 };
1475 
1476 
1477 }    // tinyxml2
1478 
1479 
1480 #endif // TINYXML2_INCLUDED
1481