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