Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:18:25

0001 /*

0002 Original code by Lee Thomason (www.grinninglizard.com)

0003 

0004 This software is provided 'as-is', without any express or implied

0005 warranty. In no event will the authors be held liable for any

0006 damages arising from the use of this software.

0007 

0008 Permission is granted to anyone to use this software for any

0009 purpose, including commercial applications, and to alter it and

0010 redistribute it freely, subject to the following restrictions:

0011 

0012 1. The origin of this software must not be misrepresented; you must

0013 not claim that you wrote the original software. If you use this

0014 software in a product, an acknowledgment in the product documentation

0015 would be appreciated but is not required.

0016 

0017 2. Altered source versions must be plainly marked as such, and

0018 must not be misrepresented as being the original software.

0019 

0020 3. This notice may not be removed or altered from any source

0021 distribution.

0022 */
0023 
0024 #ifndef TINYXML2_INCLUDED
0025 #define TINYXML2_INCLUDED
0026 
0027 #if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)
0028 #   include <ctype.h>
0029 #   include <limits.h>
0030 #   include <stdio.h>
0031 #   include <stdlib.h>
0032 #   include <string.h>
0033 #   if defined(__PS3__)
0034 #       include <stddef.h>
0035 #   endif
0036 #else
0037 #   include <cctype>
0038 #   include <climits>
0039 #   include <cstdio>
0040 #   include <cstdlib>
0041 #   include <cstring>
0042 #endif
0043 #include <stdint.h>
0044 
0045 /*

0046    TODO: intern strings instead of allocation.

0047 */
0048 /*

0049     gcc:

0050         g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe

0051 

0052     Formatting, Artistic Style:

0053         AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h

0054 */
0055 
0056 #if defined( _DEBUG ) || defined (__DEBUG__)
0057 #   ifndef TINYXML2_DEBUG
0058 #       define TINYXML2_DEBUG
0059 #   endif
0060 #endif
0061 
0062 #ifdef _MSC_VER
0063 #   pragma warning(push)
0064 #   pragma warning(disable: 4251)
0065 #endif
0066 
0067 #ifdef _WIN32
0068 #   ifdef TINYXML2_EXPORT
0069 #       define TINYXML2_LIB __declspec(dllexport)
0070 #   elif defined(TINYXML2_IMPORT)
0071 #       define TINYXML2_LIB __declspec(dllimport)
0072 #   else
0073 #       define TINYXML2_LIB
0074 #   endif
0075 #elif __GNUC__ >= 4
0076 #   define TINYXML2_LIB __attribute__((visibility("default")))
0077 #else
0078 #   define TINYXML2_LIB
0079 #endif
0080 
0081 
0082 #if !defined(TIXMLASSERT)
0083 #if defined(TINYXML2_DEBUG)
0084 #   if defined(_MSC_VER)
0085 #       // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like

0086 #       define TIXMLASSERT( x )           do { if ( !((void)0,(x))) { __debugbreak(); } } while(false)
0087 #   elif defined (ANDROID_NDK)
0088 #       include <android/log.h>
0089 #       define TIXMLASSERT( x )           do { if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } } while(false)
0090 #   else
0091 #       include <assert.h>
0092 #       define TIXMLASSERT                assert
0093 #   endif
0094 #else
0095 #   define TIXMLASSERT( x )               do {} while(false)
0096 #endif
0097 #endif
0098 
0099 /* Versioning, past 1.0.14:

0100     http://semver.org/

0101 */
0102 static const int TIXML2_MAJOR_VERSION = 9;
0103 static const int TIXML2_MINOR_VERSION = 0;
0104 static const int TIXML2_PATCH_VERSION = 0;
0105 
0106 #define TINYXML2_MAJOR_VERSION 9
0107 #define TINYXML2_MINOR_VERSION 0
0108 #define TINYXML2_PATCH_VERSION 0
0109 
0110 // A fixed element depth limit is problematic. There needs to be a

0111 // limit to avoid a stack overflow. However, that limit varies per

0112 // system, and the capacity of the stack. On the other hand, it's a trivial

0113 // attack that can result from ill, malicious, or even correctly formed XML,

0114 // so there needs to be a limit in place.

0115 static const int TINYXML2_MAX_ELEMENT_DEPTH = 500;
0116 
0117 namespace tinyxml2
0118 {
0119 class XMLDocument;
0120 class XMLElement;
0121 class XMLAttribute;
0122 class XMLComment;
0123 class XMLText;
0124 class XMLDeclaration;
0125 class XMLUnknown;
0126 class XMLPrinter;
0127 
0128 /*

0129     A class that wraps strings. Normally stores the start and end

0130     pointers into the XML file itself, and will apply normalization

0131     and entity translation if actually read. Can also store (and memory

0132     manage) a traditional char[]

0133 

0134     Isn't clear why TINYXML2_LIB is needed; but seems to fix #719

0135 */
0136 class TINYXML2_LIB StrPair
0137 {
0138 public:
0139     enum Mode {
0140         NEEDS_ENTITY_PROCESSING         = 0x01,
0141         NEEDS_NEWLINE_NORMALIZATION     = 0x02,
0142         NEEDS_WHITESPACE_COLLAPSING     = 0x04,
0143 
0144         TEXT_ELEMENT                    = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
0145         TEXT_ELEMENT_LEAVE_ENTITIES     = NEEDS_NEWLINE_NORMALIZATION,
0146         ATTRIBUTE_NAME                  = 0,
0147         ATTRIBUTE_VALUE                 = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
0148         ATTRIBUTE_VALUE_LEAVE_ENTITIES  = NEEDS_NEWLINE_NORMALIZATION,
0149         COMMENT                         = NEEDS_NEWLINE_NORMALIZATION
0150     };
0151 
0152     StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
0153     ~StrPair();
0154 
0155     void Set( char* start, char* end, int flags ) {
0156         TIXMLASSERT( start );
0157         TIXMLASSERT( end );
0158         Reset();
0159         _start  = start;
0160         _end    = end;
0161         _flags  = flags | NEEDS_FLUSH;
0162     }
0163 
0164     const char* GetStr();
0165 
0166     bool Empty() const {
0167         return _start == _end;
0168     }
0169 
0170     void SetInternedStr( const char* str ) {
0171         Reset();
0172         _start = const_cast<char*>(str);
0173     }
0174 
0175     void SetStr( const char* str, int flags=0 );
0176 
0177     char* ParseText( char* in, const char* endTag, int strFlags, int* curLineNumPtr );
0178     char* ParseName( char* in );
0179 
0180     void TransferTo( StrPair* other );
0181     void Reset();
0182 
0183 private:
0184     void CollapseWhitespace();
0185 
0186     enum {
0187         NEEDS_FLUSH = 0x100,
0188         NEEDS_DELETE = 0x200
0189     };
0190 
0191     int     _flags;
0192     char*   _start;
0193     char*   _end;
0194 
0195     StrPair( const StrPair& other );    // not supported

0196     void operator=( const StrPair& other ); // not supported, use TransferTo()

0197 };
0198 
0199 
0200 /*

0201     A dynamic array of Plain Old Data. Doesn't support constructors, etc.

0202     Has a small initial memory pool, so that low or no usage will not

0203     cause a call to new/delete

0204 */
0205 template <class T, int INITIAL_SIZE>
0206 class DynArray
0207 {
0208 public:
0209     DynArray() :
0210         _mem( _pool ),
0211         _allocated( INITIAL_SIZE ),
0212         _size( 0 )
0213     {
0214     }
0215 
0216     ~DynArray() {
0217         if ( _mem != _pool ) {
0218             delete [] _mem;
0219         }
0220     }
0221 
0222     void Clear() {
0223         _size = 0;
0224     }
0225 
0226     void Push( T t ) {
0227         TIXMLASSERT( _size < INT_MAX );
0228         EnsureCapacity( _size+1 );
0229         _mem[_size] = t;
0230         ++_size;
0231     }
0232 
0233     T* PushArr( int count ) {
0234         TIXMLASSERT( count >= 0 );
0235         TIXMLASSERT( _size <= INT_MAX - count );
0236         EnsureCapacity( _size+count );
0237         T* ret = &_mem[_size];
0238         _size += count;
0239         return ret;
0240     }
0241 
0242     T Pop() {
0243         TIXMLASSERT( _size > 0 );
0244         --_size;
0245         return _mem[_size];
0246     }
0247 
0248     void PopArr( int count ) {
0249         TIXMLASSERT( _size >= count );
0250         _size -= count;
0251     }
0252 
0253     bool Empty() const                  {
0254         return _size == 0;
0255     }
0256 
0257     T& operator[](int i)                {
0258         TIXMLASSERT( i>= 0 && i < _size );
0259         return _mem[i];
0260     }
0261 
0262     const T& operator[](int i) const    {
0263         TIXMLASSERT( i>= 0 && i < _size );
0264         return _mem[i];
0265     }
0266 
0267     const T& PeekTop() const            {
0268         TIXMLASSERT( _size > 0 );
0269         return _mem[ _size - 1];
0270     }
0271 
0272     int Size() const                    {
0273         TIXMLASSERT( _size >= 0 );
0274         return _size;
0275     }
0276 
0277     int Capacity() const                {
0278         TIXMLASSERT( _allocated >= INITIAL_SIZE );
0279         return _allocated;
0280     }
0281 
0282     void SwapRemove(int i) {
0283         TIXMLASSERT(i >= 0 && i < _size);
0284         TIXMLASSERT(_size > 0);
0285         _mem[i] = _mem[_size - 1];
0286         --_size;
0287     }
0288 
0289     const T* Mem() const                {
0290         TIXMLASSERT( _mem );
0291         return _mem;
0292     }
0293 
0294     T* Mem() {
0295         TIXMLASSERT( _mem );
0296         return _mem;
0297     }
0298 
0299 private:
0300     DynArray( const DynArray& ); // not supported

0301     void operator=( const DynArray& ); // not supported

0302 
0303     void EnsureCapacity( int cap ) {
0304         TIXMLASSERT( cap > 0 );
0305         if ( cap > _allocated ) {
0306             TIXMLASSERT( cap <= INT_MAX / 2 );
0307             const int newAllocated = cap * 2;
0308             T* newMem = new T[newAllocated];
0309             TIXMLASSERT( newAllocated >= _size );
0310             memcpy( newMem, _mem, sizeof(T)*_size );    // warning: not using constructors, only works for PODs

0311             if ( _mem != _pool ) {
0312                 delete [] _mem;
0313             }
0314             _mem = newMem;
0315             _allocated = newAllocated;
0316         }
0317     }
0318 
0319     T*  _mem;
0320     T   _pool[INITIAL_SIZE];
0321     int _allocated;     // objects allocated

0322     int _size;          // number objects in use

0323 };
0324 
0325 
0326 /*

0327     Parent virtual class of a pool for fast allocation

0328     and deallocation of objects.

0329 */
0330 class MemPool
0331 {
0332 public:
0333     MemPool() {}
0334     virtual ~MemPool() {}
0335 
0336     virtual int ItemSize() const = 0;
0337     virtual void* Alloc() = 0;
0338     virtual void Free( void* ) = 0;
0339     virtual void SetTracked() = 0;
0340 };
0341 
0342 
0343 /*

0344     Template child class to create pools of the correct type.

0345 */
0346 template< int ITEM_SIZE >
0347 class MemPoolT : public MemPool
0348 {
0349 public:
0350     MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0)  {}
0351     ~MemPoolT() {
0352         MemPoolT< ITEM_SIZE >::Clear();
0353     }
0354 
0355     void Clear() {
0356         // Delete the blocks.

0357         while( !_blockPtrs.Empty()) {
0358             Block* lastBlock = _blockPtrs.Pop();
0359             delete lastBlock;
0360         }
0361         _root = 0;
0362         _currentAllocs = 0;
0363         _nAllocs = 0;
0364         _maxAllocs = 0;
0365         _nUntracked = 0;
0366     }
0367 
0368     virtual int ItemSize() const    {
0369         return ITEM_SIZE;
0370     }
0371     int CurrentAllocs() const       {
0372         return _currentAllocs;
0373     }
0374 
0375     virtual void* Alloc() {
0376         if ( !_root ) {
0377             // Need a new block.

0378             Block* block = new Block;
0379             _blockPtrs.Push( block );
0380 
0381             Item* blockItems = block->items;
0382             for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {
0383                 blockItems[i].next = &(blockItems[i + 1]);
0384             }
0385             blockItems[ITEMS_PER_BLOCK - 1].next = 0;
0386             _root = blockItems;
0387         }
0388         Item* const result = _root;
0389         TIXMLASSERT( result != 0 );
0390         _root = _root->next;
0391 
0392         ++_currentAllocs;
0393         if ( _currentAllocs > _maxAllocs ) {
0394             _maxAllocs = _currentAllocs;
0395         }
0396         ++_nAllocs;
0397         ++_nUntracked;
0398         return result;
0399     }
0400 
0401     virtual void Free( void* mem ) {
0402         if ( !mem ) {
0403             return;
0404         }
0405         --_currentAllocs;
0406         Item* item = static_cast<Item*>( mem );
0407 #ifdef TINYXML2_DEBUG
0408         memset( item, 0xfe, sizeof( *item ) );
0409 #endif
0410         item->next = _root;
0411         _root = item;
0412     }
0413     void Trace( const char* name ) {
0414         printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
0415                 name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs,
0416                 ITEM_SIZE, _nAllocs, _blockPtrs.Size() );
0417     }
0418 
0419     void SetTracked() {
0420         --_nUntracked;
0421     }
0422 
0423     int Untracked() const {
0424         return _nUntracked;
0425     }
0426 
0427     // This number is perf sensitive. 4k seems like a good tradeoff on my machine.

