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