• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Original code by Lee Thomason (www.grinninglizard.com)
3 
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any
6 damages arising from the use of this software.
7 
8 Permission is granted to anyone to use this software for any
9 purpose, including commercial applications, and to alter it and
10 redistribute it freely, subject to the following restrictions:
11 
12 1. The origin of this software must not be misrepresented; you must
13 not claim that you wrote the original software. If you use this
14 software in a product, an acknowledgment in the product documentation
15 would be appreciated but is not required.
16 
17 2. Altered source versions must be plainly marked as such, and
18 must not be misrepresented as being the original software.
19 
20 3. This notice may not be removed or altered from any source
21 distribution.
22 */
23 
24 #ifndef TINYXML2_INCLUDED
25 #define TINYXML2_INCLUDED
26 
27 #if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)
28 #   include <ctype.h>
29 #   include <limits.h>
30 #   include <stdio.h>
31 #   include <stdlib.h>
32 #   include <string.h>
33 #	if defined(__PS3__)
34 #		include <stddef.h>
35 #	endif
36 #else
37 #   include <cctype>
38 #   include <climits>
39 #   include <cstdio>
40 #   include <cstdlib>
41 #   include <cstring>
42 #endif
43 #include <stdint.h>
44 
45 /*
46    TODO: intern strings instead of allocation.
47 */
48 /*
49 	gcc:
50         g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
51 
52     Formatting, Artistic Style:
53         AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
54 */
55 
56 #if defined( _DEBUG ) || defined (__DEBUG__)
57 #   ifndef TINYXML2_DEBUG
58 #       define TINYXML2_DEBUG
59 #   endif
60 #endif
61 
62 #ifdef _MSC_VER
63 #   pragma warning(push)
64 #   pragma warning(disable: 4251)
65 #endif
66 
67 #ifdef _WIN32
68 #   ifdef TINYXML2_EXPORT
69 #       define TINYXML2_LIB __declspec(dllexport)
70 #   elif defined(TINYXML2_IMPORT)
71 #       define TINYXML2_LIB __declspec(dllimport)
72 #   else
73 #       define TINYXML2_LIB
74 #   endif
75 #elif __GNUC__ >= 4
76 #   define TINYXML2_LIB __attribute__((visibility("default")))
77 #else
78 #   define TINYXML2_LIB
79 #endif
80 
81 
82 #if defined(TINYXML2_DEBUG)
83 #   if defined(_MSC_VER)
84 #       // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
85 #       define TIXMLASSERT( x )           if ( !((void)0,(x))) { __debugbreak(); }
86 #   elif defined (ANDROID_NDK)
87 #       include <android/log.h>
88 #       define TIXMLASSERT( x )           if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
89 #   else
90 #       include <assert.h>
91 #       define TIXMLASSERT                assert
92 #   endif
93 #else
94 #   define TIXMLASSERT( x )               {}
95 #endif
96 
97 
98 /* Versioning, past 1.0.14:
99 	http://semver.org/
100 */
101 static const int TIXML2_MAJOR_VERSION = 8;
102 static const int TIXML2_MINOR_VERSION = 0;
103 static const int TIXML2_PATCH_VERSION = 0;
104 
105 #define TINYXML2_MAJOR_VERSION 8
106 #define TINYXML2_MINOR_VERSION 0
107 #define TINYXML2_PATCH_VERSION 0
108 
109 // A fixed element depth limit is problematic. There needs to be a
110 // limit to avoid a stack overflow. However, that limit varies per
111 // system, and the capacity of the stack. On the other hand, it's a trivial
112 // attack that can result from ill, malicious, or even correctly formed XML,
113 // so there needs to be a limit in place.
114 static const int TINYXML2_MAX_ELEMENT_DEPTH = 100;
115 
116 namespace tinyxml2
117 {
118 class XMLDocument;
119 class XMLElement;
120 class XMLAttribute;
121 class XMLComment;
122 class XMLText;
123 class XMLDeclaration;
124 class XMLUnknown;
125 class XMLPrinter;
126 
127 /*
128 	A class that wraps strings. Normally stores the start and end
129 	pointers into the XML file itself, and will apply normalization
130 	and entity translation if actually read. Can also store (and memory
131 	manage) a traditional char[]
132 
133     Isn't clear why TINYXML2_LIB is needed; but seems to fix #719
134 */
135 class TINYXML2_LIB StrPair
136 {
137 public:
138     enum {
139         NEEDS_ENTITY_PROCESSING			= 0x01,
140         NEEDS_NEWLINE_NORMALIZATION		= 0x02,
141         NEEDS_WHITESPACE_COLLAPSING     = 0x04,
142 
143         TEXT_ELEMENT		            = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
144         TEXT_ELEMENT_LEAVE_ENTITIES		= NEEDS_NEWLINE_NORMALIZATION,
145         ATTRIBUTE_NAME		            = 0,
146         ATTRIBUTE_VALUE		            = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
147         ATTRIBUTE_VALUE_LEAVE_ENTITIES  = NEEDS_NEWLINE_NORMALIZATION,
148         COMMENT							= NEEDS_NEWLINE_NORMALIZATION
149     };
150 
StrPair()151     StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
152     ~StrPair();
153 
Set(char * start,char * end,int flags)154     void Set( char* start, char* end, int flags ) {
155         TIXMLASSERT( start );
156         TIXMLASSERT( end );
157         Reset();
158         _start  = start;
159         _end    = end;
160         _flags  = flags | NEEDS_FLUSH;
161     }
162 
163     const char* GetStr();
164 
Empty()165     bool Empty() const {
166         return _start == _end;
167     }
168 
SetInternedStr(const char * str)169     void SetInternedStr( const char* str ) {
170         Reset();
171         _start = const_cast<char*>(str);
172     }
173 
174     void SetStr( const char* str, int flags=0 );
175 
176     char* ParseText( char* in, const char* endTag, int strFlags, int* curLineNumPtr );
177     char* ParseName( char* in );
178 
179     void TransferTo( StrPair* other );
180 	void Reset();
181 
182 private:
183     void CollapseWhitespace();
184 
185     enum {
186         NEEDS_FLUSH = 0x100,
187         NEEDS_DELETE = 0x200
188     };
189 
190     int     _flags;
191     char*   _start;
192     char*   _end;
193 
194     StrPair( const StrPair& other );	// not supported
195     void operator=( const StrPair& other );	// not supported, use TransferTo()
196 };
197 
198 
199 /*
200 	A dynamic array of Plain Old Data. Doesn't support constructors, etc.
201 	Has a small initial memory pool, so that low or no usage will not
202 	cause a call to new/delete
203 */
204 template <class T, int INITIAL_SIZE>
205 class DynArray
206 {
207 public:
DynArray()208     DynArray() :
209         _mem( _pool ),
210         _allocated( INITIAL_SIZE ),
211         _size( 0 )
212     {
213     }
214 
~DynArray()215     ~DynArray() {
216         if ( _mem != _pool ) {
217             delete [] _mem;
218         }
219     }
220 
Clear()221     void Clear() {
222         _size = 0;
223     }
224 
Push(T t)225     void Push( T t ) {
226         TIXMLASSERT( _size < INT_MAX );
227         EnsureCapacity( _size+1 );
228         _mem[_size] = t;
229         ++_size;
230     }
231 
PushArr(int count)232     T* PushArr( int count ) {
233         TIXMLASSERT( count >= 0 );
234         TIXMLASSERT( _size <= INT_MAX - count );
235         EnsureCapacity( _size+count );
236         T* ret = &_mem[_size];
237         _size += count;
238         return ret;
239     }
240 
Pop()241     T Pop() {
242         TIXMLASSERT( _size > 0 );
243         --_size;
244         return _mem[_size];
245     }
246 
PopArr(int count)247     void PopArr( int count ) {
248         TIXMLASSERT( _size >= count );
249         _size -= count;
250     }
251 
Empty()252     bool Empty() const					{
253         return _size == 0;
254     }
255 
256     T& operator[](int i)				{
257         TIXMLASSERT( i>= 0 && i < _size );
258         return _mem[i];
259     }
260 
261     const T& operator[](int i) const	{
262         TIXMLASSERT( i>= 0 && i < _size );
263         return _mem[i];
264     }
265 
PeekTop()266     const T& PeekTop() const            {
267         TIXMLASSERT( _size > 0 );
268         return _mem[ _size - 1];
269     }
270 
Size()271     int Size() const					{
272         TIXMLASSERT( _size >= 0 );
273         return _size;
274     }
275 
Capacity()276     int Capacity() const				{
277         TIXMLASSERT( _allocated >= INITIAL_SIZE );
278         return _allocated;
279     }
280 
SwapRemove(int i)281 	void SwapRemove(int i) {
282 		TIXMLASSERT(i >= 0 && i < _size);
283 		TIXMLASSERT(_size > 0);
284 		_mem[i] = _mem[_size - 1];
285 		--_size;
286 	}
287 
Mem()288     const T* Mem() const				{
289         TIXMLASSERT( _mem );
290         return _mem;
291     }
292 
Mem()293     T* Mem() {
294         TIXMLASSERT( _mem );
295         return _mem;
296     }
297 
298 private:
299     DynArray( const DynArray& ); // not supported
300     void operator=( const DynArray& ); // not supported
301 
EnsureCapacity(int cap)302     void EnsureCapacity( int cap ) {
303         TIXMLASSERT( cap > 0 );
304         if ( cap > _allocated ) {
305             TIXMLASSERT( cap <= INT_MAX / 2 );
306             const int newAllocated = cap * 2;
307             T* newMem = new T[newAllocated];
308             TIXMLASSERT( newAllocated >= _size );
309             memcpy( newMem, _mem, sizeof(T)*_size );	// warning: not using constructors, only works for PODs
310             if ( _mem != _pool ) {
311                 delete [] _mem;
312             }
313             _mem = newMem;
314             _allocated = newAllocated;
315         }
316     }
317 
318     T*  _mem;
319     T   _pool[INITIAL_SIZE];
320     int _allocated;		// objects allocated
321     int _size;			// number objects in use
322 };
323 
324 
325 /*
326 	Parent virtual class of a pool for fast allocation
327 	and deallocation of objects.
328 */
329 class MemPool
330 {
331 public:
MemPool()332     MemPool() {}
~MemPool()333     virtual ~MemPool() {}
334 
335     virtual int ItemSize() const = 0;
336     virtual void* Alloc() = 0;
337     virtual void Free( void* ) = 0;
338     virtual void SetTracked() = 0;
339 };
340 
341 
342 /*
343 	Template child class to create pools of the correct type.
344 */
345 template< int ITEM_SIZE >
346 class MemPoolT : public MemPool
347 {
348 public:
MemPoolT()349     MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0)	{}
~MemPoolT()350     ~MemPoolT() {
351         MemPoolT< ITEM_SIZE >::Clear();
352     }
353 
Clear()354     void Clear() {
355         // Delete the blocks.
356         while( !_blockPtrs.Empty()) {
357             Block* lastBlock = _blockPtrs.Pop();
358             delete lastBlock;
359         }
360         _root = 0;
361         _currentAllocs = 0;
362         _nAllocs = 0;
363         _maxAllocs = 0;
364         _nUntracked = 0;
365     }
366 
ItemSize()367     virtual int ItemSize() const	{
368         return ITEM_SIZE;
369     }
CurrentAllocs()370     int CurrentAllocs() const		{
371         return _currentAllocs;
372     }
373 
Alloc()374     virtual void* Alloc() {
375         if ( !_root ) {
376             // Need a new block.
377             Block* block = new Block();
378             _blockPtrs.Push( block );
379 
380             Item* blockItems = block->items;
381             for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {
382                 blockItems[i].next = &(blockItems[i + 1]);
383             }
384             blockItems[ITEMS_PER_BLOCK - 1].next = 0;
385             _root = blockItems;
386         }
387         Item* const result = _root;
388         TIXMLASSERT( result != 0 );
389         _root = _root->next;
390 
391         ++_currentAllocs;
392         if ( _currentAllocs > _maxAllocs ) {
393             _maxAllocs = _currentAllocs;
394         }
395         ++_nAllocs;
396         ++_nUntracked;
397         return result;
398     }
399 
Free(void * mem)400     virtual void Free( void* mem ) {
401         if ( !mem ) {
402             return;
403         }
404         --_currentAllocs;
405         Item* item = static_cast<Item*>( mem );
406 #ifdef TINYXML2_DEBUG
407         memset( item, 0xfe, sizeof( *item ) );
408 #endif
409         item->next = _root;
410         _root = item;
411     }
Trace(const char * name)412     void Trace( const char* name ) {
413         printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
414                 name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs,
415                 ITEM_SIZE, _nAllocs, _blockPtrs.Size() );
416     }
417 
SetTracked()418     void SetTracked() {
419         --_nUntracked;
420     }
421 
Untracked()422     int Untracked() const {
423         return _nUntracked;
424     }
425 
426 	// This number is perf sensitive. 4k seems like a good tradeoff on my machine.
427 	// The test file is large, 170k.
428 	// Release:		VS2010 gcc(no opt)
429 	//		1k:		4000
430 	//		2k:		4000
431 	//		4k:		3900	21000
432 	//		16k:	5200
433 	//		32k:	4300
434 	//		64k:	4000	21000
435     // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK
436     // in private part if ITEMS_PER_BLOCK is private
437     enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE };
438 
439 private:
440     MemPoolT( const MemPoolT& ); // not supported
441     void operator=( const MemPoolT& ); // not supported
442 
443     union Item {
444         Item*   next;
445         char    itemData[ITEM_SIZE];
446     };
447     struct Block {
448         Item items[ITEMS_PER_BLOCK];
449     };
450     DynArray< Block*, 10 > _blockPtrs;
451     Item* _root;
452 
453     int _currentAllocs;
454     int _nAllocs;
455     int _maxAllocs;
456     int _nUntracked;
457 };
458 
459 
460 
461 /**
462 	Implements the interface to the "Visitor pattern" (see the Accept() method.)
463 	If you call the Accept() method, it requires being passed a XMLVisitor
464 	class to handle callbacks. For nodes that contain other nodes (Document, Element)
465 	you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
466 	are simply called with Visit().
467 
468 	If you return 'true' from a Visit method, recursive parsing will continue. If you return
469 	false, <b>no children of this node or its siblings</b> will be visited.
470 
471 	All flavors of Visit methods have a default implementation that returns 'true' (continue
472 	visiting). You need to only override methods that are interesting to you.
473 
474 	Generally Accept() is called on the XMLDocument, although all nodes support visiting.
475 
476 	You should never change the document from a callback.
477 
478 	@sa XMLNode::Accept()
479 */
480 class TINYXML2_LIB XMLVisitor
481 {
482 public:
~XMLVisitor()483     virtual ~XMLVisitor() {}
484 
485     /// Visit a document.
VisitEnter(const XMLDocument &)486     virtual bool VisitEnter( const XMLDocument& /*doc*/ )			{
487         return true;
488     }
489     /// Visit a document.
VisitExit(const XMLDocument &)490     virtual bool VisitExit( const XMLDocument& /*doc*/ )			{
491         return true;
492     }
493 
494     /// Visit an element.
VisitEnter(const XMLElement &,const XMLAttribute *)495     virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )	{
496         return true;
497     }
498     /// Visit an element.
VisitExit(const XMLElement &)499     virtual bool VisitExit( const XMLElement& /*element*/ )			{
500         return true;
501     }
502 
503     /// Visit a declaration.
Visit(const XMLDeclaration &)504     virtual bool Visit( const XMLDeclaration& /*declaration*/ )		{
505         return true;
506     }
507     /// Visit a text node.
Visit(const XMLText &)508     virtual bool Visit( const XMLText& /*text*/ )					{
509         return true;
510     }
511     /// Visit a comment node.
Visit(const XMLComment &)512     virtual bool Visit( const XMLComment& /*comment*/ )				{
513         return true;
514     }
515     /// Visit an unknown node.
Visit(const XMLUnknown &)516     virtual bool Visit( const XMLUnknown& /*unknown*/ )				{
517         return true;
518     }
519 };
520 
521 // WARNING: must match XMLDocument::_errorNames[]
522 enum XMLError {
523     XML_SUCCESS = 0,
524     XML_NO_ATTRIBUTE,
525     XML_WRONG_ATTRIBUTE_TYPE,
526     XML_ERROR_FILE_NOT_FOUND,
527     XML_ERROR_FILE_COULD_NOT_BE_OPENED,
528     XML_ERROR_FILE_READ_ERROR,
529     XML_ERROR_PARSING_ELEMENT,
530     XML_ERROR_PARSING_ATTRIBUTE,
531     XML_ERROR_PARSING_TEXT,
532     XML_ERROR_PARSING_CDATA,
533     XML_ERROR_PARSING_COMMENT,
534     XML_ERROR_PARSING_DECLARATION,
535     XML_ERROR_PARSING_UNKNOWN,
536     XML_ERROR_EMPTY_DOCUMENT,
537     XML_ERROR_MISMATCHED_ELEMENT,
538     XML_ERROR_PARSING,
539     XML_CAN_NOT_CONVERT_TEXT,
540     XML_NO_TEXT_NODE,
541 	XML_ELEMENT_DEPTH_EXCEEDED,
542 
543 	XML_ERROR_COUNT
544 };
545 
546 
547 /*
548 	Utility functionality.
549 */
550 class TINYXML2_LIB XMLUtil
551 {
552 public:
SkipWhiteSpace(const char * p,int * curLineNumPtr)553     static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr )	{
554         TIXMLASSERT( p );
555 
556         while( IsWhiteSpace(*p) ) {
557             if (curLineNumPtr && *p == '\n') {
558                 ++(*curLineNumPtr);
559             }
560             ++p;
561         }
562         TIXMLASSERT( p );
563         return p;
564     }
SkipWhiteSpace(char * const p,int * curLineNumPtr)565     static char* SkipWhiteSpace( char* const p, int* curLineNumPtr ) {
566         return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p), curLineNumPtr ) );
567     }
568 
569     // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
570     // correct, but simple, and usually works.
IsWhiteSpace(char p)571     static bool IsWhiteSpace( char p )					{
572         return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
573     }
574 
IsNameStartChar(unsigned char ch)575     inline static bool IsNameStartChar( unsigned char ch ) {
576         if ( ch >= 128 ) {
577             // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
578             return true;
579         }
580         if ( isalpha( ch ) ) {
581             return true;
582         }
583         return ch == ':' || ch == '_';
584     }
585 
IsNameChar(unsigned char ch)586     inline static bool IsNameChar( unsigned char ch ) {
587         return IsNameStartChar( ch )
588                || isdigit( ch )
589                || ch == '.'
590                || ch == '-';
591     }
592 
593     inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {
594         if ( p == q ) {
595             return true;
596         }
597         TIXMLASSERT( p );
598         TIXMLASSERT( q );
599         TIXMLASSERT( nChar >= 0 );
600         return strncmp( p, q, nChar ) == 0;
601     }
602 
IsUTF8Continuation(const char p)603     inline static bool IsUTF8Continuation( const char p ) {
604         return ( p & 0x80 ) != 0;
605     }
606 
607     static const char* ReadBOM( const char* p, bool* hasBOM );
608     // p is the starting location,
609     // the UTF-8 value of the entity will be placed in value, and length filled in.
610     static const char* GetCharacterRef( const char* p, char* value, int* length );
611     static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
612 
613     // converts primitive types to strings
614     static void ToStr( int v, char* buffer, int bufferSize );
615     static void ToStr( unsigned v, char* buffer, int bufferSize );
616     static void ToStr( bool v, char* buffer, int bufferSize );
617     static void ToStr( float v, char* buffer, int bufferSize );
618     static void ToStr( double v, char* buffer, int bufferSize );
619 	static void ToStr(int64_t v, char* buffer, int bufferSize);
620     static void ToStr(uint64_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     static bool ToUnsigned64(const char* str, uint64_t* value);
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     explicit 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     explicit 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     explicit 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     explicit 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     explicit 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 
Unsigned64Value()1168     uint64_t Unsigned64Value() const {
1169         uint64_t i = 0;
1170         QueryUnsigned64Value(&i);
1171         return i;
1172     }
1173 
1174     /// Query as an unsigned integer. See IntValue()
UnsignedValue()1175     unsigned UnsignedValue() const			{
1176         unsigned i=0;
1177         QueryUnsignedValue( &i );
1178         return i;
1179     }
1180     /// Query as a boolean. See IntValue()
BoolValue()1181     bool	 BoolValue() const				{
1182         bool b=false;
1183         QueryBoolValue( &b );
1184         return b;
1185     }
1186     /// Query as a double. See IntValue()
DoubleValue()1187     double 	 DoubleValue() const			{
1188         double d=0;
1189         QueryDoubleValue( &d );
1190         return d;
1191     }
1192     /// Query as a float. See IntValue()
FloatValue()1193     float	 FloatValue() const				{
1194         float f=0;
1195         QueryFloatValue( &f );
1196         return f;
1197     }
1198 
1199     /** QueryIntValue interprets the attribute as an integer, and returns the value
1200     	in the provided parameter. The function will return XML_SUCCESS on success,
1201     	and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1202     */
1203     XMLError QueryIntValue( int* value ) const;
1204     /// See QueryIntValue
1205     XMLError QueryUnsignedValue( unsigned int* value ) const;
1206 	/// See QueryIntValue
1207 	XMLError QueryInt64Value(int64_t* value) const;
1208     /// See QueryIntValue
1209     XMLError QueryUnsigned64Value(uint64_t* value) const;
1210 	/// See QueryIntValue
1211     XMLError QueryBoolValue( bool* value ) const;
1212     /// See QueryIntValue
1213     XMLError QueryDoubleValue( double* value ) const;
1214     /// See QueryIntValue
1215     XMLError QueryFloatValue( float* value ) const;
1216 
1217     /// Set the attribute to a string value.
1218     void SetAttribute( const char* value );
1219     /// Set the attribute to value.
1220     void SetAttribute( int value );
1221     /// Set the attribute to value.
1222     void SetAttribute( unsigned value );
1223 	/// Set the attribute to value.
1224 	void SetAttribute(int64_t value);
1225     /// Set the attribute to value.
1226     void SetAttribute(uint64_t value);
1227     /// Set the attribute to value.
1228     void SetAttribute( bool value );
1229     /// Set the attribute to value.
1230     void SetAttribute( double value );
1231     /// Set the attribute to value.
1232     void SetAttribute( float value );
1233 
1234 private:
1235     enum { BUF_SIZE = 200 };
1236 
XMLAttribute()1237     XMLAttribute() : _name(), _value(),_parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {}
~XMLAttribute()1238     virtual ~XMLAttribute()	{}
1239 
1240     XMLAttribute( const XMLAttribute& );	// not supported
1241     void operator=( const XMLAttribute& );	// not supported
1242     void SetName( const char* name );
1243 
1244     char* ParseDeep( char* p, bool processEntities, int* curLineNumPtr );
1245 
1246     mutable StrPair _name;
1247     mutable StrPair _value;
1248     int             _parseLineNum;
1249     XMLAttribute*   _next;
1250     MemPool*        _memPool;
1251 };
1252 
1253 
1254 /** The element is a container class. It has a value, the element name,
1255 	and can contain other elements, text, comments, and unknowns.
1256 	Elements also contain an arbitrary number of attributes.
1257 */
1258 class TINYXML2_LIB XMLElement : public XMLNode
1259 {
1260     friend class XMLDocument;
1261 public:
1262     /// Get the name of an element (which is the Value() of the node.)
Name()1263     const char* Name() const		{
1264         return Value();
1265     }
1266     /// Set the name of the element.
1267     void SetName( const char* str, bool staticMem=false )	{
1268         SetValue( str, staticMem );
1269     }
1270 
ToElement()1271     virtual XMLElement* ToElement()				{
1272         return this;
1273     }
ToElement()1274     virtual const XMLElement* ToElement() const {
1275         return this;
1276     }
1277     virtual bool Accept( XMLVisitor* visitor ) const;
1278 
1279     /** Given an attribute name, Attribute() returns the value
1280     	for the attribute of that name, or null if none
1281     	exists. For example:
1282 
1283     	@verbatim
1284     	const char* value = ele->Attribute( "foo" );
1285     	@endverbatim
1286 
1287     	The 'value' parameter is normally null. However, if specified,
1288     	the attribute will only be returned if the 'name' and 'value'
1289     	match. This allow you to write code:
1290 
1291     	@verbatim
1292     	if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1293     	@endverbatim
1294 
1295     	rather than:
1296     	@verbatim
1297     	if ( ele->Attribute( "foo" ) ) {
1298     		if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1299     	}
1300     	@endverbatim
1301     */
1302     const char* Attribute( const char* name, const char* value=0 ) const;
1303 
1304     /** Given an attribute name, IntAttribute() returns the value
1305     	of the attribute interpreted as an integer. The default
1306         value will be returned if the attribute isn't present,
1307         or if there is an error. (For a method with error
1308     	checking, see QueryIntAttribute()).
1309     */
1310 	int IntAttribute(const char* name, int defaultValue = 0) const;
1311     /// See IntAttribute()
1312 	unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const;
1313 	/// See IntAttribute()
1314 	int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const;
1315     /// See IntAttribute()
1316     uint64_t Unsigned64Attribute(const char* name, uint64_t defaultValue = 0) const;
1317 	/// See IntAttribute()
1318 	bool BoolAttribute(const char* name, bool defaultValue = false) const;
1319     /// See IntAttribute()
1320 	double DoubleAttribute(const char* name, double defaultValue = 0) const;
1321     /// See IntAttribute()
1322 	float FloatAttribute(const char* name, float defaultValue = 0) const;
1323 
1324     /** Given an attribute name, QueryIntAttribute() returns
1325     	XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1326     	can't be performed, or XML_NO_ATTRIBUTE if the attribute
1327     	doesn't exist. If successful, the result of the conversion
1328     	will be written to 'value'. If not successful, nothing will
1329     	be written to 'value'. This allows you to provide default
1330     	value:
1331 
1332     	@verbatim
1333     	int value = 10;
1334     	QueryIntAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
1335     	@endverbatim
1336     */
QueryIntAttribute(const char * name,int * value)1337     XMLError QueryIntAttribute( const char* name, int* value ) const				{
1338         const XMLAttribute* a = FindAttribute( name );
1339         if ( !a ) {
1340             return XML_NO_ATTRIBUTE;
1341         }
1342         return a->QueryIntValue( value );
1343     }
1344 
1345 	/// See QueryIntAttribute()
QueryUnsignedAttribute(const char * name,unsigned int * value)1346     XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const	{
1347         const XMLAttribute* a = FindAttribute( name );
1348         if ( !a ) {
1349             return XML_NO_ATTRIBUTE;
1350         }
1351         return a->QueryUnsignedValue( value );
1352     }
1353 
1354 	/// See QueryIntAttribute()
QueryInt64Attribute(const char * name,int64_t * value)1355 	XMLError QueryInt64Attribute(const char* name, int64_t* value) const {
1356 		const XMLAttribute* a = FindAttribute(name);
1357 		if (!a) {
1358 			return XML_NO_ATTRIBUTE;
1359 		}
1360 		return a->QueryInt64Value(value);
1361 	}
1362 
1363     /// See QueryIntAttribute()
QueryUnsigned64Attribute(const char * name,uint64_t * value)1364     XMLError QueryUnsigned64Attribute(const char* name, uint64_t* value) const {
1365         const XMLAttribute* a = FindAttribute(name);
1366         if(!a) {
1367             return XML_NO_ATTRIBUTE;
1368         }
1369         return a->QueryUnsigned64Value(value);
1370     }
1371 
1372 	/// See QueryIntAttribute()
QueryBoolAttribute(const char * name,bool * value)1373     XMLError QueryBoolAttribute( const char* name, bool* value ) const				{
1374         const XMLAttribute* a = FindAttribute( name );
1375         if ( !a ) {
1376             return XML_NO_ATTRIBUTE;
1377         }
1378         return a->QueryBoolValue( value );
1379     }
1380     /// See QueryIntAttribute()
QueryDoubleAttribute(const char * name,double * value)1381     XMLError QueryDoubleAttribute( const char* name, double* value ) const			{
1382         const XMLAttribute* a = FindAttribute( name );
1383         if ( !a ) {
1384             return XML_NO_ATTRIBUTE;
1385         }
1386         return a->QueryDoubleValue( value );
1387     }
1388     /// See QueryIntAttribute()
QueryFloatAttribute(const char * name,float * value)1389     XMLError QueryFloatAttribute( const char* name, float* value ) const			{
1390         const XMLAttribute* a = FindAttribute( name );
1391         if ( !a ) {
1392             return XML_NO_ATTRIBUTE;
1393         }
1394         return a->QueryFloatValue( value );
1395     }
1396 
1397 	/// See QueryIntAttribute()
QueryStringAttribute(const char * name,const char ** value)1398 	XMLError QueryStringAttribute(const char* name, const char** value) const {
1399 		const XMLAttribute* a = FindAttribute(name);
1400 		if (!a) {
1401 			return XML_NO_ATTRIBUTE;
1402 		}
1403 		*value = a->Value();
1404 		return XML_SUCCESS;
1405 	}
1406 
1407 
1408 
1409     /** Given an attribute name, QueryAttribute() returns
1410     	XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1411     	can't be performed, or XML_NO_ATTRIBUTE if the attribute
1412     	doesn't exist. It is overloaded for the primitive types,
1413 		and is a generally more convenient replacement of
1414 		QueryIntAttribute() and related functions.
1415 
1416 		If successful, the result of the conversion
1417     	will be written to 'value'. If not successful, nothing will
1418     	be written to 'value'. This allows you to provide default
1419     	value:
1420 
1421     	@verbatim
1422     	int value = 10;
1423     	QueryAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
1424     	@endverbatim
1425     */
QueryAttribute(const char * name,int * value)1426 	XMLError QueryAttribute( const char* name, int* value ) const {
1427 		return QueryIntAttribute( name, value );
1428 	}
1429 
QueryAttribute(const char * name,unsigned int * value)1430 	XMLError QueryAttribute( const char* name, unsigned int* value ) const {
1431 		return QueryUnsignedAttribute( name, value );
1432 	}
1433 
QueryAttribute(const char * name,int64_t * value)1434 	XMLError QueryAttribute(const char* name, int64_t* value) const {
1435 		return QueryInt64Attribute(name, value);
1436 	}
1437 
QueryAttribute(const char * name,uint64_t * value)1438     XMLError QueryAttribute(const char* name, uint64_t* value) const {
1439         return QueryUnsigned64Attribute(name, value);
1440     }
1441 
QueryAttribute(const char * name,bool * value)1442     XMLError QueryAttribute( const char* name, bool* value ) const {
1443 		return QueryBoolAttribute( name, value );
1444 	}
1445 
QueryAttribute(const char * name,double * value)1446 	XMLError QueryAttribute( const char* name, double* value ) const {
1447 		return QueryDoubleAttribute( name, value );
1448 	}
1449 
QueryAttribute(const char * name,float * value)1450 	XMLError QueryAttribute( const char* name, float* value ) const {
1451 		return QueryFloatAttribute( name, value );
1452 	}
1453 
1454 	/// Sets the named attribute to value.
SetAttribute(const char * name,const char * value)1455     void SetAttribute( const char* name, const char* value )	{
1456         XMLAttribute* a = FindOrCreateAttribute( name );
1457         a->SetAttribute( value );
1458     }
1459     /// Sets the named attribute to value.
SetAttribute(const char * name,int value)1460     void SetAttribute( const char* name, int value )			{
1461         XMLAttribute* a = FindOrCreateAttribute( name );
1462         a->SetAttribute( value );
1463     }
1464     /// Sets the named attribute to value.
SetAttribute(const char * name,unsigned value)1465     void SetAttribute( const char* name, unsigned value )		{
1466         XMLAttribute* a = FindOrCreateAttribute( name );
1467         a->SetAttribute( value );
1468     }
1469 
1470 	/// Sets the named attribute to value.
SetAttribute(const char * name,int64_t value)1471 	void SetAttribute(const char* name, int64_t value) {
1472 		XMLAttribute* a = FindOrCreateAttribute(name);
1473 		a->SetAttribute(value);
1474 	}
1475 
1476     /// Sets the named attribute to value.
SetAttribute(const char * name,uint64_t value)1477     void SetAttribute(const char* name, uint64_t value) {
1478         XMLAttribute* a = FindOrCreateAttribute(name);
1479         a->SetAttribute(value);
1480     }
1481 
1482     /// Sets the named attribute to value.
SetAttribute(const char * name,bool value)1483     void SetAttribute( const char* name, bool value )			{
1484         XMLAttribute* a = FindOrCreateAttribute( name );
1485         a->SetAttribute( value );
1486     }
1487     /// Sets the named attribute to value.
SetAttribute(const char * name,double value)1488     void SetAttribute( const char* name, double value )		{
1489         XMLAttribute* a = FindOrCreateAttribute( name );
1490         a->SetAttribute( value );
1491     }
1492     /// Sets the named attribute to value.
SetAttribute(const char * name,float value)1493     void SetAttribute( const char* name, float value )		{
1494         XMLAttribute* a = FindOrCreateAttribute( name );
1495         a->SetAttribute( value );
1496     }
1497 
1498     /**
1499     	Delete an attribute.
1500     */
1501     void DeleteAttribute( const char* name );
1502 
1503     /// Return the first attribute in the list.
FirstAttribute()1504     const XMLAttribute* FirstAttribute() const {
1505         return _rootAttribute;
1506     }
1507     /// Query a specific attribute in the list.
1508     const XMLAttribute* FindAttribute( const char* name ) const;
1509 
1510     /** Convenience function for easy access to the text inside an element. Although easy
1511     	and concise, GetText() is limited compared to getting the XMLText child
1512     	and accessing it directly.
1513 
1514     	If the first child of 'this' is a XMLText, the GetText()
1515     	returns the character string of the Text node, else null is returned.
1516 
1517     	This is a convenient method for getting the text of simple contained text:
1518     	@verbatim
1519     	<foo>This is text</foo>
1520     		const char* str = fooElement->GetText();
1521     	@endverbatim
1522 
1523     	'str' will be a pointer to "This is text".
1524 
1525     	Note that this function can be misleading. If the element foo was created from
1526     	this XML:
1527     	@verbatim
1528     		<foo><b>This is text</b></foo>
1529     	@endverbatim
1530 
1531     	then the value of str would be null. The first child node isn't a text node, it is
1532     	another element. From this XML:
1533     	@verbatim
1534     		<foo>This is <b>text</b></foo>
1535     	@endverbatim
1536     	GetText() will return "This is ".
1537     */
1538     const char* GetText() const;
1539 
1540     /** Convenience function for easy access to the text inside an element. Although easy
1541     	and concise, SetText() is limited compared to creating an XMLText child
1542     	and mutating it directly.
1543 
1544     	If the first child of 'this' is a XMLText, SetText() sets its value to
1545 		the given string, otherwise it will create a first child that is an XMLText.
1546 
1547     	This is a convenient method for setting the text of simple contained text:
1548     	@verbatim
1549     	<foo>This is text</foo>
1550     		fooElement->SetText( "Hullaballoo!" );
1551      	<foo>Hullaballoo!</foo>
1552 		@endverbatim
1553 
1554     	Note that this function can be misleading. If the element foo was created from
1555     	this XML:
1556     	@verbatim
1557     		<foo><b>This is text</b></foo>
1558     	@endverbatim
1559 
1560     	then it will not change "This is text", but rather prefix it with a text element:
1561     	@verbatim
1562     		<foo>Hullaballoo!<b>This is text</b></foo>
1563     	@endverbatim
1564 
1565 		For this XML:
1566     	@verbatim
1567     		<foo />
1568     	@endverbatim
1569     	SetText() will generate
1570     	@verbatim
1571     		<foo>Hullaballoo!</foo>
1572     	@endverbatim
1573     */
1574 	void SetText( const char* inText );
1575     /// Convenience method for setting text inside an element. See SetText() for important limitations.
1576     void SetText( int value );
1577     /// Convenience method for setting text inside an element. See SetText() for important limitations.
1578     void SetText( unsigned value );
1579 	/// Convenience method for setting text inside an element. See SetText() for important limitations.
1580 	void SetText(int64_t value);
1581     /// Convenience method for setting text inside an element. See SetText() for important limitations.
1582     void SetText(uint64_t value);
1583 	/// Convenience method for setting text inside an element. See SetText() for important limitations.
1584     void SetText( bool value );
1585     /// Convenience method for setting text inside an element. See SetText() for important limitations.
1586     void SetText( double value );
1587     /// Convenience method for setting text inside an element. See SetText() for important limitations.
1588     void SetText( float value );
1589 
1590     /**
1591     	Convenience method to query the value of a child text node. This is probably best
1592     	shown by example. Given you have a document is this form:
1593     	@verbatim
1594     		<point>
1595     			<x>1</x>
1596     			<y>1.4</y>
1597     		</point>
1598     	@endverbatim
1599 
1600     	The QueryIntText() and similar functions provide a safe and easier way to get to the
1601     	"value" of x and y.
1602 
1603     	@verbatim
1604     		int x = 0;
1605     		float y = 0;	// types of x and y are contrived for example
1606     		const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1607     		const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1608     		xElement->QueryIntText( &x );
1609     		yElement->QueryFloatText( &y );
1610     	@endverbatim
1611 
1612     	@returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1613     			 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
1614 
1615     */
1616     XMLError QueryIntText( int* ival ) const;
1617     /// See QueryIntText()
1618     XMLError QueryUnsignedText( unsigned* uval ) const;
1619 	/// See QueryIntText()
1620 	XMLError QueryInt64Text(int64_t* uval) const;
1621 	/// See QueryIntText()
1622 	XMLError QueryUnsigned64Text(uint64_t* uval) const;
1623 	/// See QueryIntText()
1624     XMLError QueryBoolText( bool* bval ) const;
1625     /// See QueryIntText()
1626     XMLError QueryDoubleText( double* dval ) const;
1627     /// See QueryIntText()
1628     XMLError QueryFloatText( float* fval ) const;
1629 
1630 	int IntText(int defaultValue = 0) const;
1631 
1632 	/// See QueryIntText()
1633 	unsigned UnsignedText(unsigned defaultValue = 0) const;
1634 	/// See QueryIntText()
1635 	int64_t Int64Text(int64_t defaultValue = 0) const;
1636     /// See QueryIntText()
1637     uint64_t Unsigned64Text(uint64_t defaultValue = 0) const;
1638 	/// See QueryIntText()
1639 	bool BoolText(bool defaultValue = false) const;
1640 	/// See QueryIntText()
1641 	double DoubleText(double defaultValue = 0) const;
1642 	/// See QueryIntText()
1643     float FloatText(float defaultValue = 0) const;
1644 
1645     /**
1646         Convenience method to create a new XMLElement and add it as last (right)
1647         child of this node. Returns the created and inserted element.
1648     */
1649     XMLElement* InsertNewChildElement(const char* name);
1650     /// See InsertNewChildElement()
1651     XMLComment* InsertNewComment(const char* comment);
1652     /// See InsertNewChildElement()
1653     XMLText* InsertNewText(const char* text);
1654     /// See InsertNewChildElement()
1655     XMLDeclaration* InsertNewDeclaration(const char* text);
1656     /// See InsertNewChildElement()
1657     XMLUnknown* InsertNewUnknown(const char* text);
1658 
1659 
1660     // internal:
1661     enum ElementClosingType {
1662         OPEN,		// <foo>
1663         CLOSED,		// <foo/>
1664         CLOSING		// </foo>
1665     };
ClosingType()1666     ElementClosingType ClosingType() const {
1667         return _closingType;
1668     }
1669     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1670     virtual bool ShallowEqual( const XMLNode* compare ) const;
1671 
1672 protected:
1673     char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
1674 
1675 private:
1676     XMLElement( XMLDocument* doc );
1677     virtual ~XMLElement();
1678     XMLElement( const XMLElement& );	// not supported
1679     void operator=( const XMLElement& );	// not supported
1680 
1681     XMLAttribute* FindOrCreateAttribute( const char* name );
1682     char* ParseAttributes( char* p, int* curLineNumPtr );
1683     static void DeleteAttribute( XMLAttribute* attribute );
1684     XMLAttribute* CreateAttribute();
1685 
1686     enum { BUF_SIZE = 200 };
1687     ElementClosingType _closingType;
1688     // The attribute list is ordered; there is no 'lastAttribute'
1689     // because the list needs to be scanned for dupes before adding
1690     // a new attribute.
1691     XMLAttribute* _rootAttribute;
1692 };
1693 
1694 
1695 enum Whitespace {
1696     PRESERVE_WHITESPACE,
1697     COLLAPSE_WHITESPACE
1698 };
1699 
1700 
1701 /** A Document binds together all the functionality.
1702 	It can be saved, loaded, and printed to the screen.
1703 	All Nodes are connected and allocated to a Document.
1704 	If the Document is deleted, all its Nodes are also deleted.
1705 */
1706 class TINYXML2_LIB XMLDocument : public XMLNode
1707 {
1708     friend class XMLElement;
1709     // Gives access to SetError and Push/PopDepth, but over-access for everything else.
1710     // Wishing C++ had "internal" scope.
1711     friend class XMLNode;
1712     friend class XMLText;
1713     friend class XMLComment;
1714     friend class XMLDeclaration;
1715     friend class XMLUnknown;
1716 public:
1717     /// constructor
1718     XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE );
1719     ~XMLDocument();
1720 
ToDocument()1721     virtual XMLDocument* ToDocument()				{
1722         TIXMLASSERT( this == _document );
1723         return this;
1724     }
ToDocument()1725     virtual const XMLDocument* ToDocument() const	{
1726         TIXMLASSERT( this == _document );
1727         return this;
1728     }
1729 
1730     /**
1731     	Parse an XML file from a character string.
1732     	Returns XML_SUCCESS (0) on success, or
1733     	an errorID.
1734 
1735     	You may optionally pass in the 'nBytes', which is
1736     	the number of bytes which will be parsed. If not
1737     	specified, TinyXML-2 will assume 'xml' points to a
1738     	null terminated string.
1739     */
1740     XMLError Parse( const char* xml, size_t nBytes=static_cast<size_t>(-1) );
1741 
1742     /**
1743     	Load an XML file from disk.
1744     	Returns XML_SUCCESS (0) on success, or
1745     	an errorID.
1746     */
1747     XMLError LoadFile( const char* filename );
1748 
1749     /**
1750     	Load an XML file from disk. You are responsible
1751     	for providing and closing the FILE*.
1752 
1753         NOTE: The file should be opened as binary ("rb")
1754         not text in order for TinyXML-2 to correctly
1755         do newline normalization.
1756 
1757     	Returns XML_SUCCESS (0) on success, or
1758     	an errorID.
1759     */
1760     XMLError LoadFile( FILE* );
1761 
1762     /**
1763     	Save the XML file to disk.
1764     	Returns XML_SUCCESS (0) on success, or
1765     	an errorID.
1766     */
1767     XMLError SaveFile( const char* filename, bool compact = false );
1768 
1769     /**
1770     	Save the XML file to disk. You are responsible
1771     	for providing and closing the FILE*.
1772 
1773     	Returns XML_SUCCESS (0) on success, or
1774     	an errorID.
1775     */
1776     XMLError SaveFile( FILE* fp, bool compact = false );
1777 
ProcessEntities()1778     bool ProcessEntities() const		{
1779         return _processEntities;
1780     }
WhitespaceMode()1781     Whitespace WhitespaceMode() const	{
1782         return _whitespaceMode;
1783     }
1784 
1785     /**
1786     	Returns true if this document has a leading Byte Order Mark of UTF8.
1787     */
HasBOM()1788     bool HasBOM() const {
1789         return _writeBOM;
1790     }
1791     /** Sets whether to write the BOM when writing the file.
1792     */
SetBOM(bool useBOM)1793     void SetBOM( bool useBOM ) {
1794         _writeBOM = useBOM;
1795     }
1796 
1797     /** Return the root element of DOM. Equivalent to FirstChildElement().
1798         To get the first node, use FirstChild().
1799     */
RootElement()1800     XMLElement* RootElement()				{
1801         return FirstChildElement();
1802     }
RootElement()1803     const XMLElement* RootElement() const	{
1804         return FirstChildElement();
1805     }
1806 
1807     /** Print the Document. If the Printer is not provided, it will
1808         print to stdout. If you provide Printer, this can print to a file:
1809     	@verbatim
1810     	XMLPrinter printer( fp );
1811     	doc.Print( &printer );
1812     	@endverbatim
1813 
1814     	Or you can use a printer to print to memory:
1815     	@verbatim
1816     	XMLPrinter printer;
1817     	doc.Print( &printer );
1818     	// printer.CStr() has a const char* to the XML
1819     	@endverbatim
1820     */
1821     void Print( XMLPrinter* streamer=0 ) const;
1822     virtual bool Accept( XMLVisitor* visitor ) const;
1823 
1824     /**
1825     	Create a new Element associated with
1826     	this Document. The memory for the Element
1827     	is managed by the Document.
1828     */
1829     XMLElement* NewElement( const char* name );
1830     /**
1831     	Create a new Comment associated with
1832     	this Document. The memory for the Comment
1833     	is managed by the Document.
1834     */
1835     XMLComment* NewComment( const char* comment );
1836     /**
1837     	Create a new Text associated with
1838     	this Document. The memory for the Text
1839     	is managed by the Document.
1840     */
1841     XMLText* NewText( const char* text );
1842     /**
1843     	Create a new Declaration associated with
1844     	this Document. The memory for the object
1845     	is managed by the Document.
1846 
1847     	If the 'text' param is null, the standard
1848     	declaration is used.:
1849     	@verbatim
1850     		<?xml version="1.0" encoding="UTF-8"?>
1851     	@endverbatim
1852     */
1853     XMLDeclaration* NewDeclaration( const char* text=0 );
1854     /**
1855     	Create a new Unknown associated with
1856     	this Document. The memory for the object
1857     	is managed by the Document.
1858     */
1859     XMLUnknown* NewUnknown( const char* text );
1860 
1861     /**
1862     	Delete a node associated with this document.
1863     	It will be unlinked from the DOM.
1864     */
1865     void DeleteNode( XMLNode* node );
1866 
ClearError()1867     void ClearError() {
1868         SetError(XML_SUCCESS, 0, 0);
1869     }
1870 
1871     /// Return true if there was an error parsing the document.
Error()1872     bool Error() const {
1873         return _errorID != XML_SUCCESS;
1874     }
1875     /// Return the errorID.
ErrorID()1876     XMLError  ErrorID() const {
1877         return _errorID;
1878     }
1879 	const char* ErrorName() const;
1880     static const char* ErrorIDToName(XMLError errorID);
1881 
1882     /** Returns a "long form" error description. A hopefully helpful
1883         diagnostic with location, line number, and/or additional info.
1884     */
1885 	const char* ErrorStr() const;
1886 
1887     /// A (trivial) utility function that prints the ErrorStr() to stdout.
1888     void PrintError() const;
1889 
1890     /// Return the line where the error occurred, or zero if unknown.
ErrorLineNum()1891     int ErrorLineNum() const
1892     {
1893         return _errorLineNum;
1894     }
1895 
1896     /// Clear the document, resetting it to the initial state.
1897     void Clear();
1898 
1899 	/**
1900 		Copies this document to a target document.
1901 		The target will be completely cleared before the copy.
1902 		If you want to copy a sub-tree, see XMLNode::DeepClone().
1903 
1904 		NOTE: that the 'target' must be non-null.
1905 	*/
1906 	void DeepCopy(XMLDocument* target) const;
1907 
1908 	// internal
1909     char* Identify( char* p, XMLNode** node );
1910 
1911 	// internal
1912 	void MarkInUse(const XMLNode* const);
1913 
ShallowClone(XMLDocument *)1914     virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const	{
1915         return 0;
1916     }
ShallowEqual(const XMLNode *)1917     virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const	{
1918         return false;
1919     }
1920 
1921 private:
1922     XMLDocument( const XMLDocument& );	// not supported
1923     void operator=( const XMLDocument& );	// not supported
1924 
1925     bool			_writeBOM;
1926     bool			_processEntities;
1927     XMLError		_errorID;
1928     Whitespace		_whitespaceMode;
1929     mutable StrPair	_errorStr;
1930     int             _errorLineNum;
1931     char*			_charBuffer;
1932     int				_parseCurLineNum;
1933 	int				_parsingDepth;
1934 	// Memory tracking does add some overhead.
1935 	// However, the code assumes that you don't
1936 	// have a bunch of unlinked nodes around.
1937 	// Therefore it takes less memory to track
1938 	// in the document vs. a linked list in the XMLNode,
1939 	// and the performance is the same.
1940 	DynArray<XMLNode*, 10> _unlinked;
1941 
1942     MemPoolT< sizeof(XMLElement) >	 _elementPool;
1943     MemPoolT< sizeof(XMLAttribute) > _attributePool;
1944     MemPoolT< sizeof(XMLText) >		 _textPool;
1945     MemPoolT< sizeof(XMLComment) >	 _commentPool;
1946 
1947 	static const char* _errorNames[XML_ERROR_COUNT];
1948 
1949     void Parse();
1950 
1951     void SetError( XMLError error, int lineNum, const char* format, ... );
1952 
1953 	// Something of an obvious security hole, once it was discovered.
1954 	// Either an ill-formed XML or an excessively deep one can overflow
1955 	// the stack. Track stack depth, and error out if needed.
1956 	class DepthTracker {
1957 	public:
DepthTracker(XMLDocument * document)1958 		explicit DepthTracker(XMLDocument * document) {
1959 			this->_document = document;
1960 			document->PushDepth();
1961 		}
~DepthTracker()1962 		~DepthTracker() {
1963 			_document->PopDepth();
1964 		}
1965 	private:
1966 		XMLDocument * _document;
1967 	};
1968 	void PushDepth();
1969 	void PopDepth();
1970 
1971     template<class NodeType, int PoolElementSize>
1972     NodeType* CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool );
1973 };
1974 
1975 template<class NodeType, int PoolElementSize>
CreateUnlinkedNode(MemPoolT<PoolElementSize> & pool)1976 inline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool )
1977 {
1978     TIXMLASSERT( sizeof( NodeType ) == PoolElementSize );
1979     TIXMLASSERT( sizeof( NodeType ) == pool.ItemSize() );
1980     NodeType* returnNode = new (pool.Alloc()) NodeType( this );
1981     TIXMLASSERT( returnNode );
1982     returnNode->_memPool = &pool;
1983 
1984 	_unlinked.Push(returnNode);
1985     return returnNode;
1986 }
1987 
1988 /**
1989 	A XMLHandle is a class that wraps a node pointer with null checks; this is
1990 	an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
1991 	DOM structure. It is a separate utility class.
1992 
1993 	Take an example:
1994 	@verbatim
1995 	<Document>
1996 		<Element attributeA = "valueA">
1997 			<Child attributeB = "value1" />
1998 			<Child attributeB = "value2" />
1999 		</Element>
2000 	</Document>
2001 	@endverbatim
2002 
2003 	Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
2004 	easy to write a *lot* of code that looks like:
2005 
2006 	@verbatim
2007 	XMLElement* root = document.FirstChildElement( "Document" );
2008 	if ( root )
2009 	{
2010 		XMLElement* element = root->FirstChildElement( "Element" );
2011 		if ( element )
2012 		{
2013 			XMLElement* child = element->FirstChildElement( "Child" );
2014 			if ( child )
2015 			{
2016 				XMLElement* child2 = child->NextSiblingElement( "Child" );
2017 				if ( child2 )
2018 				{
2019 					// Finally do something useful.
2020 	@endverbatim
2021 
2022 	And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
2023 	of such code. A XMLHandle checks for null pointers so it is perfectly safe
2024 	and correct to use:
2025 
2026 	@verbatim
2027 	XMLHandle docHandle( &document );
2028 	XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();
2029 	if ( child2 )
2030 	{
2031 		// do something useful
2032 	@endverbatim
2033 
2034 	Which is MUCH more concise and useful.
2035 
2036 	It is also safe to copy handles - internally they are nothing more than node pointers.
2037 	@verbatim
2038 	XMLHandle handleCopy = handle;
2039 	@endverbatim
2040 
2041 	See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
2042 */
2043 class TINYXML2_LIB XMLHandle
2044 {
2045 public:
2046     /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
XMLHandle(XMLNode * node)2047     explicit XMLHandle( XMLNode* node ) : _node( node ) {
2048     }
2049     /// Create a handle from a node.
XMLHandle(XMLNode & node)2050     explicit XMLHandle( XMLNode& node ) : _node( &node ) {
2051     }
2052     /// Copy constructor
XMLHandle(const XMLHandle & ref)2053     XMLHandle( const XMLHandle& ref ) : _node( ref._node ) {
2054     }
2055     /// Assignment
2056     XMLHandle& operator=( const XMLHandle& ref )							{
2057         _node = ref._node;
2058         return *this;
2059     }
2060 
2061     /// Get the first child of this handle.
FirstChild()2062     XMLHandle FirstChild() 													{
2063         return XMLHandle( _node ? _node->FirstChild() : 0 );
2064     }
2065     /// Get the first child element of this handle.
2066     XMLHandle FirstChildElement( const char* name = 0 )						{
2067         return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
2068     }
2069     /// Get the last child of this handle.
LastChild()2070     XMLHandle LastChild()													{
2071         return XMLHandle( _node ? _node->LastChild() : 0 );
2072     }
2073     /// Get the last child element of this handle.
2074     XMLHandle LastChildElement( const char* name = 0 )						{
2075         return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
2076     }
2077     /// Get the previous sibling of this handle.
PreviousSibling()2078     XMLHandle PreviousSibling()												{
2079         return XMLHandle( _node ? _node->PreviousSibling() : 0 );
2080     }
2081     /// Get the previous sibling element of this handle.
2082     XMLHandle PreviousSiblingElement( const char* name = 0 )				{
2083         return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
2084     }
2085     /// Get the next sibling of this handle.
NextSibling()2086     XMLHandle NextSibling()													{
2087         return XMLHandle( _node ? _node->NextSibling() : 0 );
2088     }
2089     /// Get the next sibling element of this handle.
2090     XMLHandle NextSiblingElement( const char* name = 0 )					{
2091         return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
2092     }
2093 
2094     /// Safe cast to XMLNode. This can return null.
ToNode()2095     XMLNode* ToNode()							{
2096         return _node;
2097     }
2098     /// Safe cast to XMLElement. This can return null.
ToElement()2099     XMLElement* ToElement() 					{
2100         return ( _node ? _node->ToElement() : 0 );
2101     }
2102     /// Safe cast to XMLText. This can return null.
ToText()2103     XMLText* ToText() 							{
2104         return ( _node ? _node->ToText() : 0 );
2105     }
2106     /// Safe cast to XMLUnknown. This can return null.
ToUnknown()2107     XMLUnknown* ToUnknown() 					{
2108         return ( _node ? _node->ToUnknown() : 0 );
2109     }
2110     /// Safe cast to XMLDeclaration. This can return null.
ToDeclaration()2111     XMLDeclaration* ToDeclaration() 			{
2112         return ( _node ? _node->ToDeclaration() : 0 );
2113     }
2114 
2115 private:
2116     XMLNode* _node;
2117 };
2118 
2119 
2120 /**
2121 	A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
2122 	same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
2123 */
2124 class TINYXML2_LIB XMLConstHandle
2125 {
2126 public:
XMLConstHandle(const XMLNode * node)2127     explicit XMLConstHandle( const XMLNode* node ) : _node( node ) {
2128     }
XMLConstHandle(const XMLNode & node)2129     explicit XMLConstHandle( const XMLNode& node ) : _node( &node ) {
2130     }
XMLConstHandle(const XMLConstHandle & ref)2131     XMLConstHandle( const XMLConstHandle& ref ) : _node( ref._node ) {
2132     }
2133 
2134     XMLConstHandle& operator=( const XMLConstHandle& ref )							{
2135         _node = ref._node;
2136         return *this;
2137     }
2138 
FirstChild()2139     const XMLConstHandle FirstChild() const											{
2140         return XMLConstHandle( _node ? _node->FirstChild() : 0 );
2141     }
2142     const XMLConstHandle FirstChildElement( const char* name = 0 ) const				{
2143         return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
2144     }
LastChild()2145     const XMLConstHandle LastChild()	const										{
2146         return XMLConstHandle( _node ? _node->LastChild() : 0 );
2147     }
2148     const XMLConstHandle LastChildElement( const char* name = 0 ) const				{
2149         return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
2150     }
PreviousSibling()2151     const XMLConstHandle PreviousSibling() const									{
2152         return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
2153     }
2154     const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const		{
2155         return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
2156     }
NextSibling()2157     const XMLConstHandle NextSibling() const										{
2158         return XMLConstHandle( _node ? _node->NextSibling() : 0 );
2159     }
2160     const XMLConstHandle NextSiblingElement( const char* name = 0 ) const			{
2161         return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
2162     }
2163 
2164 
ToNode()2165     const XMLNode* ToNode() const				{
2166         return _node;
2167     }
ToElement()2168     const XMLElement* ToElement() const			{
2169         return ( _node ? _node->ToElement() : 0 );
2170     }
ToText()2171     const XMLText* ToText() const				{
2172         return ( _node ? _node->ToText() : 0 );
2173     }
ToUnknown()2174     const XMLUnknown* ToUnknown() const			{
2175         return ( _node ? _node->ToUnknown() : 0 );
2176     }
ToDeclaration()2177     const XMLDeclaration* ToDeclaration() const	{
2178         return ( _node ? _node->ToDeclaration() : 0 );
2179     }
2180 
2181 private:
2182     const XMLNode* _node;
2183 };
2184 
2185 
2186 /**
2187 	Printing functionality. The XMLPrinter gives you more
2188 	options than the XMLDocument::Print() method.
2189 
2190 	It can:
2191 	-# Print to memory.
2192 	-# Print to a file you provide.
2193 	-# Print XML without a XMLDocument.
2194 
2195 	Print to Memory
2196 
2197 	@verbatim
2198 	XMLPrinter printer;
2199 	doc.Print( &printer );
2200 	SomeFunction( printer.CStr() );
2201 	@endverbatim
2202 
2203 	Print to a File
2204 
2205 	You provide the file pointer.
2206 	@verbatim
2207 	XMLPrinter printer( fp );
2208 	doc.Print( &printer );
2209 	@endverbatim
2210 
2211 	Print without a XMLDocument
2212 
2213 	When loading, an XML parser is very useful. However, sometimes
2214 	when saving, it just gets in the way. The code is often set up
2215 	for streaming, and constructing the DOM is just overhead.
2216 
2217 	The Printer supports the streaming case. The following code
2218 	prints out a trivially simple XML file without ever creating
2219 	an XML document.
2220 
2221 	@verbatim
2222 	XMLPrinter printer( fp );
2223 	printer.OpenElement( "foo" );
2224 	printer.PushAttribute( "foo", "bar" );
2225 	printer.CloseElement();
2226 	@endverbatim
2227 */
2228 class TINYXML2_LIB XMLPrinter : public XMLVisitor
2229 {
2230 public:
2231     /** Construct the printer. If the FILE* is specified,
2232     	this will print to the FILE. Else it will print
2233     	to memory, and the result is available in CStr().
2234     	If 'compact' is set to true, then output is created
2235     	with only required whitespace and newlines.
2236     */
2237     XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
~XMLPrinter()2238     virtual ~XMLPrinter()	{}
2239 
2240     /** If streaming, write the BOM and declaration. */
2241     void PushHeader( bool writeBOM, bool writeDeclaration );
2242     /** If streaming, start writing an element.
2243         The element must be closed with CloseElement()
2244     */
2245     void OpenElement( const char* name, bool compactMode=false );
2246     /// If streaming, add an attribute to an open element.
2247     void PushAttribute( const char* name, const char* value );
2248     void PushAttribute( const char* name, int value );
2249     void PushAttribute( const char* name, unsigned value );
2250 	void PushAttribute( const char* name, int64_t value );
2251 	void PushAttribute( const char* name, uint64_t value );
2252 	void PushAttribute( const char* name, bool value );
2253     void PushAttribute( const char* name, double value );
2254     /// If streaming, close the Element.
2255     virtual void CloseElement( bool compactMode=false );
2256 
2257     /// Add a text node.
2258     void PushText( const char* text, bool cdata=false );
2259     /// Add a text node from an integer.
2260     void PushText( int value );
2261     /// Add a text node from an unsigned.
2262     void PushText( unsigned value );
2263 	/// Add a text node from a signed 64bit integer.
2264 	void PushText( int64_t value );
2265 	/// Add a text node from an unsigned 64bit integer.
2266 	void PushText( uint64_t value );
2267 	/// Add a text node from a bool.
2268     void PushText( bool value );
2269     /// Add a text node from a float.
2270     void PushText( float value );
2271     /// Add a text node from a double.
2272     void PushText( double value );
2273 
2274     /// Add a comment
2275     void PushComment( const char* comment );
2276 
2277     void PushDeclaration( const char* value );
2278     void PushUnknown( const char* value );
2279 
2280     virtual bool VisitEnter( const XMLDocument& /*doc*/ );
VisitExit(const XMLDocument &)2281     virtual bool VisitExit( const XMLDocument& /*doc*/ )			{
2282         return true;
2283     }
2284 
2285     virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2286     virtual bool VisitExit( const XMLElement& element );
2287 
2288     virtual bool Visit( const XMLText& text );
2289     virtual bool Visit( const XMLComment& comment );
2290     virtual bool Visit( const XMLDeclaration& declaration );
2291     virtual bool Visit( const XMLUnknown& unknown );
2292 
2293     /**
2294     	If in print to memory mode, return a pointer to
2295     	the XML file in memory.
2296     */
CStr()2297     const char* CStr() const {
2298         return _buffer.Mem();
2299     }
2300     /**
2301     	If in print to memory mode, return the size
2302     	of the XML file in memory. (Note the size returned
2303     	includes the terminating null.)
2304     */
CStrSize()2305     int CStrSize() const {
2306         return _buffer.Size();
2307     }
2308     /**
2309     	If in print to memory mode, reset the buffer to the
2310     	beginning.
2311     */
2312     void ClearBuffer( bool resetToFirstElement = true ) {
2313         _buffer.Clear();
2314         _buffer.Push(0);
2315 		_firstElement = resetToFirstElement;
2316     }
2317 
2318 protected:
CompactMode(const XMLElement &)2319 	virtual bool CompactMode( const XMLElement& )	{ return _compactMode; }
2320 
2321 	/** Prints out the space before an element. You may override to change
2322 	    the space and tabs used. A PrintSpace() override should call Print().
2323 	*/
2324     virtual void PrintSpace( int depth );
2325     void Print( const char* format, ... );
2326     void Write( const char* data, size_t size );
Write(const char * data)2327     inline void Write( const char* data )           { Write( data, strlen( data ) ); }
2328     void Putc( char ch );
2329 
2330     void SealElementIfJustOpened();
2331     bool _elementJustOpened;
2332     DynArray< const char*, 10 > _stack;
2333 
2334 private:
2335     void PrintString( const char*, bool restrictedEntitySet );	// prints out, after detecting entities.
2336 
2337     bool _firstElement;
2338     FILE* _fp;
2339     int _depth;
2340     int _textDepth;
2341     bool _processEntities;
2342 	bool _compactMode;
2343 
2344     enum {
2345         ENTITY_RANGE = 64,
2346         BUF_SIZE = 200
2347     };
2348     bool _entityFlag[ENTITY_RANGE];
2349     bool _restrictedEntityFlag[ENTITY_RANGE];
2350 
2351     DynArray< char, 20 > _buffer;
2352 
2353     // Prohibit cloning, intentionally not implemented
2354     XMLPrinter( const XMLPrinter& );
2355     XMLPrinter& operator=( const XMLPrinter& );
2356 };
2357 
2358 
2359 }	// tinyxml2
2360 
2361 #if defined(_MSC_VER)
2362 #   pragma warning(pop)
2363 #endif
2364 
2365 #endif // TINYXML2_INCLUDED
2366