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