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