0428     // The test file is large, 170k.

0429     // Release:     VS2010 gcc(no opt)

0430     //      1k:     4000

0431     //      2k:     4000

0432     //      4k:     3900    21000

0433     //      16k:    5200

0434     //      32k:    4300

0435     //      64k:    4000    21000

0436     // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK

0437     // in private part if ITEMS_PER_BLOCK is private

0438     enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE };
0439 
0440 private:
0441     MemPoolT( const MemPoolT& ); // not supported

0442     void operator=( const MemPoolT& ); // not supported

0443 
0444     union Item {
0445         Item*   next;
0446         char    itemData[ITEM_SIZE];
0447     };
0448     struct Block {
0449         Item items[ITEMS_PER_BLOCK];
0450     };
0451     DynArray< Block*, 10 > _blockPtrs;
0452     Item* _root;
0453 
0454     int _currentAllocs;
0455     int _nAllocs;
0456     int _maxAllocs;
0457     int _nUntracked;
0458 };
0459 
0460 
0461 
0462 /**

0463     Implements the interface to the "Visitor pattern" (see the Accept() method.)

0464     If you call the Accept() method, it requires being passed a XMLVisitor

0465     class to handle callbacks. For nodes that contain other nodes (Document, Element)

0466     you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs

0467     are simply called with Visit().

0468 

0469     If you return 'true' from a Visit method, recursive parsing will continue. If you return

0470     false, <b>no children of this node or its siblings</b> will be visited.

0471 

0472     All flavors of Visit methods have a default implementation that returns 'true' (continue

0473     visiting). You need to only override methods that are interesting to you.

0474 

0475     Generally Accept() is called on the XMLDocument, although all nodes support visiting.

0476 

0477     You should never change the document from a callback.

0478 

0479     @sa XMLNode::Accept()

0480 */
0481 class TINYXML2_LIB XMLVisitor
0482 {
0483 public:
0484     virtual ~XMLVisitor() {}
0485 
0486     /// Visit a document.

0487     virtual bool VisitEnter( const XMLDocument& /*doc*/ )           {
0488         return true;
0489     }
0490     /// Visit a document.

0491     virtual bool VisitExit( const XMLDocument& /*doc*/ )            {
0492         return true;
0493     }
0494 
0495     /// Visit an element.

0496     virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )    {
0497         return true;
0498     }
0499     /// Visit an element.

0500     virtual bool VisitExit( const XMLElement& /*element*/ )         {
0501         return true;
0502     }
0503 
0504     /// Visit a declaration.

0505     virtual bool Visit( const XMLDeclaration& /*declaration*/ )     {
0506         return true;
0507     }
0508     /// Visit a text node.

0509     virtual bool Visit( const XMLText& /*text*/ )                   {
0510         return true;
0511     }
0512     /// Visit a comment node.

0513     virtual bool Visit( const XMLComment& /*comment*/ )             {
0514         return true;
0515     }
0516     /// Visit an unknown node.

0517     virtual bool Visit( const XMLUnknown& /*unknown*/ )             {
0518         return true;
0519     }
0520 };
0521 
0522 // WARNING: must match XMLDocument::_errorNames[]

0523 enum XMLError {
0524     XML_SUCCESS = 0,
0525     XML_NO_ATTRIBUTE,
0526     XML_WRONG_ATTRIBUTE_TYPE,
0527     XML_ERROR_FILE_NOT_FOUND,
0528     XML_ERROR_FILE_COULD_NOT_BE_OPENED,
0529     XML_ERROR_FILE_READ_ERROR,
0530     XML_ERROR_PARSING_ELEMENT,
0531     XML_ERROR_PARSING_ATTRIBUTE,
0532     XML_ERROR_PARSING_TEXT,
0533     XML_ERROR_PARSING_CDATA,
0534     XML_ERROR_PARSING_COMMENT,
0535     XML_ERROR_PARSING_DECLARATION,
0536     XML_ERROR_PARSING_UNKNOWN,
0537     XML_ERROR_EMPTY_DOCUMENT,
0538     XML_ERROR_MISMATCHED_ELEMENT,
0539     XML_ERROR_PARSING,
0540     XML_CAN_NOT_CONVERT_TEXT,
0541     XML_NO_TEXT_NODE,
0542     XML_ELEMENT_DEPTH_EXCEEDED,
0543 
0544     XML_ERROR_COUNT
0545 };
0546 
0547 
0548 /*

0549     Utility functionality.

0550 */
0551 class TINYXML2_LIB XMLUtil
0552 {
0553 public:
0554     static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr )  {
0555         TIXMLASSERT( p );
0556 
0557         while( IsWhiteSpace(*p) ) {
0558             if (curLineNumPtr && *p == '\n') {
0559                 ++(*curLineNumPtr);
0560             }
0561             ++p;
0562         }
0563         TIXMLASSERT( p );
0564         return p;
0565     }
0566     static char* SkipWhiteSpace( char* const p, int* curLineNumPtr ) {
0567         return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p), curLineNumPtr ) );
0568     }
0569 
0570     // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't

0571     // correct, but simple, and usually works.

0572     static bool IsWhiteSpace( char p )                  {
0573         return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
0574     }
0575 
0576     inline static bool IsNameStartChar( unsigned char ch ) {
0577         if ( ch >= 128 ) {
0578             // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()

0579             return true;
0580         }
0581         if ( isalpha( ch ) ) {
0582             return true;
0583         }
0584         return ch == ':' || ch == '_';
0585     }
0586 
0587     inline static bool IsNameChar( unsigned char ch ) {
0588         return IsNameStartChar( ch )
0589                || isdigit( ch )
0590                || ch == '.'
0591                || ch == '-';
0592     }
0593 
0594     inline static bool IsPrefixHex( const char* p) {
0595         p = SkipWhiteSpace(p, 0);
0596         return p && *p == '0' && ( *(p + 1) == 'x' || *(p + 1) == 'X');
0597     }
0598 
0599     inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {
0600         if ( p == q ) {
0601             return true;
0602         }
0603         TIXMLASSERT( p );
0604         TIXMLASSERT( q );
0605         TIXMLASSERT( nChar >= 0 );
0606         return strncmp( p, q, nChar ) == 0;
0607     }
0608 
0609     inline static bool IsUTF8Continuation( const char p ) {
0610         return ( p & 0x80 ) != 0;
0611     }
0612 
0613     static const char* ReadBOM( const char* p, bool* hasBOM );
0614     // p is the starting location,

0615     // the UTF-8 value of the entity will be placed in value, and length filled in.

