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#include "tinyxml2.h"
24c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
25c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#include <cstdio>
26c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#include <cstdlib>
27c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#include <new>
28c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#include <cstddef>
29c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
30c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#include <fcntl.h>
31c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieusing namespace tinyxml2;
32c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
33c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiestatic const char LINE_FEED                = (char)0x0a;            // all line endings are normalized to LF
34c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiestatic const char LF = LINE_FEED;
35c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiestatic const char CARRIAGE_RETURN        = (char)0x0d;            // CR gets filtered out
36c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiestatic const char CR = CARRIAGE_RETURN;
37c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiestatic const char SINGLE_QUOTE            = '\'';
38c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiestatic const char DOUBLE_QUOTE            = '\"';
39c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
40c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie// Bunch of unicode info at:
41c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie//        http://www.unicode.org/faq/utf_bom.html
42c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie//    ef bb bf (Microsoft "lead bytes") - designates UTF-8
43c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
44c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiestatic const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
45c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiestatic const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
46c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiestatic const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
47c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
48c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
49c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#define DELETE_NODE( node )    {            \
50c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( node ) {                        \
51c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        MemPool* pool = node->memPool;    \
52c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        node->~XMLNode();                \
53c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        pool->Free( node );                \
54c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }                                    \
55c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
56c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#define DELETE_ATTRIBUTE( attrib ) {        \
57c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( attrib ) {                            \
58c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        MemPool* pool = attrib->memPool;    \
59c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        attrib->~XMLAttribute();            \
60c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        pool->Free( attrib );                \
61c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }                                        \
62c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
63c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
64c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiestruct Entity {
65c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const char* pattern;
66c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    int length;
67c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char value;
68c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie};
69c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
70c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiestatic const int NUM_ENTITIES = 5;
71c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiestatic const Entity entities[NUM_ENTITIES] =
72c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
73c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    { "quot", 4,    DOUBLE_QUOTE },
74c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    { "amp", 3,        '&'  },
75c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    { "apos", 4,    SINGLE_QUOTE },
76c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    { "lt",    2,         '<'     },
77c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    { "gt",    2,        '>'     }
78c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie};
79c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
80c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
81c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieStrPair::~StrPair()
82c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
83c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    Reset();
84c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
85c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
86c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
87c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid StrPair::Reset()
88c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
89c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( flags & NEEDS_DELETE ) {
90c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        delete [] start;
91c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
92c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    flags = 0;
93c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    start = 0;
94c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    end = 0;
95c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
96c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
97c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
98c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid StrPair::SetStr( const char* str, int flags )
99c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
100c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    Reset();
101c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    size_t len = strlen( str );
102c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    start = new char[ len+1 ];
103c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    memcpy( start, str, len+1 );
104c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    end = start + len;
105c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    this->flags = flags | NEEDS_DELETE;
106c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
107c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
108c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
109c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiechar* StrPair::ParseText( char* p, const char* endTag, int strFlags )
110c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
111c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXMLASSERT( endTag && *endTag );
112c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
113c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char* start = p;    // fixme: hides a member
114c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char  endChar = *endTag;
115c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    size_t length = strlen( endTag );
116c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
117c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // Inner loop of text parsing.
118c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    while ( *p ) {
119c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
120c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            Set( start, p, strFlags );
121c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return p + length;
122c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
123c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        ++p;
124c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
125c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return 0;
126c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
127c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
128c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
129c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiechar* StrPair::ParseName( char* p )
130c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
131c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char* start = p;
132c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
133c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !start || !(*start) ) {
134c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return 0;
135c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
136c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
137c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !XMLUtil::IsAlpha( *p ) ) {
138c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return 0;
139c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
140c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
141c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    while( *p && (
142c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie               XMLUtil::IsAlphaNum( (unsigned char) *p )
143c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            || *p == '_'
144c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            || *p == '-'
145c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            || *p == '.'
146c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            || *p == ':' ))
147c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    {
148c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        ++p;
149c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
150c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
151c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( p > start ) {
152c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        Set( start, p, 0 );
153c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return p;
154c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
155c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return 0;
156c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
157c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
158c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
159c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
160c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieconst char* StrPair::GetStr()
161c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
162c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( flags & NEEDS_FLUSH ) {
163c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        *end = 0;
164c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        flags ^= NEEDS_FLUSH;
165c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
166c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( flags ) {
167c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            char* p = start;    // the read pointer
168c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            char* q = start;    // the write pointer
169c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
170c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            while( p < end ) {
171c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                if ( (flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) {
172c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    // CR-LF pair becomes LF
173c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    // CR alone becomes LF
174c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    // LF-CR becomes LF
175c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    if ( *(p+1) == LF ) {
176c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        p += 2;
177c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    }
178c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    else {
179c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        ++p;
180c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    }
181c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    *q++ = LF;
182c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                }
183c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                else if ( (flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {
184c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    if ( *(p+1) == CR ) {
185c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        p += 2;
186c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    }
187c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    else {
188c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        ++p;
189c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    }
190c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    *q++ = LF;
191c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                }
192c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                else if ( (flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {
193c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    // Entities handled by tinyXML2:
194c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    // - special entities in the entity table [in/out]
195c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    // - numeric character reference [in]
196c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    //   &#20013; or &#x4e2d;
197c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
198c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    if ( *(p+1) == '#' ) {
199c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        char buf[10] = { 0 };
200c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        int len;
201c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        p = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );
202c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        for( int i=0; i<len; ++i ) {
203c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                            *q++ = buf[i];
204c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        }
205c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        TIXMLASSERT( q <= p );
206c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    }
207c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    else {
208c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        int i=0;
209c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        for(; i<NUM_ENTITIES; ++i ) {
210c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                            if (    strncmp( p+1, entities[i].pattern, entities[i].length ) == 0
211c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                                 && *(p+entities[i].length+1) == ';' )
212c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                            {
213c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                                // Found an entity convert;
214c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                                *q = entities[i].value;
215c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                                ++q;
216c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                                p += entities[i].length + 2;
217c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                                break;
218c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                            }
219c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        }
220c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        if ( i == NUM_ENTITIES ) {
221c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                            // fixme: treat as error?
222c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                            ++p;
223c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                            ++q;
224c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        }
225c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    }
226c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                }
227c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                else {
228c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    *q = *p;
229c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    ++p;
230c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    ++q;
231c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                }
232c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
233c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            *q = 0;
234c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
235c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        flags = (flags & NEEDS_DELETE);
236c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
237c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return start;
238c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
239c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
240c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
241c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
242c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
243c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie// --------- XMLUtil ----------- //
244c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
245c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieconst char* XMLUtil::ReadBOM( const char* p, bool* bom )
246c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
247c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    *bom = false;
248c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const unsigned char* pu = reinterpret_cast<const unsigned char*>(p);
249c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // Check for BOM:
250c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if (    *(pu+0) == TIXML_UTF_LEAD_0
251c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie         && *(pu+1) == TIXML_UTF_LEAD_1
252c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie         && *(pu+2) == TIXML_UTF_LEAD_2 )
253c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    {
254c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        *bom = true;
255c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        p += 3;
256c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
257c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return p;
258c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
259c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
260c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
261c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
262c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
263c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const unsigned long BYTE_MASK = 0xBF;
264c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const unsigned long BYTE_MARK = 0x80;
265c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
266c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
267c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if (input < 0x80)
268c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        *length = 1;
269c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else if ( input < 0x800 )
270c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        *length = 2;
271c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else if ( input < 0x10000 )
272c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        *length = 3;
273c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else if ( input < 0x200000 )
274c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        *length = 4;
275c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else
276c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        { *length = 0; return; }    // This code won't covert this correctly anyway.
277c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
278c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    output += *length;
279c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
280c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // Scary scary fall throughs.
281c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    switch (*length)
282c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    {
283c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        case 4:
284c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            --output;
285c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            *output = (char)((input | BYTE_MARK) & BYTE_MASK);
286c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            input >>= 6;
287c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        case 3:
288c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            --output;
289c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            *output = (char)((input | BYTE_MARK) & BYTE_MASK);
290c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            input >>= 6;
291c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        case 2:
292c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            --output;
293c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            *output = (char)((input | BYTE_MARK) & BYTE_MASK);
294c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            input >>= 6;
295c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        case 1:
296c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            --output;
297c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            *output = (char)(input | FIRST_BYTE_MARK[*length]);
298c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
299c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
300c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
301c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
302c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieconst char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )
303c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
304c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // Presume an entity, and pull it out.
305c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    *length = 0;
306c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
307c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( *(p+1) == '#' && *(p+2) )
308c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    {
309c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        unsigned long ucs = 0;
310c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        ptrdiff_t delta = 0;
311c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        unsigned mult = 1;
312c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
313c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( *(p+2) == 'x' )
314c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        {
315c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            // Hexadecimal.
316c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( !*(p+3) ) return 0;
317c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
318c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            const char* q = p+3;
319c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            q = strchr( q, ';' );
320c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
321c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( !q || !*q ) return 0;
322c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
323c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            delta = q-p;
324c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            --q;
325c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
326c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            while ( *q != 'x' )
327c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            {
328c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                if ( *q >= '0' && *q <= '9' )
329c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    ucs += mult * (*q - '0');
330c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                else if ( *q >= 'a' && *q <= 'f' )
331c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    ucs += mult * (*q - 'a' + 10);
332c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                else if ( *q >= 'A' && *q <= 'F' )
333c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    ucs += mult * (*q - 'A' + 10 );
334c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                else
335c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    return 0;
336c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                mult *= 16;
337c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                --q;
338c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
339c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
340c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        else
341c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        {
342c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            // Decimal.
343c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( !*(p+2) ) return 0;
344c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
345c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            const char* q = p+2;
346c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            q = strchr( q, ';' );
347c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
348c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( !q || !*q ) return 0;
349c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
350c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            delta = q-p;
351c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            --q;
352c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
353c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            while ( *q != '#' )
354c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            {
355c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                if ( *q >= '0' && *q <= '9' )
356c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    ucs += mult * (*q - '0');
357c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                else
358c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    return 0;
359c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                mult *= 10;
360c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                --q;
361c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
362c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
363c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        // convert the UCS to UTF-8
364c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        ConvertUTF32ToUTF8( ucs, value, length );
365c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return p + delta + 1;
366c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
367c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return p+1;
368c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
369c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
370c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
371c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLUtil::ToStr( int v, char* buffer, int bufferSize )
372c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
373c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXML_SNPRINTF( buffer, bufferSize, "%d", v );
374c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
375c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
376c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
377c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize )
378c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
379c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXML_SNPRINTF( buffer, bufferSize, "%u", v );
380c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
381c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
382c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
383c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLUtil::ToStr( bool v, char* buffer, int bufferSize )
384c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
385c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 );
386c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
387c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
388c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
389c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLUtil::ToStr( float v, char* buffer, int bufferSize )
390c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
391c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXML_SNPRINTF( buffer, bufferSize, "%f", v );
392c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
393c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
394c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
395c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLUtil::ToStr( double v, char* buffer, int bufferSize )
396c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
397c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXML_SNPRINTF( buffer, bufferSize, "%f", v );
398c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
399c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
400c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
401c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLUtil::ToInt( const char* str, int* value )
402c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
403c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( TIXML_SSCANF( str, "%d", value ) == 1 )
404c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return true;
405c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return false;
406c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
407c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
408c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLUtil::ToUnsigned( const char* str, unsigned *value )
409c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
410c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( TIXML_SSCANF( str, "%u", value ) == 1 )
411c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return true;
412c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return false;
413c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
414c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
415c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLUtil::ToBool( const char* str, bool* value )
416c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
417c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    int ival = 0;
418c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( ToInt( str, &ival )) {
419c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        *value = (ival==0) ? false : true;
420c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return true;
421c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
422c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( StringEqual( str, "true" ) ) {
423c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        *value = true;
424c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return true;
425c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
426c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else if ( StringEqual( str, "false" ) ) {
427c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        *value = false;
428c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return true;
429c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
430c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return false;
431c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
432c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
433c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
434c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLUtil::ToFloat( const char* str, float* value )
435c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
436c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( TIXML_SSCANF( str, "%f", value ) == 1 ) {
437c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return true;
438c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
439c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return false;
440c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
441c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
442c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLUtil::ToDouble( const char* str, double* value )
443c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
444c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) {
445c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return true;
446c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
447c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return false;
448c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
449c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
450c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
451c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiechar* XMLDocument::Identify( char* p, XMLNode** node )
452c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
453c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLNode* returnNode = 0;
454c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char* start = p;
455c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = XMLUtil::SkipWhiteSpace( p );
456c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if( !p || !*p )
457c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    {
458c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return p;
459c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
460c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
461c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // What is this thing?
462c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // - Elements start with a letter or underscore, but xml is reserved.
463c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // - Comments: <!--
464c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // - Decleration: <?
465c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // - Everthing else is unknown to tinyxml.
466c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    //
467c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
468c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    static const char* xmlHeader        = { "<?" };
469c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    static const char* commentHeader    = { "<!--" };
470c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    static const char* dtdHeader        = { "<!" };
471c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    static const char* cdataHeader        = { "<![CDATA[" };
472c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    static const char* elementHeader    = { "<" };    // and a header for everything else; check last.
473c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
474c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    static const int xmlHeaderLen        = 2;
475c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    static const int commentHeaderLen    = 4;
476c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    static const int dtdHeaderLen        = 2;
477c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    static const int cdataHeaderLen        = 9;
478c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    static const int elementHeaderLen    = 1;
479c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
480c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#if defined(_MSC_VER)
481c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#pragma warning ( push )
482c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#pragma warning ( disable : 4127 )
483c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#endif
484c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) );        // use same memory pool
485c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) );    // use same memory pool
486c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#if defined(_MSC_VER)
487c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#pragma warning (pop)
488c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#endif
489c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
490c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        returnNode = new (commentPool.Alloc()) XMLDeclaration( this );
491c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        returnNode->memPool = &commentPool;
492c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        p += xmlHeaderLen;
493c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
494c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) {
495c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        returnNode = new (commentPool.Alloc()) XMLComment( this );
496c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        returnNode->memPool = &commentPool;
497c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        p += commentHeaderLen;
498c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
499c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) {
500c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        XMLText* text = new (textPool.Alloc()) XMLText( this );
501c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        returnNode = text;
502c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        returnNode->memPool = &textPool;
503c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        p += cdataHeaderLen;
504c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        text->SetCData( true );
505c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
506c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) {
507c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        returnNode = new (commentPool.Alloc()) XMLUnknown( this );
508c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        returnNode->memPool = &commentPool;
509c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        p += dtdHeaderLen;
510c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
511c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {
512c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        returnNode = new (elementPool.Alloc()) XMLElement( this );
513c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        returnNode->memPool = &elementPool;
514c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        p += elementHeaderLen;
515c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
516c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else {
517c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        returnNode = new (textPool.Alloc()) XMLText( this );
518c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        returnNode->memPool = &textPool;
519c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        p = start;    // Back it up, all the text counts.
520c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
521c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
522c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    *node = returnNode;
523c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return p;
524c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
525c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
526c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
527c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLDocument::Accept( XMLVisitor* visitor ) const
528c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
529c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( visitor->VisitEnter( *this ) )
530c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    {
531c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() )
532c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        {
533c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( !node->Accept( visitor ) )
534c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                break;
535c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
536c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
537c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return visitor->VisitExit( *this );
538c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
539c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
540c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
541c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie// --------- XMLNode ----------- //
542c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
543c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLNode::XMLNode( XMLDocument* doc ) :
544c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    document( doc ),
545c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    parent( 0 ),
546c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    firstChild( 0 ), lastChild( 0 ),
547c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    prev( 0 ), next( 0 )
548c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
549c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
550c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
551c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
552c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLNode::~XMLNode()
553c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
554c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    DeleteChildren();
555c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( parent ) {
556c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        parent->Unlink( this );
557c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
558c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
559c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
560c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
561c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLNode::SetValue( const char* str, bool staticMem )
562c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
563c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( staticMem )
564c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        value.SetInternedStr( str );
565c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else
566c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        value.SetStr( str );
567c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
568c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
569c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
570c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLNode::DeleteChildren()
571c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
572c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    while( firstChild ) {
573c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        XMLNode* node = firstChild;
574c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        Unlink( node );
575c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
576c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        DELETE_NODE( node );
577c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
578c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    firstChild = lastChild = 0;
579c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
580c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
581c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
582c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLNode::Unlink( XMLNode* child )
583c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
584c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXMLASSERT( child->parent == this );
585c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( child == firstChild )
586c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        firstChild = firstChild->next;
587c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( child == lastChild )
588c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        lastChild = lastChild->prev;
589c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
590c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( child->prev ) {
591c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        child->prev->next = child->next;
592c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
593c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( child->next ) {
594c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        child->next->prev = child->prev;
595c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
596c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    child->parent = 0;
597c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
598c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
599c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
600c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLNode::DeleteChild( XMLNode* node )
601c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
602c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXMLASSERT( node->parent == this );
603c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    DELETE_NODE( node );
604c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
605c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
606c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
607c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLNode* XMLNode::InsertEndChild( XMLNode* addThis )
608c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
609c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( lastChild ) {
610c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        TIXMLASSERT( firstChild );
611c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        TIXMLASSERT( lastChild->next == 0 );
612c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        lastChild->next = addThis;
613c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        addThis->prev = lastChild;
614c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        lastChild = addThis;
615c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
616c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        addThis->next = 0;
617c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
618c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else {
619c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        TIXMLASSERT( firstChild == 0 );
620c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        firstChild = lastChild = addThis;
621c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
622c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        addThis->prev = 0;
623c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        addThis->next = 0;
624c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
625c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    addThis->parent = this;
626c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return addThis;
627c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
628c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
629c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
630c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLNode* XMLNode::InsertFirstChild( XMLNode* addThis )
631c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
632c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( firstChild ) {
633c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        TIXMLASSERT( lastChild );
634c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        TIXMLASSERT( firstChild->prev == 0 );
635c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
636c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        firstChild->prev = addThis;
637c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        addThis->next = firstChild;
638c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        firstChild = addThis;
639c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
640c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        addThis->prev = 0;
641c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
642c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else {
643c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        TIXMLASSERT( lastChild == 0 );
644c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        firstChild = lastChild = addThis;
645c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
646c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        addThis->prev = 0;
647c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        addThis->next = 0;
648c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
649c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    addThis->parent = this;
650c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return addThis;
651c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
652c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
653c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
654c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )
655c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
656c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXMLASSERT( afterThis->parent == this );
657c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( afterThis->parent != this )
658c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return 0;
659c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
660c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( afterThis->next == 0 ) {
661c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        // The last node or the only node.
662c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return InsertEndChild( addThis );
663c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
664c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    addThis->prev = afterThis;
665c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    addThis->next = afterThis->next;
666c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    afterThis->next->prev = addThis;
667c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    afterThis->next = addThis;
668c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    addThis->parent = this;
669c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return addThis;
670c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
671c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
672c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
673c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
674c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
675c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieconst XMLElement* XMLNode::FirstChildElement( const char* value ) const
676c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
677c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    for( XMLNode* node=firstChild; node; node=node->next ) {
678c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        XMLElement* element = node->ToElement();
679c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( element ) {
680c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
681c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                return element;
682c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
683c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
684c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
685c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return 0;
686c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
687c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
688c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
689c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieconst XMLElement* XMLNode::LastChildElement( const char* value ) const
690c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
691c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    for( XMLNode* node=lastChild; node; node=node->prev ) {
692c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        XMLElement* element = node->ToElement();
693c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( element ) {
694c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
695c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                return element;
696c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
697c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
698c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
699c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return 0;
700c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
701c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
702c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
703c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieconst XMLElement* XMLNode::NextSiblingElement( const char* value ) const
704c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
705c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    for( XMLNode* element=this->next; element; element = element->next ) {
706c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if (    element->ToElement()
707c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie             && (!value || XMLUtil::StringEqual( value, element->Value() )))
708c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        {
709c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return element->ToElement();
710c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
711c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
712c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return 0;
713c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
714c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
715c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
716c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieconst XMLElement* XMLNode::PreviousSiblingElement( const char* value ) const
717c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
718c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    for( XMLNode* element=this->prev; element; element = element->prev ) {
719c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if (    element->ToElement()
720c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie             && (!value || XMLUtil::StringEqual( value, element->Value() )))
721c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        {
722c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return element->ToElement();
723c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
724c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
725c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return 0;
726c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
727c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
728c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
729c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiechar* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
730c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
731c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // This is a recursive method, but thinking about it "at the current level"
732c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // it is a pretty simple flat list:
733c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    //        <foo/>
734c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    //        <!-- comment -->
735c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    //
736c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // With a special case:
737c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    //        <foo>
738c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    //        </foo>
739c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    //        <!-- comment -->
740c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    //
741c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // Where the closing element (/foo) *must* be the next thing after the opening
742c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // element, and the names must match. BUT the tricky bit is that the closing
743c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // element will be read by the child.
744c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    //
745c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // 'endTag' is the end tag for this node, it is returned by a call to a child.
746c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // 'parentEnd' is the end tag for the parent, which is filled in and returned.
747c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
748c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    while( p && *p ) {
749c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        XMLNode* node = 0;
750c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
751c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        p = document->Identify( p, &node );
752c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( p == 0 || node == 0 ) {
753c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            break;
754c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
755c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
756c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        StrPair endTag;
757c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        p = node->ParseDeep( p, &endTag );
758c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( !p ) {
759c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            DELETE_NODE( node );
760c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            node = 0;
761c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( !document->Error() ) {
762c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                document->SetError( XML_ERROR_PARSING, 0, 0 );
763c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
764c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            break;
765c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
766c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
767c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        // We read the end tag. Return it to the parent.
768c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( node->ToElement() && node->ToElement()->ClosingType() == XMLElement::CLOSING ) {
769c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( parentEnd ) {
770c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                *parentEnd = static_cast<XMLElement*>(node)->value;
771c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
772c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            DELETE_NODE( node );
773c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return p;
774c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
775c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
776c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        // Handle an end tag returned to this level.
777c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        // And handle a bunch of annoying errors.
778c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        XMLElement* ele = node->ToElement();
779c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( ele ) {
780c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( endTag.Empty() && ele->ClosingType() == XMLElement::OPEN ) {
781c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
782c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                p = 0;
783c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
784c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            else if ( !endTag.Empty() && ele->ClosingType() != XMLElement::OPEN ) {
785c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
786c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                p = 0;
787c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
788c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            else if ( !endTag.Empty() ) {
789c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                if ( !XMLUtil::StringEqual( endTag.GetStr(), node->Value() )) {
790c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
791c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    p = 0;
792c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                }
793c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
794c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
795c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( p == 0 ) {
796c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            DELETE_NODE( node );
797c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            node = 0;
798c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
799c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( node ) {
800c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            this->InsertEndChild( node );
801c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
802c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
803c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return 0;
804c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
805c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
806c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie// --------- XMLText ---------- //
807c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiechar* XMLText::ParseDeep( char* p, StrPair* )
808c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
809c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const char* start = p;
810c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( this->CData() ) {
811c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        p = value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
812c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( !p ) {
813c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            document->SetError( XML_ERROR_PARSING_CDATA, start, 0 );
814c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
815c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return p;
816c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
817c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else {
818c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        p = value.ParseText( p, "<", document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES );
819c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( !p ) {
820c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            document->SetError( XML_ERROR_PARSING_TEXT, start, 0 );
821c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
822c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( p && *p ) {
823c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return p-1;
824c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
825c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
826c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return 0;
827c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
828c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
829c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
830c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLNode* XMLText::ShallowClone( XMLDocument* doc ) const
831c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
832c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !doc ) {
833c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        doc = document;
834c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
835c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLText* text = doc->NewText( Value() );    // fixme: this will always allocate memory. Intern?
836c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    text->SetCData( this->CData() );
837c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return text;
838c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
839c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
840c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
841c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLText::ShallowEqual( const XMLNode* compare ) const
842c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
843c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return ( compare->ToText() && XMLUtil::StringEqual( compare->ToText()->Value(), Value() ));
844c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
845c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
846c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
847c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLText::Accept( XMLVisitor* visitor ) const
848c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
849c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return visitor->Visit( *this );
850c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
851c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
852c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
853c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie// --------- XMLComment ---------- //
854c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
855c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc )
856c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
857c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
858c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
859c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
860c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLComment::~XMLComment()
861c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
862c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    //printf( "~XMLComment\n" );
863c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
864c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
865c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
866c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiechar* XMLComment::ParseDeep( char* p, StrPair* )
867c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
868c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // Comment parses as text.
869c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const char* start = p;
870c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = value.ParseText( p, "-->", StrPair::COMMENT );
871c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( p == 0 ) {
872c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        document->SetError( XML_ERROR_PARSING_COMMENT, start, 0 );
873c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
874c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return p;
875c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
876c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
877c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
878c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const
879c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
880c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !doc ) {
881c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        doc = document;
882c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
883c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLComment* comment = doc->NewComment( Value() );    // fixme: this will always allocate memory. Intern?
884c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return comment;
885c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
886c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
887c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
888c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLComment::ShallowEqual( const XMLNode* compare ) const
889c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
890c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return ( compare->ToComment() && XMLUtil::StringEqual( compare->ToComment()->Value(), Value() ));
891c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
892c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
893c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
894c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLComment::Accept( XMLVisitor* visitor ) const
895c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
896c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return visitor->Visit( *this );
897c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
898c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
899c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
900c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie// --------- XMLDeclaration ---------- //
901c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
902c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc )
903c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
904c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
905c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
906c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
907c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLDeclaration::~XMLDeclaration()
908c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
909c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    //printf( "~XMLDeclaration\n" );
910c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
911c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
912c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
913c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiechar* XMLDeclaration::ParseDeep( char* p, StrPair* )
914c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
915c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // Declaration parses as text.
916c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const char* start = p;
917c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
918c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( p == 0 ) {
919c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0 );
920c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
921c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return p;
922c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
923c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
924c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
925c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const
926c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
927c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !doc ) {
928c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        doc = document;
929c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
930c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLDeclaration* dec = doc->NewDeclaration( Value() );    // fixme: this will always allocate memory. Intern?
931c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return dec;
932c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
933c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
934c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
935c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const
936c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
937c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return ( compare->ToDeclaration() && XMLUtil::StringEqual( compare->ToDeclaration()->Value(), Value() ));
938c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
939c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
940c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
941c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
942c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLDeclaration::Accept( XMLVisitor* visitor ) const
943c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
944c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return visitor->Visit( *this );
945c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
946c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
947c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie// --------- XMLUnknown ---------- //
948c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
949c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc )
950c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
951c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
952c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
953c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
954c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLUnknown::~XMLUnknown()
955c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
956c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
957c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
958c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
959c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiechar* XMLUnknown::ParseDeep( char* p, StrPair* )
960c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
961c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // Unknown parses as text.
962c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const char* start = p;
963c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
964c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION );
965c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !p ) {
966c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 );
967c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
968c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return p;
969c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
970c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
971c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
972c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const
973c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
974c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !doc ) {
975c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        doc = document;
976c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
977c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUnknown* text = doc->NewUnknown( Value() );    // fixme: this will always allocate memory. Intern?
978c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return text;
979c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
980c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
981c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
982c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLUnknown::ShallowEqual( const XMLNode* compare ) const
983c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
984c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return ( compare->ToUnknown() && XMLUtil::StringEqual( compare->ToUnknown()->Value(), Value() ));
985c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
986c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
987c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
988c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLUnknown::Accept( XMLVisitor* visitor ) const
989c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
990c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return visitor->Visit( *this );
991c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
992c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
993c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie// --------- XMLAttribute ---------- //
994c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiechar* XMLAttribute::ParseDeep( char* p, bool processEntities )
995c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
996c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // Parse using the name rules: bug fix, was using ParseText before
997c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = name.ParseName( p );
998c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !p || !*p ) return 0;
999c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1000c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // Skip white space before =
1001c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = XMLUtil::SkipWhiteSpace( p );
1002c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !p || *p != '=' ) return 0;
1003c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1004c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    ++p;    // move up to opening quote
1005c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = XMLUtil::SkipWhiteSpace( p );
1006c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( *p != '\"' && *p != '\'' ) return 0;
1007c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1008c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char endTag[2] = { *p, 0 };
1009c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    ++p;    // move past opening quote
1010c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1011c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES );
1012c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return p;
1013c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1014c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1015c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1016c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLAttribute::SetName( const char* n )
1017c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1018c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    name.SetStr( n );
1019c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1020c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1021c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1022c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieint XMLAttribute::QueryIntValue( int* value ) const
1023c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1024c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( XMLUtil::ToInt( Value(), value ))
1025c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return XML_NO_ERROR;
1026c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return XML_WRONG_ATTRIBUTE_TYPE;
1027c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1028c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1029c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1030c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieint XMLAttribute::QueryUnsignedValue( unsigned int* value ) const
1031c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1032c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( XMLUtil::ToUnsigned( Value(), value ))
1033c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return XML_NO_ERROR;
1034c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return XML_WRONG_ATTRIBUTE_TYPE;
1035c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1036c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1037c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1038c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieint XMLAttribute::QueryBoolValue( bool* value ) const
1039c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1040c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( XMLUtil::ToBool( Value(), value )) {
1041c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return XML_NO_ERROR;
1042c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1043c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return XML_WRONG_ATTRIBUTE_TYPE;
1044c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1045c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1046c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1047c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieint XMLAttribute::QueryFloatValue( float* value ) const
1048c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1049c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( XMLUtil::ToFloat( Value(), value ))
1050c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return XML_NO_ERROR;
1051c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return XML_WRONG_ATTRIBUTE_TYPE;
1052c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1053c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1054c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1055c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieint XMLAttribute::QueryDoubleValue( double* value ) const
1056c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1057c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( XMLUtil::ToDouble( Value(), value ))
1058c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return XML_NO_ERROR;
1059c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return XML_WRONG_ATTRIBUTE_TYPE;
1060c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1061c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1062c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1063c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLAttribute::SetAttribute( const char* v )
1064c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1065c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    value.SetStr( v );
1066c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1067c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1068c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1069c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLAttribute::SetAttribute( int v )
1070c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1071c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char buf[BUF_SIZE];
1072c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUtil::ToStr( v, buf, BUF_SIZE );
1073c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    value.SetStr( buf );
1074c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1075c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1076c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1077c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLAttribute::SetAttribute( unsigned v )
1078c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1079c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char buf[BUF_SIZE];
1080c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUtil::ToStr( v, buf, BUF_SIZE );
1081c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    value.SetStr( buf );
1082c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1083c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1084c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1085c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLAttribute::SetAttribute( bool v )
1086c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1087c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char buf[BUF_SIZE];
1088c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUtil::ToStr( v, buf, BUF_SIZE );
1089c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    value.SetStr( buf );
1090c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1091c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1092c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLAttribute::SetAttribute( double v )
1093c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1094c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char buf[BUF_SIZE];
1095c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUtil::ToStr( v, buf, BUF_SIZE );
1096c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    value.SetStr( buf );
1097c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1098c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1099c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLAttribute::SetAttribute( float v )
1100c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1101c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char buf[BUF_SIZE];
1102c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUtil::ToStr( v, buf, BUF_SIZE );
1103c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    value.SetStr( buf );
1104c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1105c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1106c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1107c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie// --------- XMLElement ---------- //
1108c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ),
1109c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    closingType( 0 ),
1110c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    rootAttribute( 0 )
1111c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1112c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1113c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1114c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1115c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLElement::~XMLElement()
1116c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1117c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    while( rootAttribute ) {
1118c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        XMLAttribute* next = rootAttribute->next;
1119c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        DELETE_ATTRIBUTE( rootAttribute );
1120c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        rootAttribute = next;
1121c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1122c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1123c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1124c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1125c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLAttribute* XMLElement::FindAttribute( const char* name )
1126c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1127c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLAttribute* a = 0;
1128c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    for( a=rootAttribute; a; a = a->next ) {
1129c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( XMLUtil::StringEqual( a->Name(), name ) )
1130c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return a;
1131c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1132c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return 0;
1133c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1134c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1135c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1136c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieconst XMLAttribute* XMLElement::FindAttribute( const char* name ) const
1137c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1138c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLAttribute* a = 0;
1139c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    for( a=rootAttribute; a; a = a->next ) {
1140c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( XMLUtil::StringEqual( a->Name(), name ) )
1141c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return a;
1142c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1143c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return 0;
1144c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1145c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1146c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1147c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieconst char* XMLElement::Attribute( const char* name, const char* value ) const
1148c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1149c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const XMLAttribute* a = FindAttribute( name );
1150c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !a )
1151c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return 0;
1152c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !value || XMLUtil::StringEqual( a->Value(), value ))
1153c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return a->Value();
1154c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return 0;
1155c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1156c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1157c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1158c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieconst char* XMLElement::GetText() const
1159c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1160c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( FirstChild() && FirstChild()->ToText() ) {
1161c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return FirstChild()->ToText()->Value();
1162c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1163c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return 0;
1164c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1165c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1166c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1167c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieint XMLElement::QueryIntText( int* _value ) const
1168c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1169c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( FirstChild() && FirstChild()->ToText() ) {
1170c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        const char* t = FirstChild()->ToText()->Value();
1171c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( XMLUtil::ToInt( t, _value ) ) {
1172c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return XML_SUCCESS;
1173c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1174c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return XML_CAN_NOT_CONVERT_TEXT;
1175c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1176c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return XML_NO_TEXT_NODE;
1177c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1178c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1179c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1180c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieint XMLElement::QueryUnsignedText( unsigned* _value ) const
1181c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1182c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( FirstChild() && FirstChild()->ToText() ) {
1183c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        const char* t = FirstChild()->ToText()->Value();
1184c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( XMLUtil::ToUnsigned( t, _value ) ) {
1185c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return XML_SUCCESS;
1186c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1187c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return XML_CAN_NOT_CONVERT_TEXT;
1188c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1189c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return XML_NO_TEXT_NODE;
1190c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1191c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1192c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1193c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieint XMLElement::QueryBoolText( bool* _value ) const
1194c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1195c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( FirstChild() && FirstChild()->ToText() ) {
1196c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        const char* t = FirstChild()->ToText()->Value();
1197c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( XMLUtil::ToBool( t, _value ) ) {
1198c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return XML_SUCCESS;
1199c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1200c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return XML_CAN_NOT_CONVERT_TEXT;
1201c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1202c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return XML_NO_TEXT_NODE;
1203c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1204c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1205c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1206c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieint XMLElement::QueryDoubleText( double* _value ) const
1207c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1208c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( FirstChild() && FirstChild()->ToText() ) {
1209c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        const char* t = FirstChild()->ToText()->Value();
1210c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( XMLUtil::ToDouble( t, _value ) ) {
1211c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return XML_SUCCESS;
1212c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1213c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return XML_CAN_NOT_CONVERT_TEXT;
1214c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1215c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return XML_NO_TEXT_NODE;
1216c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1217c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1218c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1219c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieint XMLElement::QueryFloatText( float* _value ) const
1220c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1221c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( FirstChild() && FirstChild()->ToText() ) {
1222c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        const char* t = FirstChild()->ToText()->Value();
1223c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( XMLUtil::ToFloat( t, _value ) ) {
1224c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return XML_SUCCESS;
1225c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1226c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return XML_CAN_NOT_CONVERT_TEXT;
1227c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1228c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return XML_NO_TEXT_NODE;
1229c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1230c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1231c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1232c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1233c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )
1234c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1235c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLAttribute* last = 0;
1236c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLAttribute* attrib = 0;
1237c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    for( attrib = rootAttribute;
1238c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie         attrib;
1239c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie         last = attrib, attrib = attrib->next )
1240c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    {
1241c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( XMLUtil::StringEqual( attrib->Name(), name ) ) {
1242c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            break;
1243c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1244c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1245c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !attrib ) {
1246c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        attrib = new (document->attributePool.Alloc() ) XMLAttribute();
1247c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        attrib->memPool = &document->attributePool;
1248c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( last ) {
1249c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            last->next = attrib;
1250c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1251c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        else {
1252c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            rootAttribute = attrib;
1253c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1254c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        attrib->SetName( name );
1255c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1256c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return attrib;
1257c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1258c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1259c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1260c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLElement::DeleteAttribute( const char* name )
1261c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1262c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLAttribute* prev = 0;
1263c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    for( XMLAttribute* a=rootAttribute; a; a=a->next ) {
1264c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( XMLUtil::StringEqual( name, a->Name() ) ) {
1265c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( prev ) {
1266c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                prev->next = a->next;
1267c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
1268c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            else {
1269c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                rootAttribute = a->next;
1270c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
1271c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            DELETE_ATTRIBUTE( a );
1272c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            break;
1273c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1274c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        prev = a;
1275c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1276c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1277c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1278c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1279c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiechar* XMLElement::ParseAttributes( char* p )
1280c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1281c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const char* start = p;
1282c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLAttribute* prevAttribute = 0;
1283c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1284c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // Read the attributes.
1285c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    while( p ) {
1286c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        p = XMLUtil::SkipWhiteSpace( p );
1287c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( !p || !(*p) ) {
1288c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() );
1289c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return 0;
1290c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1291c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1292c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        // attribute.
1293c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( XMLUtil::IsAlpha( *p ) ) {
1294c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            XMLAttribute* attrib = new (document->attributePool.Alloc() ) XMLAttribute();
1295c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            attrib->memPool = &document->attributePool;
1296c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1297c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            p = attrib->ParseDeep( p, document->ProcessEntities() );
1298c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( !p || Attribute( attrib->Name() ) ) {
1299c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                DELETE_ATTRIBUTE( attrib );
1300c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p );
1301c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                return 0;
1302c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
1303c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            // There is a minor bug here: if the attribute in the source xml
1304c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            // document is duplicated, it will not be detected and the
1305c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            // attribute will be doubly added. However, tracking the 'prevAttribute'
1306c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            // avoids re-scanning the attribute list. Preferring performance for
1307c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            // now, may reconsider in the future.
1308c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( prevAttribute ) {
1309c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                prevAttribute->next = attrib;
1310c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
1311c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            else {
1312c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                rootAttribute = attrib;
1313c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
1314c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            prevAttribute = attrib;
1315c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1316c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        // end of the tag
1317c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        else if ( *p == '/' && *(p+1) == '>' ) {
1318c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            closingType = CLOSED;
1319c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return p+2;    // done; sealed element.
1320c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1321c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        // end of the tag
1322c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        else if ( *p == '>' ) {
1323c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            ++p;
1324c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            break;
1325c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1326c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        else {
1327c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            document->SetError( XML_ERROR_PARSING_ELEMENT, start, p );
1328c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return 0;
1329c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1330c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1331c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return p;
1332c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1333c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1334c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1335c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie//
1336c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie//    <ele></ele>
1337c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie//    <ele>foo<b>bar</b></ele>
1338c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie//
1339c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiechar* XMLElement::ParseDeep( char* p, StrPair* strPair )
1340c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1341c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // Read the element name.
1342c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = XMLUtil::SkipWhiteSpace( p );
1343c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !p ) return 0;
1344c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1345c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // The closing element is the </element> form. It is
1346c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // parsed just like a regular element then deleted from
1347c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // the DOM.
1348c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( *p == '/' ) {
1349c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        closingType = CLOSING;
1350c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        ++p;
1351c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1352c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1353c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = value.ParseName( p );
1354c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( value.Empty() ) return 0;
1355c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1356c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = ParseAttributes( p );
1357c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !p || !*p || closingType )
1358c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return p;
1359c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1360c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = XMLNode::ParseDeep( p, strPair );
1361c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return p;
1362c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1363c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1364c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1365c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1366c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const
1367c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1368c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !doc ) {
1369c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        doc = document;
1370c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1371c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLElement* element = doc->NewElement( Value() );                    // fixme: this will always allocate memory. Intern?
1372c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) {
1373c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        element->SetAttribute( a->Name(), a->Value() );                    // fixme: this will always allocate memory. Intern?
1374c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1375c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return element;
1376c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1377c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1378c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1379c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLElement::ShallowEqual( const XMLNode* compare ) const
1380c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1381c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const XMLElement* other = compare->ToElement();
1382c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( other && XMLUtil::StringEqual( other->Value(), Value() )) {
1383c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1384c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        const XMLAttribute* a=FirstAttribute();
1385c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        const XMLAttribute* b=other->FirstAttribute();
1386c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1387c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        while ( a && b ) {
1388c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) {
1389c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                return false;
1390c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
1391c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            a = a->Next();
1392c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            b = b->Next();
1393c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1394c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( a || b ) {
1395c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            // different count
1396c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            return false;
1397c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1398c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return true;
1399c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1400c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return false;
1401c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1402c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1403c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1404c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLElement::Accept( XMLVisitor* visitor ) const
1405c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1406c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( visitor->VisitEnter( *this, rootAttribute ) )
1407c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    {
1408c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() )
1409c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        {
1410c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( !node->Accept( visitor ) )
1411c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                break;
1412c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1413c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1414c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return visitor->VisitExit( *this );
1415c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1416c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1417c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1418c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie// --------- XMLDocument ----------- //
1419c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLDocument::XMLDocument( bool _processEntities ) :
1420c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLNode( 0 ),
1421c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    writeBOM( false ),
1422c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    processEntities( _processEntities ),
1423c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    errorID( 0 ),
1424c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    errorStr1( 0 ),
1425c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    errorStr2( 0 ),
1426c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    charBuffer( 0 )
1427c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1428c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    document = this;    // avoid warning about 'this' in initializer list
1429c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1430c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1431c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1432c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLDocument::~XMLDocument()
1433c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1434c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    DeleteChildren();
1435c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    delete [] charBuffer;
1436c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1437c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#if 0
1438c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    textPool.Trace( "text" );
1439c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    elementPool.Trace( "element" );
1440c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    commentPool.Trace( "comment" );
1441c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    attributePool.Trace( "attribute" );
1442c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#endif
1443c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1444c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXMLASSERT( textPool.CurrentAllocs() == 0 );
1445c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXMLASSERT( elementPool.CurrentAllocs() == 0 );
1446c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXMLASSERT( commentPool.CurrentAllocs() == 0 );
1447c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXMLASSERT( attributePool.CurrentAllocs() == 0 );
1448c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1449c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1450c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1451c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLDocument::InitDocument()
1452c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1453c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    errorID = XML_NO_ERROR;
1454c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    errorStr1 = 0;
1455c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    errorStr2 = 0;
1456c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1457c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    delete [] charBuffer;
1458c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    charBuffer = 0;
1459c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1460c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1461c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1462c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1463c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLElement* XMLDocument::NewElement( const char* name )
1464c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1465c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLElement* ele = new (elementPool.Alloc()) XMLElement( this );
1466c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    ele->memPool = &elementPool;
1467c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    ele->SetName( name );
1468c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return ele;
1469c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1470c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1471c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1472c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLComment* XMLDocument::NewComment( const char* str )
1473c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1474c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLComment* comment = new (commentPool.Alloc()) XMLComment( this );
1475c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    comment->memPool = &commentPool;
1476c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    comment->SetValue( str );
1477c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return comment;
1478c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1479c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1480c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1481c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLText* XMLDocument::NewText( const char* str )
1482c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1483c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLText* text = new (textPool.Alloc()) XMLText( this );
1484c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    text->memPool = &textPool;
1485c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    text->SetValue( str );
1486c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return text;
1487c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1488c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1489c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1490c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLDeclaration* XMLDocument::NewDeclaration( const char* str )
1491c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1492c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLDeclaration* dec = new (commentPool.Alloc()) XMLDeclaration( this );
1493c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    dec->memPool = &commentPool;
1494c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" );
1495c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return dec;
1496c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1497c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1498c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1499c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLUnknown* XMLDocument::NewUnknown( const char* str )
1500c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1501c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUnknown* unk = new (commentPool.Alloc()) XMLUnknown( this );
1502c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    unk->memPool = &commentPool;
1503c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    unk->SetValue( str );
1504c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return unk;
1505c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1506c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1507c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1508c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieint XMLDocument::LoadFile( const char* filename )
1509c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1510c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    DeleteChildren();
1511c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    InitDocument();
1512c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1513c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#if defined(_MSC_VER)
1514c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#pragma warning ( push )
1515c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#pragma warning ( disable : 4996 )        // Fail to see a compelling reason why this should be deprecated.
1516c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#endif
1517c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    FILE* fp = fopen( filename, "rb" );
1518c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#if defined(_MSC_VER)
1519c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#pragma warning ( pop )
1520c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#endif
1521c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !fp ) {
1522c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 );
1523c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return errorID;
1524c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1525c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    LoadFile( fp );
1526c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    fclose( fp );
1527c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return errorID;
1528c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1529c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1530c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1531c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieint XMLDocument::LoadFile( FILE* fp )
1532c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1533c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    DeleteChildren();
1534c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    InitDocument();
1535c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1536c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    fseek( fp, 0, SEEK_END );
1537c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    unsigned size = ftell( fp );
1538c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    fseek( fp, 0, SEEK_SET );
1539c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1540c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( size == 0 ) {
1541c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return errorID;
1542c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1543c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1544c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    charBuffer = new char[size+1];
1545c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    size_t read = fread( charBuffer, 1, size, fp );
1546c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( read != size ) {
1547c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
1548c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return errorID;
1549c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1550c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1551c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    charBuffer[size] = 0;
1552c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1553c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const char* p = charBuffer;
1554c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = XMLUtil::SkipWhiteSpace( p );
1555c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = XMLUtil::ReadBOM( p, &writeBOM );
1556c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !p || !*p ) {
1557c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
1558c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return errorID;
1559c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1560c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1561c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    ParseDeep( charBuffer + (p-charBuffer), 0 );
1562c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return errorID;
1563c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1564c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1565c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1566c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieint XMLDocument::SaveFile( const char* filename )
1567c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1568c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#if defined(_MSC_VER)
1569c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#pragma warning ( push )
1570c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#pragma warning ( disable : 4996 )        // Fail to see a compelling reason why this should be deprecated.
1571c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#endif
1572c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    int fd = open(filename, O_RDWR|O_CREAT, 0644);
1573c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    FILE* fp = fdopen(fd, "w");
1574c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    //FILE* fp = fopen( filename, "w" );
1575c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#if defined(_MSC_VER)
1576c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#pragma warning ( pop )
1577c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie#endif
1578c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !fp ) {
1579c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 );
1580c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return errorID;
1581c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1582c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    SaveFile(fp);
1583c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    fclose( fp );
1584c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return errorID;
1585c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1586c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1587c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1588c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieint XMLDocument::SaveFile( FILE* fp )
1589c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1590c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLPrinter stream( fp );
1591c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    Print( &stream );
1592c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return errorID;
1593c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1594c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1595c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1596c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xieint XMLDocument::Parse( const char* p )
1597c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1598c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    DeleteChildren();
1599c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    InitDocument();
1600c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1601c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !p || !*p ) {
1602c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
1603c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return errorID;
1604c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1605c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = XMLUtil::SkipWhiteSpace( p );
1606c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    p = XMLUtil::ReadBOM( p, &writeBOM );
1607c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !p || !*p ) {
1608c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
1609c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        return errorID;
1610c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1611c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1612c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    size_t len = strlen( p );
1613c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    charBuffer = new char[ len+1 ];
1614c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    memcpy( charBuffer, p, len+1 );
1615c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1616c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1617c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    ParseDeep( charBuffer, 0 );
1618c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return errorID;
1619c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1620c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1621c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1622c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLDocument::Print( XMLPrinter* streamer )
1623c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1624c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLPrinter stdStreamer( stdout );
1625c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !streamer )
1626c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        streamer = &stdStreamer;
1627c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    Accept( streamer );
1628c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1629c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1630c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1631c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLDocument::SetError( int error, const char* str1, const char* str2 )
1632c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1633c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    errorID = error;
1634c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    errorStr1 = str1;
1635c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    errorStr2 = str2;
1636c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1637c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1638c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1639c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLDocument::PrintError() const
1640c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1641c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( errorID ) {
1642c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        static const int LEN = 20;
1643c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        char buf1[LEN] = { 0 };
1644c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        char buf2[LEN] = { 0 };
1645c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1646c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( errorStr1 ) {
1647c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            TIXML_SNPRINTF( buf1, LEN, "%s", errorStr1 );
1648c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1649c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( errorStr2 ) {
1650c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            TIXML_SNPRINTF( buf2, LEN, "%s", errorStr2 );
1651c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1652c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1653c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        printf( "XMLDocument error id=%d str1=%s str2=%s\n",
1654c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                errorID, buf1, buf2 );
1655c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1656c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1657c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1658c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1659c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew XieXMLPrinter::XMLPrinter( FILE* file, bool compact ) :
1660c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    elementJustOpened( false ),
1661c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    firstElement( true ),
1662c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    fp( file ),
1663c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    depth( 0 ),
1664c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    textDepth( -1 ),
1665c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    processEntities( true ),
1666c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    compactMode( compact )
1667c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1668c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    for( int i=0; i<ENTITY_RANGE; ++i ) {
1669c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        entityFlag[i] = false;
1670c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        restrictedEntityFlag[i] = false;
1671c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1672c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    for( int i=0; i<NUM_ENTITIES; ++i ) {
1673c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        TIXMLASSERT( entities[i].value < ENTITY_RANGE );
1674c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( entities[i].value < ENTITY_RANGE ) {
1675c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            entityFlag[ (int)entities[i].value ] = true;
1676c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1677c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1678c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    restrictedEntityFlag[(int)'&'] = true;
1679c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    restrictedEntityFlag[(int)'<'] = true;
1680c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    restrictedEntityFlag[(int)'>'] = true;    // not required, but consistency is nice
1681c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    buffer.Push( 0 );
1682c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1683c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1684c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1685c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::Print( const char* format, ... )
1686c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1687c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    va_list     va;
1688c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    va_start( va, format );
1689c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1690c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( fp ) {
1691c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        vfprintf( fp, format, va );
1692c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1693c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else {
1694c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        // This seems brutally complex. Haven't figured out a better
1695c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        // way on windows.
1696c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        #ifdef _MSC_VER
1697c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            int len = -1;
1698c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            int expand = 1000;
1699c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            while ( len < 0 ) {
1700c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                len = vsnprintf_s( accumulator.Mem(), accumulator.Capacity(), _TRUNCATE, format, va );
1701c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                if ( len < 0 ) {
1702c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    expand *= 3/2;
1703c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    accumulator.PushArr( expand );
1704c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                }
1705c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
1706c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            char* p = buffer.PushArr( len ) - 1;
1707c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            memcpy( p, accumulator.Mem(), len+1 );
1708c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        #else
1709c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            int len = vsnprintf( 0, 0, format, va );
1710c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            // Close out and re-start the va-args
1711c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            va_end( va );
1712c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            va_start( va, format );
1713c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            char* p = buffer.PushArr( len ) - 1;
1714c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            vsnprintf( p, len+1, format, va );
1715c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        #endif
1716c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1717c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    va_end( va );
1718c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1719c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1720c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1721c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PrintSpace( int depth )
1722c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1723c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    for( int i=0; i<depth; ++i ) {
1724c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        Print( "    " );
1725c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1726c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1727c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1728c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1729c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PrintString( const char* p, bool restricted )
1730c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1731c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // Look for runs of bytes between entities to print.
1732c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const char* q = p;
1733c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const bool* flag = restricted ? restrictedEntityFlag : entityFlag;
1734c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1735c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( processEntities ) {
1736c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        while ( *q ) {
1737c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            // Remember, char is sometimes signed. (How many times has that bitten me?)
1738c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            if ( *q > 0 && *q < ENTITY_RANGE ) {
1739c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                // Check for entities. If one is found, flush
1740c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                // the stream up until the entity, write the
1741c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                // entity, and keep looking.
1742c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                if ( flag[(unsigned)(*q)] ) {
1743c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    while ( p < q ) {
1744c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        Print( "%c", *p );
1745c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        ++p;
1746c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    }
1747c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    for( int i=0; i<NUM_ENTITIES; ++i ) {
1748c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        if ( entities[i].value == *q ) {
1749c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                            Print( "&%s;", entities[i].pattern );
1750c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                            break;
1751c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                        }
1752c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    }
1753c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                    ++p;
1754c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie                }
1755c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            }
1756c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            ++q;
1757c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1758c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1759c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // Flush the remaining string. This will be the entire
1760c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    // string if an entity wasn't found.
1761c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( !processEntities || (q-p > 0) ) {
1762c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        Print( "%s", p );
1763c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1764c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1765c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1766c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1767c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
1768c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1769c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };
1770c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( writeBOM ) {
1771c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        Print( "%s", bom );
1772c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1773c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( writeDec ) {
1774c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        PushDeclaration( "xml version=\"1.0\"" );
1775c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1776c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1777c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1778c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1779c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::OpenElement( const char* name )
1780c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1781c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( elementJustOpened ) {
1782c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        SealElement();
1783c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1784c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    stack.Push( name );
1785c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1786c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( textDepth < 0 && !firstElement && !compactMode ) {
1787c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        Print( "\n" );
1788c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        PrintSpace( depth );
1789c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1790c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1791c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    Print( "<%s", name );
1792c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    elementJustOpened = true;
1793c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    firstElement = false;
1794c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    ++depth;
1795c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1796c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1797c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1798c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PushAttribute( const char* name, const char* value )
1799c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1800c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    TIXMLASSERT( elementJustOpened );
1801c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    Print( " %s=\"", name );
1802c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    PrintString( value, false );
1803c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    Print( "\"" );
1804c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1805c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1806c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1807c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PushAttribute( const char* name, int v )
1808c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1809c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char buf[BUF_SIZE];
1810c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUtil::ToStr( v, buf, BUF_SIZE );
1811c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    PushAttribute( name, buf );
1812c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1813c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1814c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1815c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PushAttribute( const char* name, unsigned v )
1816c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1817c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char buf[BUF_SIZE];
1818c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUtil::ToStr( v, buf, BUF_SIZE );
1819c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    PushAttribute( name, buf );
1820c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1821c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1822c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1823c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PushAttribute( const char* name, bool v )
1824c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1825c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char buf[BUF_SIZE];
1826c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUtil::ToStr( v, buf, BUF_SIZE );
1827c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    PushAttribute( name, buf );
1828c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1829c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1830c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1831c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PushAttribute( const char* name, double v )
1832c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1833c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char buf[BUF_SIZE];
1834c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUtil::ToStr( v, buf, BUF_SIZE );
1835c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    PushAttribute( name, buf );
1836c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1837c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1838c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1839c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::CloseElement()
1840c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1841c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    --depth;
1842c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    const char* name = stack.Pop();
1843c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1844c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( elementJustOpened ) {
1845c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        Print( "/>" );
1846c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1847c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else {
1848c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        if ( textDepth < 0 && !compactMode) {
1849c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            Print( "\n" );
1850c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie            PrintSpace( depth );
1851c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        }
1852c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        Print( "</%s>", name );
1853c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1854c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1855c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( textDepth == depth )
1856c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        textDepth = -1;
1857c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( depth == 0 && !compactMode)
1858c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        Print( "\n" );
1859c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    elementJustOpened = false;
1860c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1861c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1862c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1863c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::SealElement()
1864c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1865c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    elementJustOpened = false;
1866c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    Print( ">" );
1867c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1868c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1869c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1870c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PushText( const char* text, bool cdata )
1871c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1872c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    textDepth = depth-1;
1873c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1874c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( elementJustOpened ) {
1875c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        SealElement();
1876c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1877c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( cdata ) {
1878c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        Print( "<![CDATA[" );
1879c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        Print( "%s", text );
1880c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        Print( "]]>" );
1881c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1882c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    else {
1883c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        PrintString( text, true );
1884c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1885c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1886c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1887c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PushText( int value )
1888c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1889c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char buf[BUF_SIZE];
1890c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUtil::ToStr( value, buf, BUF_SIZE );
1891c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    PushText( buf, false );
1892c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1893c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1894c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1895c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PushText( unsigned value )
1896c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1897c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char buf[BUF_SIZE];
1898c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUtil::ToStr( value, buf, BUF_SIZE );
1899c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    PushText( buf, false );
1900c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1901c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1902c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1903c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PushText( bool value )
1904c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1905c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char buf[BUF_SIZE];
1906c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUtil::ToStr( value, buf, BUF_SIZE );
1907c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    PushText( buf, false );
1908c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1909c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1910c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1911c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PushText( float value )
1912c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1913c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char buf[BUF_SIZE];
1914c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUtil::ToStr( value, buf, BUF_SIZE );
1915c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    PushText( buf, false );
1916c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1917c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1918c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1919c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PushText( double value )
1920c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1921c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    char buf[BUF_SIZE];
1922c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    XMLUtil::ToStr( value, buf, BUF_SIZE );
1923c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    PushText( buf, false );
1924c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1925c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1926c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1927c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PushComment( const char* comment )
1928c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1929c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( elementJustOpened ) {
1930c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        SealElement();
1931c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1932c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( textDepth < 0 && !firstElement && !compactMode) {
1933c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        Print( "\n" );
1934c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        PrintSpace( depth );
1935c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1936c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    firstElement = false;
1937c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    Print( "<!--%s-->", comment );
1938c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1939c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1940c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1941c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PushDeclaration( const char* value )
1942c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1943c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( elementJustOpened ) {
1944c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        SealElement();
1945c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1946c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( textDepth < 0 && !firstElement && !compactMode) {
1947c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        Print( "\n" );
1948c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        PrintSpace( depth );
1949c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1950c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    firstElement = false;
1951c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    Print( "<?%s?>", value );
1952c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1953c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1954c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1955c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xievoid XMLPrinter::PushUnknown( const char* value )
1956c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1957c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( elementJustOpened ) {
1958c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        SealElement();
1959c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1960c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( textDepth < 0 && !firstElement && !compactMode) {
1961c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        Print( "\n" );
1962c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        PrintSpace( depth );
1963c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1964c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    firstElement = false;
1965c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    Print( "<!%s>", value );
1966c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1967c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1968c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1969c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLPrinter::VisitEnter( const XMLDocument& doc )
1970c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1971c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    processEntities = doc.ProcessEntities();
1972c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    if ( doc.HasBOM() ) {
1973c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        PushHeader( true, false );
1974c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1975c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return true;
1976c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1977c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1978c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1979c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
1980c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1981c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    OpenElement( element.Name() );
1982c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    while ( attribute ) {
1983c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        PushAttribute( attribute->Name(), attribute->Value() );
1984c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie        attribute = attribute->Next();
1985c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    }
1986c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return true;
1987c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1988c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1989c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1990c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLPrinter::VisitExit( const XMLElement& )
1991c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1992c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    CloseElement();
1993c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return true;
1994c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
1995c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1996c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
1997c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLPrinter::Visit( const XMLText& text )
1998c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
1999c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    PushText( text.Value(), text.CData() );
2000c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return true;
2001c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
2002c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
2003c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
2004c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLPrinter::Visit( const XMLComment& comment )
2005c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
2006c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    PushComment( comment.Value() );
2007c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return true;
2008c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
2009c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
2010c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLPrinter::Visit( const XMLDeclaration& declaration )
2011c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
2012c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    PushDeclaration( declaration.Value() );
2013c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return true;
2014c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
2015c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
2016c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie
2017c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xiebool XMLPrinter::Visit( const XMLUnknown& unknown )
2018c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie{
2019c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    PushUnknown( unknown.Value() );
2020c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie    return true;
2021c74b546f5af36968ffa56d7fd4529f4273b96f48Matthew Xie}
2022