Coverage Report

Created: 2025-01-24 06:31

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