Coverage Report

Created: 2026-08-14 06:06

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