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