0616     static const char* GetCharacterRef( const char* p, char* value, int* length );
0617     static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
0618 
0619     // converts primitive types to strings

0620     static void ToStr( int v, char* buffer, int bufferSize );
0621     static void ToStr( unsigned v, char* buffer, int bufferSize );
0622     static void ToStr( bool v, char* buffer, int bufferSize );
0623     static void ToStr( float v, char* buffer, int bufferSize );
0624     static void ToStr( double v, char* buffer, int bufferSize );
0625     static void ToStr(int64_t v, char* buffer, int bufferSize);
0626     static void ToStr(uint64_t v, char* buffer, int bufferSize);
0627 
0628     // converts strings to primitive types

0629     static bool ToInt( const char* str, int* value );
0630     static bool ToUnsigned( const char* str, unsigned* value );
0631     static bool ToBool( const char* str, bool* value );
0632     static bool ToFloat( const char* str, float* value );
0633     static bool ToDouble( const char* str, double* value );
0634     static bool ToInt64(const char* str, int64_t* value);
0635     static bool ToUnsigned64(const char* str, uint64_t* value);
0636     // Changes what is serialized for a boolean value.

0637     // Default to "true" and "false". Shouldn't be changed

0638     // unless you have a special testing or compatibility need.

0639     // Be careful: static, global, & not thread safe.

0640     // Be sure to set static const memory as parameters.

0641     static void SetBoolSerialization(const char* writeTrue, const char* writeFalse);
0642 
0643 private:
0644     static const char* writeBoolTrue;
0645     static const char* writeBoolFalse;
0646 };
0647 
0648 
0649 /** XMLNode is a base class for every object that is in the

0650     XML Document Object Model (DOM), except XMLAttributes.

0651     Nodes have siblings, a parent, and children which can

0652     be navigated. A node is always in a XMLDocument.

0653     The type of a XMLNode can be queried, and it can

0654     be cast to its more defined type.

0655 

0656     A XMLDocument allocates memory for all its Nodes.

0657     When the XMLDocument gets deleted, all its Nodes

0658     will also be deleted.

0659 

0660     @verbatim

0661     A Document can contain: Element (container or leaf)

0662                             Comment (leaf)

0663                             Unknown (leaf)

0664                             Declaration( leaf )

0665 

0666     An Element can contain: Element (container or leaf)

0667                             Text    (leaf)

0668                             Attributes (not on tree)

0669                             Comment (leaf)

0670                             Unknown (leaf)

0671 

0672     @endverbatim

0673 */
0674 class TINYXML2_LIB XMLNode
0675 {
0676     friend class XMLDocument;
0677     friend class XMLElement;
0678 public:
0679 
0680     /// Get the XMLDocument that owns this XMLNode.

0681     const XMLDocument* GetDocument() const  {
0682         TIXMLASSERT( _document );
0683         return _document;
0684     }
0685     /// Get the XMLDocument that owns this XMLNode.

0686     XMLDocument* GetDocument()              {
0687         TIXMLASSERT( _document );
0688         return _document;
0689     }
0690 
0691     /// Safely cast to an Element, or null.

0692     virtual XMLElement*     ToElement()     {
0693         return 0;
0694     }
0695     /// Safely cast to Text, or null.

0696     virtual XMLText*        ToText()        {
0697         return 0;
0698     }
0699     /// Safely cast to a Comment, or null.

0700     virtual XMLComment*     ToComment()     {
0701         return 0;
0702     }
0703     /// Safely cast to a Document, or null.

0704     virtual XMLDocument*    ToDocument()    {
0705         return 0;
0706     }
0707     /// Safely cast to a Declaration, or null.

0708     virtual XMLDeclaration* ToDeclaration() {
0709         return 0;
0710     }
0711     /// Safely cast to an Unknown, or null.

0712     virtual XMLUnknown*     ToUnknown()     {
0713         return 0;
0714     }
0715 
0716     virtual const XMLElement*       ToElement() const       {
0717         return 0;
0718     }
0719     virtual const XMLText*          ToText() const          {
0720         return 0;
0721     }
0722     virtual const XMLComment*       ToComment() const       {
0723         return 0;
0724     }
0725     virtual const XMLDocument*      ToDocument() const      {
0726         return 0;
0727     }
0728     virtual const XMLDeclaration*   ToDeclaration() const   {
0729         return 0;
0730     }
0731     virtual const XMLUnknown*       ToUnknown() const       {
0732         return 0;
0733     }
0734 
0735     /** The meaning of 'value' changes for the specific type.

0736         @verbatim

0737         Document:   empty (NULL is returned, not an empty string)

0738         Element:    name of the element

0739         Comment:    the comment text

0740         Unknown:    the tag contents

0741         Text:       the text string

0742         @endverbatim

0743     */
0744     const char* Value() const;
0745 
0746     /** Set the Value of an XML node.

0747         @sa Value()

0748     */
0749     void SetValue( const char* val, bool staticMem=false );
0750 
0751     /// Gets the line number the node is in, if the document was parsed from a file.

0752     int GetLineNum() const { return _parseLineNum; }
0753 
0754     /// Get the parent of this node on the DOM.

0755     const XMLNode*  Parent() const          {
0756         return _parent;
0757     }
0758 
0759     XMLNode* Parent()                       {
0760         return _parent;
0761     }
0762 
0763     /// Returns true if this node has no children.

0764     bool NoChildren() const                 {
0765         return !_firstChild;
0766     }
0767 
0768     /// Get the first child node, or null if none exists.

0769     const XMLNode*  FirstChild() const      {
0770         return _firstChild;
0771     }
0772 
0773     XMLNode*        FirstChild()            {
0774         return _firstChild;
0775     }
0776 
0777     /** Get the first child element, or optionally the first child

0778         element with the specified name.

0779     */
0780     const XMLElement* FirstChildElement( const char* name = 0 ) const;
0781 
0782     XMLElement* FirstChildElement( const char* name = 0 )   {
0783         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));
0784     }
0785 
0786     /// Get the last child node, or null if none exists.

0787     const XMLNode*  LastChild() const                       {
0788         return _lastChild;
0789     }
0790 
0791     XMLNode*        LastChild()                             {
0792         return _lastChild;
0793     }
0794 
0795     /** Get the last child element or optionally the last child

0796         element with the specified name.

0797     */
0798     const XMLElement* LastChildElement( const char* name = 0 ) const;
0799 
0800     XMLElement* LastChildElement( const char* name = 0 )    {
0801         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );
0802     }
0803 
0804     /// Get the previous (left) sibling node of this node.

0805     const XMLNode*  PreviousSibling() const                 {
0806         return _prev;
0807     }
0808 
0809     XMLNode*    PreviousSibling()                           {
0810         return _prev;
0811     }
0812 
0813     /// Get the previous (left) sibling element of this node, with an optionally supplied name.

0814     const XMLElement*   PreviousSiblingElement( const char* name = 0 ) const ;
0815 
0816     XMLElement* PreviousSiblingElement( const char* name = 0 ) {
0817         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );
0818     }
0819 
0820     /// Get the next (right) sibling node of this node.

0821     const XMLNode*  NextSibling() const                     {
0822         return _next;
0823     }
0824 
0825     XMLNode*    NextSibling()                               {
0826         return _next;
0827     }
0828 
0829     /// Get the next (right) sibling element of this node, with an optionally supplied name.

0830     const XMLElement*   NextSiblingElement( const char* name = 0 ) const;
0831 
0832     XMLElement* NextSiblingElement( const char* name = 0 )  {
0833         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );
0834     }
0835 
0836     /**

0837         Add a child node as the last (right) child.

0838         If the child node is already part of the document,

0839         it is moved from its old location to the new location.

0840         Returns the addThis argument or 0 if the node does not

0841         belong to the same document.

0842     */
0843     XMLNode* InsertEndChild( XMLNode* addThis );
0844 
0845     XMLNode* LinkEndChild( XMLNode* addThis )   {
0846         return InsertEndChild( addThis );
0847     }
0848     /**

0849         Add a child node as the first (left) child.

0850         If the child node is already part of the document,

0851         it is moved from its old location to the new location.

0852         Returns the addThis argument or 0 if the node does not

0853         belong to the same document.

0854     */
0855     XMLNode* InsertFirstChild( XMLNode* addThis );
0856     /**

0857         Add a node after the specified child node.

0858         If the child node is already part of the document,

0859         it is moved from its old location to the new location.

0860         Returns the addThis argument or 0 if the afterThis node

0861         is not a child of this node, or if the node does not

0862         belong to the same document.

0863     */
0864     XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
0865 
0866     /**

0867         Delete all the children of this node.

0868     */
0869     void DeleteChildren();
0870 
0871     /**

0872         Delete a child of this node.

0873     */
0874     void DeleteChild( XMLNode* node );
0875 
0876     /**

0877         Make a copy of this node, but not its children.

0878         You may pass in a Document pointer that will be

0879         the owner of the new Node. If the 'document' is

0880         null, then the node returned will be allocated

0881         from the current Document. (this->GetDocument())

0882 

0883         Note: if called on a XMLDocument, this will return null.

0884     */
0885     virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
0886 
0887     /**

0888         Make a copy of this node and all its children.

0889 

0890         If the 'target' is null, then the nodes will

0891         be allocated in the current document. If 'target'

0892         is specified, the memory will be allocated is the

0893         specified XMLDocument.

0894 

0895         NOTE: This is probably not the correct tool to

0896         copy a document, since XMLDocuments can have multiple

0897         top level XMLNodes. You probably want to use

0898         XMLDocument::DeepCopy()

0899     */
0900     XMLNode* DeepClone( XMLDocument* target ) const;
0901 
0902     /**

0903         Test if 2 nodes are the same, but don't test children.

0904         The 2 nodes do not need to be in the same Document.

0905 

0906         Note: if called on a XMLDocument, this will return false.

0907     */
0908     virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
0909 
0910     /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the

0911         XML tree will be conditionally visited and the host will be called back

0912         via the XMLVisitor interface.

0913 

0914         This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse

0915         the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this

0916         interface versus any other.)

0917 

