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