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