Coverage Report

Created: 2025-03-23 06:20

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