0918         The interface has been based on ideas from:

0919 

0920         - http://www.saxproject.org/

0921         - http://c2.com/cgi/wiki?HierarchicalVisitorPattern

0922 

0923         Which are both good references for "visiting".

0924 

0925         An example of using Accept():

0926         @verbatim

0927         XMLPrinter printer;

0928         tinyxmlDoc.Accept( &printer );

0929         const char* xmlcstr = printer.CStr();

0930         @endverbatim

0931     */
0932     virtual bool Accept( XMLVisitor* visitor ) const = 0;
0933 
0934     /**

0935         Set user data into the XMLNode. TinyXML-2 in

0936         no way processes or interprets user data.

0937         It is initially 0.

0938     */
0939     void SetUserData(void* userData)    { _userData = userData; }
0940 
0941     /**

0942         Get user data set into the XMLNode. TinyXML-2 in

0943         no way processes or interprets user data.

0944         It is initially 0.

0945     */
0946     void* GetUserData() const           { return _userData; }
0947 
0948 protected:
0949     explicit XMLNode( XMLDocument* );
0950     virtual ~XMLNode();
0951 
0952     virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);
0953 
0954     XMLDocument*    _document;
0955     XMLNode*        _parent;
0956     mutable StrPair _value;
0957     int             _parseLineNum;
0958 
0959     XMLNode*        _firstChild;
0960     XMLNode*        _lastChild;
0961 
0962     XMLNode*        _prev;
0963     XMLNode*        _next;
0964 
0965     void*           _userData;
0966 
0967 private:
0968     MemPool*        _memPool;
0969     void Unlink( XMLNode* child );
0970     static void DeleteNode( XMLNode* node );
0971     void InsertChildPreamble( XMLNode* insertThis ) const;
0972     const XMLElement* ToElementWithName( const char* name ) const;
0973 
0974     XMLNode( const XMLNode& );  // not supported

0975     XMLNode& operator=( const XMLNode& );   // not supported

0976 };
0977 
0978 
0979 /** XML text.

0980 

0981     Note that a text node can have child element nodes, for example:

0982     @verbatim

0983     <root>This is <b>bold</b></root>

0984     @endverbatim

0985 

0986     A text node can have 2 ways to output the next. "normal" output

0987     and CDATA. It will default to the mode it was parsed from the XML file and

0988     you generally want to leave it alone, but you can change the output mode with

0989     SetCData() and query it with CData().

0990 */
0991 class TINYXML2_LIB XMLText : public XMLNode
0992 {
0993     friend class XMLDocument;
0994 public:
0995     virtual bool Accept( XMLVisitor* visitor ) const;
0996 
0997     virtual XMLText* ToText()           {
0998         return this;
0999     }
1000     virtual const XMLText* ToText() const   {
1001         return this;
1002     }
1003 
1004     /// Declare whether this should be CDATA or standard text.

1005     void SetCData( bool isCData )           {
1006         _isCData = isCData;
1007     }
1008     /// Returns true if this is a CDATA text element.

1009     bool CData() const                      {
1010         return _isCData;
1011     }
1012 
1013     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1014     virtual bool ShallowEqual( const XMLNode* compare ) const;
1015 
1016 protected:
1017     explicit XMLText( XMLDocument* doc )    : XMLNode( doc ), _isCData( false ) {}
1018     virtual ~XMLText()                                              {}
1019 
1020     char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
1021 
1022 private:
1023     bool _isCData;
1024 
1025     XMLText( const XMLText& );  // not supported

1026     XMLText& operator=( const XMLText& );   // not supported

1027 };
1028 
1029 
1030 /** An XML Comment. */
1031 class TINYXML2_LIB XMLComment : public XMLNode
1032 {
1033     friend class XMLDocument;
1034 public:
1035     virtual XMLComment* ToComment()                 {
1036         return this;
1037     }
1038     virtual const XMLComment* ToComment() const     {
1039         return this;
1040     }
1041 
1042     virtual bool Accept( XMLVisitor* visitor ) const;
1043 
1044     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1045     virtual bool ShallowEqual( const XMLNode* compare ) const;
1046 
1047 protected:
1048     explicit XMLComment( XMLDocument* doc );
1049     virtual ~XMLComment();
1050 
1051     char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);
1052 
1053 private:
1054     XMLComment( const XMLComment& );    // not supported

1055     XMLComment& operator=( const XMLComment& ); // not supported

