LCOV - code coverage report
Current view: top level - tarch/tinyxml2 - tinyxml2.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 15 17 88.2 %
Date: 2025-06-25 11:26:37 Functions: 2 2 100.0 %

          Line data    Source code
       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             : #   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             :     StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
     150             :     ~StrPair();
     151             : 
     152             :     void Set( char* start, char* end, int flags ) {
     153             :         TIXMLASSERT( start );
     154             :         TIXMLASSERT( end );
     155             :         Reset();
     156             :         _start  = start;
     157             :         _end    = end;
     158             :         _flags  = flags | NEEDS_FLUSH;
     159             :     }
     160             : 
     161             :     const char* GetStr();
     162             : 
     163             :     bool Empty() const {
     164             :         return _start == _end;
     165             :     }
     166             : 
     167             :     void SetInternedStr( const char* str ) {
     168             :         Reset();
     169             :         _start = const_cast<char*>(str);
     170             :     }
     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             :         _mem( _pool ),
     208             :         _allocated( INITIAL_SIZE ),
     209             :         _size( 0 )
     210             :     {
     211             :     }
     212             : 
     213             :     ~DynArray() {
     214             :         if ( _mem != _pool ) {
     215             :             delete [] _mem;
     216             :         }
     217             :     }
     218             : 
     219             :     void Clear() {
     220             :         _size = 0;
     221             :     }
     222             : 
     223             :     void Push( T t ) {
     224             :         TIXMLASSERT( _size < INT_MAX );
     225             :         EnsureCapacity( _size+1 );
     226             :         _mem[_size] = t;
     227             :         ++_size;
     228             :     }
     229             : 
     230             :     T* PushArr( int count ) {
     231             :         TIXMLASSERT( count >= 0 );
     232             :         TIXMLASSERT( _size <= INT_MAX - count );
     233             :         EnsureCapacity( _size+count );
     234             :         T* ret = &_mem[_size];
     235             :         _size += count;
     236             :         return ret;
     237             :     }
     238             : 
     239             :     T Pop() {
     240             :         TIXMLASSERT( _size > 0 );
     241             :         --_size;
     242             :         return _mem[_size];
     243             :     }
     244             : 
     245             :     void PopArr( int count ) {
     246             :         TIXMLASSERT( _size >= count );
     247             :         _size -= count;
     248             :     }
     249             : 
     250             :     bool Empty() const                                  {
     251             :         return _size == 0;
     252             :     }
     253             : 
     254             :     T& operator[](int i)                            {
     255             :         TIXMLASSERT( i>= 0 && i < _size );
     256             :         return _mem[i];
     257             :     }
     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             :     int Size() const                                    {
     270             :         TIXMLASSERT( _size >= 0 );
     271             :         return _size;
     272             :     }
     273             : 
     274             :     int Capacity() const                                {
     275             :         TIXMLASSERT( _allocated >= INITIAL_SIZE );
     276             :         return _allocated;
     277             :     }
     278             : 
     279             :         void SwapRemove(int i) {
     280             :                 TIXMLASSERT(i >= 0 && i < _size);
     281             :                 TIXMLASSERT(_size > 0);
     282             :                 _mem[i] = _mem[_size - 1];
     283             :                 --_size;
     284             :         }
     285             : 
     286             :     const T* Mem() const                                {
     287             :         TIXMLASSERT( _mem );
     288             :         return _mem;
     289             :     }
     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             :     void EnsureCapacity( int cap ) {
     301             :         TIXMLASSERT( cap > 0 );
     302             :         if ( cap > _allocated ) {
     303             :             TIXMLASSERT( cap <= INT_MAX / 2 );
     304             :             const int newAllocated = cap * 2;
     305             :             T* newMem = new T[static_cast<unsigned int>(newAllocated)];
     306             :             TIXMLASSERT( newAllocated >= _size );
     307             :             memcpy( newMem, _mem, sizeof(T)*static_cast<size_t>(_size) ); // warning: not using constructors, only works for PODs
     308             :             if ( _mem != _pool ) {
     309             :                 delete [] _mem;
     310             :             }
     311             :             _mem = newMem;
     312             :             _allocated = newAllocated;
     313             :         }
     314             :     }
     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             :     MemPool() {}
     331             :     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             :     MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0)  {}
     348             :     ~MemPoolT() {
     349             :         MemPoolT< ITEM_SIZE >::Clear();
     350             :     }
     351             : 
     352             :     void Clear() {
     353             :         // Delete the blocks.
     354             :         while( !_blockPtrs.Empty()) {
     355             :             Block* lastBlock = _blockPtrs.Pop();
     356             :             delete lastBlock;
     357             :         }
     358             :         _root = 0;
     359             :         _currentAllocs = 0;
     360             :         _nAllocs = 0;
     361             :         _maxAllocs = 0;
     362             :         _nUntracked = 0;
     363             :     }
     364             : 
     365             :     virtual int ItemSize() const override{
     366             :         return ITEM_SIZE;
     367             :     }
     368             :     int CurrentAllocs() const           {
     369             :         return _currentAllocs;
     370             :     }
     371             : 
     372             :     virtual void* Alloc() override{
     373             :         if ( !_root ) {
     374             :             // Need a new block.
     375             :             Block* block = new Block;
     376             :             _blockPtrs.Push( block );
     377             : 
     378             :             Item* blockItems = block->items;
     379             :             for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {
     380             :                 blockItems[i].next = &(blockItems[i + 1]);
     381             :             }
     382             :             blockItems[ITEMS_PER_BLOCK - 1].next = 0;
     383             :             _root = blockItems;
     384             :         }
     385             :         Item* const result = _root;
     386             :         TIXMLASSERT( result != 0 );
     387             :         _root = _root->next;
     388             : 
     389             :         ++_currentAllocs;
     390             :         if ( _currentAllocs > _maxAllocs ) {
     391             :             _maxAllocs = _currentAllocs;
     392             :         }
     393             :         ++_nAllocs;
     394             :         ++_nUntracked;
     395             :         return result;
     396             :     }
     397             : 
     398             :     virtual void Free( void* mem ) override {
     399             :         if ( !mem ) {
     400             :             return;
     401             :         }
     402             :         --_currentAllocs;
     403             :         Item* item = static_cast<Item*>( mem );
     404             : #ifdef TINYXML2_DEBUG
     405             :         memset( item, 0xfe, sizeof( *item ) );
     406             : #endif
     407             :         item->next = _root;
     408             :         _root = item;
     409             :     }
     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             :     void SetTracked() override {
     417             :         --_nUntracked;
     418             :     }
     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             :     virtual ~XMLVisitor() {}
     482             : 
     483             :     /// Visit a document.
     484             :     virtual bool VisitEnter( const XMLDocument& /*doc*/ )                   {
     485             :         return true;
     486             :     }
     487             :     /// Visit a document.
     488             :     virtual bool VisitExit( const XMLDocument& /*doc*/ )                    {
     489             :         return true;
     490             :     }
     491             : 
     492             :     /// Visit an element.
     493             :     virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )        {
     494             :         return true;
     495             :     }
     496             :     /// Visit an element.
     497             :     virtual bool VisitExit( const XMLElement& /*element*/ )                 {
     498             :         return true;
     499             :     }
     500             : 
     501             :     /// Visit a declaration.
     502             :     virtual bool Visit( const XMLDeclaration& /*declaration*/ )             {
     503             :         return true;
     504             :     }
     505             :     /// Visit a text node.
     506             :     virtual bool Visit( const XMLText& /*text*/ )                                   {
     507             :         return true;
     508             :     }
     509             :     /// Visit a comment node.
     510             :     virtual bool Visit( const XMLComment& /*comment*/ )                             {
     511             :         return true;
     512             :     }
     513             :     /// Visit an unknown node.
     514             :     virtual bool Visit( const XMLUnknown& /*unknown*/ )                             {
     515             :         return true;
     516             :     }
     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             :     static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr )      {
     552             :         TIXMLASSERT( p );
     553             : 
     554             :         while( IsWhiteSpace(*p) ) {
     555             :             if (curLineNumPtr && *p == '\n') {
     556             :                 ++(*curLineNumPtr);
     557             :             }
     558             :             ++p;
     559             :         }
     560             :         TIXMLASSERT( p );
     561             :         return p;
     562             :     }
     563             :     static char* SkipWhiteSpace( char* const p, int* curLineNumPtr ) {
     564             :         return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p), curLineNumPtr ) );
     565             :     }
     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             :     static bool IsWhiteSpace( char p )                                  {
     570             :         return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
     571             :     }
     572             : 
     573             :     inline static bool IsNameStartChar( unsigned char ch ) {
     574             :         if ( ch >= 128 ) {
     575             :             // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
     576             :             return true;
     577             :         }
     578             :         if ( isalpha( ch ) ) {
     579             :             return true;
     580             :         }
     581             :         return ch == ':' || ch == '_';
     582             :     }
     583             : 
     584             :     inline static bool IsNameChar( unsigned char ch ) {
     585             :         return IsNameStartChar( ch )
     586             :                || isdigit( ch )
     587             :                || ch == '.'
     588             :                || ch == '-';
     589             :     }
     590             : 
     591             :     inline static bool IsPrefixHex( const char* p) {
     592             :         p = SkipWhiteSpace(p, 0);
     593             :         return p && *p == '0' && ( *(p + 1) == 'x' || *(p + 1) == 'X');
     594             :     }
     595             : 
     596             :     inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {
     597             :         if ( p == q ) {
     598             :             return true;
     599             :         }
     600             :         TIXMLASSERT( p );
     601             :         TIXMLASSERT( q );
     602             :         TIXMLASSERT( nChar >= 0 );
     603             :         return strncmp( p, q, static_cast<size_t>(nChar) ) == 0;
     604             :     }
     605             : 
     606             :     inline static bool IsUTF8Continuation( const char p ) {
     607             :         return ( p & 0x80 ) != 0;
     608             :     }
     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             :     const XMLDocument* GetDocument() const      {
     679             :         TIXMLASSERT( _document );
     680             :         return _document;
     681             :     }
     682             :     /// Get the XMLDocument that owns this XMLNode.
     683          20 :     XMLDocument* GetDocument()                          {
     684          20 :         TIXMLASSERT( _document );
     685          20 :         return _document;
     686             :     }
     687             : 
     688             :     /// Safely cast to an Element, or null.
     689             :     virtual XMLElement*         ToElement()             {
     690             :         return 0;
     691             :     }
     692             :     /// Safely cast to Text, or null.
     693             :     virtual XMLText*            ToText()                {
     694             :         return 0;
     695             :     }
     696             :     /// Safely cast to a Comment, or null.
     697             :     virtual XMLComment*         ToComment()             {
     698             :         return 0;
     699             :     }
     700             :     /// Safely cast to a Document, or null.
     701             :     virtual XMLDocument*        ToDocument()    {
     702             :         return 0;
     703             :     }
     704             :     /// Safely cast to a Declaration, or null.
     705             :     virtual XMLDeclaration*     ToDeclaration() {
     706             :         return 0;
     707             :     }
     708             :     /// Safely cast to an Unknown, or null.
     709             :     virtual XMLUnknown*         ToUnknown()             {
     710             :         return 0;
     711             :     }
     712             : 
     713             :     virtual const XMLElement*           ToElement() const               {
     714             :         return 0;
     715             :     }
     716             :     virtual const XMLText*                      ToText() const                  {
     717             :         return 0;
     718             :     }
     719             :     virtual const XMLComment*           ToComment() const               {
     720             :         return 0;
     721             :     }
     722             :     virtual const XMLDocument*          ToDocument() const              {
     723             :         return 0;
     724             :     }
     725             :     virtual const XMLDeclaration*       ToDeclaration() const   {
     726             :         return 0;
     727             :     }
     728             :     virtual const XMLUnknown*           ToUnknown() const               {
     729             :         return 0;
     730             :     }
     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             :     int GetLineNum() const { return _parseLineNum; }
     756             : 
     757             :     /// Get the parent of this node on the DOM.
     758             :     const XMLNode*      Parent() const                  {
     759             :         return _parent;
     760             :     }
     761             : 
     762             :     XMLNode* Parent()                                           {
     763             :         return _parent;
     764             :     }
     765             : 
     766             :     /// Returns true if this node has no children.
     767             :     bool NoChildren() const                                     {
     768             :         return !_firstChild;
     769             :     }
     770             : 
     771             :     /// Get the first child node, or null if none exists.
     772             :     const XMLNode*  FirstChild() const          {
     773             :         return _firstChild;
     774             :     }
     775             : 
     776             :     XMLNode*            FirstChild()                    {
     777             :         return _firstChild;
     778             :     }
     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          68 :     XMLElement* FirstChildElement( const char* name = 0 )       {
     786          68 :         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));
     787             :     }
     788             : 
     789             :     /// Get the last child node, or null if none exists.
     790             :     const XMLNode*      LastChild() const                                               {
     791             :         return _lastChild;
     792             :     }
     793             : 
     794             :     XMLNode*            LastChild()                                                             {
     795             :         return _lastChild;
     796             :     }
     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             :     XMLElement* LastChildElement( const char* name = 0 )        {
     804             :         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );
     805             :     }
     806             : 
     807             :     /// Get the previous (left) sibling node of this node.
     808             :     const XMLNode*      PreviousSibling() const                                 {
     809             :         return _prev;
     810             :     }
     811             : 
     812             :     XMLNode*    PreviousSibling()                                                       {
     813             :         return _prev;
     814             :     }
     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             :     XMLElement* PreviousSiblingElement( const char* name = 0 ) {
     820             :         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );
     821             :     }
     822             : 
     823             :     /// Get the next (right) sibling node of this node.
     824             :     const XMLNode*      NextSibling() const                                             {
     825             :         return _next;
     826             :     }
     827             : 
     828             :     XMLNode*    NextSibling()                                                           {
     829             :         return _next;
     830             :     }
     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          44 :     XMLElement* NextSiblingElement( const char* name = 0 )      {
     836          44 :         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );
     837             :     }
     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             :     XMLNode* LinkEndChild( XMLNode* addThis )   {
     849             :         return InsertEndChild( addThis );
     850             :     }
     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             :         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             :         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             :     virtual XMLText* ToText() override          {
    1001             :         return this;
    1002             :     }
    1003             :     virtual const XMLText* ToText() const override {
    1004             :         return this;
    1005             :     }
    1006             : 
    1007             :     /// Declare whether this should be CDATA or standard text.
    1008             :     void SetCData( bool isCData )                       {
    1009             :         _isCData = isCData;
    1010             :     }
    1011             :     /// Returns true if this is a CDATA text element.
    1012             :     bool CData() const                                          {
    1013             :         return _isCData;
    1014             :     }
    1015             : 
    1016             :     virtual XMLNode* ShallowClone( XMLDocument* document ) const override;
    1017             :     virtual bool ShallowEqual( const XMLNode* compare ) const override;
    1018             : 
    1019             : protected:
    1020             :     explicit XMLText( XMLDocument* doc )        : XMLNode( doc ), _isCData( false )     {}
    1021             :     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             :     virtual XMLComment* ToComment() override            {
    1039             :         return this;
    1040             :     }
    1041             :     virtual const XMLComment* ToComment() const override {
    1042             :         return this;
    1043             :     }
    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             :     virtual XMLDeclaration*     ToDeclaration() override                {
    1078             :         return this;
    1079             :     }
    1080             :     virtual const XMLDeclaration* ToDeclaration() const override {
    1081             :         return this;
    1082             :     }
    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             :     virtual XMLUnknown* ToUnknown() override            {
    1113             :         return this;
    1114             :     }
    1115             :     virtual const XMLUnknown* ToUnknown() const override {
    1116             :         return this;
    1117             :     }
    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             :     int GetLineNum() const { return _parseLineNum; }
    1155             : 
    1156             :     /// The next attribute in the list.
    1157             :     const XMLAttribute* Next() const {
    1158             :         return _next;
    1159             :     }
    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             :         int     IntValue() const {
    1166             :                 int i = 0;
    1167             :                 QueryIntValue(&i);
    1168             :                 return i;
    1169             :         }
    1170             : 
    1171             :         int64_t Int64Value() const {
    1172             :                 int64_t i = 0;
    1173             :                 QueryInt64Value(&i);
    1174             :                 return i;
    1175             :         }
    1176             : 
    1177             :     uint64_t Unsigned64Value() const {
    1178             :         uint64_t i = 0;
    1179             :         QueryUnsigned64Value(&i);
    1180             :         return i;
    1181             :     }
    1182             : 
    1183             :     /// Query as an unsigned integer. See IntValue()
    1184             :     unsigned UnsignedValue() const                      {
    1185             :         unsigned i=0;
    1186             :         QueryUnsignedValue( &i );
    1187             :         return i;
    1188             :     }
    1189             :     /// Query as a boolean. See IntValue()
    1190             :     bool         BoolValue() const                              {
    1191             :         bool b=false;
    1192             :         QueryBoolValue( &b );
    1193             :         return b;
    1194             :     }
    1195             :     /// Query as a double. See IntValue()
    1196             :     double       DoubleValue() const                    {
    1197             :         double d=0;
    1198             :         QueryDoubleValue( &d );
    1199             :         return d;
    1200             :     }
    1201             :     /// Query as a float. See IntValue()
    1202             :     float        FloatValue() const                             {
    1203             :         float f=0;
    1204             :         QueryFloatValue( &f );
    1205             :         return f;
    1206             :     }
    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             :     XMLAttribute() : _name(), _value(),_parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {}
    1247             :     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             :     }
    1275             :     /// Set the name of the element.
    1276             :     void SetName( const char* str, bool staticMem=false )       {
    1277             :         SetValue( str, staticMem );
    1278             :     }
    1279             : 
    1280             :     virtual XMLElement* ToElement() override    {
    1281             :         return this;
    1282             :     }
    1283             :     virtual const XMLElement* ToElement() const override {
    1284             :         return this;
    1285             :     }
    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          56 :     XMLError QueryIntAttribute( const char* name, int* value ) const                            {
    1347          56 :         const XMLAttribute* a = FindAttribute( name );
    1348          56 :         if ( !a ) {
    1349             :             return XML_NO_ATTRIBUTE;
    1350             :         }
    1351          56 :         return a->QueryIntValue( value );
    1352             :     }
    1353             : 
    1354             :         /// See QueryIntAttribute()
    1355             :     XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const      {
    1356             :         const XMLAttribute* a = FindAttribute( name );
    1357             :         if ( !a ) {
    1358             :             return XML_NO_ATTRIBUTE;
    1359             :         }
    1360             :         return a->QueryUnsignedValue( value );
    1361             :     }
    1362             : 
    1363             :         /// See QueryIntAttribute()
    1364             :         XMLError QueryInt64Attribute(const char* name, int64_t* value) const {
    1365             :                 const XMLAttribute* a = FindAttribute(name);
    1366             :                 if (!a) {
    1367             :                         return XML_NO_ATTRIBUTE;
    1368             :                 }
    1369             :                 return a->QueryInt64Value(value);
    1370             :         }
    1371             : 
    1372             :     /// See QueryIntAttribute()
    1373             :     XMLError QueryUnsigned64Attribute(const char* name, uint64_t* value) const {
    1374             :         const XMLAttribute* a = FindAttribute(name);
    1375             :         if(!a) {
    1376             :             return XML_NO_ATTRIBUTE;
    1377             :         }
    1378             :         return a->QueryUnsigned64Value(value);
    1379             :     }
    1380             : 
    1381             :         /// See QueryIntAttribute()
    1382             :     XMLError QueryBoolAttribute( const char* name, bool* value ) const                          {
    1383             :         const XMLAttribute* a = FindAttribute( name );
    1384             :         if ( !a ) {
    1385             :             return XML_NO_ATTRIBUTE;
    1386             :         }
    1387             :         return a->QueryBoolValue( value );
    1388             :     }
    1389             :     /// See QueryIntAttribute()
    1390          36 :     XMLError QueryDoubleAttribute( const char* name, double* value ) const                      {
    1391          36 :         const XMLAttribute* a = FindAttribute( name );
    1392          36 :         if ( !a ) {
    1393             :             return XML_NO_ATTRIBUTE;
    1394             :         }
    1395          36 :         return a->QueryDoubleValue( value );
    1396             :     }
    1397             :     /// See QueryIntAttribute()
    1398             :     XMLError QueryFloatAttribute( const char* name, float* value ) const                        {
    1399             :         const XMLAttribute* a = FindAttribute( name );
    1400             :         if ( !a ) {
    1401             :             return XML_NO_ATTRIBUTE;
    1402             :         }
    1403             :         return a->QueryFloatValue( value );
    1404             :     }
    1405             : 
    1406             :         /// See QueryIntAttribute()
    1407             :         XMLError QueryStringAttribute(const char* name, const char** value) const {
    1408             :                 const XMLAttribute* a = FindAttribute(name);
    1409             :                 if (!a) {
    1410             :                         return XML_NO_ATTRIBUTE;
    1411             :                 }
    1412             :                 *value = a->Value();
    1413             :                 return XML_SUCCESS;
    1414             :         }
    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             :         XMLError QueryAttribute( const char* name, int* value ) const {
    1436             :                 return QueryIntAttribute( name, value );
    1437             :         }
    1438             : 
    1439             :         XMLError QueryAttribute( const char* name, unsigned int* value ) const {
    1440             :                 return QueryUnsignedAttribute( name, value );
    1441             :         }
    1442             : 
    1443             :         XMLError QueryAttribute(const char* name, int64_t* value) const {
    1444             :                 return QueryInt64Attribute(name, value);
    1445             :         }
    1446             : 
    1447             :     XMLError QueryAttribute(const char* name, uint64_t* value) const {
    1448             :         return QueryUnsigned64Attribute(name, value);
    1449             :     }
    1450             : 
    1451             :     XMLError QueryAttribute( const char* name, bool* value ) const {
    1452             :                 return QueryBoolAttribute( name, value );
    1453             :         }
    1454             : 
    1455             :         XMLError QueryAttribute( const char* name, double* value ) const {
    1456             :                 return QueryDoubleAttribute( name, value );
    1457             :         }
    1458             : 
    1459             :         XMLError QueryAttribute( const char* name, float* value ) const {
    1460             :                 return QueryFloatAttribute( name, value );
    1461             :         }
    1462             : 
    1463             :         XMLError QueryAttribute(const char* name, const char** value) const {
    1464             :                 return QueryStringAttribute(name, value);
    1465             :         }
    1466             : 
    1467             :         /// Sets the named attribute to value.
    1468             :     void SetAttribute( const char* name, const char* value )    {
    1469             :         XMLAttribute* a = FindOrCreateAttribute( name );
    1470             :         a->SetAttribute( value );
    1471             :     }
    1472             :     /// Sets the named attribute to value.
    1473             :     void SetAttribute( const char* name, int value )                    {
    1474             :         XMLAttribute* a = FindOrCreateAttribute( name );
    1475             :         a->SetAttribute( value );
    1476             :     }
    1477             :     /// Sets the named attribute to value.
    1478             :     void SetAttribute( const char* name, unsigned value )               {
    1479             :         XMLAttribute* a = FindOrCreateAttribute( name );
    1480             :         a->SetAttribute( value );
    1481             :     }
    1482             : 
    1483             :         /// Sets the named attribute to value.
    1484             :         void SetAttribute(const char* name, int64_t value) {
    1485             :                 XMLAttribute* a = FindOrCreateAttribute(name);
    1486             :                 a->SetAttribute(value);
    1487             :         }
    1488             : 
    1489             :     /// Sets the named attribute to value.
    1490             :     void SetAttribute(const char* name, uint64_t value) {
    1491             :         XMLAttribute* a = FindOrCreateAttribute(name);
    1492             :         a->SetAttribute(value);
    1493             :     }
    1494             : 
    1495             :     /// Sets the named attribute to value.
    1496             :     void SetAttribute( const char* name, bool value )                   {
    1497             :         XMLAttribute* a = FindOrCreateAttribute( name );
    1498             :         a->SetAttribute( value );
    1499             :     }
    1500             :     /// Sets the named attribute to value.
    1501             :     void SetAttribute( const char* name, double value )         {
    1502             :         XMLAttribute* a = FindOrCreateAttribute( name );
    1503             :         a->SetAttribute( value );
    1504             :     }
    1505             :     /// Sets the named attribute to value.
    1506             :     void SetAttribute( const char* name, float value )          {
    1507             :         XMLAttribute* a = FindOrCreateAttribute( name );
    1508             :         a->SetAttribute( value );
    1509             :     }
    1510             : 
    1511             :     /**
    1512             :         Delete an attribute.
    1513             :     */
    1514             :     void DeleteAttribute( const char* name );
    1515             : 
    1516             :     /// Return the first attribute in the list.
    1517             :     const XMLAttribute* FirstAttribute() const {
    1518             :         return _rootAttribute;
    1519             :     }
    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             :     ElementClosingType ClosingType() const {
    1680             :         return _closingType;
    1681             :     }
    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             :     virtual XMLDocument* ToDocument() override          {
    1736             :         TIXMLASSERT( this == _document );
    1737             :         return this;
    1738             :     }
    1739             :     virtual const XMLDocument* ToDocument() const override {
    1740             :         TIXMLASSERT( this == _document );
    1741             :         return this;
    1742             :     }
    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             :     bool ProcessEntities() const                {
    1793             :         return _processEntities;
    1794             :     }
    1795             :     Whitespace WhitespaceMode() const   {
    1796             :         return _whitespaceMode;
    1797             :     }
    1798             : 
    1799             :     /**
    1800             :         Returns true if this document has a leading Byte Order Mark of UTF8.
    1801             :     */
    1802             :     bool HasBOM() const {
    1803             :         return _writeBOM;
    1804             :     }
    1805             :     /** Sets whether to write the BOM when writing the file.
    1806             :     */
    1807             :     void SetBOM( bool useBOM ) {
    1808             :         _writeBOM = useBOM;
    1809             :     }
    1810             : 
    1811             :     /** Return the root element of DOM. Equivalent to FirstChildElement().
    1812             :         To get the first node, use FirstChild().
    1813             :     */
    1814             :     XMLElement* RootElement()                           {
    1815             :         return FirstChildElement();
    1816             :     }
    1817             :     const XMLElement* RootElement() const       {
    1818             :         return FirstChildElement();
    1819             :     }
    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             :     bool Error() const {
    1886             :         return _errorID != XML_SUCCESS;
    1887             :     }
    1888             :     /// Return the errorID.
    1889             :     XMLError  ErrorID() const {
    1890             :         return _errorID;
    1891             :     }
    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             :     {
    1906             :         return _errorLineNum;
    1907             :     }
    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             :     virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const override{
    1928             :         return 0;
    1929             :     }
    1930             :     virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const override{
    1931             :         return false;
    1932             :     }
    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             :                 explicit DepthTracker(XMLDocument * document) {
    1972             :                         this->_document = document;
    1973             :                         document->PushDepth();
    1974             :                 }
    1975             :                 ~DepthTracker() {
    1976             :                         _document->PopDepth();
    1977             :                 }
    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             : {
    1991             :     TIXMLASSERT( sizeof( NodeType ) == PoolElementSize );
    1992             :     TIXMLASSERT( sizeof( NodeType ) == pool.ItemSize() );
    1993             :     NodeType* returnNode = new (pool.Alloc()) NodeType( this );
    1994             :     TIXMLASSERT( returnNode );
    1995             :     returnNode->_memPool = &pool;
    1996             : 
    1997             :         _unlinked.Push(returnNode);
    1998             :     return returnNode;
    1999             : }
    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             :     explicit XMLHandle( XMLNode* node ) : _node( node ) {
    2061             :     }
    2062             :     /// Create a handle from a node.
    2063             :     explicit XMLHandle( XMLNode& node ) : _node( &node ) {
    2064             :     }
    2065             :     /// Copy constructor
    2066             :     XMLHandle( const XMLHandle& ref ) : _node( ref._node ) {
    2067             :     }
    2068             :     /// Assignment
    2069             :     XMLHandle& operator=( const XMLHandle& ref )                                                        {
    2070             :         _node = ref._node;
    2071             :         return *this;
    2072             :     }
    2073             : 
    2074             :     /// Get the first child of this handle.
    2075             :     XMLHandle FirstChild()                                                                                                      {
    2076             :         return XMLHandle( _node ? _node->FirstChild() : 0 );
    2077             :     }
    2078             :     /// Get the first child element of this handle.
    2079             :     XMLHandle FirstChildElement( const char* name = 0 )                                         {
    2080             :         return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
    2081             :     }
    2082             :     /// Get the last child of this handle.
    2083             :     XMLHandle LastChild()                                                                                                       {
    2084             :         return XMLHandle( _node ? _node->LastChild() : 0 );
    2085             :     }
    2086             :     /// Get the last child element of this handle.
    2087             :     XMLHandle LastChildElement( const char* name = 0 )                                          {
    2088             :         return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
    2089             :     }
    2090             :     /// Get the previous sibling of this handle.
    2091             :     XMLHandle PreviousSibling()                                                                                         {
    2092             :         return XMLHandle( _node ? _node->PreviousSibling() : 0 );
    2093             :     }
    2094             :     /// Get the previous sibling element of this handle.
    2095             :     XMLHandle PreviousSiblingElement( const char* name = 0 )                            {
    2096             :         return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
    2097             :     }
    2098             :     /// Get the next sibling of this handle.
    2099             :     XMLHandle NextSibling()                                                                                                     {
    2100             :         return XMLHandle( _node ? _node->NextSibling() : 0 );
    2101             :     }
    2102             :     /// Get the next sibling element of this handle.
    2103             :     XMLHandle NextSiblingElement( const char* name = 0 )                                        {
    2104             :         return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
    2105             :     }
    2106             : 
    2107             :     /// Safe cast to XMLNode. This can return null.
    2108             :     XMLNode* ToNode()                                                   {
    2109             :         return _node;
    2110             :     }
    2111             :     /// Safe cast to XMLElement. This can return null.
    2112             :     XMLElement* ToElement()                                     {
    2113             :         return ( _node ? _node->ToElement() : 0 );
    2114             :     }
    2115             :     /// Safe cast to XMLText. This can return null.
    2116             :     XMLText* ToText()                                                   {
    2117             :         return ( _node ? _node->ToText() : 0 );
    2118             :     }
    2119             :     /// Safe cast to XMLUnknown. This can return null.
    2120             :     XMLUnknown* ToUnknown()                                     {
    2121             :         return ( _node ? _node->ToUnknown() : 0 );
    2122             :     }
    2123             :     /// Safe cast to XMLDeclaration. This can return null.
    2124             :     XMLDeclaration* ToDeclaration()                     {
    2125             :         return ( _node ? _node->ToDeclaration() : 0 );
    2126             :     }
    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             :     explicit XMLConstHandle( const XMLNode* node ) : _node( node ) {
    2141             :     }
    2142             :     explicit XMLConstHandle( const XMLNode& node ) : _node( &node ) {
    2143             :     }
    2144             :     XMLConstHandle( const XMLConstHandle& ref ) : _node( ref._node ) {
    2145             :     }
    2146             : 
    2147             :     XMLConstHandle& operator=( const XMLConstHandle& ref )                                                      {
    2148             :         _node = ref._node;
    2149             :         return *this;
    2150             :     }
    2151             : 
    2152             :     const XMLConstHandle FirstChild() const                                                                                     {
    2153             :         return XMLConstHandle( _node ? _node->FirstChild() : 0 );
    2154             :     }
    2155             :     const XMLConstHandle FirstChildElement( const char* name = 0 ) const                                {
    2156             :         return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
    2157             :     }
    2158             :     const XMLConstHandle LastChild()    const                                                                           {
    2159             :         return XMLConstHandle( _node ? _node->LastChild() : 0 );
    2160             :     }
    2161             :     const XMLConstHandle LastChildElement( const char* name = 0 ) const                         {
    2162             :         return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
    2163             :     }
    2164             :     const XMLConstHandle PreviousSibling() const                                                                        {
    2165             :         return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
    2166             :     }
    2167             :     const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const           {
    2168             :         return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
    2169             :     }
    2170             :     const XMLConstHandle NextSibling() const                                                                            {
    2171             :         return XMLConstHandle( _node ? _node->NextSibling() : 0 );
    2172             :     }
    2173             :     const XMLConstHandle NextSiblingElement( const char* name = 0 ) const                       {
    2174             :         return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
    2175             :     }
    2176             : 
    2177             : 
    2178             :     const XMLNode* ToNode() const                               {
    2179             :         return _node;
    2180             :     }
    2181             :     const XMLElement* ToElement() const                 {
    2182             :         return ( _node ? _node->ToElement() : 0 );
    2183             :     }
    2184             :     const XMLText* ToText() const                               {
    2185             :         return ( _node ? _node->ToText() : 0 );
    2186             :     }
    2187             :     const XMLUnknown* ToUnknown() const                 {
    2188             :         return ( _node ? _node->ToUnknown() : 0 );
    2189             :     }
    2190             :     const XMLDeclaration* ToDeclaration() const {
    2191             :         return ( _node ? _node->ToDeclaration() : 0 );
    2192             :     }
    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             :     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             :     virtual bool VisitExit( const XMLDocument& /*doc*/ ) override   {
    2295             :         return true;
    2296             :     }
    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             :     const char* CStr() const {
    2311             :         return _buffer.Mem();
    2312             :     }
    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             :     int CStrSize() const {
    2319             :         return _buffer.Size();
    2320             :     }
    2321             :     /**
    2322             :         If in print to memory mode, reset the buffer to the
    2323             :         beginning.
    2324             :     */
    2325             :     void ClearBuffer( bool resetToFirstElement = true ) {
    2326             :         _buffer.Clear();
    2327             :         _buffer.Push(0);
    2328             :                 _firstElement = resetToFirstElement;
    2329             :     }
    2330             : 
    2331             : protected:
    2332             :         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             :     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

Generated by: LCOV version 1.14