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 #ifdef ANDROID_NDK
28 	#include <ctype.h>
29 	#include <limits.h>
30 	#include <stdio.h>
31 	#include <stdlib.h>
32 	#include <string.h>
33 	#include <stdarg.h>
34 #else
35 	#include <cctype>
36 	#include <climits>
37 	#include <cstdio>
38 	#include <cstdlib>
39 	#include <cstring>
40 	#include <cstdarg>
41 #endif
42 
43 /*
44    TODO: intern strings instead of allocation.
45 */
46 /*
47 	gcc: g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
48 */
49 
50 #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
51 	#ifndef DEBUG
52 		#define DEBUG
53 	#endif
54 #endif
55 
56 
57 #if defined(DEBUG)
58         #if defined(_MSC_VER)
59                 #define TIXMLASSERT( x )           if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
60         #elif defined (ANDROID_NDK)
61                 #include <android/log.h>
62                 #define TIXMLASSERT( x )           if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
63         #else
64                 #include <assert.h>
65                 #define TIXMLASSERT                assert
66         #endif
67 #else
68         #define TIXMLASSERT( x )           {}
69 #endif
70 
71 
72 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
73 	// Microsoft visual studio, version 2005 and higher.
74 	/*int _snprintf_s(
75 	   char *buffer,
76 	   size_t sizeOfBuffer,
77 	   size_t count,
78 	   const char *format [,
79 		  argument] ...
80 	);*/
TIXML_SNPRINTF(char * buffer,size_t size,const char * format,...)81 	inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) {
82 	    va_list va;
83 		va_start( va, format );
84 		int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
85 	    va_end( va );
86 		return result;
87 	}
88 	#define TIXML_SSCANF   sscanf_s
89 #else
90 	// GCC version 3 and higher
91 	//#warning( "Using sn* functions." )
92 	#define TIXML_SNPRINTF snprintf
93 	#define TIXML_SSCANF   sscanf
94 #endif
95 
96 static const int TIXML2_MAJOR_VERSION = 1;
97 static const int TIXML2_MINOR_VERSION = 0;
98 static const int TIXML2_PATCH_VERSION = 8;
99 
100 namespace tinyxml2
101 {
102 class XMLDocument;
103 class XMLElement;
104 class XMLAttribute;
105 class XMLComment;
106 class XMLNode;
107 class XMLText;
108 class XMLDeclaration;
109 class XMLUnknown;
110 
111 class XMLPrinter;
112 
113 /*
114 	A class that wraps strings. Normally stores the start and end
115 	pointers into the XML file itself, and will apply normalization
116 	and entity translation if actually read. Can also store (and memory
117 	manage) a traditional char[]
118 */
119 class StrPair
120 {
121 public:
122 	enum {
123 		NEEDS_ENTITY_PROCESSING			= 0x01,
124 		NEEDS_NEWLINE_NORMALIZATION		= 0x02,
125 		COLLAPSE_WHITESPACE				= 0x04,
126 
127 		TEXT_ELEMENT		= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
128 		TEXT_ELEMENT_LEAVE_ENTITIES		= NEEDS_NEWLINE_NORMALIZATION,
129 		ATTRIBUTE_NAME		= 0,
130 		ATTRIBUTE_VALUE		= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
131 		ATTRIBUTE_VALUE_LEAVE_ENTITIES		= NEEDS_NEWLINE_NORMALIZATION,
132 		COMMENT				= NEEDS_NEWLINE_NORMALIZATION
133 	};
134 
StrPair()135 	StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
136 	~StrPair();
137 
Set(char * _start,char * _end,int _flags)138 	void Set( char* _start, char* _end, int _flags ) {
139 		Reset();
140 		this->start = _start; this->end = _end; this->flags = _flags | NEEDS_FLUSH;
141 	}
142 	const char* GetStr();
Empty()143 	bool Empty() const { return start == end; }
144 
SetInternedStr(const char * str)145 	void SetInternedStr( const char* str ) { Reset(); this->start = const_cast<char*>(str); }
146 	void SetStr( const char* str, int flags=0 );
147 
148 	char* ParseText( char* in, const char* endTag, int strFlags );
149 	char* ParseName( char* in );
150 
151 
152 private:
153 	void Reset();
154 	void CollapseWhitespace();
155 
156 	enum {
157 		NEEDS_FLUSH = 0x100,
158 		NEEDS_DELETE = 0x200
159 	};
160 
161 	// After parsing, if *end != 0, it can be set to zero.
162 	int flags;
163 	char* start;
164 	char* end;
165 };
166 
167 
168 /*
169 	A dynamic array of Plain Old Data. Doesn't support constructors, etc.
170 	Has a small initial memory pool, so that low or no usage will not
171 	cause a call to new/delete
172 */
173 template <class T, int INIT>
174 class DynArray
175 {
176 public:
177 	DynArray< T, INIT >()
178 	{
179 		mem = pool;
180 		allocated = INIT;
181 		size = 0;
182 	}
~DynArray()183 	~DynArray()
184 	{
185 		if ( mem != pool ) {
186 			delete [] mem;
187 		}
188 	}
Push(T t)189 	void Push( T t )
190 	{
191 		EnsureCapacity( size+1 );
192 		mem[size++] = t;
193 	}
194 
PushArr(int count)195 	T* PushArr( int count )
196 	{
197 		EnsureCapacity( size+count );
198 		T* ret = &mem[size];
199 		size += count;
200 		return ret;
201 	}
Pop()202 	T Pop() {
203 		return mem[--size];
204 	}
PopArr(int count)205 	void PopArr( int count )
206 	{
207 		TIXMLASSERT( size >= count );
208 		size -= count;
209 	}
210 
Empty()211 	bool Empty() const					{ return size == 0; }
212 	T& operator[](int i)				{ TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
213 	const T& operator[](int i) const	{ TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
Size()214 	int Size() const					{ return size; }
Capacity()215 	int Capacity() const				{ return allocated; }
Mem()216 	const T* Mem() const				{ return mem; }
Mem()217 	T* Mem()							{ return mem; }
218 
219 
220 private:
EnsureCapacity(int cap)221 	void EnsureCapacity( int cap ) {
222 		if ( cap > allocated ) {
223 			int newAllocated = cap * 2;
224 			T* newMem = new T[newAllocated];
225 			memcpy( newMem, mem, sizeof(T)*size );	// warning: not using constructors, only works for PODs
226 			if ( mem != pool ) delete [] mem;
227 			mem = newMem;
228 			allocated = newAllocated;
229 		}
230 	}
231 
232 	T* mem;
233 	T pool[INIT];
234 	int allocated;		// objects allocated
235 	int size;			// number objects in use
236 };
237 
238 
239 /*
240 	Parent virtual class of a pool for fast allocation
241 	and deallocation of objects.
242 */
243 class MemPool
244 {
245 public:
MemPool()246 	MemPool() {}
~MemPool()247 	virtual ~MemPool() {}
248 
249 	virtual int ItemSize() const = 0;
250 	virtual void* Alloc() = 0;
251 	virtual void Free( void* ) = 0;
252 };
253 
254 
255 /*
256 	Template child class to create pools of the correct type.
257 */
258 template< int SIZE >
259 class MemPoolT : public MemPool
260 {
261 public:
MemPoolT()262 	MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0)	{}
~MemPoolT()263 	~MemPoolT() {
264 		// Delete the blocks.
265 		for( int i=0; i<blockPtrs.Size(); ++i ) {
266 			delete blockPtrs[i];
267 		}
268 	}
269 
ItemSize()270 	virtual int ItemSize() const	{ return SIZE; }
CurrentAllocs()271 	int CurrentAllocs() const		{ return currentAllocs; }
272 
Alloc()273 	virtual void* Alloc() {
274 		if ( !root ) {
275 			// Need a new block.
276 			Block* block = new Block();
277 			blockPtrs.Push( block );
278 
279 			for( int i=0; i<COUNT-1; ++i ) {
280 				block->chunk[i].next = &block->chunk[i+1];
281 			}
282 			block->chunk[COUNT-1].next = 0;
283 			root = block->chunk;
284 		}
285 		void* result = root;
286 		root = root->next;
287 
288 		++currentAllocs;
289 		if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
290 		nAllocs++;
291 		return result;
292 	}
Free(void * mem)293 	virtual void Free( void* mem ) {
294 		if ( !mem ) return;
295 		--currentAllocs;
296 		Chunk* chunk = (Chunk*)mem;
297 #ifdef DEBUG
298 		memset( chunk, 0xfe, sizeof(Chunk) );
299 #endif
300 		chunk->next = root;
301 		root = chunk;
302 	}
Trace(const char * name)303 	void Trace( const char* name ) {
304 		printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
305 				 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
306 	}
307 
308 private:
309 	enum { COUNT = 1024/SIZE };
310 	union Chunk {
311 		Chunk* next;
312 		char mem[SIZE];
313 	};
314 	struct Block {
315 		Chunk chunk[COUNT];
316 	};
317 	DynArray< Block*, 10 > blockPtrs;
318 	Chunk* root;
319 
320 	int currentAllocs;
321 	int nAllocs;
322 	int maxAllocs;
323 };
324 
325 
326 
327 /**
328 	Implements the interface to the "Visitor pattern" (see the Accept() method.)
329 	If you call the Accept() method, it requires being passed a XMLVisitor
330 	class to handle callbacks. For nodes that contain other nodes (Document, Element)
331 	you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
332 	are simply called with Visit().
333 
334 	If you return 'true' from a Visit method, recursive parsing will continue. If you return
335 	false, <b>no children of this node or its sibilings</b> will be visited.
336 
337 	All flavors of Visit methods have a default implementation that returns 'true' (continue
338 	visiting). You need to only override methods that are interesting to you.
339 
340 	Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
341 
342 	You should never change the document from a callback.
343 
344 	@sa XMLNode::Accept()
345 */
346 class XMLVisitor
347 {
348 public:
~XMLVisitor()349 	virtual ~XMLVisitor() {}
350 
351 	/// Visit a document.
VisitEnter(const XMLDocument &)352 	virtual bool VisitEnter( const XMLDocument& /*doc*/ )			{ return true; }
353 	/// Visit a document.
VisitExit(const XMLDocument &)354 	virtual bool VisitExit( const XMLDocument& /*doc*/ )			{ return true; }
355 
356 	/// Visit an element.
VisitEnter(const XMLElement &,const XMLAttribute *)357 	virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )	{ return true; }
358 	/// Visit an element.
VisitExit(const XMLElement &)359 	virtual bool VisitExit( const XMLElement& /*element*/ )			{ return true; }
360 
361 	/// Visit a declaration.
Visit(const XMLDeclaration &)362 	virtual bool Visit( const XMLDeclaration& /*declaration*/ )		{ return true; }
363 	/// Visit a text node.
Visit(const XMLText &)364 	virtual bool Visit( const XMLText& /*text*/ )					{ return true; }
365 	/// Visit a comment node.
Visit(const XMLComment &)366 	virtual bool Visit( const XMLComment& /*comment*/ )				{ return true; }
367 	/// Visit an unknown node.
Visit(const XMLUnknown &)368 	virtual bool Visit( const XMLUnknown& /*unknown*/ )				{ return true; }
369 };
370 
371 
372 /*
373 	Utility functionality.
374 */
375 class XMLUtil
376 {
377 public:
378 	// Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
379 	// correct, but simple, and usually works.
SkipWhiteSpace(const char * p)380 	static const char* SkipWhiteSpace( const char* p )	{ while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) { ++p; } return p; }
SkipWhiteSpace(char * p)381 	static char* SkipWhiteSpace( char* p )				{ while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) )		{ ++p; } return p; }
IsWhiteSpace(char p)382 	static bool IsWhiteSpace( char p )					{ return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) ); }
383 
384 	inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {
385 		int n = 0;
386 		if ( p == q ) {
387 			return true;
388 		}
389 		while( *p && *q && *p == *q && n<nChar ) {
390 			++p; ++q; ++n;
391 		}
392 		if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
393 			return true;
394 		}
395 		return false;
396 	}
IsUTF8Continuation(const char p)397 	inline static int IsUTF8Continuation( const char p ) { return p & 0x80; }
IsAlphaNum(unsigned char anyByte)398 	inline static int IsAlphaNum( unsigned char anyByte )	{ return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
IsAlpha(unsigned char anyByte)399 	inline static int IsAlpha( unsigned char anyByte )		{ return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
400 
401 	static const char* ReadBOM( const char* p, bool* hasBOM );
402 	// p is the starting location,
403 	// the UTF-8 value of the entity will be placed in value, and length filled in.
404 	static const char* GetCharacterRef( const char* p, char* value, int* length );
405 	static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
406 
407 	// converts primitive types to strings
408 	static void ToStr( int v, char* buffer, int bufferSize );
409 	static void ToStr( unsigned v, char* buffer, int bufferSize );
410 	static void ToStr( bool v, char* buffer, int bufferSize );
411 	static void ToStr( float v, char* buffer, int bufferSize );
412 	static void ToStr( double v, char* buffer, int bufferSize );
413 
414 	// converts strings to primitive types
415 	static bool	ToInt( const char* str, int* value );
416 	static bool ToUnsigned( const char* str, unsigned* value );
417 	static bool	ToBool( const char* str, bool* value );
418 	static bool	ToFloat( const char* str, float* value );
419 	static bool ToDouble( const char* str, double* value );
420 };
421 
422 
423 /** XMLNode is a base class for every object that is in the
424 	XML Document Object Model (DOM), except XMLAttributes.
425 	Nodes have siblings, a parent, and children which can
426 	be navigated. A node is always in a XMLDocument.
427 	The type of a XMLNode can be queried, and it can
428 	be cast to its more defined type.
429 
430 	A XMLDocument allocates memory for all its Nodes.
431 	When the XMLDocument gets deleted, all its Nodes
432 	will also be deleted.
433 
434 	@verbatim
435 	A Document can contain:	Element	(container or leaf)
436 							Comment (leaf)
437 							Unknown (leaf)
438 							Declaration( leaf )
439 
440 	An Element can contain:	Element (container or leaf)
441 							Text	(leaf)
442 							Attributes (not on tree)
443 							Comment (leaf)
444 							Unknown (leaf)
445 
446 	@endverbatim
447 */
448 class XMLNode
449 {
450 	friend class XMLDocument;
451 	friend class XMLElement;
452 public:
453 
454 	/// Get the XMLDocument that owns this XMLNode.
GetDocument()455 	const XMLDocument* GetDocument() const	{ return document; }
456 	/// Get the XMLDocument that owns this XMLNode.
GetDocument()457 	XMLDocument* GetDocument()				{ return document; }
458 
ToElement()459 	virtual XMLElement*		ToElement()		{ return 0; }	///< Safely cast to an Element, or null.
ToText()460 	virtual XMLText*		ToText()		{ return 0; }	///< Safely cast to Text, or null.
ToComment()461 	virtual XMLComment*		ToComment()		{ return 0; }	///< Safely cast to a Comment, or null.
ToDocument()462 	virtual XMLDocument*	ToDocument()	{ return 0; }	///< Safely cast to a Document, or null.
ToDeclaration()463 	virtual XMLDeclaration*	ToDeclaration()	{ return 0; }	///< Safely cast to a Declaration, or null.
ToUnknown()464 	virtual XMLUnknown*		ToUnknown()		{ return 0; }	///< Safely cast to an Unknown, or null.
465 
ToElement()466 	virtual const XMLElement*		ToElement() const		{ return 0; }
ToText()467 	virtual const XMLText*			ToText() const			{ return 0; }
ToComment()468 	virtual const XMLComment*		ToComment() const		{ return 0; }
ToDocument()469 	virtual const XMLDocument*		ToDocument() const		{ return 0; }
ToDeclaration()470 	virtual const XMLDeclaration*	ToDeclaration() const	{ return 0; }
ToUnknown()471 	virtual const XMLUnknown*		ToUnknown() const		{ return 0; }
472 
473 	/** The meaning of 'value' changes for the specific type.
474 		@verbatim
475 		Document:	empty
476 		Element:	name of the element
477 		Comment:	the comment text
478 		Unknown:	the tag contents
479 		Text:		the text string
480 		@endverbatim
481 	*/
Value()482 	const char* Value() const			{ return value.GetStr(); }
483 	/** Set the Value of an XML node.
484 		@sa Value()
485 	*/
486 	void SetValue( const char* val, bool staticMem=false );
487 
488 	/// Get the parent of this node on the DOM.
Parent()489 	const XMLNode*	Parent() const			{ return parent; }
Parent()490 	XMLNode* Parent()						{ return parent; }
491 
492 	/// Returns true if this node has no children.
NoChildren()493 	bool NoChildren() const					{ return !firstChild; }
494 
495 	/// Get the first child node, or null if none exists.
FirstChild()496 	const XMLNode*  FirstChild() const		{ return firstChild; }
FirstChild()497 	XMLNode*		FirstChild()			{ return firstChild; }
498 	/** Get the first child element, or optionally the first child
499 	    element with the specified name.
500 	*/
501 	const XMLElement* FirstChildElement( const char* value=0 ) const;
502 	XMLElement* FirstChildElement( const char* _value=0 )	{ return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( _value )); }
503 
504 	/// Get the last child node, or null if none exists.
LastChild()505 	const XMLNode*	LastChild() const						{ return lastChild; }
LastChild()506 	XMLNode*		LastChild()								{ return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
507 
508 	/** Get the last child element or optionally the last child
509 	    element with the specified name.
510 	*/
511 	const XMLElement* LastChildElement( const char* value=0 ) const;
512 	XMLElement* LastChildElement( const char* _value=0 )	{ return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(_value) ); }
513 
514 	/// Get the previous (left) sibling node of this node.
PreviousSibling()515 	const XMLNode*	PreviousSibling() const					{ return prev; }
PreviousSibling()516 	XMLNode*	PreviousSibling()							{ return prev; }
517 
518 	/// Get the previous (left) sibling element of this node, with an opitionally supplied name.
519 	const XMLElement*	PreviousSiblingElement( const char* value=0 ) const ;
520 	XMLElement*	PreviousSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( _value ) ); }
521 
522 	/// Get the next (right) sibling node of this node.
NextSibling()523 	const XMLNode*	NextSibling() const						{ return next; }
NextSibling()524 	XMLNode*	NextSibling()								{ return next; }
525 
526 	/// Get the next (right) sibling element of this node, with an opitionally supplied name.
527 	const XMLElement*	NextSiblingElement( const char* value=0 ) const;
528  	XMLElement*	NextSiblingElement( const char* _value=0 )	{ return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( _value ) ); }
529 
530 	/**
531 		Add a child node as the last (right) child.
532 	*/
533 	XMLNode* InsertEndChild( XMLNode* addThis );
534 
LinkEndChild(XMLNode * addThis)535 	XMLNode* LinkEndChild( XMLNode* addThis )	{ return InsertEndChild( addThis ); }
536 	/**
537 		Add a child node as the first (left) child.
538 	*/
539 	XMLNode* InsertFirstChild( XMLNode* addThis );
540 	/**
541 		Add a node after the specified child node.
542 	*/
543 	XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
544 
545 	/**
546 		Delete all the children of this node.
547 	*/
548 	void DeleteChildren();
549 
550 	/**
551 		Delete a child of this node.
552 	*/
553 	void DeleteChild( XMLNode* node );
554 
555 	/**
556 		Make a copy of this node, but not its children.
557 		You may pass in a Document pointer that will be
558 		the owner of the new Node. If the 'document' is
559 		null, then the node returned will be allocated
560 		from the current Document. (this->GetDocument())
561 
562 		Note: if called on a XMLDocument, this will return null.
563 	*/
564 	virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
565 
566 	/**
567 		Test if 2 nodes are the same, but don't test children.
568 		The 2 nodes do not need to be in the same Document.
569 
570 		Note: if called on a XMLDocument, this will return false.
571 	*/
572 	virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
573 
574 	/** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
575 		XML tree will be conditionally visited and the host will be called back
576 		via the TiXmlVisitor interface.
577 
578 		This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
579 		the XML for the callbacks, so the performance of TinyXML is unchanged by using this
580 		interface versus any other.)
581 
582 		The interface has been based on ideas from:
583 
584 		- http://www.saxproject.org/
585 		- http://c2.com/cgi/wiki?HierarchicalVisitorPattern
586 
587 		Which are both good references for "visiting".
588 
589 		An example of using Accept():
590 		@verbatim
591 		TiXmlPrinter printer;
592 		tinyxmlDoc.Accept( &printer );
593 		const char* xmlcstr = printer.CStr();
594 		@endverbatim
595 	*/
596 	virtual bool Accept( XMLVisitor* visitor ) const = 0;
597 
598 	// internal
599 	virtual char* ParseDeep( char*, StrPair* );
600 
601 protected:
602 	XMLNode( XMLDocument* );
603 	virtual ~XMLNode();
604 	XMLNode( const XMLNode& );	// not supported
605 	XMLNode& operator=( const XMLNode& );	// not supported
606 
607 	XMLDocument*	document;
608 	XMLNode*		parent;
609 	mutable StrPair	value;
610 
611 	XMLNode*		firstChild;
612 	XMLNode*		lastChild;
613 
614 	XMLNode*		prev;
615 	XMLNode*		next;
616 
617 private:
618 	MemPool*		memPool;
619 	void Unlink( XMLNode* child );
620 };
621 
622 
623 /** XML text.
624 
625 	Note that a text node can have child element nodes, for example:
626 	@verbatim
627 	<root>This is <b>bold</b></root>
628 	@endverbatim
629 
630 	A text node can have 2 ways to output the next. "normal" output
631 	and CDATA. It will default to the mode it was parsed from the XML file and
632 	you generally want to leave it alone, but you can change the output mode with
633 	SetCDATA() and query it with CDATA().
634 */
635 class XMLText : public XMLNode
636 {
637 	friend class XMLBase;
638 	friend class XMLDocument;
639 public:
640 	virtual bool Accept( XMLVisitor* visitor ) const;
641 
ToText()642 	virtual XMLText*	ToText()			{ return this; }
ToText()643 	virtual const XMLText*	ToText() const	{ return this; }
644 
645 	/// Declare whether this should be CDATA or standard text.
SetCData(bool _isCData)646 	void SetCData( bool _isCData )			{ this->isCData = _isCData; }
647 	/// Returns true if this is a CDATA text element.
CData()648 	bool CData() const						{ return isCData; }
649 
650 	char* ParseDeep( char*, StrPair* endTag );
651 	virtual XMLNode* ShallowClone( XMLDocument* document ) const;
652 	virtual bool ShallowEqual( const XMLNode* compare ) const;
653 
654 
655 protected:
XMLText(XMLDocument * doc)656 	XMLText( XMLDocument* doc )	: XMLNode( doc ), isCData( false )	{}
~XMLText()657 	virtual ~XMLText()												{}
658 	XMLText( const XMLText& );	// not supported
659 	XMLText& operator=( const XMLText& );	// not supported
660 
661 private:
662 	bool isCData;
663 };
664 
665 
666 /** An XML Comment. */
667 class XMLComment : public XMLNode
668 {
669 	friend class XMLDocument;
670 public:
ToComment()671 	virtual XMLComment*	ToComment()					{ return this; }
ToComment()672 	virtual const XMLComment* ToComment() const		{ return this; }
673 
674 	virtual bool Accept( XMLVisitor* visitor ) const;
675 
676 	char* ParseDeep( char*, StrPair* endTag );
677 	virtual XMLNode* ShallowClone( XMLDocument* document ) const;
678 	virtual bool ShallowEqual( const XMLNode* compare ) const;
679 
680 protected:
681 	XMLComment( XMLDocument* doc );
682 	virtual ~XMLComment();
683 	XMLComment( const XMLComment& );	// not supported
684 	XMLComment& operator=( const XMLComment& );	// not supported
685 
686 private:
687 };
688 
689 
690 /** In correct XML the declaration is the first entry in the file.
691 	@verbatim
692 		<?xml version="1.0" standalone="yes"?>
693 	@endverbatim
694 
695 	TinyXML2 will happily read or write files without a declaration,
696 	however.
697 
698 	The text of the declaration isn't interpreted. It is parsed
699 	and written as a string.
700 */
701 class XMLDeclaration : public XMLNode
702 {
703 	friend class XMLDocument;
704 public:
ToDeclaration()705 	virtual XMLDeclaration*	ToDeclaration()					{ return this; }
ToDeclaration()706 	virtual const XMLDeclaration* ToDeclaration() const		{ return this; }
707 
708 	virtual bool Accept( XMLVisitor* visitor ) const;
709 
710 	char* ParseDeep( char*, StrPair* endTag );
711 	virtual XMLNode* ShallowClone( XMLDocument* document ) const;
712 	virtual bool ShallowEqual( const XMLNode* compare ) const;
713 
714 protected:
715 	XMLDeclaration( XMLDocument* doc );
716 	virtual ~XMLDeclaration();
717 	XMLDeclaration( const XMLDeclaration& );	// not supported
718 	XMLDeclaration& operator=( const XMLDeclaration& );	// not supported
719 };
720 
721 
722 /** Any tag that tinyXml doesn't recognize is saved as an
723 	unknown. It is a tag of text, but should not be modified.
724 	It will be written back to the XML, unchanged, when the file
725 	is saved.
726 
727 	DTD tags get thrown into TiXmlUnknowns.
728 */
729 class XMLUnknown : public XMLNode
730 {
731 	friend class XMLDocument;
732 public:
ToUnknown()733 	virtual XMLUnknown*	ToUnknown()					{ return this; }
ToUnknown()734 	virtual const XMLUnknown* ToUnknown() const		{ return this; }
735 
736 	virtual bool Accept( XMLVisitor* visitor ) const;
737 
738 	char* ParseDeep( char*, StrPair* endTag );
739 	virtual XMLNode* ShallowClone( XMLDocument* document ) const;
740 	virtual bool ShallowEqual( const XMLNode* compare ) const;
741 
742 protected:
743 	XMLUnknown( XMLDocument* doc );
744 	virtual ~XMLUnknown();
745 	XMLUnknown( const XMLUnknown& );	// not supported
746 	XMLUnknown& operator=( const XMLUnknown& );	// not supported
747 };
748 
749 
750 enum {
751 	XML_NO_ERROR = 0,
752 	XML_SUCCESS = 0,
753 
754 	XML_NO_ATTRIBUTE,
755 	XML_WRONG_ATTRIBUTE_TYPE,
756 
757 	XML_ERROR_FILE_NOT_FOUND,
758 	XML_ERROR_FILE_COULD_NOT_BE_OPENED,
759 	XML_ERROR_FILE_READ_ERROR,
760 	XML_ERROR_ELEMENT_MISMATCH,
761 	XML_ERROR_PARSING_ELEMENT,
762 	XML_ERROR_PARSING_ATTRIBUTE,
763 	XML_ERROR_IDENTIFYING_TAG,
764 	XML_ERROR_PARSING_TEXT,
765 	XML_ERROR_PARSING_CDATA,
766 	XML_ERROR_PARSING_COMMENT,
767 	XML_ERROR_PARSING_DECLARATION,
768 	XML_ERROR_PARSING_UNKNOWN,
769 	XML_ERROR_EMPTY_DOCUMENT,
770 	XML_ERROR_MISMATCHED_ELEMENT,
771 	XML_ERROR_PARSING,
772 
773 	XML_CAN_NOT_CONVERT_TEXT,
774 	XML_NO_TEXT_NODE
775 };
776 
777 
778 /** An attribute is a name-value pair. Elements have an arbitrary
779 	number of attributes, each with a unique name.
780 
781 	@note The attributes are not XMLNodes. You may only query the
782 	Next() attribute in a list.
783 */
784 class XMLAttribute
785 {
786 	friend class XMLElement;
787 public:
Name()788 	const char* Name() const { return name.GetStr(); }			///< The name of the attribute.
Value()789 	const char* Value() const { return value.GetStr(); }		///< The value of the attribute.
Next()790 	const XMLAttribute* Next() const { return next; }			///< The next attribute in the list.
791 
792 	/** IntAttribute interprets the attribute as an integer, and returns the value.
793 	    If the value isn't an integer, 0 will be returned. There is no error checking;
794 		use QueryIntAttribute() if you need error checking.
795 	*/
IntValue()796 	int		 IntValue() const				{ int i=0;		QueryIntValue( &i );		return i; }
797 	/// Query as an unsigned integer. See IntAttribute()
UnsignedValue()798 	unsigned UnsignedValue() const			{ unsigned i=0; QueryUnsignedValue( &i );	return i; }
799 	/// Query as a boolean. See IntAttribute()
BoolValue()800 	bool	 BoolValue() const				{ bool b=false; QueryBoolValue( &b );		return b; }
801 	/// Query as a double. See IntAttribute()
DoubleValue()802 	double 	 DoubleValue() const			{ double d=0;	QueryDoubleValue( &d );		return d; }
803 	/// Query as a float. See IntAttribute()
FloatValue()804 	float	 FloatValue() const				{ float f=0;	QueryFloatValue( &f );		return f; }
805 
806 	/** QueryIntAttribute interprets the attribute as an integer, and returns the value
807 		in the provided paremeter. The function will return XML_NO_ERROR on success,
808 		and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
809 	*/
810 	int QueryIntValue( int* value ) const;
811 	/// See QueryIntAttribute
812 	int QueryUnsignedValue( unsigned int* value ) const;
813 	/// See QueryIntAttribute
814 	int QueryBoolValue( bool* value ) const;
815 	/// See QueryIntAttribute
816 	int QueryDoubleValue( double* value ) const;
817 	/// See QueryIntAttribute
818 	int QueryFloatValue( float* value ) const;
819 
820 	/// Set the attribute to a string value.
821 	void SetAttribute( const char* value );
822 	/// Set the attribute to value.
823 	void SetAttribute( int value );
824 	/// Set the attribute to value.
825 	void SetAttribute( unsigned value );
826 	/// Set the attribute to value.
827 	void SetAttribute( bool value );
828 	/// Set the attribute to value.
829 	void SetAttribute( double value );
830 	/// Set the attribute to value.
831 	void SetAttribute( float value );
832 
833 private:
834 	enum { BUF_SIZE = 200 };
835 
XMLAttribute()836 	XMLAttribute() : next( 0 ) {}
~XMLAttribute()837 	virtual ~XMLAttribute()	{}
838 	XMLAttribute( const XMLAttribute& );	// not supported
839 	void operator=( const XMLAttribute& );	// not supported
840 	void SetName( const char* name );
841 
842 	char* ParseDeep( char* p, bool processEntities );
843 
844 	mutable StrPair name;
845 	mutable StrPair value;
846 	XMLAttribute* next;
847 	MemPool* memPool;
848 };
849 
850 
851 /** The element is a container class. It has a value, the element name,
852 	and can contain other elements, text, comments, and unknowns.
853 	Elements also contain an arbitrary number of attributes.
854 */
855 class XMLElement : public XMLNode
856 {
857 	friend class XMLBase;
858 	friend class XMLDocument;
859 public:
860 	/// Get the name of an element (which is the Value() of the node.)
Name()861 	const char* Name() const		{ return Value(); }
862 	/// Set the name of the element.
863 	void SetName( const char* str, bool staticMem=false )	{ SetValue( str, staticMem ); }
864 
ToElement()865 	virtual XMLElement* ToElement()				{ return this; }
ToElement()866 	virtual const XMLElement* ToElement() const { return this; }
867 	virtual bool Accept( XMLVisitor* visitor ) const;
868 
869 	/** Given an attribute name, Attribute() returns the value
870 		for the attribute of that name, or null if none
871 		exists. For example:
872 
873 		@verbatim
874 		const char* value = ele->Attribute( "foo" );
875 		@endverbatim
876 
877 		The 'value' parameter is normally null. However, if specified,
878 		the attribute will only be returned if the 'name' and 'value'
879 		match. This allow you to write code:
880 
881 		@verbatim
882 		if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
883 		@endverbatim
884 
885 		rather than:
886 		@verbatim
887 		if ( ele->Attribute( "foo" ) ) {
888 			if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
889 		}
890 		@endverbatim
891 	*/
892 	const char* Attribute( const char* name, const char* value=0 ) const;
893 
894 	/** Given an attribute name, IntAttribute() returns the value
895 		of the attribute interpreted as an integer. 0 will be
896 		returned if there is an error. For a method with error
897 		checking, see QueryIntAttribute()
898 	*/
IntAttribute(const char * name)899 	int		 IntAttribute( const char* name ) const		{ int i=0;		QueryIntAttribute( name, &i );		return i; }
900 	/// See IntAttribute()
UnsignedAttribute(const char * name)901 	unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; }
902 	/// See IntAttribute()
BoolAttribute(const char * name)903 	bool	 BoolAttribute( const char* name ) const	{ bool b=false; QueryBoolAttribute( name, &b );		return b; }
904 	/// See IntAttribute()
DoubleAttribute(const char * name)905 	double 	 DoubleAttribute( const char* name ) const	{ double d=0;	QueryDoubleAttribute( name, &d );	return d; }
906 	/// See IntAttribute()
FloatAttribute(const char * name)907 	float	 FloatAttribute( const char* name ) const	{ float f=0;	QueryFloatAttribute( name, &f );	return f; }
908 
909 	/** Given an attribute name, QueryIntAttribute() returns
910 		XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
911 		can't be performed, or XML_NO_ATTRIBUTE if the attribute
912 		doesn't exist. If successful, the result of the conversion
913 		will be written to 'value'. If not successful, nothing will
914 		be written to 'value'. This allows you to provide default
915 		value:
916 
917 		@verbatim
918 		int value = 10;
919 		QueryIntAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
920 		@endverbatim
921 	*/
QueryIntAttribute(const char * name,int * _value)922 	int QueryIntAttribute( const char* name, int* _value ) const				{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryIntValue( _value ); }
923 	/// See QueryIntAttribute()
QueryUnsignedAttribute(const char * name,unsigned int * _value)924 	int QueryUnsignedAttribute( const char* name, unsigned int* _value ) const	{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryUnsignedValue( _value ); }
925 	/// See QueryIntAttribute()
QueryBoolAttribute(const char * name,bool * _value)926 	int QueryBoolAttribute( const char* name, bool* _value ) const				{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryBoolValue( _value ); }
927 	/// See QueryIntAttribute()
QueryDoubleAttribute(const char * name,double * _value)928 	int QueryDoubleAttribute( const char* name, double* _value ) const			{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryDoubleValue( _value ); }
929 	/// See QueryIntAttribute()
QueryFloatAttribute(const char * name,float * _value)930 	int QueryFloatAttribute( const char* name, float* _value ) const			{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryFloatValue( _value ); }
931 
932 	/// Sets the named attribute to value.
SetAttribute(const char * name,const char * _value)933 	void SetAttribute( const char* name, const char* _value )	{ XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
934 	/// Sets the named attribute to value.
SetAttribute(const char * name,int _value)935 	void SetAttribute( const char* name, int _value )			{ XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
936 	/// Sets the named attribute to value.
SetAttribute(const char * name,unsigned _value)937 	void SetAttribute( const char* name, unsigned _value )		{ XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
938 	/// Sets the named attribute to value.
SetAttribute(const char * name,bool _value)939 	void SetAttribute( const char* name, bool _value )			{ XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
940 	/// Sets the named attribute to value.
SetAttribute(const char * name,double _value)941 	void SetAttribute( const char* name, double _value )		{ XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
942 
943 	/**
944 		Delete an attribute.
945 	*/
946 	void DeleteAttribute( const char* name );
947 
948 	/// Return the first attribute in the list.
FirstAttribute()949 	const XMLAttribute* FirstAttribute() const { return rootAttribute; }
950 	/// Query a specific attribute in the list.
951 	const XMLAttribute* FindAttribute( const char* name ) const;
952 
953 	/** Convenience function for easy access to the text inside an element. Although easy
954 		and concise, GetText() is limited compared to getting the TiXmlText child
955 		and accessing it directly.
956 
957 		If the first child of 'this' is a TiXmlText, the GetText()
958 		returns the character string of the Text node, else null is returned.
959 
960 		This is a convenient method for getting the text of simple contained text:
961 		@verbatim
962 		<foo>This is text</foo>
963 			const char* str = fooElement->GetText();
964 		@endverbatim
965 
966 		'str' will be a pointer to "This is text".
967 
968 		Note that this function can be misleading. If the element foo was created from
969 		this XML:
970 		@verbatim
971 			<foo><b>This is text</b></foo>
972 		@endverbatim
973 
974 		then the value of str would be null. The first child node isn't a text node, it is
975 		another element. From this XML:
976 		@verbatim
977 			<foo>This is <b>text</b></foo>
978 		@endverbatim
979 		GetText() will return "This is ".
980 	*/
981 	const char* GetText() const;
982 
983 	/**
984 		Convenience method to query the value of a child text node. This is probably best
985 		shown by example. Given you have a document is this form:
986 		@verbatim
987 			<point>
988 				<x>1</x>
989 				<y>1.4</y>
990 			</point>
991 		@endverbatim
992 
993 		The QueryIntText() and similar functions provide a safe and easier way to get to the
994 		"value" of x and y.
995 
996 		@verbatim
997 			int x = 0;
998 			float y = 0;	// types of x and y are contrived for example
999 			const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1000 			const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1001 			xElement->QueryIntText( &x );
1002 			yElement->QueryFloatText( &y );
1003 		@endverbatim
1004 
1005 		@returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1006 				 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
1007 
1008 	*/
1009 	int QueryIntText( int* _value ) const;
1010 	/// See QueryIntText()
1011 	int QueryUnsignedText( unsigned* _value ) const;
1012 	/// See QueryIntText()
1013 	int QueryBoolText( bool* _value ) const;
1014 	/// See QueryIntText()
1015 	int QueryDoubleText( double* _value ) const;
1016 	/// See QueryIntText()
1017 	int QueryFloatText( float* _value ) const;
1018 
1019 	// internal:
1020 	enum {
1021 		OPEN,		// <foo>
1022 		CLOSED,		// <foo/>
1023 		CLOSING		// </foo>
1024 	};
ClosingType()1025 	int ClosingType() const { return closingType; }
1026 	char* ParseDeep( char* p, StrPair* endTag );
1027 	virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1028 	virtual bool ShallowEqual( const XMLNode* compare ) const;
1029 
1030 private:
1031 	XMLElement( XMLDocument* doc );
1032 	virtual ~XMLElement();
1033 	XMLElement( const XMLElement& );	// not supported
1034 	void operator=( const XMLElement& );	// not supported
1035 
1036 	XMLAttribute* FindAttribute( const char* name );
1037 	XMLAttribute* FindOrCreateAttribute( const char* name );
1038 	//void LinkAttribute( XMLAttribute* attrib );
1039 	char* ParseAttributes( char* p );
1040 
1041 	int closingType;
1042 	// The attribute list is ordered; there is no 'lastAttribute'
1043 	// because the list needs to be scanned for dupes before adding
1044 	// a new attribute.
1045 	XMLAttribute* rootAttribute;
1046 };
1047 
1048 
1049 enum Whitespace {
1050 	PRESERVE_WHITESPACE,
1051 	COLLAPSE_WHITESPACE
1052 };
1053 
1054 
1055 /** A Document binds together all the functionality.
1056 	It can be saved, loaded, and printed to the screen.
1057 	All Nodes are connected and allocated to a Document.
1058 	If the Document is deleted, all its Nodes are also deleted.
1059 */
1060 class XMLDocument : public XMLNode
1061 {
1062 	friend class XMLElement;
1063 public:
1064 	/// constructor
1065 	XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1066 	~XMLDocument();
1067 
ToDocument()1068 	virtual XMLDocument* ToDocument()				{ return this; }
ToDocument()1069 	virtual const XMLDocument* ToDocument() const	{ return this; }
1070 
1071 	/**
1072 		Parse an XML file from a character string.
1073 		Returns XML_NO_ERROR (0) on success, or
1074 		an errorID.
1075 
1076 		You may optionally pass in the 'nBytes', which is
1077 		the number of bytes which will be parsed. If not
1078 		specified, TinyXML will assume 'xml' points to a
1079 		null terminated string.
1080 	*/
1081 	int Parse( const char* xml, size_t nBytes=(size_t)(-1) );
1082 
1083 	/**
1084 		Load an XML file from disk.
1085 		Returns XML_NO_ERROR (0) on success, or
1086 		an errorID.
1087 	*/
1088 	int LoadFile( const char* filename );
1089 
1090 	/**
1091 		Load an XML file from disk. You are responsible
1092 		for providing and closing the FILE*.
1093 
1094 		Returns XML_NO_ERROR (0) on success, or
1095 		an errorID.
1096 	*/
1097 	int LoadFile( FILE* );
1098 
1099 	/**
1100 		Save the XML file to disk.
1101 		Returns XML_NO_ERROR (0) on success, or
1102 		an errorID.
1103 	*/
1104 	int SaveFile( const char* filename, bool compact = false );
1105 
1106 	/**
1107 		Save the XML file to disk. You are responsible
1108 		for providing and closing the FILE*.
1109 
1110 		Returns XML_NO_ERROR (0) on success, or
1111 		an errorID.
1112 	*/
1113 	int SaveFile( FILE* fp, bool compact = false );
1114 
ProcessEntities()1115 	bool ProcessEntities() const		{ return processEntities; }
WhitespaceMode()1116 	Whitespace WhitespaceMode() const	{ return whitespace; }
1117 
1118 	/**
1119 		Returns true if this document has a leading Byte Order Mark of UTF8.
1120 	*/
HasBOM()1121 	bool HasBOM() const { return writeBOM; }
1122 	/** Sets whether to write the BOM when writing the file.
1123 	*/
SetBOM(bool useBOM)1124 	void SetBOM( bool useBOM ) { writeBOM = useBOM; }
1125 
1126 	/** Return the root element of DOM. Equivalent to FirstChildElement().
1127 	    To get the first node, use FirstChild().
1128 	*/
RootElement()1129 	XMLElement* RootElement()				{ return FirstChildElement(); }
RootElement()1130 	const XMLElement* RootElement() const	{ return FirstChildElement(); }
1131 
1132 	/** Print the Document. If the Printer is not provided, it will
1133 	    print to stdout. If you provide Printer, this can print to a file:
1134 		@verbatim
1135 		XMLPrinter printer( fp );
1136 		doc.Print( &printer );
1137 		@endverbatim
1138 
1139 		Or you can use a printer to print to memory:
1140 		@verbatim
1141 		XMLPrinter printer;
1142 		doc->Print( &printer );
1143 		// printer.CStr() has a const char* to the XML
1144 		@endverbatim
1145 	*/
1146 	void Print( XMLPrinter* streamer=0 );
1147 	virtual bool Accept( XMLVisitor* visitor ) const;
1148 
1149 	/**
1150 		Create a new Element associated with
1151 		this Document. The memory for the Element
1152 		is managed by the Document.
1153 	*/
1154 	XMLElement* NewElement( const char* name );
1155 	/**
1156 		Create a new Comment associated with
1157 		this Document. The memory for the Comment
1158 		is managed by the Document.
1159 	*/
1160 	XMLComment* NewComment( const char* comment );
1161 	/**
1162 		Create a new Text associated with
1163 		this Document. The memory for the Text
1164 		is managed by the Document.
1165 	*/
1166 	XMLText* NewText( const char* text );
1167 	/**
1168 		Create a new Declaration associated with
1169 		this Document. The memory for the object
1170 		is managed by the Document.
1171 
1172 		If the 'text' param is null, the standard
1173 		declaration is used.:
1174 		@verbatim
1175 			<?xml version="1.0" encoding="UTF-8"?>
1176 		@endverbatim
1177 	*/
1178 	XMLDeclaration* NewDeclaration( const char* text=0 );
1179 	/**
1180 		Create a new Unknown associated with
1181 		this Document. The memory for the object
1182 		is managed by the Document.
1183 	*/
1184 	XMLUnknown* NewUnknown( const char* text );
1185 
1186 	/**
1187 		Delete a node associated with this document.
1188 		It will be unlinked from the DOM.
1189 	*/
DeleteNode(XMLNode * node)1190 	void DeleteNode( XMLNode* node )	{ node->parent->DeleteChild( node ); }
1191 
1192 	void SetError( int error, const char* str1, const char* str2 );
1193 
1194 	/// Return true if there was an error parsing the document.
Error()1195 	bool Error() const { return errorID != XML_NO_ERROR; }
1196 	/// Return the errorID.
ErrorID()1197 	int  ErrorID() const { return errorID; }
1198 	/// Return a possibly helpful diagnostic location or string.
GetErrorStr1()1199 	const char* GetErrorStr1() const { return errorStr1; }
1200 	/// Return a possibly helpful secondary diagnostic location or string.
GetErrorStr2()1201 	const char* GetErrorStr2() const { return errorStr2; }
1202 	/// If there is an error, print it to stdout.
1203 	void PrintError() const;
1204 
1205 	// internal
1206 	char* Identify( char* p, XMLNode** node );
1207 
ShallowClone(XMLDocument *)1208 	virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const	{ return 0; }
ShallowEqual(const XMLNode *)1209 	virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const	{ return false; }
1210 
1211 private:
1212 	XMLDocument( const XMLDocument& );	// not supported
1213 	void operator=( const XMLDocument& );	// not supported
1214 	void InitDocument();
1215 
1216 	bool writeBOM;
1217 	bool processEntities;
1218 	int errorID;
1219 	Whitespace whitespace;
1220 	const char* errorStr1;
1221 	const char* errorStr2;
1222 	char* charBuffer;
1223 
1224 	MemPoolT< sizeof(XMLElement) >	elementPool;
1225 	MemPoolT< sizeof(XMLAttribute) > attributePool;
1226 	MemPoolT< sizeof(XMLText) >		textPool;
1227 	MemPoolT< sizeof(XMLComment) >	commentPool;
1228 };
1229 
1230 
1231 /**
1232 	A XMLHandle is a class that wraps a node pointer with null checks; this is
1233 	an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
1234 	DOM structure. It is a separate utility class.
1235 
1236 	Take an example:
1237 	@verbatim
1238 	<Document>
1239 		<Element attributeA = "valueA">
1240 			<Child attributeB = "value1" />
1241 			<Child attributeB = "value2" />
1242 		</Element>
1243 	</Document>
1244 	@endverbatim
1245 
1246 	Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
1247 	easy to write a *lot* of code that looks like:
1248 
1249 	@verbatim
1250 	XMLElement* root = document.FirstChildElement( "Document" );
1251 	if ( root )
1252 	{
1253 		XMLElement* element = root->FirstChildElement( "Element" );
1254 		if ( element )
1255 		{
1256 			XMLElement* child = element->FirstChildElement( "Child" );
1257 			if ( child )
1258 			{
1259 				XMLElement* child2 = child->NextSiblingElement( "Child" );
1260 				if ( child2 )
1261 				{
1262 					// Finally do something useful.
1263 	@endverbatim
1264 
1265 	And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
1266 	of such code. A XMLHandle checks for null pointers so it is perfectly safe
1267 	and correct to use:
1268 
1269 	@verbatim
1270 	XMLHandle docHandle( &document );
1271 	XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
1272 	if ( child2 )
1273 	{
1274 		// do something useful
1275 	@endverbatim
1276 
1277 	Which is MUCH more concise and useful.
1278 
1279 	It is also safe to copy handles - internally they are nothing more than node pointers.
1280 	@verbatim
1281 	XMLHandle handleCopy = handle;
1282 	@endverbatim
1283 
1284 	See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
1285 */
1286 class XMLHandle
1287 {
1288 public:
1289 	/// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
XMLHandle(XMLNode * _node)1290 	XMLHandle( XMLNode* _node )												{ node = _node; }
1291 	/// Create a handle from a node.
XMLHandle(XMLNode & _node)1292 	XMLHandle( XMLNode& _node )												{ node = &_node; }
1293 	/// Copy constructor
XMLHandle(const XMLHandle & ref)1294 	XMLHandle( const XMLHandle& ref )										{ node = ref.node; }
1295 	/// Assignment
1296 	XMLHandle& operator=( const XMLHandle& ref )							{ node = ref.node; return *this; }
1297 
1298 	/// Get the first child of this handle.
FirstChild()1299 	XMLHandle FirstChild() 													{ return XMLHandle( node ? node->FirstChild() : 0 ); }
1300 	/// Get the first child element of this handle.
1301 	XMLHandle FirstChildElement( const char* value=0 )						{ return XMLHandle( node ? node->FirstChildElement( value ) : 0 ); }
1302 	/// Get the last child of this handle.
LastChild()1303 	XMLHandle LastChild()													{ return XMLHandle( node ? node->LastChild() : 0 ); }
1304 	/// Get the last child element of this handle.
1305 	XMLHandle LastChildElement( const char* _value=0 )						{ return XMLHandle( node ? node->LastChildElement( _value ) : 0 ); }
1306 	/// Get the previous sibling of this handle.
PreviousSibling()1307 	XMLHandle PreviousSibling()												{ return XMLHandle( node ? node->PreviousSibling() : 0 ); }
1308 	/// Get the previous sibling element of this handle.
1309 	XMLHandle PreviousSiblingElement( const char* _value=0 )				{ return XMLHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
1310 	/// Get the next sibling of this handle.
NextSibling()1311 	XMLHandle NextSibling()													{ return XMLHandle( node ? node->NextSibling() : 0 ); }
1312 	/// Get the next sibling element of this handle.
1313 	XMLHandle NextSiblingElement( const char* _value=0 )					{ return XMLHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
1314 
1315 	/// Safe cast to XMLNode. This can return null.
ToNode()1316 	XMLNode* ToNode()							{ return node; }
1317 	/// Safe cast to XMLElement. This can return null.
ToElement()1318 	XMLElement* ToElement() 					{ return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
1319 	/// Safe cast to XMLText. This can return null.
ToText()1320 	XMLText* ToText() 							{ return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
1321 	/// Safe cast to XMLUnknown. This can return null.
ToUnknown()1322 	XMLUnknown* ToUnknown() 					{ return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
1323 	/// Safe cast to XMLDeclaration. This can return null.
ToDeclaration()1324 	XMLDeclaration* ToDeclaration() 			{ return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
1325 
1326 private:
1327 	XMLNode* node;
1328 };
1329 
1330 
1331 /**
1332 	A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1333 	same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
1334 */
1335 class XMLConstHandle
1336 {
1337 public:
XMLConstHandle(const XMLNode * _node)1338 	XMLConstHandle( const XMLNode* _node )											{ node = _node; }
XMLConstHandle(const XMLNode & _node)1339 	XMLConstHandle( const XMLNode& _node )											{ node = &_node; }
XMLConstHandle(const XMLConstHandle & ref)1340 	XMLConstHandle( const XMLConstHandle& ref )										{ node = ref.node; }
1341 
1342 	XMLConstHandle& operator=( const XMLConstHandle& ref )							{ node = ref.node; return *this; }
1343 
FirstChild()1344 	const XMLConstHandle FirstChild() const											{ return XMLConstHandle( node ? node->FirstChild() : 0 ); }
1345 	const XMLConstHandle FirstChildElement( const char* value=0 ) const				{ return XMLConstHandle( node ? node->FirstChildElement( value ) : 0 ); }
LastChild()1346 	const XMLConstHandle LastChild()	const										{ return XMLConstHandle( node ? node->LastChild() : 0 ); }
1347 	const XMLConstHandle LastChildElement( const char* _value=0 ) const				{ return XMLConstHandle( node ? node->LastChildElement( _value ) : 0 ); }
PreviousSibling()1348 	const XMLConstHandle PreviousSibling() const									{ return XMLConstHandle( node ? node->PreviousSibling() : 0 ); }
1349 	const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const		{ return XMLConstHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
NextSibling()1350 	const XMLConstHandle NextSibling() const										{ return XMLConstHandle( node ? node->NextSibling() : 0 ); }
1351 	const XMLConstHandle NextSiblingElement( const char* _value=0 ) const			{ return XMLConstHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
1352 
1353 
ToNode()1354 	const XMLNode* ToNode() const				{ return node; }
ToElement()1355 	const XMLElement* ToElement() const			{ return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
ToText()1356 	const XMLText* ToText() const				{ return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
ToUnknown()1357 	const XMLUnknown* ToUnknown() const			{ return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
ToDeclaration()1358 	const XMLDeclaration* ToDeclaration() const	{ return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
1359 
1360 private:
1361 	const XMLNode* node;
1362 };
1363 
1364 
1365 /**
1366 	Printing functionality. The XMLPrinter gives you more
1367 	options than the XMLDocument::Print() method.
1368 
1369 	It can:
1370 	-# Print to memory.
1371 	-# Print to a file you provide.
1372 	-# Print XML without a XMLDocument.
1373 
1374 	Print to Memory
1375 
1376 	@verbatim
1377 	XMLPrinter printer;
1378 	doc->Print( &printer );
1379 	SomeFunction( printer.CStr() );
1380 	@endverbatim
1381 
1382 	Print to a File
1383 
1384 	You provide the file pointer.
1385 	@verbatim
1386 	XMLPrinter printer( fp );
1387 	doc.Print( &printer );
1388 	@endverbatim
1389 
1390 	Print without a XMLDocument
1391 
1392 	When loading, an XML parser is very useful. However, sometimes
1393 	when saving, it just gets in the way. The code is often set up
1394 	for streaming, and constructing the DOM is just overhead.
1395 
1396 	The Printer supports the streaming case. The following code
1397 	prints out a trivially simple XML file without ever creating
1398 	an XML document.
1399 
1400 	@verbatim
1401 	XMLPrinter printer( fp );
1402 	printer.OpenElement( "foo" );
1403 	printer.PushAttribute( "foo", "bar" );
1404 	printer.CloseElement();
1405 	@endverbatim
1406 */
1407 class XMLPrinter : public XMLVisitor
1408 {
1409 public:
1410 	/** Construct the printer. If the FILE* is specified,
1411 		this will print to the FILE. Else it will print
1412 		to memory, and the result is available in CStr().
1413 		If 'compact' is set to true, then output is created
1414 		with only required whitespace and newlines.
1415 	*/
1416 	XMLPrinter( FILE* file=0, bool compact = false );
~XMLPrinter()1417 	~XMLPrinter()	{}
1418 
1419 	/** If streaming, write the BOM and declaration. */
1420 	void PushHeader( bool writeBOM, bool writeDeclaration );
1421 	/** If streaming, start writing an element.
1422 	    The element must be closed with CloseElement()
1423 	*/
1424 	void OpenElement( const char* name );
1425 	/// If streaming, add an attribute to an open element.
1426 	void PushAttribute( const char* name, const char* value );
1427 	void PushAttribute( const char* name, int value );
1428 	void PushAttribute( const char* name, unsigned value );
1429 	void PushAttribute( const char* name, bool value );
1430 	void PushAttribute( const char* name, double value );
1431 	/// If streaming, close the Element.
1432 	void CloseElement();
1433 
1434 	/// Add a text node.
1435 	void PushText( const char* text, bool cdata=false );
1436 	/// Add a text node from an integer.
1437 	void PushText( int value );
1438 	/// Add a text node from an unsigned.
1439 	void PushText( unsigned value );
1440 	/// Add a text node from a bool.
1441 	void PushText( bool value );
1442 	/// Add a text node from a float.
1443 	void PushText( float value );
1444 	/// Add a text node from a double.
1445 	void PushText( double value );
1446 
1447 	/// Add a comment
1448 	void PushComment( const char* comment );
1449 
1450 	void PushDeclaration( const char* value );
1451 	void PushUnknown( const char* value );
1452 
1453 	virtual bool VisitEnter( const XMLDocument& /*doc*/ );
VisitExit(const XMLDocument &)1454 	virtual bool VisitExit( const XMLDocument& /*doc*/ )			{ return true; }
1455 
1456 	virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1457 	virtual bool VisitExit( const XMLElement& element );
1458 
1459 	virtual bool Visit( const XMLText& text );
1460 	virtual bool Visit( const XMLComment& comment );
1461 	virtual bool Visit( const XMLDeclaration& declaration );
1462 	virtual bool Visit( const XMLUnknown& unknown );
1463 
1464 	/**
1465 		If in print to memory mode, return a pointer to
1466 		the XML file in memory.
1467 	*/
CStr()1468 	const char* CStr() const { return buffer.Mem(); }
1469 	/**
1470    		If in print to memory mode, return the size
1471 		of the XML file in memory. (Note the size returned
1472 		includes the terminating null.)
1473   	*/
CStrSize()1474   	int CStrSize() const { return buffer.Size(); }
1475 
1476 private:
1477 	void SealElement();
1478 	void PrintSpace( int depth );
1479 	void PrintString( const char*, bool restrictedEntitySet );	// prints out, after detecting entities.
1480 	void Print( const char* format, ... );
1481 
1482 	bool elementJustOpened;
1483 	bool firstElement;
1484 	FILE* fp;
1485 	int depth;
1486 	int textDepth;
1487 	bool processEntities;
1488 	bool compactMode;
1489 
1490 	enum {
1491 		ENTITY_RANGE = 64,
1492 		BUF_SIZE = 200
1493 	};
1494 	bool entityFlag[ENTITY_RANGE];
1495 	bool restrictedEntityFlag[ENTITY_RANGE];
1496 
1497 	DynArray< const char*, 10 > stack;
1498 	DynArray< char, 20 > buffer;
1499 #ifdef _MSC_VER
1500 	DynArray< char, 20 > accumulator;
1501 #endif
1502 };
1503 
1504 
1505 }	// tinyxml2
1506 
1507 
1508 #endif // TINYXML2_INCLUDED
1509