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