1056 };
1057 
1058 
1059 /** In correct XML the declaration is the first entry in the file.

1060     @verbatim

1061         <?xml version="1.0" standalone="yes"?>

1062     @endverbatim

1063 

1064     TinyXML-2 will happily read or write files without a declaration,

1065     however.

1066 

1067     The text of the declaration isn't interpreted. It is parsed

1068     and written as a string.

1069 */
1070 class TINYXML2_LIB XMLDeclaration : public XMLNode
1071 {
1072     friend class XMLDocument;
1073 public:
1074     virtual XMLDeclaration* ToDeclaration()                 {
1075         return this;
1076     }
1077     virtual const XMLDeclaration* ToDeclaration() const     {
1078         return this;
1079     }
1080 
1081     virtual bool Accept( XMLVisitor* visitor ) const;
1082 
1083     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1084     virtual bool ShallowEqual( const XMLNode* compare ) const;
1085 
1086 protected:
1087     explicit XMLDeclaration( XMLDocument* doc );
1088     virtual ~XMLDeclaration();
1089 
1090     char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
1091 
1092 private:
1093     XMLDeclaration( const XMLDeclaration& );    // not supported

1094     XMLDeclaration& operator=( const XMLDeclaration& ); // not supported

1095 };
1096 
1097 
1098 /** Any tag that TinyXML-2 doesn't recognize is saved as an

1099     unknown. It is a tag of text, but should not be modified.

1100     It will be written back to the XML, unchanged, when the file

1101     is saved.

1102 

1103     DTD tags get thrown into XMLUnknowns.

1104 */
1105 class TINYXML2_LIB XMLUnknown : public XMLNode
1106 {
1107     friend class XMLDocument;
1108 public:
1109     virtual XMLUnknown* ToUnknown()                 {
1110         return this;
1111     }
1112     virtual const XMLUnknown* ToUnknown() const     {
1113         return this;
1114     }
1115 
1116     virtual bool Accept( XMLVisitor* visitor ) const;
1117 
1118     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1119     virtual bool ShallowEqual( const XMLNode* compare ) const;
1120 
1121 protected:
1122     explicit XMLUnknown( XMLDocument* doc );
1123     virtual ~XMLUnknown();
1124 
1125     char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
1126 
1127 private:
1128     XMLUnknown( const XMLUnknown& );    // not supported

1129     XMLUnknown& operator=( const XMLUnknown& ); // not supported

1130 };
1131 
1132 
1133 
1134 /** An attribute is a name-value pair. Elements have an arbitrary

1135     number of attributes, each with a unique name.

1136 

1137     @note The attributes are not XMLNodes. You may only query the

1138     Next() attribute in a list.

1139 */
1140 class TINYXML2_LIB XMLAttribute
1141 {
1142     friend class XMLElement;
1143 public:
1144     /// The name of the attribute.

1145     const char* Name() const;
1146 
1147     /// The value of the attribute.

1148     const char* Value() const;
1149 
1150     /// Gets the line number the attribute is in, if the document was parsed from a file.

1151     int GetLineNum() const { return _parseLineNum; }
1152 
1153     /// The next attribute in the list.

1154     const XMLAttribute* Next() const {
1155         return _next;
1156     }
1157 
1158     /** IntValue interprets the attribute as an integer, and returns the value.

1159         If the value isn't an integer, 0 will be returned. There is no error checking;

1160         use QueryIntValue() if you need error checking.

1161     */
1162     int IntValue() const {
1163         int i = 0;
1164         QueryIntValue(&i);
1165         return i;
1166     }
1167 
1168     int64_t Int64Value() const {
1169         int64_t i = 0;
1170         QueryInt64Value(&i);
1171         return i;
1172     }
1173 
1174     uint64_t Unsigned64Value() const {
1175         uint64_t i = 0;
1176         QueryUnsigned64Value(&i);
1177         return i;
1178     }
1179 
1180     /// Query as an unsigned integer. See IntValue()

1181     unsigned UnsignedValue() const          {
1182         unsigned i=0;
1183         QueryUnsignedValue( &i );
1184         return i;
1185     }
1186     /// Query as a boolean. See IntValue()

1187     bool     BoolValue() const              {
1188         bool b=false;
1189         QueryBoolValue( &b );
1190         return b;
1191     }
1192     /// Query as a double. See IntValue()

1193     double   DoubleValue() const            {
1194         double d=0;
1195         QueryDoubleValue( &d );
1196         return d;
1197     }
1198     /// Query as a float. See IntValue()

1199     float    FloatValue() const             {
1200         float f=0;
1201         QueryFloatValue( &f );
1202         return f;
1203     }
1204 
1205     /** QueryIntValue interprets the attribute as an integer, and returns the value

1206         in the provided parameter. The function will return XML_SUCCESS on success,

1207         and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.

1208     */
1209     XMLError QueryIntValue( int* value ) const;
1210     /// See QueryIntValue

1211     XMLError QueryUnsignedValue( unsigned int* value ) const;
1212     /// See QueryIntValue

1213     XMLError QueryInt64Value(int64_t* value) const;
1214     /// See QueryIntValue

1215     XMLError QueryUnsigned64Value(uint64_t* value) const;
1216     /// See QueryIntValue

1217     XMLError QueryBoolValue( bool* value ) const;
1218     /// See QueryIntValue

1219     XMLError QueryDoubleValue( double* value ) const;
1220     /// See QueryIntValue

1221     XMLError QueryFloatValue( float* value ) const;
1222 
1223     /// Set the attribute to a string value.

1224     void SetAttribute( const char* value );
1225     /// Set the attribute to value.

1226     void SetAttribute( int value );
1227     /// Set the attribute to value.

1228     void SetAttribute( unsigned value );
1229     /// Set the attribute to value.

1230     void SetAttribute(int64_t value);
1231     /// Set the attribute to value.

1232     void SetAttribute(uint64_t value);
1233     /// Set the attribute to value.

1234     void SetAttribute( bool value );
1235     /// Set the attribute to value.

1236     void SetAttribute( double value );
1237     /// Set the attribute to value.

1238     void SetAttribute( float value );
1239 
1240 private:
1241     enum { BUF_SIZE = 200 };
1242 
1243     XMLAttribute() : _name(), _value(),_parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {}
1244     virtual ~XMLAttribute() {}
1245 
1246     XMLAttribute( const XMLAttribute& );    // not supported

1247     void operator=( const XMLAttribute& );  // not supported

1248     void SetName( const char* name );
1249 
1250     char* ParseDeep( char* p, bool processEntities, int* curLineNumPtr );
1251 
1252     mutable StrPair _name;
1253     mutable StrPair _value;
1254     int             _parseLineNum;
1255     XMLAttribute*   _next;
1256     MemPool*        _memPool;
1257 };
1258 
1259 
1260 /** The element is a container class. It has a value, the element name,

1261     and can contain other elements, text, comments, and unknowns.

1262     Elements also contain an arbitrary number of attributes.

1263 */
1264 class TINYXML2_LIB XMLElement : public XMLNode
1265 {
1266     friend class XMLDocument;
1267 public:
1268     /// Get the name of an element (which is the Value() of the node.)

1269     const char* Name() const        {
1270         return Value();
1271     }
1272     /// Set the name of the element.

1273     void SetName( const char* str, bool staticMem=false )   {
1274         SetValue( str, staticMem );
1275     }
1276 
1277     virtual XMLElement* ToElement()             {
1278         return this;
1279     }
1280     virtual const XMLElement* ToElement() const {
1281         return this;
1282     }
1283     virtual bool Accept( XMLVisitor* visitor ) const;
1284 
1285     /** Given an attribute name, Attribute() returns the value

1286         for the attribute of that name, or null if none

1287         exists. For example:

1288 

1289         @verbatim

1290         const char* value = ele->Attribute( "foo" );

1291         @endverbatim

1292 

1293         The 'value' parameter is normally null. However, if specified,

1294         the attribute will only be returned if the 'name' and 'value'

1295         match. This allow you to write code:

1296 

1297         @verbatim

1298         if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();

1299         @endverbatim

1300 

1301         rather than:

1302         @verbatim

1303         if ( ele->Attribute( "foo" ) ) {

1304             if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();

1305         }

1306         @endverbatim

1307     */
1308     const char* Attribute( const char* name, const char* value=0 ) const;
1309 
1310     /** Given an attribute name, IntAttribute() returns the value

1311         of the attribute interpreted as an integer. The default

1312         value will be returned if the attribute isn't present,

1313         or if there is an error. (For a method with error

1314         checking, see QueryIntAttribute()).

1315     */
1316     int IntAttribute(const char* name, int defaultValue = 0) const;
1317     /// See IntAttribute()

1318     unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const;
1319     /// See IntAttribute()

1320     int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const;
1321     /// See IntAttribute()

1322     uint64_t Unsigned64Attribute(const char* name, uint64_t defaultValue = 0) const;
1323     /// See IntAttribute()

1324     bool BoolAttribute(const char* name, bool defaultValue = false) const;
1325     /// See IntAttribute()

1326     double DoubleAttribute(const char* name, double defaultValue = 0) const;
1327     /// See IntAttribute()

1328     float FloatAttribute(const char* name, float defaultValue = 0) const;
1329 
1330     /** Given an attribute name, QueryIntAttribute() returns

1331         XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion

1332         can't be performed, or XML_NO_ATTRIBUTE if the attribute

1333         doesn't exist. If successful, the result of the conversion

1334         will be written to 'value'. If not successful, nothing will

1335         be written to 'value'. This allows you to provide default

1336         value:

1337 

1338         @verbatim

1339         int value = 10;

1340         QueryIntAttribute( "foo", &value );     // if "foo" isn't found, value will still be 10

1341         @endverbatim

1342     */
1343     XMLError QueryIntAttribute( const char* name, int* value ) const                {
1344         const XMLAttribute* a = FindAttribute( name );
1345         if ( !a ) {
1346             return XML_NO_ATTRIBUTE;
1347         }
1348         return a->QueryIntValue( value );
1349     }
1350 
1351     /// See QueryIntAttribute()

1352     XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const  {
1353         const XMLAttribute* a = FindAttribute( name );
1354         if ( !a ) {
1355             return XML_NO_ATTRIBUTE;
1356         }
1357         return a->QueryUnsignedValue( value );
1358     }
1359 
1360     /// See QueryIntAttribute()

1361     XMLError QueryInt64Attribute(const char* name, int64_t* value) const {
1362         const XMLAttribute* a = FindAttribute(name);
1363         if (!a) {
1364             return XML_NO_ATTRIBUTE;
1365         }
1366         return a->QueryInt64Value(value);
1367     }
1368 
1369     /// See QueryIntAttribute()

1370     XMLError QueryUnsigned64Attribute(const char* name, uint64_t* value) const {
1371         const XMLAttribute* a = FindAttribute(name);
1372         if(!a) {
1373             return XML_NO_ATTRIBUTE;
1374         }
1375         return a->QueryUnsigned64Value(value);
1376     }
1377 
1378     /// See QueryIntAttribute()

1379     XMLError QueryBoolAttribute( const char* name, bool* value ) const              {
1380         const XMLAttribute* a = FindAttribute( name );
1381         if ( !a ) {
1382             return XML_NO_ATTRIBUTE;
1383         }
1384         return a->QueryBoolValue( value );
1385     }
1386     /// See QueryIntAttribute()

1387     XMLError QueryDoubleAttribute( const char* name, double* value ) const          {
1388         const XMLAttribute* a = FindAttribute( name );
1389         if ( !a ) {
1390             return XML_NO_ATTRIBUTE;
1391         }
1392         return a->QueryDoubleValue( value );
1393     }
1394     /// See QueryIntAttribute()

1395     XMLError QueryFloatAttribute( const char* name, float* value ) const            {
1396         const XMLAttribute* a = FindAttribute( name );
1397         if ( !a ) {
1398             return XML_NO_ATTRIBUTE;
1399         }
1400         return a->QueryFloatValue( value );
1401     }
1402 
1403     /// See QueryIntAttribute()

1404     XMLError QueryStringAttribute(const char* name, const char** value) const {
1405         const XMLAttribute* a = FindAttribute(name);
1406         if (!a) {
1407             return XML_NO_ATTRIBUTE;
1408         }
1409         *value = a->Value();
1410         return XML_SUCCESS;
1411     }
1412 
1413 
1414 
1415     /** Given an attribute name, QueryAttribute() returns

1416         XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion

1417         can't be performed, or XML_NO_ATTRIBUTE if the attribute

1418         doesn't exist. It is overloaded for the primitive types,

1419         and is a generally more convenient replacement of

1420         QueryIntAttribute() and related functions.

1421 

1422         If successful, the result of the conversion

1423         will be written to 'value'. If not successful, nothing will

1424         be written to 'value'. This allows you to provide default

1425         value:

1426 

1427         @verbatim

1428         int value = 10;

1429         QueryAttribute( "foo", &value );        // if "foo" isn't found, value will still be 10

1430         @endverbatim

1431     */
1432     XMLError QueryAttribute( const char* name, int* value ) const {
1433         return QueryIntAttribute( name, value );
1434     }
1435 
1436     XMLError QueryAttribute( const char* name, unsigned int* value ) const {
1437         return QueryUnsignedAttribute( name, value );
1438     }
1439 
1440     XMLError QueryAttribute(const char* name, int64_t* value) const {
1441         return QueryInt64Attribute(name, value);
1442     }
1443 
1444     XMLError QueryAttribute(const char* name, uint64_t* value) const {
1445         return QueryUnsigned64Attribute(name, value);
1446     }
1447 
1448     XMLError QueryAttribute( const char* name, bool* value ) const {
1449         return QueryBoolAttribute( name, value );
1450     }
1451 
1452     XMLError QueryAttribute( const char* name, double* value ) const {
1453         return QueryDoubleAttribute( name, value );
1454     }
1455 
1456     XMLError QueryAttribute( const char* name, float* value ) const {
1457         return QueryFloatAttribute( name, value );
1458     }
1459 
1460     XMLError QueryAttribute(const char* name, const char** value) const {
1461         return QueryStringAttribute(name, value);
1462     }
1463 
1464     /// Sets the named attribute to value.

1465     void SetAttribute( const char* name, const char* value )    {
1466         XMLAttribute* a = FindOrCreateAttribute( name );
1467         a->SetAttribute( value );
1468     }
1469     /// Sets the named attribute to value.

1470     void SetAttribute( const char* name, int value )            {
1471         XMLAttribute* a = FindOrCreateAttribute( name );
1472         a->SetAttribute( value );
1473     }
1474     /// Sets the named attribute to value.

1475     void SetAttribute( const char* name, unsigned value )       {
1476         XMLAttribute* a = FindOrCreateAttribute( name );
1477         a->SetAttribute( value );
1478     }
1479 
1480     /// Sets the named attribute to value.

1481     void SetAttribute(const char* name, int64_t value) {
1482         XMLAttribute* a = FindOrCreateAttribute(name);
1483         a->SetAttribute(value);
1484     }
1485 
1486     /// Sets the named attribute to value.

1487     void SetAttribute(const char* name, uint64_t value) {
1488         XMLAttribute* a = FindOrCreateAttribute(name);
1489         a->SetAttribute(value);
1490     }
1491 
1492     /// Sets the named attribute to value.

1493     void SetAttribute( const char* name, bool value )           {
1494         XMLAttribute* a = FindOrCreateAttribute( name );
1495         a->SetAttribute( value );
1496     }
1497     /// Sets the named attribute to value.

1498     void SetAttribute( const char* name, double value )     {
1499         XMLAttribute* a = FindOrCreateAttribute( name );
1500         a->SetAttribute( value );
1501     }
1502     /// Sets the named attribute to value.

1503     void SetAttribute( const char* name, float value )      {
1504         XMLAttribute* a = FindOrCreateAttribute( name );
1505         a->SetAttribute( value );
1506     }
1507 
1508     /**

1509         Delete an attribute.

1510     */
1511     void DeleteAttribute( const char* name );
1512 
1513     /// Return the first attribute in the list.

1514     const XMLAttribute* FirstAttribute() const {
1515         return _rootAttribute;
1516     }
1517     /// Query a specific attribute in the list.

1518     const XMLAttribute* FindAttribute( const char* name ) const;
1519 
1520     /** Convenience function for easy access to the text inside an element. Although easy

1521         and concise, GetText() is limited compared to getting the XMLText child

1522         and accessing it directly.

1523 

1524         If the first child of 'this' is a XMLText, the GetText()

1525         returns the character string of the Text node, else null is returned.

1526 

1527         This is a convenient method for getting the text of simple contained text:

1528         @verbatim

1529         <foo>This is text</foo>

1530             const char* str = fooElement->GetText();

1531         @endverbatim

1532 

1533         'str' will be a pointer to "This is text".

1534 

1535         Note that this function can be misleading. If the element foo was created from

1536         this XML:

1537         @verbatim

1538             <foo><b>This is text</b></foo>

1539         @endverbatim

1540 

1541         then the value of str would be null. The first child node isn't a text node, it is

1542         another element. From this XML:

1543         @verbatim

1544             <foo>This is <b>text</b></foo>

1545         @endverbatim

1546         GetText() will return "This is ".

1547     */
1548     const char* GetText() const;
1549 
1550     /** Convenience function for easy access to the text inside an element. Although easy

1551         and concise, SetText() is limited compared to creating an XMLText child

1552         and mutating it directly.

1553 

1554         If the first child of 'this' is a XMLText, SetText() sets its value to

1555         the given string, otherwise it will create a first child that is an XMLText.

1556 

1557         This is a convenient method for setting the text of simple contained text:

1558         @verbatim

1559         <foo>This is text</foo>

1560             fooElement->SetText( "Hullaballoo!" );

1561         <foo>Hullaballoo!</foo>

1562         @endverbatim

1563 

1564         Note that this function can be misleading. If the element foo was created from

1565         this XML:

1566         @verbatim

1567             <foo><b>This is text</b></foo>

1568         @endverbatim

1569 

1570         then it will not change "This is text", but rather prefix it with a text element:

1571         @verbatim

1572             <foo>Hullaballoo!<b>This is text</b></foo>

1573         @endverbatim

1574 

1575         For this XML:

1576         @verbatim

1577             <foo />

1578         @endverbatim

1579         SetText() will generate

1580         @verbatim

1581             <foo>Hullaballoo!</foo>

1582         @endverbatim

1583     */
1584     void SetText( const char* inText );
1585     /// Convenience method for setting text inside an element. See SetText() for important limitations.

1586     void SetText( int value );
1587     /// Convenience method for setting text inside an element. See SetText() for important limitations.

1588     void SetText( unsigned value );
1589     /// Convenience method for setting text inside an element. See SetText() for important limitations.

1590     void SetText(int64_t value);
1591     /// Convenience method for setting text inside an element. See SetText() for important limitations.

1592     void SetText(uint64_t value);
1593     /// Convenience method for setting text inside an element. See SetText() for important limitations.

1594     void SetText( bool value );
1595     /// Convenience method for setting text inside an element. See SetText() for important limitations.

1596     void SetText( double value );
1597     /// Convenience method for setting text inside an element. See SetText() for important limitations.

1598     void SetText( float value );
1599 
1600     /**

1601         Convenience method to query the value of a child text node. This is probably best

1602         shown by example. Given you have a document is this form:

1603         @verbatim

1604             <point>

1605                 <x>1</x>

1606                 <y>1.4</y>

1607             </point>

1608         @endverbatim

1609 

1610         The QueryIntText() and similar functions provide a safe and easier way to get to the

1611         "value" of x and y.

1612 

1613         @verbatim

1614             int x = 0;

1615             float y = 0;    // types of x and y are contrived for example

1616             const XMLElement* xElement = pointElement->FirstChildElement( "x" );

1617             const XMLElement* yElement = pointElement->FirstChildElement( "y" );

1618             xElement->QueryIntText( &x );

1619             yElement->QueryFloatText( &y );

1620         @endverbatim

1621 

1622         @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted

1623                  to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.

1624 

1625     */
1626     XMLError QueryIntText( int* ival ) const;
1627     /// See QueryIntText()

1628     XMLError QueryUnsignedText( unsigned* uval ) const;
1629     /// See QueryIntText()

1630     XMLError QueryInt64Text(int64_t* uval) const;
1631     /// See QueryIntText()

1632     XMLError QueryUnsigned64Text(uint64_t* uval) const;
1633     /// See QueryIntText()

1634     XMLError QueryBoolText( bool* bval ) const;
1635     /// See QueryIntText()

1636     XMLError QueryDoubleText( double* dval ) const;
1637     /// See QueryIntText()

1638     XMLError QueryFloatText( float* fval ) const;
1639 
1640     int IntText(int defaultValue = 0) const;
1641 
1642     /// See QueryIntText()

1643     unsigned UnsignedText(unsigned defaultValue = 0) const;
1644     /// See QueryIntText()

1645     int64_t Int64Text(int64_t defaultValue = 0) const;
1646     /// See QueryIntText()

1647     uint64_t Unsigned64Text(uint64_t defaultValue = 0) const;
1648     /// See QueryIntText()

1649     bool BoolText(bool defaultValue = false) const;
1650     /// See QueryIntText()

1651     double DoubleText(double defaultValue = 0) const;
1652     /// See QueryIntText()

1653     float FloatText(float defaultValue = 0) const;
1654 
1655     /**

1656         Convenience method to create a new XMLElement and add it as last (right)

1657         child of this node. Returns the created and inserted element.

1658     */
1659     XMLElement* InsertNewChildElement(const char* name);
1660     /// See InsertNewChildElement()

1661     XMLComment* InsertNewComment(const char* comment);
1662     /// See InsertNewChildElement()

1663     XMLText* InsertNewText(const char* text);
1664     /// See InsertNewChildElement()

1665     XMLDeclaration* InsertNewDeclaration(const char* text);
1666     /// See InsertNewChildElement()

1667     XMLUnknown* InsertNewUnknown(const char* text);
1668 
1669 
1670     // internal:

1671     enum ElementClosingType {
1672         OPEN,       // <foo>

1673         CLOSED,     // <foo/>

1674         CLOSING     // </foo>

1675     };
1676     ElementClosingType ClosingType() const {
1677         return _closingType;
1678     }
1679     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1680     virtual bool ShallowEqual( const XMLNode* compare ) const;
1681 
1682 protected:
1683     char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
1684 
1685 private:
1686     XMLElement( XMLDocument* doc );
1687     virtual ~XMLElement();
1688     XMLElement( const XMLElement& );    // not supported

1689     void operator=( const XMLElement& );    // not supported

1690 
1691     XMLAttribute* FindOrCreateAttribute( const char* name );
1692     char* ParseAttributes( char* p, int* curLineNumPtr );
1693     static void DeleteAttribute( XMLAttribute* attribute );
1694     XMLAttribute* CreateAttribute();
1695 
1696     enum { BUF_SIZE = 200 };
1697     ElementClosingType _closingType;
1698     // The attribute list is ordered; there is no 'lastAttribute'

1699     // because the list needs to be scanned for dupes before adding

1700     // a new attribute.

1701     XMLAttribute* _rootAttribute;
1702 };
1703 
1704 
1705 enum Whitespace {
1706     PRESERVE_WHITESPACE,
1707     COLLAPSE_WHITESPACE
1708 };
1709 
1710 
1711 /** A Document binds together all the functionality.

1712     It can be saved, loaded, and printed to the screen.

1713     All Nodes are connected and allocated to a Document.

1714     If the Document is deleted, all its Nodes are also deleted.

1715 */
1716 class TINYXML2_LIB XMLDocument : public XMLNode
1717 {
1718     friend class XMLElement;
1719     // Gives access to SetError and Push/PopDepth, but over-access for everything else.

1720     // Wishing C++ had "internal" scope.

1721     friend class XMLNode;
1722     friend class XMLText;
1723     friend class XMLComment;
1724     friend class XMLDeclaration;
1725     friend class XMLUnknown;
1726 public:
1727     /// constructor

1728     XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE );
1729     ~XMLDocument();
1730 
1731     virtual XMLDocument* ToDocument()               {
1732         TIXMLASSERT( this == _document );
1733         return this;
1734     }
1735     virtual const XMLDocument* ToDocument() const   {
1736         TIXMLASSERT( this == _document );
1737         return this;
1738     }
1739 
1740     /**

1741         Parse an XML file from a character string.

1742         Returns XML_SUCCESS (0) on success, or

1743         an errorID.

1744 

1745         You may optionally pass in the 'nBytes', which is

1746         the number of bytes which will be parsed. If not

1747         specified, TinyXML-2 will assume 'xml' points to a

1748         null terminated string.

1749     */
1750     XMLError Parse( const char* xml, size_t nBytes=static_cast<size_t>(-1) );
1751 
1752     /**

1753         Load an XML file from disk.

1754         Returns XML_SUCCESS (0) on success, or

1755         an errorID.

1756     */
1757     XMLError LoadFile( const char* filename );
1758 
1759     /**

1760         Load an XML file from disk. You are responsible

1761         for providing and closing the FILE*.

1762 

1763         NOTE: The file should be opened as binary ("rb")

1764         not text in order for TinyXML-2 to correctly

1765         do newline normalization.

1766 

1767         Returns XML_SUCCESS (0) on success, or

1768         an errorID.

1769     */
1770     XMLError LoadFile( FILE* );
1771 
1772     /**

1773         Save the XML file to disk.

1774         Returns XML_SUCCESS (0) on success, or

1775         an errorID.

1776     */
1777     XMLError SaveFile( const char* filename, bool compact = false );
1778 
1779     /**

1780         Save the XML file to disk. You are responsible

1781         for providing and closing the FILE*.

1782 

1783         Returns XML_SUCCESS (0) on success, or

1784         an errorID.

1785     */
1786     XMLError SaveFile( FILE* fp, bool compact = false );
1787 
1788     bool ProcessEntities() const        {
1789         return _processEntities;
1790     }
1791     Whitespace WhitespaceMode() const   {
1792         return _whitespaceMode;
1793     }
1794 
1795     /**

1796         Returns true if this document has a leading Byte Order Mark of UTF8.

1797     */
1798     bool HasBOM() const {
1799         return _writeBOM;
1800     }
1801     /** Sets whether to write the BOM when writing the file.

1802     */
1803     void SetBOM( bool useBOM ) {
1804         _writeBOM = useBOM;
1805     }
1806 
1807     /** Return the root element of DOM. Equivalent to FirstChildElement().

1808         To get the first node, use FirstChild().

1809     */
1810     XMLElement* RootElement()               {
1811         return FirstChildElement();
1812     }
1813     const XMLElement* RootElement() const   {
1814         return FirstChildElement();
1815     }
1816 
1817     /** Print the Document. If the Printer is not provided, it will

1818         print to stdout. If you provide Printer, this can print to a file:

1819         @verbatim

1820         XMLPrinter printer( fp );

1821         doc.Print( &printer );

1822         @endverbatim

1823 

1824         Or you can use a printer to print to memory:

1825         @verbatim

1826         XMLPrinter printer;

1827         doc.Print( &printer );

1828         // printer.CStr() has a const char* to the XML

1829         @endverbatim

1830     */
1831     void Print( XMLPrinter* streamer=0 ) const;
1832     virtual bool Accept( XMLVisitor* visitor ) const;
1833 
1834     /**

1835         Create a new Element associated with

1836         this Document. The memory for the Element

1837         is managed by the Document.

1838     */
1839     XMLElement* NewElement( const char* name );
1840     /**

1841         Create a new Comment associated with

1842         this Document. The memory for the Comment

1843         is managed by the Document.

1844     */
1845     XMLComment* NewComment( const char* comment );
1846     /**

1847         Create a new Text associated with

1848         this Document. The memory for the Text

1849         is managed by the Document.

1850     */
1851     XMLText* NewText( const char* text );
1852     /**

1853         Create a new Declaration associated with

1854         this Document. The memory for the object

1855         is managed by the Document.

1856 

1857         If the 'text' param is null, the standard

1858         declaration is used.:

1859         @verbatim

1860             <?xml version="1.0" encoding="UTF-8"?>

1861         @endverbatim

1862     */
1863     XMLDeclaration* NewDeclaration( const char* text=0 );
1864     /**

1865         Create a new Unknown associated with

1866         this Document. The memory for the object

1867         is managed by the Document.

1868     */
1869     XMLUnknown* NewUnknown( const char* text );
1870 
1871     /**

1872         Delete a node associated with this document.

1873         It will be unlinked from the DOM.

1874     */
1875     void DeleteNode( XMLNode* node );
1876 
1877     /// Clears the error flags.

