1/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
172. Altered source versions must be plainly marked as such, and
18must not be misrepresented as being the original software.
19
203. This notice may not be removed or altered from any source
21distribution.
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
86static const int TIXML2_MAJOR_VERSION = 1;
87static const int TIXML2_MINOR_VERSION = 0;
88static const int TIXML2_PATCH_VERSION = 6;
89
90namespace tinyxml2
91{
92class XMLDocument;
93class XMLElement;
94class XMLAttribute;
95class XMLComment;
96class XMLNode;
97class XMLText;
98class XMLDeclaration;
99class XMLUnknown;
100
101class 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*/
109class StrPair
110{
111public:
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
141private:
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*/
161template <class T, int INIT>
162class DynArray
163{
164public:
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
208private:
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*/
231class MemPool
232{
233public:
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*/
246template< int SIZE >
247class MemPoolT : public MemPool
248{
249public:
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
294private:
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*/
332class XMLVisitor
333{
334public:
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*/
361class XMLUtil
362{
363public:
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*/
433class XMLNode
434{
435    friend class XMLDocument;
436    friend class XMLElement;
437public:
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
586protected:
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
602private:
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*/
620class XMLText : public XMLNode
621{
622    friend class XMLBase;
623    friend class XMLDocument;
624public:
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
640protected:
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
646private:
647    bool isCData;
648};
649
650
651/** An XML Comment. */
652class XMLComment : public XMLNode
653{
654    friend class XMLDocument;
655public:
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
665protected:
666    XMLComment( XMLDocument* doc );
667    virtual ~XMLComment();
668    XMLComment( const XMLComment& );    // not supported
669    XMLComment& operator=( const XMLComment& );    // not supported
670
671private:
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*/
686class XMLDeclaration : public XMLNode
687{
688    friend class XMLDocument;
689public:
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
699protected:
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*/
714class XMLUnknown : public XMLNode
715{
716    friend class XMLDocument;
717public:
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
727protected:
728    XMLUnknown( XMLDocument* doc );
729    virtual ~XMLUnknown();
730    XMLUnknown( const XMLUnknown& );    // not supported
731    XMLUnknown& operator=( const XMLUnknown& );    // not supported
732};
733
734
735enum {
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*/
769class XMLAttribute
770{
771    friend class XMLElement;
772public:
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
818private:
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*/
840class XMLElement : public XMLNode
841{
842    friend class XMLBase;
843    friend class XMLDocument;
844public:
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
1015private:
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*/
1039class XMLDocument : public XMLNode
1040{
1041    friend class XMLElement;
1042public:
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
1184private:
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*/
1258class XMLHandle
1259{
1260public:
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
1298private:
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*/
1307class XMLConstHandle
1308{
1309public:
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
1332private:
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*/
1379class XMLPrinter : public XMLVisitor
1380{
1381public:
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
1448private:
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