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