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