1878     void ClearError();
1879 
1880     /// Return true if there was an error parsing the document.

1881     bool Error() const {
1882         return _errorID != XML_SUCCESS;
1883     }
1884     /// Return the errorID.

1885     XMLError  ErrorID() const {
1886         return _errorID;
1887     }
1888     const char* ErrorName() const;
1889     static const char* ErrorIDToName(XMLError errorID);
1890 
1891     /** Returns a "long form" error description. A hopefully helpful

1892         diagnostic with location, line number, and/or additional info.

1893     */
1894     const char* ErrorStr() const;
1895 
1896     /// A (trivial) utility function that prints the ErrorStr() to stdout.

1897     void PrintError() const;
1898 
1899     /// Return the line where the error occurred, or zero if unknown.

1900     int ErrorLineNum() const
1901     {
1902         return _errorLineNum;
1903     }
1904 
1905     /// Clear the document, resetting it to the initial state.

1906     void Clear();
1907 
1908     /**

1909         Copies this document to a target document.

1910         The target will be completely cleared before the copy.

1911         If you want to copy a sub-tree, see XMLNode::DeepClone().

1912 

1913         NOTE: that the 'target' must be non-null.

1914     */
1915     void DeepCopy(XMLDocument* target) const;
1916 
1917     // internal

