Home | History | Annotate | Download | only in tinyxml2
      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 #include <cctype>
     28 #include <climits>
     29 #include <cstdio>
     30 #include <cstring>
     31 //#include <cstdarg>
     32 #include <stdarg.h>
     33 /*
     34    TODO: intern strings instead of allocation.
     35 */
     36 /*
     37     gcc: g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
     38 */
     39 
     40 #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
     41     #ifndef DEBUG
     42         #define DEBUG
     43     #endif
     44 #endif
     45 
     46 
     47 #if defined(DEBUG)
     48         #if defined(_MSC_VER)
     49                 #define TIXMLASSERT( x )           if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
     50         #elif defined (ANDROID_NDK)
     51                 #include <android/log.h>
     52                 #define TIXMLASSERT( x )           if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
     53         #else
     54                 #include <assert.h>
     55                 #define TIXMLASSERT                assert
     56         #endif
     57 #else
     58         #define TIXMLASSERT( x )           {}
     59 #endif
     60 
     61 
     62 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
     63     // Microsoft visual studio, version 2005 and higher.
     64     /*int _snprintf_s(
     65        char *buffer,
     66        size_t sizeOfBuffer,
     67        size_t count,
     68        const char *format [,
     69           argument] ...
     70     );*/
     71     inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) {
     72         va_list va;
     73         va_start( va, format );
     74         int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
     75         va_end( va );
     76         return result;
     77     }
     78     #define TIXML_SSCANF   sscanf_s
     79 #else
     80     // GCC version 3 and higher
     81     //#warning( "Using sn* functions." )
     82     #define TIXML_SNPRINTF snprintf
     83     #define TIXML_SSCANF   sscanf
     84 #endif
     85 
     86 static const int TIXML2_MAJOR_VERSION = 1;
     87 static const int TIXML2_MINOR_VERSION = 0;
     88 static const int TIXML2_PATCH_VERSION = 6;
     89 
     90 namespace tinyxml2
     91 {
     92 class XMLDocument;
     93 class XMLElement;
     94 class XMLAttribute;
     95 class XMLComment;
     96 class XMLNode;
     97 class XMLText;
     98 class XMLDeclaration;
     99 class XMLUnknown;
    100 
    101 class XMLPrinter;
    102 
    103 /*
    104     A class that wraps strings. Normally stores the start and end
    105     pointers into the XML file itself, and will apply normalization
    106     and entity translation if actually read. Can also store (and memory
    107     manage) a traditional char[]
    108 */
    109 class StrPair
    110 {
    111 public:
    112     enum {
    113         NEEDS_ENTITY_PROCESSING            = 0x01,
    114         NEEDS_NEWLINE_NORMALIZATION        = 0x02,
    115 
    116         TEXT_ELEMENT        = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
    117         TEXT_ELEMENT_LEAVE_ENTITIES        = NEEDS_NEWLINE_NORMALIZATION,
    118         ATTRIBUTE_NAME        = 0,
    119         ATTRIBUTE_VALUE        = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
    120         ATTRIBUTE_VALUE_LEAVE_ENTITIES        = NEEDS_NEWLINE_NORMALIZATION,
    121         COMMENT                = NEEDS_NEWLINE_NORMALIZATION
    122     };
    123 
    124     StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
    125     ~StrPair();
    126 
    127     void Set( char* _start, char* _end, int _flags ) {
    128         Reset();
    129         this->start = _start; this->end = _end; this->flags = _flags | NEEDS_FLUSH;
    130     }
    131     const char* GetStr();
    132     bool Empty() const { return start == end; }
    133 
    134     void SetInternedStr( const char* str ) { Reset(); this->start = const_cast<char*>(str); }
    135     void SetStr( const char* str, int flags=0 );
    136 
    137     char* ParseText( char* in, const char* endTag, int strFlags );
    138     char* ParseName( char* in );
    139 
    140 
    141 private:
    142     void Reset();
    143 
    144     enum {
    145         NEEDS_FLUSH = 0x100,
    146         NEEDS_DELETE = 0x200
    147     };
    148 
    149     // After parsing, if *end != 0, it can be set to zero.
    150     int flags;
    151     char* start;
    152     char* end;
    153 };
    154 
    155 
    156 /*
    157     A dynamic array of Plain Old Data. Doesn't support constructors, etc.
    158     Has a small initial memory pool, so that low or no usage will not
    159     cause a call to new/delete
    160 */
    161 template <class T, int INIT>
    162 class DynArray
    163 {
    164 public:
    165     DynArray< T, INIT >()
    166     {
    167         mem = pool;
    168         allocated = INIT;
    169         size = 0;
    170     }
    171     ~DynArray()
    172     {
    173         if ( mem != pool ) {
    174             delete [] mem;
    175         }
    176     }
    177     void Push( T t )
    178     {
    179         EnsureCapacity( size+1 );
    180         mem[size++] = t;
    181     }
    182 
    183     T* PushArr( int count )
    184     {
    185         EnsureCapacity( size+count );
    186         T* ret = &mem[size];
    187         size += count;
    188         return ret;
    189     }
    190     T Pop() {
    191         return mem[--size];
    192     }
    193     void PopArr( int count )
    194     {
    195         TIXMLASSERT( size >= count );
    196         size -= count;
    197     }
    198 
    199     bool Empty() const                    { return size == 0; }
    200     T& operator[](int i)                { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
    201     const T& operator[](int i) const    { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
    202     int Size() const                    { return size; }
    203     int Capacity() const                { return allocated; }
    204     const T* Mem() const                { return mem; }
    205     T* Mem()                            { return mem; }
    206 
    207 
    208 private:
    209     void EnsureCapacity( int cap ) {
    210         if ( cap > allocated ) {
    211             int newAllocated = cap * 2;
    212             T* newMem = new T[newAllocated];
    213             memcpy( newMem, mem, sizeof(T)*size );    // warning: not using constructors, only works for PODs
    214             if ( mem != pool ) delete [] mem;
    215             mem = newMem;
    216             allocated = newAllocated;
    217         }
    218     }
    219 
    220     T* mem;
    221     T pool[INIT];
    222     int allocated;        // objects allocated
    223     int size;            // number objects in use
    224 };
    225 
    226 
    227 /*
    228     Parent virtual class of a pool for fast allocation
    229     and deallocation of objects.
    230 */
    231 class MemPool
    232 {
    233 public:
    234     MemPool() {}
    235     virtual ~MemPool() {}
    236 
    237     virtual int ItemSize() const = 0;
    238     virtual void* Alloc() = 0;
    239     virtual void Free( void* ) = 0;
    240 };
    241 
    242 
    243 /*
    244     Template child class to create pools of the correct type.
    245 */
    246 template< int SIZE >
    247 class MemPoolT : public MemPool
    248 {
    249 public:
    250     MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0)    {}
    251     ~MemPoolT() {
    252         // Delete the blocks.
    253         for( int i=0; i<blockPtrs.Size(); ++i ) {
    254             delete blockPtrs[i];
    255         }
    256     }
    257 
    258     virtual int ItemSize() const    { return SIZE; }
    259     int CurrentAllocs() const        { return currentAllocs; }
    260 
    261     virtual void* Alloc() {
    262         if ( !root ) {
    263             // Need a new block.
    264             Block* block = new Block();
    265             blockPtrs.Push( block );
    266 
    267             for( int i=0; i<COUNT-1; ++i ) {
    268                 block->chunk[i].next = &block->chunk[i+1];
    269             }
    270             block->chunk[COUNT-1].next = 0;
    271             root = block->chunk;
    272         }
    273         void* result = root;
    274         root = root->next;
    275 
    276         ++currentAllocs;
    277         if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
    278         nAllocs++;
    279         return result;
    280     }
    281     virtual void Free( void* mem ) {
    282         if ( !mem ) return;
    283         --currentAllocs;
    284         Chunk* chunk = (Chunk*)mem;
    285         memset( chunk, 0xfe, sizeof(Chunk) );
    286         chunk->next = root;
    287         root = chunk;
    288     }
    289     void Trace( const char* name ) {
    290         printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
    291                  name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
    292     }
    293 
    294 private:
    295     enum { COUNT = 1024/SIZE };
    296     union Chunk {
    297         Chunk* next;
    298         char mem[SIZE];
    299     };
    300     struct Block {
    301         Chunk chunk[COUNT];
    302     };
    303     DynArray< Block*, 10 > blockPtrs;
    304     Chunk* root;
    305 
    306     int currentAllocs;
    307     int nAllocs;
    308     int maxAllocs;
    309 };
    310 
    311 
    312 
    313 /**
    314     Implements the interface to the "Visitor pattern" (see the Accept() method.)
    315     If you call the Accept() method, it requires being passed a XMLVisitor
    316     class to handle callbacks. For nodes that contain other nodes (Document, Element)
    317     you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
    318     are simply called with Visit().
    319 
    320     If you return 'true' from a Visit method, recursive parsing will continue. If you return
    321     false, <b>no children of this node or its sibilings</b> will be visited.
    322 
    323     All flavors of Visit methods have a default implementation that returns 'true' (continue
    324     visiting). You need to only override methods that are interesting to you.
    325 
    326     Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
    327 
    328     You should never change the document from a callback.
    329 
    330     @sa XMLNode::Accept()
    331 */
    332 class XMLVisitor
    333 {
    334 public:
    335     virtual ~XMLVisitor() {}
    336 
    337     /// Visit a document.
    338     virtual bool VisitEnter( const XMLDocument& /*doc*/ )            { return true; }
    339     /// Visit a document.
    340     virtual bool VisitExit( const XMLDocument& /*doc*/ )            { return true; }
    341 
    342     /// Visit an element.
    343     virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )    { return true; }
    344     /// Visit an element.
    345     virtual bool VisitExit( const XMLElement& /*element*/ )            { return true; }
    346 
    347     /// Visit a declaration.
    348     virtual bool Visit( const XMLDeclaration& /*declaration*/ )        { return true; }
    349     /// Visit a text node.
    350     virtual bool Visit( const XMLText& /*text*/ )                    { return true; }
    351     /// Visit a comment node.
    352     virtual bool Visit( const XMLComment& /*comment*/ )                { return true; }
    353     /// Visit an unknown node.
    354     virtual bool Visit( const XMLUnknown& /*unknown*/ )                { return true; }
    355 };
    356 
    357 
    358 /*
    359     Utility functionality.
    360 */
    361 class XMLUtil
    362 {
    363 public:
    364     // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
    365     // correct, but simple, and usually works.
    366     static const char* SkipWhiteSpace( const char* p )    { while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) { ++p; } return p; }
    367     static char* SkipWhiteSpace( char* p )                { while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) )        { ++p; } return p; }
    368 
    369     inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {
    370         int n = 0;
    371         if ( p == q ) {
    372             return true;
    373         }
    374         while( *p && *q && *p == *q && n<nChar ) {
    375             ++p; ++q; ++n;
    376         }
    377         if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
    378             return true;
    379         }
    380         return false;
    381     }
    382     inline static int IsUTF8Continuation( const char p ) { return p & 0x80; }
    383     inline static int IsAlphaNum( unsigned char anyByte )    { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
    384     inline static int IsAlpha( unsigned char anyByte )        { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
    385 
    386     static const char* ReadBOM( const char* p, bool* hasBOM );
    387     // p is the starting location,
    388     // the UTF-8 value of the entity will be placed in value, and length filled in.
    389     static const char* GetCharacterRef( const char* p, char* value, int* length );
    390     static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
    391 
    392     // converts primitive types to strings
    393     static void ToStr( int v, char* buffer, int bufferSize );
    394     static void ToStr( unsigned v, char* buffer, int bufferSize );
    395     static void ToStr( bool v, char* buffer, int bufferSize );
    396     static void ToStr( float v, char* buffer, int bufferSize );
    397     static void ToStr( double v, char* buffer, int bufferSize );
    398 
    399     // converts strings to primitive types
    400     static bool    ToInt( const char* str, int* value );
    401     static bool ToUnsigned( const char* str, unsigned* value );
    402     static bool    ToBool( const char* str, bool* value );
    403     static bool    ToFloat( const char* str, float* value );
    404     static bool ToDouble( const char* str, double* value );
    405 };
    406 
    407 
    408 /** XMLNode is a base class for every object that is in the
    409     XML Document Object Model (DOM), except XMLAttributes.
    410     Nodes have siblings, a parent, and children which can
    411     be navigated. A node is always in a XMLDocument.
    412     The type of a XMLNode can be queried, and it can
    413     be cast to its more defined type.
    414 
    415     A XMLDocument allocates memory for all its Nodes.
    416     When the XMLDocument gets deleted, all its Nodes
    417     will also be deleted.
    418 
    419     @verbatim
    420     A Document can contain:    Element    (container or leaf)
    421                             Comment (leaf)
    422                             Unknown (leaf)
    423                             Declaration( leaf )
    424 
    425     An Element can contain:    Element (container or leaf)
    426                             Text    (leaf)
    427                             Attributes (not on tree)
    428                             Comment (leaf)
    429                             Unknown (leaf)
    430 
    431     @endverbatim
    432 */
    433 class XMLNode
    434 {
    435     friend class XMLDocument;
    436     friend class XMLElement;
    437 public:
    438 
    439     /// Get the XMLDocument that owns this XMLNode.
    440     const XMLDocument* GetDocument() const    { return document; }
    441     /// Get the XMLDocument that owns this XMLNode.
    442     XMLDocument* GetDocument()                { return document; }
    443 
    444     virtual XMLElement*        ToElement()        { return 0; }    ///< Safely cast to an Element, or null.
    445     virtual XMLText*        ToText()        { return 0; }    ///< Safely cast to Text, or null.
    446     virtual XMLComment*        ToComment()        { return 0; }    ///< Safely cast to a Comment, or null.
    447     virtual XMLDocument*    ToDocument()    { return 0; }    ///< Safely cast to a Document, or null.
    448     virtual XMLDeclaration*    ToDeclaration()    { return 0; }    ///< Safely cast to a Declaration, or null.
    449     virtual XMLUnknown*        ToUnknown()        { return 0; }    ///< Safely cast to an Unknown, or null.
    450 
    451     virtual const XMLElement*        ToElement() const        { return 0; }
    452     virtual const XMLText*            ToText() const            { return 0; }
    453     virtual const XMLComment*        ToComment() const        { return 0; }
    454     virtual const XMLDocument*        ToDocument() const        { return 0; }
    455     virtual const XMLDeclaration*    ToDeclaration() const    { return 0; }
    456     virtual const XMLUnknown*        ToUnknown() const        { return 0; }
    457 
    458     /** The meaning of 'value' changes for the specific type.
    459         @verbatim
    460         Document:    empty
    461         Element:    name of the element
    462         Comment:    the comment text
    463         Unknown:    the tag contents
    464         Text:        the text string
    465         @endverbatim
    466     */
    467     const char* Value() const            { return value.GetStr(); }
    468     /** Set the Value of an XML node.
    469         @sa Value()
    470     */
    471     void SetValue( const char* val, bool staticMem=false );
    472 
    473     /// Get the parent of this node on the DOM.
    474     const XMLNode*    Parent() const            { return parent; }
    475     XMLNode* Parent()                        { return parent; }
    476 
    477     /// Returns true if this node has no children.
    478     bool NoChildren() const                    { return !firstChild; }
    479 
    480     /// Get the first child node, or null if none exists.
    481     const XMLNode*  FirstChild() const        { return firstChild; }
    482     XMLNode*        FirstChild()            { return firstChild; }
    483     /** Get the first child element, or optionally the first child
    484         element with the specified name.
    485     */
    486     const XMLElement* FirstChildElement( const char* value=0 ) const;
    487     XMLElement* FirstChildElement( const char* _value=0 )    { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( _value )); }
    488 
    489     /// Get the last child node, or null if none exists.
    490     const XMLNode*    LastChild() const                        { return lastChild; }
    491     XMLNode*        LastChild()                                { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
    492 
    493     /** Get the last child element or optionally the last child
    494         element with the specified name.
    495     */
    496     const XMLElement* LastChildElement( const char* value=0 ) const;
    497     XMLElement* LastChildElement( const char* _value=0 )    { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(_value) ); }
    498 
    499     /// Get the previous (left) sibling node of this node.
    500     const XMLNode*    PreviousSibling() const                    { return prev; }
    501     XMLNode*    PreviousSibling()                            { return prev; }
    502 
    503     /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
    504     const XMLElement*    PreviousSiblingElement( const char* value=0 ) const ;
    505     XMLElement*    PreviousSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( _value ) ); }
    506 
    507     /// Get the next (right) sibling node of this node.
    508     const XMLNode*    NextSibling() const                        { return next; }
    509     XMLNode*    NextSibling()                                { return next; }
    510 
    511     /// Get the next (right) sibling element of this node, with an opitionally supplied name.
    512     const XMLElement*    NextSiblingElement( const char* value=0 ) const;
    513      XMLElement*    NextSiblingElement( const char* _value=0 )    { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( _value ) ); }
    514 
    515     /**
    516         Add a child node as the last (right) child.
    517     */
    518     XMLNode* InsertEndChild( XMLNode* addThis );
    519 
    520     XMLNode* LinkEndChild( XMLNode* addThis )    { return InsertEndChild( addThis ); }
    521     /**
    522         Add a child node as the first (left) child.
    523     */
    524     XMLNode* InsertFirstChild( XMLNode* addThis );
    525     /**
    526         Add a node after the specified child node.
    527     */
    528     XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
    529 
    530     /**
    531         Delete all the children of this node.
    532     */
    533     void DeleteChildren();
    534 
    535     /**
    536         Delete a child of this node.
    537     */
    538     void DeleteChild( XMLNode* node );
    539 
    540     /**
    541         Make a copy of this node, but not its children.
    542         You may pass in a Document pointer that will be
    543         the owner of the new Node. If the 'document' is
    544         null, then the node returned will be allocated
    545         from the current Document. (this->GetDocument())
    546 
    547         Note: if called on a XMLDocument, this will return null.
    548     */
    549     virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
    550 
    551     /**
    552         Test if 2 nodes are the same, but don't test children.
    553         The 2 nodes do not need to be in the same Document.
    554 
    555         Note: if called on a XMLDocument, this will return false.
    556     */
    557     virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
    558 
    559     /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
    560         XML tree will be conditionally visited and the host will be called back
    561         via the TiXmlVisitor interface.
    562 
    563         This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
    564         the XML for the callbacks, so the performance of TinyXML is unchanged by using this
    565         interface versus any other.)
    566 
    567         The interface has been based on ideas from:
    568 
    569         - http://www.saxproject.org/
    570         - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
    571 
    572         Which are both good references for "visiting".
    573 
    574         An example of using Accept():
    575         @verbatim
    576         TiXmlPrinter printer;
    577         tinyxmlDoc.Accept( &printer );
    578         const char* xmlcstr = printer.CStr();
    579         @endverbatim
    580     */
    581     virtual bool Accept( XMLVisitor* visitor ) const = 0;
    582 
    583     // internal
    584     virtual char* ParseDeep( char*, StrPair* );
    585 
    586 protected:
    587     XMLNode( XMLDocument* );
    588     virtual ~XMLNode();
    589     XMLNode( const XMLNode& );    // not supported
    590     XMLNode& operator=( const XMLNode& );    // not supported
    591 
    592     XMLDocument*    document;
    593     XMLNode*        parent;
    594     mutable StrPair    value;
    595 
    596     XMLNode*        firstChild;
    597     XMLNode*        lastChild;
    598 
    599     XMLNode*        prev;
    600     XMLNode*        next;
    601 
    602 private:
    603     MemPool*        memPool;
    604     void Unlink( XMLNode* child );
    605 };
    606 
    607 
    608 /** XML text.
    609 
    610     Note that a text node can have child element nodes, for example:
    611     @verbatim
    612     <root>This is <b>bold</b></root>
    613     @endverbatim
    614 
    615     A text node can have 2 ways to output the next. "normal" output
    616     and CDATA. It will default to the mode it was parsed from the XML file and
    617     you generally want to leave it alone, but you can change the output mode with
    618     SetCDATA() and query it with CDATA().
    619 */
    620 class XMLText : public XMLNode
    621 {
    622     friend class XMLBase;
    623     friend class XMLDocument;
    624 public:
    625     virtual bool Accept( XMLVisitor* visitor ) const;
    626 
    627     virtual XMLText*    ToText()            { return this; }
    628     virtual const XMLText*    ToText() const    { return this; }
    629 
    630     /// Declare whether this should be CDATA or standard text.
    631     void SetCData( bool _isCData )            { this->isCData = _isCData; }
    632     /// Returns true if this is a CDATA text element.
    633     bool CData() const                        { return isCData; }
    634 
    635     char* ParseDeep( char*, StrPair* endTag );
    636     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
    637     virtual bool ShallowEqual( const XMLNode* compare ) const;
    638 
    639 
    640 protected:
    641     XMLText( XMLDocument* doc )    : XMLNode( doc ), isCData( false )    {}
    642     virtual ~XMLText()                                                {}
    643     XMLText( const XMLText& );    // not supported
    644     XMLText& operator=( const XMLText& );    // not supported
    645 
    646 private:
    647     bool isCData;
    648 };
    649 
    650 
    651 /** An XML Comment. */
    652 class XMLComment : public XMLNode
    653 {
    654     friend class XMLDocument;
    655 public:
    656     virtual XMLComment*    ToComment()                    { return this; }
    657     virtual const XMLComment* ToComment() const        { return this; }
    658 
    659     virtual bool Accept( XMLVisitor* visitor ) const;
    660 
    661     char* ParseDeep( char*, StrPair* endTag );
    662     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
    663     virtual bool ShallowEqual( const XMLNode* compare ) const;
    664 
    665 protected:
    666     XMLComment( XMLDocument* doc );
    667     virtual ~XMLComment();
    668     XMLComment( const XMLComment& );    // not supported
    669     XMLComment& operator=( const XMLComment& );    // not supported
    670 
    671 private:
    672 };
    673 
    674 
    675 /** In correct XML the declaration is the first entry in the file.
    676     @verbatim
    677         <?xml version="1.0" standalone="yes"?>
    678     @endverbatim
    679 
    680     TinyXML2 will happily read or write files without a declaration,
    681     however.
    682 
    683     The text of the declaration isn't interpreted. It is parsed
    684     and written as a string.
    685 */
    686 class XMLDeclaration : public XMLNode
    687 {
    688     friend class XMLDocument;
    689 public:
    690     virtual XMLDeclaration*    ToDeclaration()                    { return this; }
    691     virtual const XMLDeclaration* ToDeclaration() const        { return this; }
    692 
    693     virtual bool Accept( XMLVisitor* visitor ) const;
    694 
    695     char* ParseDeep( char*, StrPair* endTag );
    696     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
    697     virtual bool ShallowEqual( const XMLNode* compare ) const;
    698 
    699 protected:
    700     XMLDeclaration( XMLDocument* doc );
    701     virtual ~XMLDeclaration();
    702     XMLDeclaration( const XMLDeclaration& );    // not supported
    703     XMLDeclaration& operator=( const XMLDeclaration& );    // not supported
    704 };
    705 
    706 
    707 /** Any tag that tinyXml doesn't recognize is saved as an
    708     unknown. It is a tag of text, but should not be modified.
    709     It will be written back to the XML, unchanged, when the file
    710     is saved.
    711 
    712     DTD tags get thrown into TiXmlUnknowns.
    713 */
    714 class XMLUnknown : public XMLNode
    715 {
    716     friend class XMLDocument;
    717 public:
    718     virtual XMLUnknown*    ToUnknown()                    { return this; }
    719     virtual const XMLUnknown* ToUnknown() const        { return this; }
    720 
    721     virtual bool Accept( XMLVisitor* visitor ) const;
    722 
    723     char* ParseDeep( char*, StrPair* endTag );
    724     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
    725     virtual bool ShallowEqual( const XMLNode* compare ) const;
    726 
    727 protected:
    728     XMLUnknown( XMLDocument* doc );
    729     virtual ~XMLUnknown();
    730     XMLUnknown( const XMLUnknown& );    // not supported
    731     XMLUnknown& operator=( const XMLUnknown& );    // not supported
    732 };
    733 
    734 
    735 enum {
    736     XML_NO_ERROR = 0,
    737     XML_SUCCESS = 0,
    738 
    739     XML_NO_ATTRIBUTE,
    740     XML_WRONG_ATTRIBUTE_TYPE,
    741 
    742     XML_ERROR_FILE_NOT_FOUND,
    743     XML_ERROR_FILE_COULD_NOT_BE_OPENED,
    744     XML_ERROR_FILE_READ_ERROR,
    745     XML_ERROR_ELEMENT_MISMATCH,
    746     XML_ERROR_PARSING_ELEMENT,
    747     XML_ERROR_PARSING_ATTRIBUTE,
    748     XML_ERROR_IDENTIFYING_TAG,
    749     XML_ERROR_PARSING_TEXT,
    750     XML_ERROR_PARSING_CDATA,
    751     XML_ERROR_PARSING_COMMENT,
    752     XML_ERROR_PARSING_DECLARATION,
    753     XML_ERROR_PARSING_UNKNOWN,
    754     XML_ERROR_EMPTY_DOCUMENT,
    755     XML_ERROR_MISMATCHED_ELEMENT,
    756     XML_ERROR_PARSING,
    757 
    758     XML_CAN_NOT_CONVERT_TEXT,
    759     XML_NO_TEXT_NODE
    760 };
    761 
    762 
    763 /** An attribute is a name-value pair. Elements have an arbitrary
    764     number of attributes, each with a unique name.
    765 
    766     @note The attributes are not XMLNodes. You may only query the
    767     Next() attribute in a list.
    768 */
    769 class XMLAttribute
    770 {
    771     friend class XMLElement;
    772 public:
    773     const char* Name() const { return name.GetStr(); }            ///< The name of the attribute.
    774     const char* Value() const { return value.GetStr(); }        ///< The value of the attribute.
    775     const XMLAttribute* Next() const { return next; }            ///< The next attribute in the list.
    776 
    777     /** IntAttribute interprets the attribute as an integer, and returns the value.
    778         If the value isn't an integer, 0 will be returned. There is no error checking;
    779         use QueryIntAttribute() if you need error checking.
    780     */
    781     int         IntValue() const                { int i=0;        QueryIntValue( &i );        return i; }
    782     /// Query as an unsigned integer. See IntAttribute()
    783     unsigned UnsignedValue() const            { unsigned i=0; QueryUnsignedValue( &i );    return i; }
    784     /// Query as a boolean. See IntAttribute()
    785     bool     BoolValue() const                { bool b=false; QueryBoolValue( &b );        return b; }
    786     /// Query as a double. See IntAttribute()
    787     double      DoubleValue() const            { double d=0;    QueryDoubleValue( &d );        return d; }
    788     /// Query as a float. See IntAttribute()
    789     float     FloatValue() const                { float f=0;    QueryFloatValue( &f );        return f; }
    790 
    791     /** QueryIntAttribute interprets the attribute as an integer, and returns the value
    792         in the provided paremeter. The function will return XML_NO_ERROR on success,
    793         and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
    794     */
    795     int QueryIntValue( int* value ) const;
    796     /// See QueryIntAttribute
    797     int QueryUnsignedValue( unsigned int* value ) const;
    798     /// See QueryIntAttribute
    799     int QueryBoolValue( bool* value ) const;
    800     /// See QueryIntAttribute
    801     int QueryDoubleValue( double* value ) const;
    802     /// See QueryIntAttribute
    803     int QueryFloatValue( float* value ) const;
    804 
    805     /// Set the attribute to a string value.
    806     void SetAttribute( const char* value );
    807     /// Set the attribute to value.
    808     void SetAttribute( int value );
    809     /// Set the attribute to value.
    810     void SetAttribute( unsigned value );
    811     /// Set the attribute to value.
    812     void SetAttribute( bool value );
    813     /// Set the attribute to value.
    814     void SetAttribute( double value );
    815     /// Set the attribute to value.
    816     void SetAttribute( float value );
    817 
    818 private:
    819     enum { BUF_SIZE = 200 };
    820 
    821     XMLAttribute() : next( 0 ) {}
    822     virtual ~XMLAttribute()    {}
    823     XMLAttribute( const XMLAttribute& );    // not supported
    824     void operator=( const XMLAttribute& );    // not supported
    825     void SetName( const char* name );
    826 
    827     char* ParseDeep( char* p, bool processEntities );
    828 
    829     mutable StrPair name;
    830     mutable StrPair value;
    831     XMLAttribute* next;
    832     MemPool* memPool;
    833 };
    834 
    835 
    836 /** The element is a container class. It has a value, the element name,
    837     and can contain other elements, text, comments, and unknowns.
    838     Elements also contain an arbitrary number of attributes.
    839 */
    840 class XMLElement : public XMLNode
    841 {
    842     friend class XMLBase;
    843     friend class XMLDocument;
    844 public:
    845     /// Get the name of an element (which is the Value() of the node.)
    846     const char* Name() const        { return Value(); }
    847     /// Set the name of the element.
    848     void SetName( const char* str, bool staticMem=false )    { SetValue( str, staticMem ); }
    849 
    850     virtual XMLElement* ToElement()                { return this; }
    851     virtual const XMLElement* ToElement() const { return this; }
    852     virtual bool Accept( XMLVisitor* visitor ) const;
    853 
    854     /** Given an attribute name, Attribute() returns the value
    855         for the attribute of that name, or null if none
    856         exists. For example:
    857 
    858         @verbatim
    859         const char* value = ele->Attribute( "foo" );
    860         @endverbatim
    861 
    862         The 'value' parameter is normally null. However, if specified,
    863         the attribute will only be returned if the 'name' and 'value'
    864         match. This allow you to write code:
    865 
    866         @verbatim
    867         if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
    868         @endverbatim
    869 
    870         rather than:
    871         @verbatim
    872         if ( ele->Attribute( "foo" ) ) {
    873             if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
    874         }
    875         @endverbatim
    876     */
    877     const char* Attribute( const char* name, const char* value=0 ) const;
    878 
    879     /** Given an attribute name, IntAttribute() returns the value
    880         of the attribute interpreted as an integer. 0 will be
    881         returned if there is an error. For a method with error
    882         checking, see QueryIntAttribute()
    883     */
    884     int         IntAttribute( const char* name ) const        { int i=0;        QueryIntAttribute( name, &i );        return i; }
    885     /// See IntAttribute()
    886     unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; }
    887     /// See IntAttribute()
    888     bool     BoolAttribute( const char* name ) const    { bool b=false; QueryBoolAttribute( name, &b );        return b; }
    889     /// See IntAttribute()
    890     double      DoubleAttribute( const char* name ) const    { double d=0;    QueryDoubleAttribute( name, &d );    return d; }
    891     /// See IntAttribute()
    892     float     FloatAttribute( const char* name ) const    { float f=0;    QueryFloatAttribute( name, &f );    return f; }
    893 
    894     /** Given an attribute name, QueryIntAttribute() returns
    895         XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
    896         can't be performed, or XML_NO_ATTRIBUTE if the attribute
    897         doesn't exist. If successful, the result of the conversion
    898         will be written to 'value'. If not successful, nothing will
    899         be written to 'value'. This allows you to provide default
    900         value:
    901 
    902         @verbatim
    903         int value = 10;
    904         QueryIntAttribute( "foo", &value );        // if "foo" isn't found, value will still be 10
    905         @endverbatim
    906     */
    907     int QueryIntAttribute( const char* name, int* _value ) const                { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryIntValue( _value ); }
    908     /// See QueryIntAttribute()
    909     int QueryUnsignedAttribute( const char* name, unsigned int* _value ) const    { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryUnsignedValue( _value ); }
    910     /// See QueryIntAttribute()
    911     int QueryBoolAttribute( const char* name, bool* _value ) const                { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryBoolValue( _value ); }
    912     /// See QueryIntAttribute()
    913     int QueryDoubleAttribute( const char* name, double* _value ) const            { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryDoubleValue( _value ); }
    914     /// See QueryIntAttribute()
    915     int QueryFloatAttribute( const char* name, float* _value ) const            { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryFloatValue( _value ); }
    916 
    917     /// Sets the named attribute to value.
    918     void SetAttribute( const char* name, const char* _value )    { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
    919     /// Sets the named attribute to value.
    920     void SetAttribute( const char* name, int _value )            { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
    921     /// Sets the named attribute to value.
    922     void SetAttribute( const char* name, unsigned _value )        { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
    923     /// Sets the named attribute to value.
    924     void SetAttribute( const char* name, bool _value )            { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
    925     /// Sets the named attribute to value.
    926     void SetAttribute( const char* name, double _value )        { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
    927 
    928     /**
    929         Delete an attribute.
    930     */
    931     void DeleteAttribute( const char* name );
    932 
    933     /// Return the first attribute in the list.
    934     const XMLAttribute* FirstAttribute() const { return rootAttribute; }
    935     /// Query a specific attribute in the list.
    936     const XMLAttribute* FindAttribute( const char* name ) const;
    937 
    938     /** Convenience function for easy access to the text inside an element. Although easy
    939         and concise, GetText() is limited compared to getting the TiXmlText child
    940         and accessing it directly.
    941 
    942         If the first child of 'this' is a TiXmlText, the GetText()
    943         returns the character string of the Text node, else null is returned.
    944 
    945         This is a convenient method for getting the text of simple contained text:
    946         @verbatim
    947         <foo>This is text</foo>
    948             const char* str = fooElement->GetText();
    949         @endverbatim
    950 
    951         'str' will be a pointer to "This is text".
    952 
    953         Note that this function can be misleading. If the element foo was created from
    954         this XML:
    955         @verbatim
    956             <foo><b>This is text</b></foo>
    957         @endverbatim
    958 
    959         then the value of str would be null. The first child node isn't a text node, it is
    960         another element. From this XML:
    961         @verbatim
    962             <foo>This is <b>text</b></foo>
    963         @endverbatim
    964         GetText() will return "This is ".
    965     */
    966     const char* GetText() const;
    967 
    968     /**
    969         Convenience method to query the value of a child text node. This is probably best
    970         shown by example. Given you have a document is this form:
    971         @verbatim
    972             <point>
    973                 <x>1</x>
    974                 <y>1.4</y>
    975             </point>
    976         @endverbatim
    977 
    978         The QueryIntText() and similar functions provide a safe and easier way to get to the
    979         "value" of x and y.
    980 
    981         @verbatim
    982             int x = 0;
    983             float y = 0;    // types of x and y are contrived for example
    984             const XMLElement* xElement = pointElement->FirstChildElement( "x" );
    985             const XMLElement* yElement = pointElement->FirstChildElement( "y" );
    986             xElement->QueryIntText( &x );
    987             yElement->QueryFloatText( &y );
    988         @endverbatim
    989 
    990         @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
    991                  to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
    992 
    993     */
    994     int QueryIntText( int* _value ) const;
    995     /// See QueryIntText()
    996     int QueryUnsignedText( unsigned* _value ) const;
    997     /// See QueryIntText()
    998     int QueryBoolText( bool* _value ) const;
    999     /// See QueryIntText()
   1000     int QueryDoubleText( double* _value ) const;
   1001     /// See QueryIntText()
   1002     int QueryFloatText( float* _value ) const;
   1003 
   1004     // internal:
   1005     enum {
   1006         OPEN,        // <foo>
   1007         CLOSED,        // <foo/>
   1008         CLOSING        // </foo>
   1009     };
   1010     int ClosingType() const { return closingType; }
   1011     char* ParseDeep( char* p, StrPair* endTag );
   1012     virtual XMLNode* ShallowClone( XMLDocument* document ) const;
   1013     virtual bool ShallowEqual( const XMLNode* compare ) const;
   1014 
   1015 private:
   1016     XMLElement( XMLDocument* doc );
   1017     virtual ~XMLElement();
   1018     XMLElement( const XMLElement& );    // not supported
   1019     void operator=( const XMLElement& );    // not supported
   1020 
   1021     XMLAttribute* FindAttribute( const char* name );
   1022     XMLAttribute* FindOrCreateAttribute( const char* name );
   1023     //void LinkAttribute( XMLAttribute* attrib );
   1024     char* ParseAttributes( char* p );
   1025 
   1026     int closingType;
   1027     // The attribute list is ordered; there is no 'lastAttribute'
   1028     // because the list needs to be scanned for dupes before adding
   1029     // a new attribute.
   1030     XMLAttribute* rootAttribute;
   1031 };
   1032 
   1033 
   1034 /** A Document binds together all the functionality.
   1035     It can be saved, loaded, and printed to the screen.
   1036     All Nodes are connected and allocated to a Document.
   1037     If the Document is deleted, all its Nodes are also deleted.
   1038 */
   1039 class XMLDocument : public XMLNode
   1040 {
   1041     friend class XMLElement;
   1042 public:
   1043     /// constructor
   1044     XMLDocument( bool processEntities = true );
   1045     ~XMLDocument();
   1046 
   1047     virtual XMLDocument* ToDocument()                { return this; }
   1048     virtual const XMLDocument* ToDocument() const    { return this; }
   1049 
   1050     /**
   1051         Parse an XML file from a character string.
   1052         Returns XML_NO_ERROR (0) on success, or
   1053         an errorID.
   1054     */
   1055     int Parse( const char* xml );
   1056 
   1057     /**
   1058         Load an XML file from disk.
   1059         Returns XML_NO_ERROR (0) on success, or
   1060         an errorID.
   1061     */
   1062     int LoadFile( const char* filename );
   1063 
   1064     /**
   1065         Load an XML file from disk. You are responsible
   1066         for providing and closing the FILE*.
   1067 
   1068         Returns XML_NO_ERROR (0) on success, or
   1069         an errorID.
   1070     */
   1071     int LoadFile( FILE* );
   1072 
   1073     /**
   1074         Save the XML file to disk.
   1075         Returns XML_NO_ERROR (0) on success, or
   1076         an errorID.
   1077     */
   1078     int SaveFile( const char* filename );
   1079 
   1080     /**
   1081         Save the XML file to disk. You are responsible
   1082         for providing and closing the FILE*.
   1083 
   1084         Returns XML_NO_ERROR (0) on success, or
   1085         an errorID.
   1086     */
   1087     int SaveFile( FILE* );
   1088 
   1089     bool ProcessEntities() const                        { return processEntities; }
   1090 
   1091     /**
   1092         Returns true if this document has a leading Byte Order Mark of UTF8.
   1093     */
   1094     bool HasBOM() const { return writeBOM; }
   1095     /** Sets whether to write the BOM when writing the file.
   1096     */
   1097     void SetBOM( bool useBOM ) { writeBOM = useBOM; }
   1098 
   1099     /** Return the root element of DOM. Equivalent to FirstChildElement().
   1100         To get the first node, use FirstChild().
   1101     */
   1102     XMLElement* RootElement()                { return FirstChildElement(); }
   1103     const XMLElement* RootElement() const    { return FirstChildElement(); }
   1104 
   1105     /** Print the Document. If the Printer is not provided, it will
   1106         print to stdout. If you provide Printer, this can print to a file:
   1107         @verbatim
   1108         XMLPrinter printer( fp );
   1109         doc.Print( &printer );
   1110         @endverbatim
   1111 
   1112         Or you can use a printer to print to memory:
   1113         @verbatim
   1114         XMLPrinter printer;
   1115         doc->Print( &printer );
   1116         // printer.CStr() has a const char* to the XML
   1117         @endverbatim
   1118     */
   1119     void Print( XMLPrinter* streamer=0 );
   1120     virtual bool Accept( XMLVisitor* visitor ) const;
   1121 
   1122     /**
   1123         Create a new Element associated with
   1124         this Document. The memory for the Element
   1125         is managed by the Document.
   1126     */
   1127     XMLElement* NewElement( const char* name );
   1128     /**
   1129         Create a new Comment associated with
   1130         this Document. The memory for the Comment
   1131         is managed by the Document.
   1132     */
   1133     XMLComment* NewComment( const char* comment );
   1134     /**
   1135         Create a new Text associated with
   1136         this Document. The memory for the Text
   1137         is managed by the Document.
   1138     */
   1139     XMLText* NewText( const char* text );
   1140     /**
   1141         Create a new Declaration associated with
   1142         this Document. The memory for the object
   1143         is managed by the Document.
   1144 
   1145         If the 'text' param is null, the standard
   1146         declaration is used.:
   1147         @verbatim
   1148             <?xml version="1.0" encoding="UTF-8"?>
   1149         @endverbatim
   1150     */
   1151     XMLDeclaration* NewDeclaration( const char* text=0 );
   1152     /**
   1153         Create a new Unknown associated with
   1154         this Document. The memory for the object
   1155         is managed by the Document.
   1156     */
   1157     XMLUnknown* NewUnknown( const char* text );
   1158 
   1159     /**
   1160         Delete a node associated with this document.
   1161         It will be unlinked from the DOM.
   1162     */
   1163     void DeleteNode( XMLNode* node )    { node->parent->DeleteChild( node ); }
   1164 
   1165     void SetError( int error, const char* str1, const char* str2 );
   1166 
   1167     /// Return true if there was an error parsing the document.
   1168     bool Error() const { return errorID != XML_NO_ERROR; }
   1169     /// Return the errorID.
   1170     int  ErrorID() const { return errorID; }
   1171     /// Return a possibly helpful diagnostic location or string.
   1172     const char* GetErrorStr1() const { return errorStr1; }
   1173     /// Return a possibly helpful secondary diagnostic location or string.
   1174     const char* GetErrorStr2() const { return errorStr2; }
   1175     /// If there is an error, print it to stdout.
   1176     void PrintError() const;
   1177 
   1178     // internal
   1179     char* Identify( char* p, XMLNode** node );
   1180 
   1181     virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const    { return 0; }
   1182     virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const    { return false; }
   1183 
   1184 private:
   1185     XMLDocument( const XMLDocument& );    // not supported
   1186     void operator=( const XMLDocument& );    // not supported
   1187     void InitDocument();
   1188 
   1189     bool writeBOM;
   1190     bool processEntities;
   1191     int errorID;
   1192     const char* errorStr1;
   1193     const char* errorStr2;
   1194     char* charBuffer;
   1195 
   1196     MemPoolT< sizeof(XMLElement) >    elementPool;
   1197     MemPoolT< sizeof(XMLAttribute) > attributePool;
   1198     MemPoolT< sizeof(XMLText) >        textPool;
   1199     MemPoolT< sizeof(XMLComment) >    commentPool;
   1200 };
   1201 
   1202 
   1203 /**
   1204     A XMLHandle is a class that wraps a node pointer with null checks; this is
   1205     an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
   1206     DOM structure. It is a separate utility class.
   1207 
   1208     Take an example:
   1209     @verbatim
   1210     <Document>
   1211         <Element attributeA = "valueA">
   1212             <Child attributeB = "value1" />
   1213             <Child attributeB = "value2" />
   1214         </Element>
   1215     </Document>
   1216     @endverbatim
   1217 
   1218     Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
   1219     easy to write a *lot* of code that looks like:
   1220 
   1221     @verbatim
   1222     XMLElement* root = document.FirstChildElement( "Document" );
   1223     if ( root )
   1224     {
   1225         XMLElement* element = root->FirstChildElement( "Element" );
   1226         if ( element )
   1227         {
   1228             XMLElement* child = element->FirstChildElement( "Child" );
   1229             if ( child )
   1230             {
   1231                 XMLElement* child2 = child->NextSiblingElement( "Child" );
   1232                 if ( child2 )
   1233                 {
   1234                     // Finally do something useful.
   1235     @endverbatim
   1236 
   1237     And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
   1238     of such code. A XMLHandle checks for null pointers so it is perfectly safe
   1239     and correct to use:
   1240 
   1241     @verbatim
   1242     XMLHandle docHandle( &document );
   1243     XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
   1244     if ( child2 )
   1245     {
   1246         // do something useful
   1247     @endverbatim
   1248 
   1249     Which is MUCH more concise and useful.
   1250 
   1251     It is also safe to copy handles - internally they are nothing more than node pointers.
   1252     @verbatim
   1253     XMLHandle handleCopy = handle;
   1254     @endverbatim
   1255 
   1256     See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
   1257 */
   1258 class XMLHandle
   1259 {
   1260 public:
   1261     /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
   1262     XMLHandle( XMLNode* _node )                                                { node = _node; }
   1263     /// Create a handle from a node.
   1264     XMLHandle( XMLNode& _node )                                                { node = &_node; }
   1265     /// Copy constructor
   1266     XMLHandle( const XMLHandle& ref )                                        { node = ref.node; }
   1267     /// Assignment
   1268     XMLHandle& operator=( const XMLHandle& ref )                            { node = ref.node; return *this; }
   1269 
   1270     /// Get the first child of this handle.
   1271     XMLHandle FirstChild()                                                     { return XMLHandle( node ? node->FirstChild() : 0 ); }
   1272     /// Get the first child element of this handle.
   1273     XMLHandle FirstChildElement( const char* value=0 )                        { return XMLHandle( node ? node->FirstChildElement( value ) : 0 ); }
   1274     /// Get the last child of this handle.
   1275     XMLHandle LastChild()                                                    { return XMLHandle( node ? node->LastChild() : 0 ); }
   1276     /// Get the last child element of this handle.
   1277     XMLHandle LastChildElement( const char* _value=0 )                        { return XMLHandle( node ? node->LastChildElement( _value ) : 0 ); }
   1278     /// Get the previous sibling of this handle.
   1279     XMLHandle PreviousSibling()                                                { return XMLHandle( node ? node->PreviousSibling() : 0 ); }
   1280     /// Get the previous sibling element of this handle.
   1281     XMLHandle PreviousSiblingElement( const char* _value=0 )                { return XMLHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
   1282     /// Get the next sibling of this handle.
   1283     XMLHandle NextSibling()                                                    { return XMLHandle( node ? node->NextSibling() : 0 ); }
   1284     /// Get the next sibling element of this handle.
   1285     XMLHandle NextSiblingElement( const char* _value=0 )                    { return XMLHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
   1286 
   1287     /// Safe cast to XMLNode. This can return null.
   1288     XMLNode* ToNode()                            { return node; }
   1289     /// Safe cast to XMLElement. This can return null.
   1290     XMLElement* ToElement()                     { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
   1291     /// Safe cast to XMLText. This can return null.
   1292     XMLText* ToText()                             { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
   1293     /// Safe cast to XMLUnknown. This can return null.
   1294     XMLUnknown* ToUnknown()                     { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
   1295     /// Safe cast to XMLDeclaration. This can return null.
   1296     XMLDeclaration* ToDeclaration()             { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
   1297 
   1298 private:
   1299     XMLNode* node;
   1300 };
   1301 
   1302 
   1303 /**
   1304     A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
   1305     same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
   1306 */
   1307 class XMLConstHandle
   1308 {
   1309 public:
   1310     XMLConstHandle( const XMLNode* _node )                                            { node = _node; }
   1311     XMLConstHandle( const XMLNode& _node )                                            { node = &_node; }
   1312     XMLConstHandle( const XMLConstHandle& ref )                                        { node = ref.node; }
   1313 
   1314     XMLConstHandle& operator=( const XMLConstHandle& ref )                            { node = ref.node; return *this; }
   1315 
   1316     const XMLConstHandle FirstChild() const                                            { return XMLConstHandle( node ? node->FirstChild() : 0 ); }
   1317     const XMLConstHandle FirstChildElement( const char* value=0 ) const                { return XMLConstHandle( node ? node->FirstChildElement( value ) : 0 ); }
   1318     const XMLConstHandle LastChild()    const                                        { return XMLConstHandle( node ? node->LastChild() : 0 ); }
   1319     const XMLConstHandle LastChildElement( const char* _value=0 ) const                { return XMLConstHandle( node ? node->LastChildElement( _value ) : 0 ); }
   1320     const XMLConstHandle PreviousSibling() const                                    { return XMLConstHandle( node ? node->PreviousSibling() : 0 ); }
   1321     const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const        { return XMLConstHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
   1322     const XMLConstHandle NextSibling() const                                        { return XMLConstHandle( node ? node->NextSibling() : 0 ); }
   1323     const XMLConstHandle NextSiblingElement( const char* _value=0 ) const            { return XMLConstHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
   1324 
   1325 
   1326     const XMLNode* ToNode() const                { return node; }
   1327     const XMLElement* ToElement() const            { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
   1328     const XMLText* ToText() const                { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
   1329     const XMLUnknown* ToUnknown() const            { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
   1330     const XMLDeclaration* ToDeclaration() const    { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
   1331 
   1332 private:
   1333     const XMLNode* node;
   1334 };
   1335 
   1336 
   1337 /**
   1338     Printing functionality. The XMLPrinter gives you more
   1339     options than the XMLDocument::Print() method.
   1340 
   1341     It can:
   1342     -# Print to memory.
   1343     -# Print to a file you provide.
   1344     -# Print XML without a XMLDocument.
   1345 
   1346     Print to Memory
   1347 
   1348     @verbatim
   1349     XMLPrinter printer;
   1350     doc->Print( &printer );
   1351     SomeFunction( printer.CStr() );
   1352     @endverbatim
   1353 
   1354     Print to a File
   1355 
   1356     You provide the file pointer.
   1357     @verbatim
   1358     XMLPrinter printer( fp );
   1359     doc.Print( &printer );
   1360     @endverbatim
   1361 
   1362     Print without a XMLDocument
   1363 
   1364     When loading, an XML parser is very useful. However, sometimes
   1365     when saving, it just gets in the way. The code is often set up
   1366     for streaming, and constructing the DOM is just overhead.
   1367 
   1368     The Printer supports the streaming case. The following code
   1369     prints out a trivially simple XML file without ever creating
   1370     an XML document.
   1371 
   1372     @verbatim
   1373     XMLPrinter printer( fp );
   1374     printer.OpenElement( "foo" );
   1375     printer.PushAttribute( "foo", "bar" );
   1376     printer.CloseElement();
   1377     @endverbatim
   1378 */
   1379 class XMLPrinter : public XMLVisitor
   1380 {
   1381 public:
   1382     /** Construct the printer. If the FILE* is specified,
   1383         this will print to the FILE. Else it will print
   1384         to memory, and the result is available in CStr().
   1385         If 'compact' is set to true, then output is created
   1386         with only required whitespace and newlines.
   1387     */
   1388     XMLPrinter( FILE* file=0, bool compact = false );
   1389     ~XMLPrinter()    {}
   1390 
   1391     /** If streaming, write the BOM and declaration. */
   1392     void PushHeader( bool writeBOM, bool writeDeclaration );
   1393     /** If streaming, start writing an element.
   1394         The element must be closed with CloseElement()
   1395     */
   1396     void OpenElement( const char* name );
   1397     /// If streaming, add an attribute to an open element.
   1398     void PushAttribute( const char* name, const char* value );
   1399     void PushAttribute( const char* name, int value );
   1400     void PushAttribute( const char* name, unsigned value );
   1401     void PushAttribute( const char* name, bool value );
   1402     void PushAttribute( const char* name, double value );
   1403     /// If streaming, close the Element.
   1404     void CloseElement();
   1405 
   1406     /// Add a text node.
   1407     void PushText( const char* text, bool cdata=false );
   1408     /// Add a text node from an integer.
   1409     void PushText( int value );
   1410     /// Add a text node from an unsigned.
   1411     void PushText( unsigned value );
   1412     /// Add a text node from a bool.
   1413     void PushText( bool value );
   1414     /// Add a text node from a float.
   1415     void PushText( float value );
   1416     /// Add a text node from a double.
   1417     void PushText( double value );
   1418 
   1419     /// Add a comment
   1420     void PushComment( const char* comment );
   1421 
   1422     void PushDeclaration( const char* value );
   1423     void PushUnknown( const char* value );
   1424 
   1425     virtual bool VisitEnter( const XMLDocument& /*doc*/ );
   1426     virtual bool VisitExit( const XMLDocument& /*doc*/ )            { return true; }
   1427 
   1428     virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
   1429     virtual bool VisitExit( const XMLElement& element );
   1430 
   1431     virtual bool Visit( const XMLText& text );
   1432     virtual bool Visit( const XMLComment& comment );
   1433     virtual bool Visit( const XMLDeclaration& declaration );
   1434     virtual bool Visit( const XMLUnknown& unknown );
   1435 
   1436     /**
   1437         If in print to memory mode, return a pointer to
   1438         the XML file in memory.
   1439     */
   1440     const char* CStr() const { return buffer.Mem(); }
   1441     /**
   1442            If in print to memory mode, return the size
   1443         of the XML file in memory. (Note the size returned
   1444         includes the terminating null.)
   1445       */
   1446       int CStrSize() const { return buffer.Size(); }
   1447 
   1448 private:
   1449     void SealElement();
   1450     void PrintSpace( int depth );
   1451     void PrintString( const char*, bool restrictedEntitySet );    // prints out, after detecting entities.
   1452     void Print( const char* format, ... );
   1453 
   1454     bool elementJustOpened;
   1455     bool firstElement;
   1456     FILE* fp;
   1457     int depth;
   1458     int textDepth;
   1459     bool processEntities;
   1460     bool compactMode;
   1461 
   1462     enum {
   1463         ENTITY_RANGE = 64,
   1464         BUF_SIZE = 200
   1465     };
   1466     bool entityFlag[ENTITY_RANGE];
   1467     bool restrictedEntityFlag[ENTITY_RANGE];
   1468 
   1469     DynArray< const char*, 10 > stack;
   1470     DynArray< char, 20 > buffer;
   1471 #ifdef _MSC_VER
   1472     DynArray< char, 20 > accumulator;
   1473 #endif
   1474 };
   1475 
   1476 
   1477 }    // tinyxml2
   1478 
   1479 
   1480 #endif // TINYXML2_INCLUDED
   1481