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