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