1918     char* Identify( char* p, XMLNode** node );
1919 
1920     // internal

1921     void MarkInUse(const XMLNode* const);
1922 
1923     virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const    {
1924         return 0;
1925     }
1926     virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const   {
1927         return false;
1928     }
1929 
1930 private:
1931     XMLDocument( const XMLDocument& );  // not supported

1932     void operator=( const XMLDocument& );   // not supported

1933 
1934     bool            _writeBOM;
1935     bool            _processEntities;
1936     XMLError        _errorID;
1937     Whitespace      _whitespaceMode;
1938     mutable StrPair _errorStr;
1939     int             _errorLineNum;
1940     char*           _charBuffer;
1941     int             _parseCurLineNum;
1942     int             _parsingDepth;
1943     // Memory tracking does add some overhead.

1944     // However, the code assumes that you don't

1945     // have a bunch of unlinked nodes around.

1946     // Therefore it takes less memory to track

1947     // in the document vs. a linked list in the XMLNode,

1948     // and the performance is the same.

1949     DynArray<XMLNode*, 10> _unlinked;
1950 
1951     MemPoolT< sizeof(XMLElement) >   _elementPool;
1952     MemPoolT< sizeof(XMLAttribute) > _attributePool;
1953     MemPoolT< sizeof(XMLText) >      _textPool;
1954     MemPoolT< sizeof(XMLComment) >   _commentPool;
1955 
1956     static const char* _errorNames[XML_ERROR_COUNT];
1957 
1958     void Parse();
1959 
1960     void SetError( XMLError error, int lineNum, const char* format, ... );
1961 
1962     // Something of an obvious security hole, once it was discovered.

1963     // Either an ill-formed XML or an excessively deep one can overflow

1964     // the stack. Track stack depth, and error out if needed.

