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