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 #if defined(ANDROID_NDK) || defined(__BORLANDC__)
28 #   include <ctype.h>
29 #   include <limits.h>
30 #   include <stdio.h>
31 #   include <stdlib.h>
32 #   include <string.h>
33 #   include <stdarg.h>
34 #else
35 #   include <cctype>
36 #   include <climits>
37 #   include <cstdio>
38 #   include <cstdlib>
39 #   include <cstring>
40 #   include <cstdarg>
41 #endif
42 
43 /*
44    TODO: intern strings instead of allocation.
45 */
46 /*
47 	gcc:
48         g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
49 
50     Formatting, Artistic Style:
51         AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
52 */
53 
54 #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
55 #   ifndef DEBUG
56 #       define DEBUG
57 #   endif
58 #endif
59 
60 
61 #if defined(DEBUG)
62 #   if defined(_MSC_VER)
63 #       define TIXMLASSERT( x )           if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
64 #   elif defined (ANDROID_NDK)
65 #       include <android/log.h>
66 #       define TIXMLASSERT( x )           if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
67 #   else
68 #       include <assert.h>
69 #       define TIXMLASSERT                assert
70 #   endif
71 #   else
72 #       define TIXMLASSERT( x )           {}
73 #endif
74 
75 
76 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
77 // Microsoft visual studio, version 2005 and higher.
78 /*int _snprintf_s(
79    char *buffer,
80    size_t sizeOfBuffer,
81    size_t count,
82    const char *format [,
83 	  argument] ...
84 );*/
TIXML_SNPRINTF(char * buffer,size_t size,const char * format,...)85 inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
86 {
87     va_list va;
88     va_start( va, format );
89     int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
90     va_end( va );
91     return result;
92 }
93 #define TIXML_SSCANF   sscanf_s
94 #else
95 // GCC version 3 and higher
96 //#warning( "Using sn* functions." )
97 #define TIXML_SNPRINTF snprintf
98 #define TIXML_SSCANF   sscanf
99 #endif
100 
101 static const int TIXML2_MAJOR_VERSION = 1;
102 static const int TIXML2_MINOR_VERSION = 0;
103 static const int TIXML2_PATCH_VERSION = 11;
104 
105 namespace tinyxml2
106 {
107 class XMLDocument;
108 class XMLElement;
109 class XMLAttribute;
110 class XMLComment;
111 class XMLNode;
112 class XMLText;
113 class XMLDeclaration;
114 class XMLUnknown;
115 
116 class XMLPrinter;
117 
118 /*
119 	A class that wraps strings. Normally stores the start and end
120 	pointers into the XML file itself, and will apply normalization
121 	and entity translation if actually read. Can also store (and memory
122 	manage) a traditional char[]
123 */
124 class StrPair
125 {
126 public:
127     enum {
128         NEEDS_ENTITY_PROCESSING			= 0x01,
129         NEEDS_NEWLINE_NORMALIZATION		= 0x02,
130         COLLAPSE_WHITESPACE	                = 0x04,
131 
132         TEXT_ELEMENT		            	= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
133         TEXT_ELEMENT_LEAVE_ENTITIES		= NEEDS_NEWLINE_NORMALIZATION,
134         ATTRIBUTE_NAME		            	= 0,
135         ATTRIBUTE_VALUE		            	= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
136         ATTRIBUTE_VALUE_LEAVE_ENTITIES  	= NEEDS_NEWLINE_NORMALIZATION,
137         COMMENT				        = NEEDS_NEWLINE_NORMALIZATION
138     };
139 
StrPair()140     StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
141     ~StrPair();
142 
Set(char * start,char * end,int flags)143     void Set( char* start, char* end, int flags ) {
144         Reset();
145         _start  = start;
146         _end    = end;
147         _flags  = flags | NEEDS_FLUSH;
148     }
149 
150     const char* GetStr();
151 
Empty()152     bool Empty() const {
153         return _start == _end;
154     }
155 
SetInternedStr(const char * str)156     void SetInternedStr( const char* str ) {
157         Reset();
158         _start = const_cast<char*>(str);
159     }
160 
161     void SetStr( const char* str, int flags=0 );
162 
163     char* ParseText( char* in, const char* endTag, int strFlags );
164     char* ParseName( char* in );
165 
166 private:
167     void Reset();
168     void CollapseWhitespace();
169 
170     enum {
171         NEEDS_FLUSH = 0x100,
172         NEEDS_DELETE = 0x200
173     };
174 
175     // After parsing, if *_end != 0, it can be set to zero.
176     int     _flags;
177     char*   _start;
178     char*   _end;
179 };
180 
181 
182 /*
183 	A dynamic array of Plain Old Data. Doesn't support constructors, etc.
184 	Has a small initial memory pool, so that low or no usage will not
185 	cause a call to new/delete
186 */
187 template <class T, int INIT>
188 class DynArray
189 {
190 public:
191     DynArray< T, INIT >() {
192         _mem = _pool;
193         _allocated = INIT;
194         _size = 0;
195     }
196 
~DynArray()197     ~DynArray() {
198         if ( _mem != _pool ) {
199             delete [] _mem;
200         }
201     }
202 
Push(T t)203     void Push( T t ) {
204         EnsureCapacity( _size+1 );
205         _mem[_size++] = t;
206     }
207 
PushArr(int count)208     T* PushArr( int count ) {
209         EnsureCapacity( _size+count );
210         T* ret = &_mem[_size];
211         _size += count;
212         return ret;
213     }
214 
Pop()215     T Pop() {
216         return _mem[--_size];
217     }
218 
PopArr(int count)219     void PopArr( int count ) {
220         TIXMLASSERT( _size >= count );
221         _size -= count;
222     }
223 
Empty()224     bool Empty() const					{
225         return _size == 0;
226     }
227 
228     T& operator[](int i)				{
229         TIXMLASSERT( i>= 0 && i < _size );
230         return _mem[i];
231     }
232 
233     const T& operator[](int i) const	{
234         TIXMLASSERT( i>= 0 && i < _size );
235         return _mem[i];
236     }
237 
Size()238     int Size() const					{
239         return _size;
240     }
241 
Capacity()242     int Capacity() const				{
243         return _allocated;
244     }
245 
Mem()246     const T* Mem() const				{
247         return _mem;
248     }
249 
Mem()250     T* Mem()							{
251         return _mem;
252     }
253 
254 private:
EnsureCapacity(int cap)255     void EnsureCapacity( int cap ) {
256         if ( cap > _allocated ) {
257             int newAllocated = cap * 2;
258             T* newMem = new T[newAllocated];
259             memcpy( newMem, _mem, sizeof(T)*_size );	// warning: not using constructors, only works for PODs
260             if ( _mem != _pool ) {
261                 delete [] _mem;
262             }
263             _mem = newMem;
264             _allocated = newAllocated;
265         }
266     }
267 
268     T*  _mem;
269     T   _pool[INIT];
270     int _allocated;		// objects allocated
271     int _size;			// number objects in use
272 };
273 
274 
275 /*
276 	Parent virtual class of a pool for fast allocation
277 	and deallocation of objects.
278 */
279 class MemPool
280 {
281 public:
MemPool()282     MemPool() {}
~MemPool()283     virtual ~MemPool() {}
284 
285     virtual int ItemSize() const = 0;
286     virtual void* Alloc() = 0;
287     virtual void Free( void* ) = 0;
288     virtual void SetTracked() = 0;
289 };
290 
291 
292 /*
293 	Template child class to create pools of the correct type.
294 */
295 template< int SIZE >
296 class MemPoolT : public MemPool
297 {
298 public:
MemPoolT()299     MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0)	{}
~MemPoolT()300     ~MemPoolT() {
301         // Delete the blocks.
302         for( int i=0; i<_blockPtrs.Size(); ++i ) {
303             delete _blockPtrs[i];
304         }
305     }
306 
ItemSize()307     virtual int ItemSize() const	{
308         return SIZE;
309     }
CurrentAllocs()310     int CurrentAllocs() const		{
311         return _currentAllocs;
312     }
313 
Alloc()314     virtual void* Alloc() {
315         if ( !_root ) {
316             // Need a new block.
317             Block* block = new Block();
318             _blockPtrs.Push( block );
319 
320             for( int i=0; i<COUNT-1; ++i ) {
321                 block->chunk[i].next = &block->chunk[i+1];
322             }
323             block->chunk[COUNT-1].next = 0;
324             _root = block->chunk;
325         }
326         void* result = _root;
327         _root = _root->next;
328 
329         ++_currentAllocs;
330         if ( _currentAllocs > _maxAllocs ) {
331             _maxAllocs = _currentAllocs;
332         }
333         _nAllocs++;
334         _nUntracked++;
335         return result;
336     }
Free(void * mem)337     virtual void Free( void* mem ) {
338         if ( !mem ) {
339             return;
340         }
341         --_currentAllocs;
342         Chunk* chunk = (Chunk*)mem;
343 #ifdef DEBUG
344         memset( chunk, 0xfe, sizeof(Chunk) );
345 #endif
346         chunk->next = _root;
347         _root = chunk;
348     }
Trace(const char * name)349     void Trace( const char* name ) {
350         printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
351                 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
352     }
353 
SetTracked()354     void SetTracked() {
355         _nUntracked--;
356     }
357 
Untracked()358     int Untracked() const {
359         return _nUntracked;
360     }
361 
362 	// This number is perf sensitive. 4k seems like a good tradeoff on my machine.
363 	// The test file is large, 170k.
364 	// Release:		VS2010 gcc(no opt)
365 	//		1k:		4000
366 	//		2k:		4000
367 	//		4k:		3900	21000
368 	//		16k:	5200
369 	//		32k:	4300
370 	//		64k:	4000	21000
371     enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
372 
373 private:
374     union Chunk {
375         Chunk*  next;
376         char    mem[SIZE];
377     };
378     struct Block {
379         Chunk chunk[COUNT];
380     };
381     DynArray< Block*, 10 > _blockPtrs;
382     Chunk* _root;
383 
384     int _currentAllocs;
385     int _nAllocs;
386     int _maxAllocs;
387     int _nUntracked;
388 };
389 
390 
391 
392 /**
393 	Implements the interface to the "Visitor pattern" (see the Accept() method.)
394 	If you call the Accept() method, it requires being passed a XMLVisitor
395 	class to handle callbacks. For nodes that contain other nodes (Document, Element)
396 	you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
397 	are simply called with Visit().
398 
399 	If you return 'true' from a Visit method, recursive parsing will continue. If you return
400 	false, <b>no children of this node or its siblings</b> will be visited.
401 
402 	All flavors of Visit methods have a default implementation that returns 'true' (continue
403 	visiting). You need to only override methods that are interesting to you.
404 
405 	Generally Accept() is called on the XMLDocument, although all nodes support visiting.
406 
407 	You should never change the document from a callback.
408 
409 	@sa XMLNode::Accept()
410 */
411 class XMLVisitor
412 {
413 public:
~XMLVisitor()414     virtual ~XMLVisitor() {}
415 
416     /// Visit a document.
VisitEnter(const XMLDocument &)417     virtual bool VisitEnter( const XMLDocument& /*doc*/ )			{
418         return true;
419     }
420     /// Visit a document.
VisitExit(const XMLDocument &)421     virtual bool VisitExit( const XMLDocument& /*doc*/ )			{
422         return true;
423     }
424 
425     /// Visit an element.
VisitEnter(const XMLElement &,const XMLAttribute *)426     virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )	{
427         return true;
428     }
429     /// Visit an element.
VisitExit(const XMLElement &)430     virtual bool VisitExit( const XMLElement& /*element*/ )			{
431         return true;
432     }
433 
434     /// Visit a declaration.
Visit(const XMLDeclaration &)435     virtual bool Visit( const XMLDeclaration& /*declaration*/ )		{
436         return true;
437     }
438     /// Visit a text node.
Visit(const XMLText &)439     virtual bool Visit( const XMLText& /*text*/ )					{
440         return true;
441     }
442     /// Visit a comment node.
Visit(const XMLComment &)443     virtual bool Visit( const XMLComment& /*comment*/ )				{
444         return true;
445     }
446     /// Visit an unknown node.
Visit(const XMLUnknown &)447     virtual bool Visit( const XMLUnknown& /*unknown*/ )				{
448         return true;
449     }
450 };
451 
452 
453 /*
454 	Utility functionality.
455 */
456 class XMLUtil
457 {
458 public:
459     // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
460     // correct, but simple, and usually works.
SkipWhiteSpace(const char * p)461     static const char* SkipWhiteSpace( const char* p )	{
462         while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
463             ++p;
464         }
465         return p;
466     }
SkipWhiteSpace(char * p)467     static char* SkipWhiteSpace( char* p )				{
468         while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) )		{
469             ++p;
470         }
471         return p;
472     }
IsWhiteSpace(char p)473     static bool IsWhiteSpace( char p )					{
474         return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
475     }
476 
IsNameStartChar(unsigned char ch)477     inline static bool IsNameStartChar( unsigned char ch ) {
478         return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
479                || ch == ':'
480                || ch == '_';
481     }
482 
IsNameChar(unsigned char ch)483     inline static bool IsNameChar( unsigned char ch ) {
484         return IsNameStartChar( ch )
485                || isdigit( ch )
486                || ch == '.'
487                || ch == '-';
488     }
489 
490     inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {
491         int n = 0;
492         if ( p == q ) {
493             return true;
494         }
495         while( *p && *q && *p == *q && n<nChar ) {
496             ++p;
497             ++q;
498             ++n;
499         }
500         if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
501             return true;
502         }
503         return false;
504     }
505 
IsUTF8Continuation(const char p)506     inline static int IsUTF8Continuation( const char p ) {
507         return p & 0x80;
508     }
509 
510     static const char* ReadBOM( const char* p, bool* hasBOM );
511     // p is the starting location,
512     // the UTF-8 value of the entity will be placed in value, and length filled in.
513     static const char* GetCharacterRef( const char* p, char* value, int* length );
514     static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
515 
516     // converts primitive types to strings
517     static void ToStr( int v, char* buffer, int bufferSize );
518     static void ToStr( unsigned v, char* buffer, int bufferSize );
519     static void ToStr( bool v, char* buffer, int bufferSize );
520     static void ToStr( float v, char* buffer, int bufferSize );
521     static void ToStr( double v, char* buffer, int bufferSize );
522 
523     // converts strings to primitive types
524     static bool	ToInt( const char* str, int* value );
525     static bool ToUnsigned( const char* str, unsigned* value );
526     static bool	ToBool( const char* str, bool* value );
527     static bool	ToFloat( const char* str, float* value );
528     static bool ToDouble( const char* str, double* value );
529 };
530 
531 
532 /** XMLNode is a base class for every object that is in the
533 	XML Document Object Model (DOM), except XMLAttributes.
534 	Nodes have siblings, a parent, and children which can
535 	be navigated. A node is always in a XMLDocument.
536 	The type of a XMLNode can be queried, and it can
537 	be cast to its more defined type.
538 
539 	A XMLDocument allocates memory for all its Nodes.
540 	When the XMLDocument gets deleted, all its Nodes
541 	will also be deleted.
542 
543 	@verbatim
544 	A Document can contain:	Element	(container or leaf)
545 							Comment (leaf)
546 							Unknown (leaf)
547 							Declaration( leaf )
548 
549 	An Element can contain:	Element (container or leaf)
550 							Text	(leaf)
551 							Attributes (not on tree)
552 							Comment (leaf)
553 							Unknown (leaf)
554 
555 	@endverbatim
556 */
557 class XMLNode
558 {
559     friend class XMLDocument;
560     friend class XMLElement;
561 public:
562 
563     /// Get the XMLDocument that owns this XMLNode.
GetDocument()564     const XMLDocument* GetDocument() const	{
565         return _document;
566     }
567     /// Get the XMLDocument that owns this XMLNode.
GetDocument()568     XMLDocument* GetDocument()				{
569         return _document;
570     }
571 
572     /// Safely cast to an Element, or null.
ToElement()573     virtual XMLElement*		ToElement()		{
574         return 0;
575     }
576     /// Safely cast to Text, or null.
ToText()577     virtual XMLText*		ToText()		{
578         return 0;
579     }
580     /// Safely cast to a Comment, or null.
ToComment()581     virtual XMLComment*		ToComment()		{
582         return 0;
583     }
584     /// Safely cast to a Document, or null.
ToDocument()585     virtual XMLDocument*	ToDocument()	{
586         return 0;
587     }
588     /// Safely cast to a Declaration, or null.
ToDeclaration()589     virtual XMLDeclaration*	ToDeclaration()	{
590         return 0;
591     }
592     /// Safely cast to an Unknown, or null.
ToUnknown()593     virtual XMLUnknown*		ToUnknown()		{
594         return 0;
595     }
596 
ToElement()597     virtual const XMLElement*		ToElement() const		{
598         return 0;
599     }
ToText()600     virtual const XMLText*			ToText() const			{
601         return 0;
602     }
ToComment()603     virtual const XMLComment*		ToComment() const		{
604         return 0;
605     }
ToDocument()606     virtual const XMLDocument*		ToDocument() const		{
607         return 0;
608     }
ToDeclaration()609     virtual const XMLDeclaration*	ToDeclaration() const	{
610         return 0;
611     }
ToUnknown()612     virtual const XMLUnknown*		ToUnknown() const		{
613         return 0;
614     }
615 
616     /** The meaning of 'value' changes for the specific type.
617     	@verbatim
618     	Document:	empty
619     	Element:	name of the element
620     	Comment:	the comment text
621     	Unknown:	the tag contents
622     	Text:		the text string
623     	@endverbatim
624     */
Value()625     const char* Value() const			{
626         return _value.GetStr();
627     }
628 
629     /** Set the Value of an XML node.
630     	@sa Value()
631     */
632     void SetValue( const char* val, bool staticMem=false );
633 
634     /// Get the parent of this node on the DOM.
Parent()635     const XMLNode*	Parent() const			{
636         return _parent;
637     }
638 
Parent()639     XMLNode* Parent()						{
640         return _parent;
641     }
642 
643     /// Returns true if this node has no children.
NoChildren()644     bool NoChildren() const					{
645         return !_firstChild;
646     }
647 
648     /// Get the first child node, or null if none exists.
FirstChild()649     const XMLNode*  FirstChild() const		{
650         return _firstChild;
651     }
652 
FirstChild()653     XMLNode*		FirstChild()			{
654         return _firstChild;
655     }
656 
657     /** Get the first child element, or optionally the first child
658         element with the specified name.
659     */
660     const XMLElement* FirstChildElement( const char* value=0 ) const;
661 
662     XMLElement* FirstChildElement( const char* value=0 )	{
663         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
664     }
665 
666     /// Get the last child node, or null if none exists.
LastChild()667     const XMLNode*	LastChild() const						{
668         return _lastChild;
669     }
670 
LastChild()671     XMLNode*		LastChild()								{
672         return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
673     }
674 
675     /** Get the last child element or optionally the last child
676         element with the specified name.
677     */
678     const XMLElement* LastChildElement( const char* value=0 ) const;
679 
680     XMLElement* LastChildElement( const char* value=0 )	{
681         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
682     }
683 
684     /// Get the previous (left) sibling node of this node.
PreviousSibling()685     const XMLNode*	PreviousSibling() const					{
686         return _prev;
687     }
688 
PreviousSibling()689     XMLNode*	PreviousSibling()							{
690         return _prev;
691     }
692 
693     /// Get the previous (left) sibling element of this node, with an optionally supplied name.
694     const XMLElement*	PreviousSiblingElement( const char* value=0 ) const ;
695 
696     XMLElement*	PreviousSiblingElement( const char* value=0 ) {
697         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
698     }
699 
700     /// Get the next (right) sibling node of this node.
NextSibling()701     const XMLNode*	NextSibling() const						{
702         return _next;
703     }
704 
NextSibling()705     XMLNode*	NextSibling()								{
706         return _next;
707     }
708 
709     /// Get the next (right) sibling element of this node, with an optionally supplied name.
710     const XMLElement*	NextSiblingElement( const char* value=0 ) const;
711 
712     XMLElement*	NextSiblingElement( const char* value=0 )	{
713         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
714     }
715 
716     /**
717     	Add a child node as the last (right) child.
718     */
719     XMLNode* InsertEndChild( XMLNode* addThis );
720 
LinkEndChild(XMLNode * addThis)721     XMLNode* LinkEndChild( XMLNode* addThis )	{
722         return InsertEndChild( addThis );
723     }
724     /**
725     	Add a child node as the first (left) child.
726     */
727     XMLNode* InsertFirstChild( XMLNode* addThis );
728     /**
729     	Add a node after the specified child node.
730     */
731     XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
732 
733     /**
734     	Delete all the children of this node.
735     */
736     void DeleteChildren();
737 
738     /**
739     	Delete a child of this node.
740     */
741     void DeleteChild( XMLNode* node );
742 
743     /**
744     	Make a copy of this node, but not its children.
745     	You may pass in a Document pointer that will be
746     	the owner of the new Node. If the 'document' is
747     	null, then the node returned will be allocated
748     	from the current Document. (this->GetDocument())
749 
750     	Note: if called on a XMLDocument, this will return null.
751     */
752     virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
753 
754     /**
755     	Test if 2 nodes are the same, but don't test children.
756     	The 2 nodes do not need to be in the same Document.
757 
758     	Note: if called on a XMLDocument, this will return false.
759     */
760     virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
761 
762     /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
763     	XML tree will be conditionally visited and the host will be called back
764     	via the XMLVisitor interface.
765 
766     	This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
767     	the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
768     	interface versus any other.)
769 
770     	The interface has been based on ideas from:
771 
772     	- http://www.saxproject.org/
773     	- http://c2.com/cgi/wiki?HierarchicalVisitorPattern
774 
775     	Which are both good references for "visiting".
776 
777     	An example of using Accept():
778     	@verbatim
779     	XMLPrinter printer;
780     	tinyxmlDoc.Accept( &printer );
781     	const char* xmlcstr = printer.CStr();
782     	@endverbatim
783     */
784     virtual bool Accept( XMLVisitor* visitor ) const = 0;
785 
786     // internal
787     virtual char* ParseDeep( char*, StrPair* );
788 
789 protected:
790     XMLNode( XMLDocument* );
791     virtual ~XMLNode();
792     XMLNode( const XMLNode& );	// not supported
793     XMLNode& operator=( const XMLNode& );	// not supported
794 
795     XMLDocument*	_document;
796     XMLNode*		_parent;
797     mutable StrPair	_value;
798 
799     XMLNode*		_firstChild;
800     XMLNode*		_lastChild;
801 
802     XMLNode*		_prev;
803     XMLNode*		_next;
804 
805 private:
806     MemPool*		_memPool;
807     void Unlink( XMLNode* child );
808 };
809 
810 
811 /** XML text.
812 
813 	Note that a text node can have child element nodes, for example:
814 	@verbatim
815 	<root>This is <b>bold</b></root>
816 	@endverbatim
817 
818 	A text node can have 2 ways to output the next. "normal" output
819 	and CDATA. It will default to the mode it was parsed from the XML file and
820 	you generally want to leave it alone, but you can change the output mode with
821 	SetCData() and query it with CData().
822 */
823 class XMLText : public XMLNode
824 {
825     friend class XMLBase;
826     friend class XMLDocument;
827 public:
828     virtual bool Accept( XMLVisitor* visitor ) const;
829 
ToText()830     virtual XMLText* ToText()			{
831         return this;
832     }
ToText()833     virtual const XMLText* ToText() const	{
834         return this;
835     }
836 
837     /// Declare whether this should be CDATA or standard text.
SetCData(bool isCData)838     void SetCData( bool isCData )			{
839         _isCData = isCData;
840     }
841     /// Returns true if this is a CDATA text element.
CData()842     bool CData() const						{
843         return _isCData;
844     }
845 
846     char* ParseDeep( char*, StrPair* endTag );
847     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
848     virtual bool ShallowEqual( const XMLNode* compare ) const;
849 
850 protected:
XMLText(XMLDocument * doc)851     XMLText( XMLDocument* doc )	: XMLNode( doc ), _isCData( false )	{}
~XMLText()852     virtual ~XMLText()												{}
853     XMLText( const XMLText& );	// not supported
854     XMLText& operator=( const XMLText& );	// not supported
855 
856 private:
857     bool _isCData;
858 };
859 
860 
861 /** An XML Comment. */
862 class XMLComment : public XMLNode
863 {
864     friend class XMLDocument;
865 public:
ToComment()866     virtual XMLComment*	ToComment()					{
867         return this;
868     }
ToComment()869     virtual const XMLComment* ToComment() const		{
870         return this;
871     }
872 
873     virtual bool Accept( XMLVisitor* visitor ) const;
874 
875     char* ParseDeep( char*, StrPair* endTag );
876     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
877     virtual bool ShallowEqual( const XMLNode* compare ) const;
878 
879 protected:
880     XMLComment( XMLDocument* doc );
881     virtual ~XMLComment();
882     XMLComment( const XMLComment& );	// not supported
883     XMLComment& operator=( const XMLComment& );	// not supported
884 
885 private:
886 };
887 
888 
889 /** In correct XML the declaration is the first entry in the file.
890 	@verbatim
891 		<?xml version="1.0" standalone="yes"?>
892 	@endverbatim
893 
894 	TinyXML-2 will happily read or write files without a declaration,
895 	however.
896 
897 	The text of the declaration isn't interpreted. It is parsed
898 	and written as a string.
899 */
900 class XMLDeclaration : public XMLNode
901 {
902     friend class XMLDocument;
903 public:
ToDeclaration()904     virtual XMLDeclaration*	ToDeclaration()					{
905         return this;
906     }
ToDeclaration()907     virtual const XMLDeclaration* ToDeclaration() const		{
908         return this;
909     }
910 
911     virtual bool Accept( XMLVisitor* visitor ) const;
912 
913     char* ParseDeep( char*, StrPair* endTag );
914     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
915     virtual bool ShallowEqual( const XMLNode* compare ) const;
916 
917 protected:
918     XMLDeclaration( XMLDocument* doc );
919     virtual ~XMLDeclaration();
920     XMLDeclaration( const XMLDeclaration& );	// not supported
921     XMLDeclaration& operator=( const XMLDeclaration& );	// not supported
922 };
923 
924 
925 /** Any tag that TinyXML-2 doesn't recognize is saved as an
926 	unknown. It is a tag of text, but should not be modified.
927 	It will be written back to the XML, unchanged, when the file
928 	is saved.
929 
930 	DTD tags get thrown into XMLUnknowns.
931 */
932 class XMLUnknown : public XMLNode
933 {
934     friend class XMLDocument;
935 public:
ToUnknown()936     virtual XMLUnknown*	ToUnknown()					{
937         return this;
938     }
ToUnknown()939     virtual const XMLUnknown* ToUnknown() const		{
940         return this;
941     }
942 
943     virtual bool Accept( XMLVisitor* visitor ) const;
944 
945     char* ParseDeep( char*, StrPair* endTag );
946     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
947     virtual bool ShallowEqual( const XMLNode* compare ) const;
948 
949 protected:
950     XMLUnknown( XMLDocument* doc );
951     virtual ~XMLUnknown();
952     XMLUnknown( const XMLUnknown& );	// not supported
953     XMLUnknown& operator=( const XMLUnknown& );	// not supported
954 };
955 
956 
957 enum XMLError {
958     XML_NO_ERROR = 0,
959     XML_SUCCESS = 0,
960 
961     XML_NO_ATTRIBUTE,
962     XML_WRONG_ATTRIBUTE_TYPE,
963 
964     XML_ERROR_FILE_NOT_FOUND,
965     XML_ERROR_FILE_COULD_NOT_BE_OPENED,
966     XML_ERROR_FILE_READ_ERROR,
967     XML_ERROR_ELEMENT_MISMATCH,
968     XML_ERROR_PARSING_ELEMENT,
969     XML_ERROR_PARSING_ATTRIBUTE,
970     XML_ERROR_IDENTIFYING_TAG,
971     XML_ERROR_PARSING_TEXT,
972     XML_ERROR_PARSING_CDATA,
973     XML_ERROR_PARSING_COMMENT,
974     XML_ERROR_PARSING_DECLARATION,
975     XML_ERROR_PARSING_UNKNOWN,
976     XML_ERROR_EMPTY_DOCUMENT,
977     XML_ERROR_MISMATCHED_ELEMENT,
978     XML_ERROR_PARSING,
979 
980     XML_CAN_NOT_CONVERT_TEXT,
981     XML_NO_TEXT_NODE
982 };
983 
984 
985 /** An attribute is a name-value pair. Elements have an arbitrary
986 	number of attributes, each with a unique name.
987 
988 	@note The attributes are not XMLNodes. You may only query the
989 	Next() attribute in a list.
990 */
991 class XMLAttribute
992 {
993     friend class XMLElement;
994 public:
995     /// The name of the attribute.
Name()996     const char* Name() const {
997         return _name.GetStr();
998     }
999     /// The value of the attribute.
Value()1000     const char* Value() const {
1001         return _value.GetStr();
1002     }
1003     /// The next attribute in the list.
Next()1004     const XMLAttribute* Next() const {
1005         return _next;
1006     }
1007 
1008     /** IntValue interprets the attribute as an integer, and returns the value.
1009         If the value isn't an integer, 0 will be returned. There is no error checking;
1010     	use QueryIntValue() if you need error checking.
1011     */
IntValue()1012     int		 IntValue() const				{
1013         int i=0;
1014         QueryIntValue( &i );
1015         return i;
1016     }
1017     /// Query as an unsigned integer. See IntValue()
UnsignedValue()1018     unsigned UnsignedValue() const			{
1019         unsigned i=0;
1020         QueryUnsignedValue( &i );
1021         return i;
1022     }
1023     /// Query as a boolean. See IntValue()
BoolValue()1024     bool	 BoolValue() const				{
1025         bool b=false;
1026         QueryBoolValue( &b );
1027         return b;
1028     }
1029     /// Query as a double. See IntValue()
DoubleValue()1030     double 	 DoubleValue() const			{
1031         double d=0;
1032         QueryDoubleValue( &d );
1033         return d;
1034     }
1035     /// Query as a float. See IntValue()
FloatValue()1036     float	 FloatValue() const				{
1037         float f=0;
1038         QueryFloatValue( &f );
1039         return f;
1040     }
1041 
1042     /** QueryIntValue interprets the attribute as an integer, and returns the value
1043     	in the provided parameter. The function will return XML_NO_ERROR on success,
1044     	and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1045     */
1046     XMLError QueryIntValue( int* value ) const;
1047     /// See QueryIntValue
1048     XMLError QueryUnsignedValue( unsigned int* value ) const;
1049     /// See QueryIntValue
1050     XMLError QueryBoolValue( bool* value ) const;
1051     /// See QueryIntValue
1052     XMLError QueryDoubleValue( double* value ) const;
1053     /// See QueryIntValue
1054     XMLError QueryFloatValue( float* value ) const;
1055 
1056     /// Set the attribute to a string value.
1057     void SetAttribute( const char* value );
1058     /// Set the attribute to value.
1059     void SetAttribute( int value );
1060     /// Set the attribute to value.
1061     void SetAttribute( unsigned value );
1062     /// Set the attribute to value.
1063     void SetAttribute( bool value );
1064     /// Set the attribute to value.
1065     void SetAttribute( double value );
1066     /// Set the attribute to value.
1067     void SetAttribute( float value );
1068 
1069 private:
1070     enum { BUF_SIZE = 200 };
1071 
XMLAttribute()1072     XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
~XMLAttribute()1073     virtual ~XMLAttribute()	{}
1074 
1075     XMLAttribute( const XMLAttribute& );	// not supported
1076     void operator=( const XMLAttribute& );	// not supported
1077     void SetName( const char* name );
1078 
1079     char* ParseDeep( char* p, bool processEntities );
1080 
1081     mutable StrPair _name;
1082     mutable StrPair _value;
1083     XMLAttribute*   _next;
1084     MemPool*        _memPool;
1085 };
1086 
1087 
1088 /** The element is a container class. It has a value, the element name,
1089 	and can contain other elements, text, comments, and unknowns.
1090 	Elements also contain an arbitrary number of attributes.
1091 */
1092 class XMLElement : public XMLNode
1093 {
1094     friend class XMLBase;
1095     friend class XMLDocument;
1096 public:
1097     /// Get the name of an element (which is the Value() of the node.)
Name()1098     const char* Name() const		{
1099         return Value();
1100     }
1101     /// Set the name of the element.
1102     void SetName( const char* str, bool staticMem=false )	{
1103         SetValue( str, staticMem );
1104     }
1105 
ToElement()1106     virtual XMLElement* ToElement()				{
1107         return this;
1108     }
ToElement()1109     virtual const XMLElement* ToElement() const {
1110         return this;
1111     }
1112     virtual bool Accept( XMLVisitor* visitor ) const;
1113 
1114     /** Given an attribute name, Attribute() returns the value
1115     	for the attribute of that name, or null if none
1116     	exists. For example:
1117 
1118     	@verbatim
1119     	const char* value = ele->Attribute( "foo" );
1120     	@endverbatim
1121 
1122     	The 'value' parameter is normally null. However, if specified,
1123     	the attribute will only be returned if the 'name' and 'value'
1124     	match. This allow you to write code:
1125 
1126     	@verbatim
1127     	if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1128     	@endverbatim
1129 
1130     	rather than:
1131     	@verbatim
1132     	if ( ele->Attribute( "foo" ) ) {
1133     		if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1134     	}
1135     	@endverbatim
1136     */
1137     const char* Attribute( const char* name, const char* value=0 ) const;
1138 
1139     /** Given an attribute name, IntAttribute() returns the value
1140     	of the attribute interpreted as an integer. 0 will be
1141     	returned if there is an error. For a method with error
1142     	checking, see QueryIntAttribute()
1143     */
IntAttribute(const char * name)1144     int		 IntAttribute( const char* name ) const		{
1145         int i=0;
1146         QueryIntAttribute( name, &i );
1147         return i;
1148     }
1149     /// See IntAttribute()
UnsignedAttribute(const char * name)1150     unsigned UnsignedAttribute( const char* name ) const {
1151         unsigned i=0;
1152         QueryUnsignedAttribute( name, &i );
1153         return i;
1154     }
1155     /// See IntAttribute()
BoolAttribute(const char * name)1156     bool	 BoolAttribute( const char* name ) const	{
1157         bool b=false;
1158         QueryBoolAttribute( name, &b );
1159         return b;
1160     }
1161     /// See IntAttribute()
DoubleAttribute(const char * name)1162     double 	 DoubleAttribute( const char* name ) const	{
1163         double d=0;
1164         QueryDoubleAttribute( name, &d );
1165         return d;
1166     }
1167     /// See IntAttribute()
FloatAttribute(const char * name)1168     float	 FloatAttribute( const char* name ) const	{
1169         float f=0;
1170         QueryFloatAttribute( name, &f );
1171         return f;
1172     }
1173 
1174     /** Given an attribute name, QueryIntAttribute() returns
1175     	XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1176     	can't be performed, or XML_NO_ATTRIBUTE if the attribute
1177     	doesn't exist. If successful, the result of the conversion
1178     	will be written to 'value'. If not successful, nothing will
1179     	be written to 'value'. This allows you to provide default
1180     	value:
1181 
1182     	@verbatim
1183     	int value = 10;
1184     	QueryIntAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
1185     	@endverbatim
1186     */
QueryIntAttribute(const char * name,int * value)1187     XMLError QueryIntAttribute( const char* name, int* value ) const				{
1188         const XMLAttribute* a = FindAttribute( name );
1189         if ( !a ) {
1190             return XML_NO_ATTRIBUTE;
1191         }
1192         return a->QueryIntValue( value );
1193     }
1194     /// See QueryIntAttribute()
QueryUnsignedAttribute(const char * name,unsigned int * value)1195     XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const	{
1196         const XMLAttribute* a = FindAttribute( name );
1197         if ( !a ) {
1198             return XML_NO_ATTRIBUTE;
1199         }
1200         return a->QueryUnsignedValue( value );
1201     }
1202     /// See QueryIntAttribute()
QueryBoolAttribute(const char * name,bool * value)1203     XMLError QueryBoolAttribute( const char* name, bool* value ) const				{
1204         const XMLAttribute* a = FindAttribute( name );
1205         if ( !a ) {
1206             return XML_NO_ATTRIBUTE;
1207         }
1208         return a->QueryBoolValue( value );
1209     }
1210     /// See QueryIntAttribute()
QueryDoubleAttribute(const char * name,double * value)1211     XMLError QueryDoubleAttribute( const char* name, double* value ) const			{
1212         const XMLAttribute* a = FindAttribute( name );
1213         if ( !a ) {
1214             return XML_NO_ATTRIBUTE;
1215         }
1216         return a->QueryDoubleValue( value );
1217     }
1218     /// See QueryIntAttribute()
QueryFloatAttribute(const char * name,float * value)1219     XMLError QueryFloatAttribute( const char* name, float* value ) const			{
1220         const XMLAttribute* a = FindAttribute( name );
1221         if ( !a ) {
1222             return XML_NO_ATTRIBUTE;
1223         }
1224         return a->QueryFloatValue( value );
1225     }
1226 
1227 
1228     /** Given an attribute name, QueryAttribute() returns
1229     	XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1230     	can't be performed, or XML_NO_ATTRIBUTE if the attribute
1231     	doesn't exist. It is overloaded for the primitive types,
1232 		and is a generally more convenient replacement of
1233 		QueryIntAttribute() and related functions.
1234 
1235 		If successful, the result of the conversion
1236     	will be written to 'value'. If not successful, nothing will
1237     	be written to 'value'. This allows you to provide default
1238     	value:
1239 
1240     	@verbatim
1241     	int value = 10;
1242     	QueryAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
1243     	@endverbatim
1244     */
QueryAttribute(const char * name,int * value)1245 	int QueryAttribute( const char* name, int* value ) const {
1246 		return QueryIntAttribute( name, value );
1247 	}
1248 
QueryAttribute(const char * name,unsigned int * value)1249 	int QueryAttribute( const char* name, unsigned int* value ) const {
1250 		return QueryUnsignedAttribute( name, value );
1251 	}
1252 
QueryAttribute(const char * name,bool * value)1253 	int QueryAttribute( const char* name, bool* value ) const {
1254 		return QueryBoolAttribute( name, value );
1255 	}
1256 
QueryAttribute(const char * name,double * value)1257 	int QueryAttribute( const char* name, double* value ) const {
1258 		return QueryDoubleAttribute( name, value );
1259 	}
1260 
QueryAttribute(const char * name,float * value)1261 	int QueryAttribute( const char* name, float* value ) const {
1262 		return QueryFloatAttribute( name, value );
1263 	}
1264 
1265 	/// Sets the named attribute to value.
SetAttribute(const char * name,const char * value)1266     void SetAttribute( const char* name, const char* value )	{
1267         XMLAttribute* a = FindOrCreateAttribute( name );
1268         a->SetAttribute( value );
1269     }
1270     /// Sets the named attribute to value.
SetAttribute(const char * name,int value)1271     void SetAttribute( const char* name, int value )			{
1272         XMLAttribute* a = FindOrCreateAttribute( name );
1273         a->SetAttribute( value );
1274     }
1275     /// Sets the named attribute to value.
SetAttribute(const char * name,unsigned value)1276     void SetAttribute( const char* name, unsigned value )		{
1277         XMLAttribute* a = FindOrCreateAttribute( name );
1278         a->SetAttribute( value );
1279     }
1280     /// Sets the named attribute to value.
SetAttribute(const char * name,bool value)1281     void SetAttribute( const char* name, bool value )			{
1282         XMLAttribute* a = FindOrCreateAttribute( name );
1283         a->SetAttribute( value );
1284     }
1285     /// Sets the named attribute to value.
SetAttribute(const char * name,double value)1286     void SetAttribute( const char* name, double value )		{
1287         XMLAttribute* a = FindOrCreateAttribute( name );
1288         a->SetAttribute( value );
1289     }
1290 
1291     /**
1292     	Delete an attribute.
1293     */
1294     void DeleteAttribute( const char* name );
1295 
1296     /// Return the first attribute in the list.
FirstAttribute()1297     const XMLAttribute* FirstAttribute() const {
1298         return _rootAttribute;
1299     }
1300     /// Query a specific attribute in the list.
1301     const XMLAttribute* FindAttribute( const char* name ) const;
1302 
1303     /** Convenience function for easy access to the text inside an element. Although easy
1304     	and concise, GetText() is limited compared to getting the XMLText child
1305     	and accessing it directly.
1306 
1307     	If the first child of 'this' is a XMLText, the GetText()
1308     	returns the character string of the Text node, else null is returned.
1309 
1310     	This is a convenient method for getting the text of simple contained text:
1311     	@verbatim
1312     	<foo>This is text</foo>
1313     		const char* str = fooElement->GetText();
1314     	@endverbatim
1315 
1316     	'str' will be a pointer to "This is text".
1317 
1318     	Note that this function can be misleading. If the element foo was created from
1319     	this XML:
1320     	@verbatim
1321     		<foo><b>This is text</b></foo>
1322     	@endverbatim
1323 
1324     	then the value of str would be null. The first child node isn't a text node, it is
1325     	another element. From this XML:
1326     	@verbatim
1327     		<foo>This is <b>text</b></foo>
1328     	@endverbatim
1329     	GetText() will return "This is ".
1330     */
1331     const char* GetText() const;
1332 
1333     /**
1334     	Convenience method to query the value of a child text node. This is probably best
1335     	shown by example. Given you have a document is this form:
1336     	@verbatim
1337     		<point>
1338     			<x>1</x>
1339     			<y>1.4</y>
1340     		</point>
1341     	@endverbatim
1342 
1343     	The QueryIntText() and similar functions provide a safe and easier way to get to the
1344     	"value" of x and y.
1345 
1346     	@verbatim
1347     		int x = 0;
1348     		float y = 0;	// types of x and y are contrived for example
1349     		const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1350     		const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1351     		xElement->QueryIntText( &x );
1352     		yElement->QueryFloatText( &y );
1353     	@endverbatim
1354 
1355     	@returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1356     			 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
1357 
1358     */
1359     XMLError QueryIntText( int* ival ) const;
1360     /// See QueryIntText()
1361     XMLError QueryUnsignedText( unsigned* uval ) const;
1362     /// See QueryIntText()
1363     XMLError QueryBoolText( bool* bval ) const;
1364     /// See QueryIntText()
1365     XMLError QueryDoubleText( double* dval ) const;
1366     /// See QueryIntText()
1367     XMLError QueryFloatText( float* fval ) const;
1368 
1369     // internal:
1370     enum {
1371         OPEN,		// <foo>
1372         CLOSED,		// <foo/>
1373         CLOSING		// </foo>
1374     };
ClosingType()1375     int ClosingType() const {
1376         return _closingType;
1377     }
1378     char* ParseDeep( char* p, StrPair* endTag );
1379     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1380     virtual bool ShallowEqual( const XMLNode* compare ) const;
1381 
1382 private:
1383     XMLElement( XMLDocument* doc );
1384     virtual ~XMLElement();
1385     XMLElement( const XMLElement& );	// not supported
1386     void operator=( const XMLElement& );	// not supported
1387 
1388     XMLAttribute* FindAttribute( const char* name );
1389     XMLAttribute* FindOrCreateAttribute( const char* name );
1390     //void LinkAttribute( XMLAttribute* attrib );
1391     char* ParseAttributes( char* p );
1392 
1393     int _closingType;
1394     // The attribute list is ordered; there is no 'lastAttribute'
1395     // because the list needs to be scanned for dupes before adding
1396     // a new attribute.
1397     XMLAttribute* _rootAttribute;
1398 };
1399 
1400 
1401 enum Whitespace {
1402     PRESERVE_WHITESPACE,
1403     COLLAPSE_WHITESPACE
1404 };
1405 
1406 
1407 /** A Document binds together all the functionality.
1408 	It can be saved, loaded, and printed to the screen.
1409 	All Nodes are connected and allocated to a Document.
1410 	If the Document is deleted, all its Nodes are also deleted.
1411 */
1412 class XMLDocument : public XMLNode
1413 {
1414     friend class XMLElement;
1415 public:
1416     /// constructor
1417     XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1418     ~XMLDocument();
1419 
ToDocument()1420     virtual XMLDocument* ToDocument()				{
1421         return this;
1422     }
ToDocument()1423     virtual const XMLDocument* ToDocument() const	{
1424         return this;
1425     }
1426 
1427     /**
1428     	Parse an XML file from a character string.
1429     	Returns XML_NO_ERROR (0) on success, or
1430     	an errorID.
1431 
1432     	You may optionally pass in the 'nBytes', which is
1433     	the number of bytes which will be parsed. If not
1434     	specified, TinyXML-2 will assume 'xml' points to a
1435     	null terminated string.
1436     */
1437     XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
1438 
1439     /**
1440     	Load an XML file from disk.
1441     	Returns XML_NO_ERROR (0) on success, or
1442     	an errorID.
1443     */
1444     XMLError LoadFile( const char* filename );
1445 
1446     /**
1447     	Load an XML file from disk. You are responsible
1448     	for providing and closing the FILE*.
1449 
1450     	Returns XML_NO_ERROR (0) on success, or
1451     	an errorID.
1452     */
1453     XMLError LoadFile( FILE* );
1454 
1455     /**
1456     	Save the XML file to disk.
1457     	Returns XML_NO_ERROR (0) on success, or
1458     	an errorID.
1459     */
1460     XMLError SaveFile( const char* filename, bool compact = false );
1461 
1462     /**
1463     	Save the XML file to disk. You are responsible
1464     	for providing and closing the FILE*.
1465 
1466     	Returns XML_NO_ERROR (0) on success, or
1467     	an errorID.
1468     */
1469     XMLError SaveFile( FILE* fp, bool compact = false );
1470 
ProcessEntities()1471     bool ProcessEntities() const		{
1472         return _processEntities;
1473     }
WhitespaceMode()1474     Whitespace WhitespaceMode() const	{
1475         return _whitespace;
1476     }
1477 
1478     /**
1479     	Returns true if this document has a leading Byte Order Mark of UTF8.
1480     */
HasBOM()1481     bool HasBOM() const {
1482         return _writeBOM;
1483     }
1484     /** Sets whether to write the BOM when writing the file.
1485     */
SetBOM(bool useBOM)1486     void SetBOM( bool useBOM ) {
1487         _writeBOM = useBOM;
1488     }
1489 
1490     /** Return the root element of DOM. Equivalent to FirstChildElement().
1491         To get the first node, use FirstChild().
1492     */
RootElement()1493     XMLElement* RootElement()				{
1494         return FirstChildElement();
1495     }
RootElement()1496     const XMLElement* RootElement() const	{
1497         return FirstChildElement();
1498     }
1499 
1500     /** Print the Document. If the Printer is not provided, it will
1501         print to stdout. If you provide Printer, this can print to a file:
1502     	@verbatim
1503     	XMLPrinter printer( fp );
1504     	doc.Print( &printer );
1505     	@endverbatim
1506 
1507     	Or you can use a printer to print to memory:
1508     	@verbatim
1509     	XMLPrinter printer;
1510     	doc.Print( &printer );
1511     	// printer.CStr() has a const char* to the XML
1512     	@endverbatim
1513     */
1514     void Print( XMLPrinter* streamer=0 );
1515     virtual bool Accept( XMLVisitor* visitor ) const;
1516 
1517     /**
1518     	Create a new Element associated with
1519     	this Document. The memory for the Element
1520     	is managed by the Document.
1521     */
1522     XMLElement* NewElement( const char* name );
1523     /**
1524     	Create a new Comment associated with
1525     	this Document. The memory for the Comment
1526     	is managed by the Document.
1527     */
1528     XMLComment* NewComment( const char* comment );
1529     /**
1530     	Create a new Text associated with
1531     	this Document. The memory for the Text
1532     	is managed by the Document.
1533     */
1534     XMLText* NewText( const char* text );
1535     /**
1536     	Create a new Declaration associated with
1537     	this Document. The memory for the object
1538     	is managed by the Document.
1539 
1540     	If the 'text' param is null, the standard
1541     	declaration is used.:
1542     	@verbatim
1543     		<?xml version="1.0" encoding="UTF-8"?>
1544     	@endverbatim
1545     */
1546     XMLDeclaration* NewDeclaration( const char* text=0 );
1547     /**
1548     	Create a new Unknown associated with
1549     	this Document. The memory for the object
1550     	is managed by the Document.
1551     */
1552     XMLUnknown* NewUnknown( const char* text );
1553 
1554     /**
1555     	Delete a node associated with this document.
1556     	It will be unlinked from the DOM.
1557     */
DeleteNode(XMLNode * node)1558     void DeleteNode( XMLNode* node )	{
1559         node->_parent->DeleteChild( node );
1560     }
1561 
1562     void SetError( XMLError error, const char* str1, const char* str2 );
1563 
1564     /// Return true if there was an error parsing the document.
Error()1565     bool Error() const {
1566         return _errorID != XML_NO_ERROR;
1567     }
1568     /// Return the errorID.
ErrorID()1569     XMLError  ErrorID() const {
1570         return _errorID;
1571     }
1572     /// Return a possibly helpful diagnostic location or string.
GetErrorStr1()1573     const char* GetErrorStr1() const {
1574         return _errorStr1;
1575     }
1576     /// Return a possibly helpful secondary diagnostic location or string.
GetErrorStr2()1577     const char* GetErrorStr2() const {
1578         return _errorStr2;
1579     }
1580     /// If there is an error, print it to stdout.
1581     void PrintError() const;
1582 
1583     /// Clear the document, resetting it to the initial state.
1584     void Clear();
1585 
1586     // internal
1587     char* Identify( char* p, XMLNode** node );
1588 
ShallowClone(XMLDocument *)1589     virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const	{
1590         return 0;
1591     }
ShallowEqual(const XMLNode *)1592     virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const	{
1593         return false;
1594     }
1595 
1596 private:
1597     XMLDocument( const XMLDocument& );	// not supported
1598     void operator=( const XMLDocument& );	// not supported
1599 
1600     bool        _writeBOM;
1601     bool        _processEntities;
1602     XMLError    _errorID;
1603     Whitespace  _whitespace;
1604     const char* _errorStr1;
1605     const char* _errorStr2;
1606     char*       _charBuffer;
1607 
1608     MemPoolT< sizeof(XMLElement) >	 _elementPool;
1609     MemPoolT< sizeof(XMLAttribute) > _attributePool;
1610     MemPoolT< sizeof(XMLText) >		 _textPool;
1611     MemPoolT< sizeof(XMLComment) >	 _commentPool;
1612 };
1613 
1614 
1615 /**
1616 	A XMLHandle is a class that wraps a node pointer with null checks; this is
1617 	an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
1618 	DOM structure. It is a separate utility class.
1619 
1620 	Take an example:
1621 	@verbatim
1622 	<Document>
1623 		<Element attributeA = "valueA">
1624 			<Child attributeB = "value1" />
1625 			<Child attributeB = "value2" />
1626 		</Element>
1627 	</Document>
1628 	@endverbatim
1629 
1630 	Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
1631 	easy to write a *lot* of code that looks like:
1632 
1633 	@verbatim
1634 	XMLElement* root = document.FirstChildElement( "Document" );
1635 	if ( root )
1636 	{
1637 		XMLElement* element = root->FirstChildElement( "Element" );
1638 		if ( element )
1639 		{
1640 			XMLElement* child = element->FirstChildElement( "Child" );
1641 			if ( child )
1642 			{
1643 				XMLElement* child2 = child->NextSiblingElement( "Child" );
1644 				if ( child2 )
1645 				{
1646 					// Finally do something useful.
1647 	@endverbatim
1648 
1649 	And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
1650 	of such code. A XMLHandle checks for null pointers so it is perfectly safe
1651 	and correct to use:
1652 
1653 	@verbatim
1654 	XMLHandle docHandle( &document );
1655 	XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
1656 	if ( child2 )
1657 	{
1658 		// do something useful
1659 	@endverbatim
1660 
1661 	Which is MUCH more concise and useful.
1662 
1663 	It is also safe to copy handles - internally they are nothing more than node pointers.
1664 	@verbatim
1665 	XMLHandle handleCopy = handle;
1666 	@endverbatim
1667 
1668 	See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
1669 */
1670 class XMLHandle
1671 {
1672 public:
1673     /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
XMLHandle(XMLNode * node)1674     XMLHandle( XMLNode* node )												{
1675         _node = node;
1676     }
1677     /// Create a handle from a node.
XMLHandle(XMLNode & node)1678     XMLHandle( XMLNode& node )												{
1679         _node = &node;
1680     }
1681     /// Copy constructor
XMLHandle(const XMLHandle & ref)1682     XMLHandle( const XMLHandle& ref )										{
1683         _node = ref._node;
1684     }
1685     /// Assignment
1686     XMLHandle& operator=( const XMLHandle& ref )							{
1687         _node = ref._node;
1688         return *this;
1689     }
1690 
1691     /// Get the first child of this handle.
FirstChild()1692     XMLHandle FirstChild() 													{
1693         return XMLHandle( _node ? _node->FirstChild() : 0 );
1694     }
1695     /// Get the first child element of this handle.
1696     XMLHandle FirstChildElement( const char* value=0 )						{
1697         return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
1698     }
1699     /// Get the last child of this handle.
LastChild()1700     XMLHandle LastChild()													{
1701         return XMLHandle( _node ? _node->LastChild() : 0 );
1702     }
1703     /// Get the last child element of this handle.
1704     XMLHandle LastChildElement( const char* _value=0 )						{
1705         return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
1706     }
1707     /// Get the previous sibling of this handle.
PreviousSibling()1708     XMLHandle PreviousSibling()												{
1709         return XMLHandle( _node ? _node->PreviousSibling() : 0 );
1710     }
1711     /// Get the previous sibling element of this handle.
1712     XMLHandle PreviousSiblingElement( const char* _value=0 )				{
1713         return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
1714     }
1715     /// Get the next sibling of this handle.
NextSibling()1716     XMLHandle NextSibling()													{
1717         return XMLHandle( _node ? _node->NextSibling() : 0 );
1718     }
1719     /// Get the next sibling element of this handle.
1720     XMLHandle NextSiblingElement( const char* _value=0 )					{
1721         return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
1722     }
1723 
1724     /// Safe cast to XMLNode. This can return null.
ToNode()1725     XMLNode* ToNode()							{
1726         return _node;
1727     }
1728     /// Safe cast to XMLElement. This can return null.
ToElement()1729     XMLElement* ToElement() 					{
1730         return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
1731     }
1732     /// Safe cast to XMLText. This can return null.
ToText()1733     XMLText* ToText() 							{
1734         return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
1735     }
1736     /// Safe cast to XMLUnknown. This can return null.
ToUnknown()1737     XMLUnknown* ToUnknown() 					{
1738         return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
1739     }
1740     /// Safe cast to XMLDeclaration. This can return null.
ToDeclaration()1741     XMLDeclaration* ToDeclaration() 			{
1742         return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
1743     }
1744 
1745 private:
1746     XMLNode* _node;
1747 };
1748 
1749 
1750 /**
1751 	A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1752 	same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
1753 */
1754 class XMLConstHandle
1755 {
1756 public:
XMLConstHandle(const XMLNode * node)1757     XMLConstHandle( const XMLNode* node )											{
1758         _node = node;
1759     }
XMLConstHandle(const XMLNode & node)1760     XMLConstHandle( const XMLNode& node )											{
1761         _node = &node;
1762     }
XMLConstHandle(const XMLConstHandle & ref)1763     XMLConstHandle( const XMLConstHandle& ref )										{
1764         _node = ref._node;
1765     }
1766 
1767     XMLConstHandle& operator=( const XMLConstHandle& ref )							{
1768         _node = ref._node;
1769         return *this;
1770     }
1771 
FirstChild()1772     const XMLConstHandle FirstChild() const											{
1773         return XMLConstHandle( _node ? _node->FirstChild() : 0 );
1774     }
1775     const XMLConstHandle FirstChildElement( const char* value=0 ) const				{
1776         return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
1777     }
LastChild()1778     const XMLConstHandle LastChild()	const										{
1779         return XMLConstHandle( _node ? _node->LastChild() : 0 );
1780     }
1781     const XMLConstHandle LastChildElement( const char* _value=0 ) const				{
1782         return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
1783     }
PreviousSibling()1784     const XMLConstHandle PreviousSibling() const									{
1785         return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
1786     }
1787     const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const		{
1788         return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
1789     }
NextSibling()1790     const XMLConstHandle NextSibling() const										{
1791         return XMLConstHandle( _node ? _node->NextSibling() : 0 );
1792     }
1793     const XMLConstHandle NextSiblingElement( const char* _value=0 ) const			{
1794         return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
1795     }
1796 
1797 
ToNode()1798     const XMLNode* ToNode() const				{
1799         return _node;
1800     }
ToElement()1801     const XMLElement* ToElement() const			{
1802         return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
1803     }
ToText()1804     const XMLText* ToText() const				{
1805         return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
1806     }
ToUnknown()1807     const XMLUnknown* ToUnknown() const			{
1808         return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
1809     }
ToDeclaration()1810     const XMLDeclaration* ToDeclaration() const	{
1811         return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
1812     }
1813 
1814 private:
1815     const XMLNode* _node;
1816 };
1817 
1818 
1819 /**
1820 	Printing functionality. The XMLPrinter gives you more
1821 	options than the XMLDocument::Print() method.
1822 
1823 	It can:
1824 	-# Print to memory.
1825 	-# Print to a file you provide.
1826 	-# Print XML without a XMLDocument.
1827 
1828 	Print to Memory
1829 
1830 	@verbatim
1831 	XMLPrinter printer;
1832 	doc.Print( &printer );
1833 	SomeFunction( printer.CStr() );
1834 	@endverbatim
1835 
1836 	Print to a File
1837 
1838 	You provide the file pointer.
1839 	@verbatim
1840 	XMLPrinter printer( fp );
1841 	doc.Print( &printer );
1842 	@endverbatim
1843 
1844 	Print without a XMLDocument
1845 
1846 	When loading, an XML parser is very useful. However, sometimes
1847 	when saving, it just gets in the way. The code is often set up
1848 	for streaming, and constructing the DOM is just overhead.
1849 
1850 	The Printer supports the streaming case. The following code
1851 	prints out a trivially simple XML file without ever creating
1852 	an XML document.
1853 
1854 	@verbatim
1855 	XMLPrinter printer( fp );
1856 	printer.OpenElement( "foo" );
1857 	printer.PushAttribute( "foo", "bar" );
1858 	printer.CloseElement();
1859 	@endverbatim
1860 */
1861 class XMLPrinter : public XMLVisitor
1862 {
1863 public:
1864     /** Construct the printer. If the FILE* is specified,
1865     	this will print to the FILE. Else it will print
1866     	to memory, and the result is available in CStr().
1867     	If 'compact' is set to true, then output is created
1868     	with only required whitespace and newlines.
1869     */
1870     XMLPrinter( FILE* file=0, bool compact = false );
~XMLPrinter()1871     ~XMLPrinter()	{}
1872 
1873     /** If streaming, write the BOM and declaration. */
1874     void PushHeader( bool writeBOM, bool writeDeclaration );
1875     /** If streaming, start writing an element.
1876         The element must be closed with CloseElement()
1877     */
1878     void OpenElement( const char* name );
1879     /// If streaming, add an attribute to an open element.
1880     void PushAttribute( const char* name, const char* value );
1881     void PushAttribute( const char* name, int value );
1882     void PushAttribute( const char* name, unsigned value );
1883     void PushAttribute( const char* name, bool value );
1884     void PushAttribute( const char* name, double value );
1885     /// If streaming, close the Element.
1886     void CloseElement();
1887 
1888     /// Add a text node.
1889     void PushText( const char* text, bool cdata=false );
1890     /// Add a text node from an integer.
1891     void PushText( int value );
1892     /// Add a text node from an unsigned.
1893     void PushText( unsigned value );
1894     /// Add a text node from a bool.
1895     void PushText( bool value );
1896     /// Add a text node from a float.
1897     void PushText( float value );
1898     /// Add a text node from a double.
1899     void PushText( double value );
1900 
1901     /// Add a comment
1902     void PushComment( const char* comment );
1903 
1904     void PushDeclaration( const char* value );
1905     void PushUnknown( const char* value );
1906 
1907     virtual bool VisitEnter( const XMLDocument& /*doc*/ );
VisitExit(const XMLDocument &)1908     virtual bool VisitExit( const XMLDocument& /*doc*/ )			{
1909         return true;
1910     }
1911 
1912     virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1913     virtual bool VisitExit( const XMLElement& element );
1914 
1915     virtual bool Visit( const XMLText& text );
1916     virtual bool Visit( const XMLComment& comment );
1917     virtual bool Visit( const XMLDeclaration& declaration );
1918     virtual bool Visit( const XMLUnknown& unknown );
1919 
1920     /**
1921     	If in print to memory mode, return a pointer to
1922     	the XML file in memory.
1923     */
CStr()1924     const char* CStr() const {
1925         return _buffer.Mem();
1926     }
1927     /**
1928     	If in print to memory mode, return the size
1929     	of the XML file in memory. (Note the size returned
1930     	includes the terminating null.)
1931     */
CStrSize()1932     int CStrSize() const {
1933         return _buffer.Size();
1934     }
1935 
1936 private:
1937     void SealElement();
1938     void PrintSpace( int depth );
1939     void PrintString( const char*, bool restrictedEntitySet );	// prints out, after detecting entities.
1940     void Print( const char* format, ... );
1941 
1942     bool _elementJustOpened;
1943     bool _firstElement;
1944     FILE* _fp;
1945     int _depth;
1946     int _textDepth;
1947     bool _processEntities;
1948     bool _compactMode;
1949 
1950     enum {
1951         ENTITY_RANGE = 64,
1952         BUF_SIZE = 200
1953     };
1954     bool _entityFlag[ENTITY_RANGE];
1955     bool _restrictedEntityFlag[ENTITY_RANGE];
1956 
1957     DynArray< const char*, 10 > _stack;
1958     DynArray< char, 20 > _buffer;
1959 #ifdef _MSC_VER
1960     DynArray< char, 20 > _accumulator;
1961 #endif
1962 };
1963 
1964 
1965 }	// tinyxml2
1966 
1967 
1968 #endif // TINYXML2_INCLUDED
1969