1965     class DepthTracker {
1966     public:
1967         explicit DepthTracker(XMLDocument * document) {
1968             this->_document = document;
1969             document->PushDepth();
1970         }
1971         ~DepthTracker() {
1972             _document->PopDepth();
1973         }
1974     private:
1975         XMLDocument * _document;
1976     };
1977     void PushDepth();
1978     void PopDepth();
1979 
1980     template<class NodeType, int PoolElementSize>
1981     NodeType* CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool );
1982 };
1983 
1984 template<class NodeType, int PoolElementSize>
1985 inline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool )
1986 {
1987     TIXMLASSERT( sizeof( NodeType ) == PoolElementSize );
1988     TIXMLASSERT( sizeof( NodeType ) == pool.ItemSize() );
1989     NodeType* returnNode = new (pool.Alloc()) NodeType( this );
1990     TIXMLASSERT( returnNode );
1991     returnNode->_memPool = &pool;
1992 
1993     _unlinked.Push(returnNode);
1994     return returnNode;
1995 }
1996 
1997 /**

1998     A XMLHandle is a class that wraps a node pointer with null checks; this is

1999     an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2

2000     DOM structure. It is a separate utility class.

2001 

2002     Take an example:

2003     @verbatim

2004     <Document>

2005         <Element attributeA = "valueA">

2006             <Child attributeB = "value1" />

2007             <Child attributeB = "value2" />

2008         </Element>

2009     </Document>

2010     @endverbatim

2011 

2012     Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very

2013     easy to write a *lot* of code that looks like:

2014 

2015     @verbatim

2016     XMLElement* root = document.FirstChildElement( "Document" );

2017     if ( root )

2018     {

2019         XMLElement* element = root->FirstChildElement( "Element" );

2020         if ( element )

2021         {

2022             XMLElement* child = element->FirstChildElement( "Child" );

2023             if ( child )

2024             {

2025                 XMLElement* child2 = child->NextSiblingElement( "Child" );

2026                 if ( child2 )

2027                 {

2028                     // Finally do something useful.

2029     @endverbatim

2030 

2031     And that doesn't even cover "else" cases. XMLHandle addresses the verbosity

2032     of such code. A XMLHandle checks for null pointers so it is perfectly safe

2033     and correct to use:

2034 

2035     @verbatim

2036     XMLHandle docHandle( &document );

2037     XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();

2038     if ( child2 )

2039     {

2040         // do something useful

2041     @endverbatim

2042 

2043     Which is MUCH more concise and useful.

2044 

2045     It is also safe to copy handles - internally they are nothing more than node pointers.

2046     @verbatim

2047     XMLHandle handleCopy = handle;

2048     @endverbatim

2049 

2050     See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.

2051 */
2052 class TINYXML2_LIB XMLHandle
2053 {
2054 public:
2055     /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.

2056     explicit XMLHandle( XMLNode* node ) : _node( node ) {
2057     }
2058     /// Create a handle from a node.

2059     explicit XMLHandle( XMLNode& node ) : _node( &node ) {
2060     }
2061     /// Copy constructor

2062     XMLHandle( const XMLHandle& ref ) : _node( ref._node ) {
2063     }
2064     /// Assignment

2065     XMLHandle& operator=( const XMLHandle& ref )                            {
2066         _node = ref._node;
2067         return *this;
2068     }
2069 
2070     /// Get the first child of this handle.

2071     XMLHandle FirstChild()                                                  {
2072         return XMLHandle( _node ? _node->FirstChild() : 0 );
2073     }
2074     /// Get the first child element of this handle.

2075     XMLHandle FirstChildElement( const char* name = 0 )                     {
2076         return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
2077     }
2078     /// Get the last child of this handle.

2079     XMLHandle LastChild()                                                   {
2080         return XMLHandle( _node ? _node->LastChild() : 0 );
2081     }
2082     /// Get the last child element of this handle.

2083     XMLHandle LastChildElement( const char* name = 0 )                      {
2084         return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
2085     }
2086     /// Get the previous sibling of this handle.

2087     XMLHandle PreviousSibling()                                             {
2088         return XMLHandle( _node ? _node->PreviousSibling() : 0 );
2089     }
2090     /// Get the previous sibling element of this handle.

2091     XMLHandle PreviousSiblingElement( const char* name = 0 )                {
2092         return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
2093     }
2094     /// Get the next sibling of this handle.

2095     XMLHandle NextSibling()                                                 {
2096         return XMLHandle( _node ? _node->NextSibling() : 0 );
2097     }
2098     /// Get the next sibling element of this handle.

2099     XMLHandle NextSiblingElement( const char* name = 0 )                    {
2100         return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
2101     }
2102 
2103     /// Safe cast to XMLNode. This can return null.

2104     XMLNode* ToNode()                           {
2105         return _node;
2106     }
2107     /// Safe cast to XMLElement. This can return null.

2108     XMLElement* ToElement()                     {
2109         return ( _node ? _node->ToElement() : 0 );
2110     }
2111     /// Safe cast to XMLText. This can return null.

2112     XMLText* ToText()                           {
2113         return ( _node ? _node->ToText() : 0 );
2114     }
2115     /// Safe cast to XMLUnknown. This can return null.

2116     XMLUnknown* ToUnknown()                     {
2117         return ( _node ? _node->ToUnknown() : 0 );
2118     }
2119     /// Safe cast to XMLDeclaration. This can return null.

2120     XMLDeclaration* ToDeclaration()             {
2121         return ( _node ? _node->ToDeclaration() : 0 );
2122     }
2123 
2124 private:
2125     XMLNode* _node;
2126 };
2127 
2128 
2129 /**

2130     A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the

2131     same in all regards, except for the 'const' qualifiers. See XMLHandle for API.

2132 */
2133 class TINYXML2_LIB XMLConstHandle
2134 {
2135 public:
2136     explicit XMLConstHandle( const XMLNode* node ) : _node( node ) {
2137     }
2138     explicit XMLConstHandle( const XMLNode& node ) : _node( &node ) {
2139     }
2140     XMLConstHandle( const XMLConstHandle& ref ) : _node( ref._node ) {
2141     }
2142 
2143     XMLConstHandle& operator=( const XMLConstHandle& ref )                          {
2144         _node = ref._node;
2145         return *this;
2146     }
2147 
2148     const XMLConstHandle FirstChild() const                                         {
2149         return XMLConstHandle( _node ? _node->FirstChild() : 0 );
2150     }
2151     const XMLConstHandle FirstChildElement( const char* name = 0 ) const                {
2152         return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
2153     }
2154     const XMLConstHandle LastChild()    const                                       {
2155         return XMLConstHandle( _node ? _node->LastChild() : 0 );
2156     }
2157     const XMLConstHandle LastChildElement( const char* name = 0 ) const             {
2158         return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
2159     }
2160     const XMLConstHandle PreviousSibling() const                                    {
2161         return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
2162     }
2163     const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const       {
2164         return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
2165     }
2166     const XMLConstHandle NextSibling() const                                        {
2167         return XMLConstHandle( _node ? _node->NextSibling() : 0 );
2168     }
2169     const XMLConstHandle NextSiblingElement( const char* name = 0 ) const           {
2170         return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
2171     }
2172 
2173 
2174     const XMLNode* ToNode() const               {
2175         return _node;
2176     }
2177     const XMLElement* ToElement() const         {
2178         return ( _node ? _node->ToElement() : 0 );
2179     }
2180     const XMLText* ToText() const               {
2181         return ( _node ? _node->ToText() : 0 );
2182     }
2183     const XMLUnknown* ToUnknown() const         {
2184         return ( _node ? _node->ToUnknown() : 0 );
2185     }
2186     const XMLDeclaration* ToDeclaration() const {
2187         return ( _node ? _node->ToDeclaration() : 0 );
2188     }
2189 
2190 private:
2191     const XMLNode* _node;
2192 };
2193 
2194 
2195 /**

2196     Printing functionality. The XMLPrinter gives you more

2197     options than the XMLDocument::Print() method.

2198 

2199     It can:

2200     -# Print to memory.

2201     -# Print to a file you provide.

2202     -# Print XML without a XMLDocument.

2203 

2204     Print to Memory

2205 

2206     @verbatim

2207     XMLPrinter printer;

2208     doc.Print( &printer );

2209     SomeFunction( printer.CStr() );

2210     @endverbatim

2211 

2212     Print to a File

2213 

2214     You provide the file pointer.

2215     @verbatim

2216     XMLPrinter printer( fp );

2217     doc.Print( &printer );

2218     @endverbatim

2219 

2220     Print without a XMLDocument

2221 

2222     When loading, an XML parser is very useful. However, sometimes

2223     when saving, it just gets in the way. The code is often set up

2224     for streaming, and constructing the DOM is just overhead.

2225 

2226     The Printer supports the streaming case. The following code

2227     prints out a trivially simple XML file without ever creating

2228     an XML document.

2229 

2230     @verbatim

2231     XMLPrinter printer( fp );

2232     printer.OpenElement( "foo" );

2233     printer.PushAttribute( "foo", "bar" );

2234     printer.CloseElement();

2235     @endverbatim

2236 */
2237 class TINYXML2_LIB XMLPrinter : public XMLVisitor
2238 {
2239 public:
2240     /** Construct the printer. If the FILE* is specified,

2241         this will print to the FILE. Else it will print

2242         to memory, and the result is available in CStr().

2243         If 'compact' is set to true, then output is created

2244         with only required whitespace and newlines.

2245     */
2246     XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
2247     virtual ~XMLPrinter()   {}
2248 
2249     /** If streaming, write the BOM and declaration. */
2250     void PushHeader( bool writeBOM, bool writeDeclaration );
2251     /** If streaming, start writing an element.

2252         The element must be closed with CloseElement()

2253     */
2254     void OpenElement( const char* name, bool compactMode=false );
2255     /// If streaming, add an attribute to an open element.

2256     void PushAttribute( const char* name, const char* value );
2257     void PushAttribute( const char* name, int value );
2258     void PushAttribute( const char* name, unsigned value );
2259     void PushAttribute( const char* name, int64_t value );
2260     void PushAttribute( const char* name, uint64_t value );
2261     void PushAttribute( const char* name, bool value );
2262     void PushAttribute( const char* name, double value );
2263     /// If streaming, close the Element.

2264     virtual void CloseElement( bool compactMode=false );
2265 
2266     /// Add a text node.

2267     void PushText( const char* text, bool cdata=false );
2268     /// Add a text node from an integer.

2269     void PushText( int value );
2270     /// Add a text node from an unsigned.

2271     void PushText( unsigned value );
2272     /// Add a text node from a signed 64bit integer.

2273     void PushText( int64_t value );
2274     /// Add a text node from an unsigned 64bit integer.

2275     void PushText( uint64_t value );
2276     /// Add a text node from a bool.

2277     void PushText( bool value );
2278     /// Add a text node from a float.

2279     void PushText( float value );
2280     /// Add a text node from a double.

2281     void PushText( double value );
2282 
2283     /// Add a comment

2284     void PushComment( const char* comment );
2285 
2286     void PushDeclaration( const char* value );
2287     void PushUnknown( const char* value );
2288 
2289     virtual bool VisitEnter( const XMLDocument& /*doc*/ );
2290     virtual bool VisitExit( const XMLDocument& /*doc*/ )            {
2291         return true;
2292     }
2293 
2294     virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2295     virtual bool VisitExit( const XMLElement& element );
2296 
2297     virtual bool Visit( const XMLText& text );
2298     virtual bool Visit( const XMLComment& comment );
2299     virtual bool Visit( const XMLDeclaration& declaration );
2300     virtual bool Visit( const XMLUnknown& unknown );
2301 
2302     /**

2303         If in print to memory mode, return a pointer to

2304         the XML file in memory.

2305     */
2306     const char* CStr() const {
2307         return _buffer.Mem();
2308     }
2309     /**

2310         If in print to memory mode, return the size

2311         of the XML file in memory. (Note the size returned

2312         includes the terminating null.)

2313     */
2314     int CStrSize() const {
2315         return _buffer.Size();
2316     }
2317     /**

2318         If in print to memory mode, reset the buffer to the

2319         beginning.

2320     */
2321     void ClearBuffer( bool resetToFirstElement = true ) {
2322         _buffer.Clear();
2323         _buffer.Push(0);
2324         _firstElement = resetToFirstElement;
2325     }
2326 
2327 protected:
2328     virtual bool CompactMode( const XMLElement& )   { return _compactMode; }
2329 
2330     /** Prints out the space before an element. You may override to change

2331         the space and tabs used. A PrintSpace() override should call Print().

2332     */
2333     virtual void PrintSpace( int depth );
2334     virtual void Print( const char* format, ... );
2335     virtual void Write( const char* data, size_t size );
2336     virtual void Putc( char ch );
2337 
2338     inline void Write(const char* data) { Write(data, strlen(data)); }
2339 
2340     void SealElementIfJustOpened();
2341     bool _elementJustOpened;
2342     DynArray< const char*, 10 > _stack;
2343 
2344 private:
2345     /**

2346        Prepares to write a new node. This includes sealing an element that was

2347        just opened, and writing any whitespace necessary if not in compact mode.

2348      */
2349     void PrepareForNewNode( bool compactMode );
2350     void PrintString( const char*, bool restrictedEntitySet );  // prints out, after detecting entities.

2351 
2352     bool _firstElement;
2353     FILE* _fp;
2354     int _depth;
2355     int _textDepth;
2356     bool _processEntities;
2357     bool _compactMode;
2358 
2359     enum {
2360         ENTITY_RANGE = 64,
2361         BUF_SIZE = 200
2362     };
2363     bool _entityFlag[ENTITY_RANGE];
2364     bool _restrictedEntityFlag[ENTITY_RANGE];
2365 
2366     DynArray< char, 20 > _buffer;
2367 
2368     // Prohibit cloning, intentionally not implemented

2369     XMLPrinter( const XMLPrinter& );
2370     XMLPrinter& operator=( const XMLPrinter& );
2371 };
2372 
2373 
2374 }   // tinyxml2

2375 
2376 #if defined(_MSC_VER)
2377 #   pragma warning(pop)
2378 #endif
2379 
2380 #endif // TINYXML2_INCLUDED