blob: ad008670089a1dffa5c398f8dfa51aefa7d30377 [file] [log] [blame]
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
172. Altered source versions must be plainly marked as such, and
18must not be misrepresented as being the original software.
19
203. This notice may not be removed or altered from any source
21distribution.
22*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080023
U-Lama\Lee560bd472011-12-28 19:42:49 -080024#include "tinyxml2.h"
25
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070026#include <new> // yes, this one new style header, is in the Android SDK.
Lee Thomasona9cf3f92012-10-11 16:56:51 -070027# ifdef ANDROID_NDK
28# include <stddef.h>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070029#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070030# include <cstddef>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070031#endif
U-Lama\Lee560bd472011-12-28 19:42:49 -080032
Lee Thomasone4422302012-01-20 17:59:50 -080033static const char LINE_FEED = (char)0x0a; // all line endings are normalized to LF
Lee Thomasonfde6a752012-01-14 18:08:12 -080034static const char LF = LINE_FEED;
35static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out
36static const char CR = CARRIAGE_RETURN;
Lee Thomasone4422302012-01-20 17:59:50 -080037static const char SINGLE_QUOTE = '\'';
38static const char DOUBLE_QUOTE = '\"';
Lee Thomasonfde6a752012-01-14 18:08:12 -080039
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -080040// Bunch of unicode info at:
41// http://www.unicode.org/faq/utf_bom.html
42// ef bb bf (Microsoft "lead bytes") - designates UTF-8
43
44static const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
45static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
46static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -080047
48
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -080049#define DELETE_NODE( node ) { \
Lee Thomasona9cf3f92012-10-11 16:56:51 -070050 if ( node ) { \
Lee Thomason624d43f2012-10-12 10:58:48 -070051 MemPool* pool = node->_memPool; \
Lee Thomasona9cf3f92012-10-11 16:56:51 -070052 node->~XMLNode(); \
53 pool->Free( node ); \
54 } \
55 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -080056#define DELETE_ATTRIBUTE( attrib ) { \
Lee Thomasona9cf3f92012-10-11 16:56:51 -070057 if ( attrib ) { \
Lee Thomason624d43f2012-10-12 10:58:48 -070058 MemPool* pool = attrib->_memPool; \
Lee Thomasona9cf3f92012-10-11 16:56:51 -070059 attrib->~XMLAttribute(); \
60 pool->Free( attrib ); \
61 } \
62 }
Lee Thomason43f59302012-02-06 18:18:11 -080063
Kevin Wojniak04c22d22012-11-08 11:02:22 -080064namespace tinyxml2
65{
66
Lee Thomason8ee79892012-01-25 17:44:30 -080067struct Entity {
Lee Thomasona9cf3f92012-10-11 16:56:51 -070068 const char* pattern;
69 int length;
70 char value;
Lee Thomason8ee79892012-01-25 17:44:30 -080071};
72
73static const int NUM_ENTITIES = 5;
Lee Thomasona9cf3f92012-10-11 16:56:51 -070074static const Entity entities[NUM_ENTITIES] = {
75 { "quot", 4, DOUBLE_QUOTE },
76 { "amp", 3, '&' },
77 { "apos", 4, SINGLE_QUOTE },
78 { "lt", 2, '<' },
79 { "gt", 2, '>' }
Lee Thomason8ee79892012-01-25 17:44:30 -080080};
81
Lee Thomasonfde6a752012-01-14 18:08:12 -080082
Lee Thomason1a1d4a72012-02-15 09:09:25 -080083StrPair::~StrPair()
84{
Lee Thomasona9cf3f92012-10-11 16:56:51 -070085 Reset();
Lee Thomason1a1d4a72012-02-15 09:09:25 -080086}
87
88
89void StrPair::Reset()
90{
Lee Thomason120b3a62012-10-12 10:06:59 -070091 if ( _flags & NEEDS_DELETE ) {
92 delete [] _start;
Lee Thomasona9cf3f92012-10-11 16:56:51 -070093 }
Lee Thomason120b3a62012-10-12 10:06:59 -070094 _flags = 0;
95 _start = 0;
96 _end = 0;
Lee Thomason1a1d4a72012-02-15 09:09:25 -080097}
98
99
100void StrPair::SetStr( const char* str, int flags )
101{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700102 Reset();
103 size_t len = strlen( str );
Lee Thomason120b3a62012-10-12 10:06:59 -0700104 _start = new char[ len+1 ];
105 memcpy( _start, str, len+1 );
106 _end = _start + len;
107 _flags = flags | NEEDS_DELETE;
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800108}
109
110
111char* StrPair::ParseText( char* p, const char* endTag, int strFlags )
112{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700113 TIXMLASSERT( endTag && *endTag );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800114
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700115 char* start = p; // fixme: hides a member
116 char endChar = *endTag;
117 size_t length = strlen( endTag );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800118
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700119 // Inner loop of text parsing.
120 while ( *p ) {
121 if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
122 Set( start, p, strFlags );
123 return p + length;
124 }
125 ++p;
126 }
127 return 0;
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800128}
129
130
131char* StrPair::ParseName( char* p )
132{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700133 char* start = p;
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800134
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700135 if ( !start || !(*start) ) {
136 return 0;
137 }
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800138
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200139 while( *p && ( p == start ? XMLUtil::IsNameStartChar( *p ) : XMLUtil::IsNameChar( *p ) )) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700140 ++p;
141 }
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800142
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700143 if ( p > start ) {
144 Set( start, p, 0 );
145 return p;
146 }
147 return 0;
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800148}
149
150
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -0700151void StrPair::CollapseWhitespace()
152{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700153 // Trim leading space.
Lee Thomason120b3a62012-10-12 10:06:59 -0700154 _start = XMLUtil::SkipWhiteSpace( _start );
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -0700155
Lee Thomason120b3a62012-10-12 10:06:59 -0700156 if ( _start && *_start ) {
157 char* p = _start; // the read pointer
158 char* q = _start; // the write pointer
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -0700159
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700160 while( *p ) {
161 if ( XMLUtil::IsWhiteSpace( *p )) {
162 p = XMLUtil::SkipWhiteSpace( p );
163 if ( *p == 0 ) {
164 break; // don't write to q; this trims the trailing space.
165 }
166 *q = ' ';
167 ++q;
168 }
169 *q = *p;
170 ++q;
171 ++p;
172 }
173 *q = 0;
174 }
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -0700175}
176
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800177
Lee Thomasone4422302012-01-20 17:59:50 -0800178const char* StrPair::GetStr()
179{
Lee Thomason120b3a62012-10-12 10:06:59 -0700180 if ( _flags & NEEDS_FLUSH ) {
181 *_end = 0;
182 _flags ^= NEEDS_FLUSH;
Lee Thomasone4422302012-01-20 17:59:50 -0800183
Lee Thomason120b3a62012-10-12 10:06:59 -0700184 if ( _flags ) {
185 char* p = _start; // the read pointer
186 char* q = _start; // the write pointer
Lee Thomasone4422302012-01-20 17:59:50 -0800187
Lee Thomason120b3a62012-10-12 10:06:59 -0700188 while( p < _end ) {
189 if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700190 // CR-LF pair becomes LF
191 // CR alone becomes LF
192 // LF-CR becomes LF
193 if ( *(p+1) == LF ) {
194 p += 2;
195 }
196 else {
197 ++p;
198 }
199 *q++ = LF;
200 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700201 else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700202 if ( *(p+1) == CR ) {
203 p += 2;
204 }
205 else {
206 ++p;
207 }
208 *q++ = LF;
209 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700210 else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700211 // Entities handled by tinyXML2:
212 // - special entities in the entity table [in/out]
213 // - numeric character reference [in]
214 // &#20013; or &#x4e2d;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800215
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700216 if ( *(p+1) == '#' ) {
217 char buf[10] = { 0 };
218 int len;
219 p = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );
220 for( int i=0; i<len; ++i ) {
221 *q++ = buf[i];
222 }
223 TIXMLASSERT( q <= p );
224 }
225 else {
226 int i=0;
227 for(; i<NUM_ENTITIES; ++i ) {
228 if ( strncmp( p+1, entities[i].pattern, entities[i].length ) == 0
229 && *(p+entities[i].length+1) == ';' ) {
230 // Found an entity convert;
231 *q = entities[i].value;
232 ++q;
233 p += entities[i].length + 2;
234 break;
235 }
236 }
237 if ( i == NUM_ENTITIES ) {
238 // fixme: treat as error?
239 ++p;
240 ++q;
241 }
242 }
243 }
244 else {
245 *q = *p;
246 ++p;
247 ++q;
248 }
249 }
250 *q = 0;
251 }
252 // The loop below has plenty going on, and this
253 // is a less useful mode. Break it out.
Lee Thomason120b3a62012-10-12 10:06:59 -0700254 if ( _flags & COLLAPSE_WHITESPACE ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700255 CollapseWhitespace();
256 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700257 _flags = (_flags & NEEDS_DELETE);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700258 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700259 return _start;
Lee Thomasone4422302012-01-20 17:59:50 -0800260}
261
Lee Thomason2c85a712012-01-31 08:24:24 -0800262
Lee Thomasone4422302012-01-20 17:59:50 -0800263
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800264
Lee Thomason56bdd022012-02-09 18:16:58 -0800265// --------- XMLUtil ----------- //
Lee Thomasond1983222012-02-06 08:41:24 -0800266
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800267const char* XMLUtil::ReadBOM( const char* p, bool* bom )
268{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700269 *bom = false;
270 const unsigned char* pu = reinterpret_cast<const unsigned char*>(p);
271 // Check for BOM:
272 if ( *(pu+0) == TIXML_UTF_LEAD_0
273 && *(pu+1) == TIXML_UTF_LEAD_1
274 && *(pu+2) == TIXML_UTF_LEAD_2 ) {
275 *bom = true;
276 p += 3;
277 }
278 return p;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800279}
280
281
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800282void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
283{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700284 const unsigned long BYTE_MASK = 0xBF;
285 const unsigned long BYTE_MARK = 0x80;
286 const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800287
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700288 if (input < 0x80) {
289 *length = 1;
290 }
291 else if ( input < 0x800 ) {
292 *length = 2;
293 }
294 else if ( input < 0x10000 ) {
295 *length = 3;
296 }
297 else if ( input < 0x200000 ) {
298 *length = 4;
299 }
300 else {
301 *length = 0; // This code won't covert this correctly anyway.
302 return;
303 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800304
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700305 output += *length;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800306
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700307 // Scary scary fall throughs.
308 switch (*length) {
309 case 4:
310 --output;
311 *output = (char)((input | BYTE_MARK) & BYTE_MASK);
312 input >>= 6;
313 case 3:
314 --output;
315 *output = (char)((input | BYTE_MARK) & BYTE_MASK);
316 input >>= 6;
317 case 2:
318 --output;
319 *output = (char)((input | BYTE_MARK) & BYTE_MASK);
320 input >>= 6;
321 case 1:
322 --output;
323 *output = (char)(input | FIRST_BYTE_MARK[*length]);
MortenMacFly4ee49f12013-01-14 20:03:14 +0100324 default:
325 break;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700326 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800327}
328
329
330const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )
331{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700332 // Presume an entity, and pull it out.
333 *length = 0;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800334
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700335 if ( *(p+1) == '#' && *(p+2) ) {
336 unsigned long ucs = 0;
337 ptrdiff_t delta = 0;
338 unsigned mult = 1;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800339
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700340 if ( *(p+2) == 'x' ) {
341 // Hexadecimal.
342 if ( !*(p+3) ) {
343 return 0;
344 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800345
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700346 const char* q = p+3;
347 q = strchr( q, ';' );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800348
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700349 if ( !q || !*q ) {
350 return 0;
351 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800352
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700353 delta = q-p;
354 --q;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800355
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700356 while ( *q != 'x' ) {
357 if ( *q >= '0' && *q <= '9' ) {
358 ucs += mult * (*q - '0');
359 }
360 else if ( *q >= 'a' && *q <= 'f' ) {
361 ucs += mult * (*q - 'a' + 10);
362 }
363 else if ( *q >= 'A' && *q <= 'F' ) {
364 ucs += mult * (*q - 'A' + 10 );
365 }
366 else {
367 return 0;
368 }
369 mult *= 16;
370 --q;
371 }
372 }
373 else {
374 // Decimal.
375 if ( !*(p+2) ) {
376 return 0;
377 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800378
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700379 const char* q = p+2;
380 q = strchr( q, ';' );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800381
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700382 if ( !q || !*q ) {
383 return 0;
384 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800385
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700386 delta = q-p;
387 --q;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800388
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700389 while ( *q != '#' ) {
390 if ( *q >= '0' && *q <= '9' ) {
391 ucs += mult * (*q - '0');
392 }
393 else {
394 return 0;
395 }
396 mult *= 10;
397 --q;
398 }
399 }
400 // convert the UCS to UTF-8
401 ConvertUTF32ToUTF8( ucs, value, length );
402 return p + delta + 1;
403 }
404 return p+1;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800405}
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800406
407
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700408void XMLUtil::ToStr( int v, char* buffer, int bufferSize )
Lee Thomason21be8822012-07-15 17:27:22 -0700409{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700410 TIXML_SNPRINTF( buffer, bufferSize, "%d", v );
Lee Thomason21be8822012-07-15 17:27:22 -0700411}
412
413
414void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize )
415{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700416 TIXML_SNPRINTF( buffer, bufferSize, "%u", v );
Lee Thomason21be8822012-07-15 17:27:22 -0700417}
418
419
420void XMLUtil::ToStr( bool v, char* buffer, int bufferSize )
421{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700422 TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 );
Lee Thomason21be8822012-07-15 17:27:22 -0700423}
424
425
426void XMLUtil::ToStr( float v, char* buffer, int bufferSize )
427{
Lee Thomason (grinliz)d6bd7362013-05-11 20:23:13 -0700428 TIXML_SNPRINTF( buffer, bufferSize, "%f", v );
Lee Thomason21be8822012-07-15 17:27:22 -0700429}
430
431
432void XMLUtil::ToStr( double v, char* buffer, int bufferSize )
433{
Lee Thomason (grinliz)d6bd7362013-05-11 20:23:13 -0700434 TIXML_SNPRINTF( buffer, bufferSize, "%f", v );
Lee Thomason21be8822012-07-15 17:27:22 -0700435}
436
437
438bool XMLUtil::ToInt( const char* str, int* value )
439{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700440 if ( TIXML_SSCANF( str, "%d", value ) == 1 ) {
441 return true;
442 }
443 return false;
Lee Thomason21be8822012-07-15 17:27:22 -0700444}
445
446bool XMLUtil::ToUnsigned( const char* str, unsigned *value )
447{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700448 if ( TIXML_SSCANF( str, "%u", value ) == 1 ) {
449 return true;
450 }
451 return false;
Lee Thomason21be8822012-07-15 17:27:22 -0700452}
453
454bool XMLUtil::ToBool( const char* str, bool* value )
455{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700456 int ival = 0;
457 if ( ToInt( str, &ival )) {
458 *value = (ival==0) ? false : true;
459 return true;
460 }
461 if ( StringEqual( str, "true" ) ) {
462 *value = true;
463 return true;
464 }
465 else if ( StringEqual( str, "false" ) ) {
466 *value = false;
467 return true;
468 }
469 return false;
Lee Thomason21be8822012-07-15 17:27:22 -0700470}
471
472
473bool XMLUtil::ToFloat( const char* str, float* value )
474{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700475 if ( TIXML_SSCANF( str, "%f", value ) == 1 ) {
476 return true;
477 }
478 return false;
Lee Thomason21be8822012-07-15 17:27:22 -0700479}
480
481bool XMLUtil::ToDouble( const char* str, double* value )
482{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700483 if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) {
484 return true;
485 }
486 return false;
Lee Thomason21be8822012-07-15 17:27:22 -0700487}
488
489
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700490char* XMLDocument::Identify( char* p, XMLNode** node )
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800491{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700492 XMLNode* returnNode = 0;
493 char* start = p;
494 p = XMLUtil::SkipWhiteSpace( p );
495 if( !p || !*p ) {
496 return p;
497 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800498
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700499 // What is this thing?
500 // - Elements start with a letter or underscore, but xml is reserved.
501 // - Comments: <!--
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700502 // - Declaration: <?
503 // - Everything else is unknown to tinyxml.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700504 //
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800505
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700506 static const char* xmlHeader = { "<?" };
507 static const char* commentHeader = { "<!--" };
508 static const char* dtdHeader = { "<!" };
509 static const char* cdataHeader = { "<![CDATA[" };
510 static const char* elementHeader = { "<" }; // and a header for everything else; check last.
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800511
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700512 static const int xmlHeaderLen = 2;
513 static const int commentHeaderLen = 4;
514 static const int dtdHeaderLen = 2;
515 static const int cdataHeaderLen = 9;
516 static const int elementHeaderLen = 1;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800517
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800518#if defined(_MSC_VER)
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -0800519#pragma warning ( push )
520#pragma warning ( disable : 4127 )
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800521#endif
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700522 TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) ); // use same memory pool
523 TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) ); // use same memory pool
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800524#if defined(_MSC_VER)
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -0800525#pragma warning (pop)
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800526#endif
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700527 if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700528 returnNode = new (_commentPool.Alloc()) XMLDeclaration( this );
529 returnNode->_memPool = &_commentPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700530 p += xmlHeaderLen;
531 }
532 else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700533 returnNode = new (_commentPool.Alloc()) XMLComment( this );
534 returnNode->_memPool = &_commentPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700535 p += commentHeaderLen;
536 }
537 else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700538 XMLText* text = new (_textPool.Alloc()) XMLText( this );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700539 returnNode = text;
Lee Thomason624d43f2012-10-12 10:58:48 -0700540 returnNode->_memPool = &_textPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700541 p += cdataHeaderLen;
542 text->SetCData( true );
543 }
544 else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700545 returnNode = new (_commentPool.Alloc()) XMLUnknown( this );
546 returnNode->_memPool = &_commentPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700547 p += dtdHeaderLen;
548 }
549 else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700550 returnNode = new (_elementPool.Alloc()) XMLElement( this );
551 returnNode->_memPool = &_elementPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700552 p += elementHeaderLen;
553 }
554 else {
Lee Thomason624d43f2012-10-12 10:58:48 -0700555 returnNode = new (_textPool.Alloc()) XMLText( this );
556 returnNode->_memPool = &_textPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700557 p = start; // Back it up, all the text counts.
558 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800559
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700560 *node = returnNode;
561 return p;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800562}
563
564
Lee Thomason751da522012-02-10 08:50:51 -0800565bool XMLDocument::Accept( XMLVisitor* visitor ) const
566{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700567 if ( visitor->VisitEnter( *this ) ) {
568 for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
569 if ( !node->Accept( visitor ) ) {
570 break;
571 }
572 }
573 }
574 return visitor->VisitExit( *this );
Lee Thomason751da522012-02-10 08:50:51 -0800575}
Lee Thomason56bdd022012-02-09 18:16:58 -0800576
577
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800578// --------- XMLNode ----------- //
579
580XMLNode::XMLNode( XMLDocument* doc ) :
Lee Thomason624d43f2012-10-12 10:58:48 -0700581 _document( doc ),
582 _parent( 0 ),
583 _firstChild( 0 ), _lastChild( 0 ),
Thomas Roß61892312013-05-12 14:07:38 +0200584 _prev( 0 ), _next( 0 ),
585 _memPool( 0 )
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800586{
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800587}
588
589
590XMLNode::~XMLNode()
591{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700592 DeleteChildren();
Lee Thomason624d43f2012-10-12 10:58:48 -0700593 if ( _parent ) {
594 _parent->Unlink( this );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700595 }
Lee Thomason18d68bd2012-01-26 18:17:26 -0800596}
597
598
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800599void XMLNode::SetValue( const char* str, bool staticMem )
600{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700601 if ( staticMem ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700602 _value.SetInternedStr( str );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700603 }
604 else {
Lee Thomason624d43f2012-10-12 10:58:48 -0700605 _value.SetStr( str );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700606 }
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800607}
608
609
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800610void XMLNode::DeleteChildren()
Lee Thomason18d68bd2012-01-26 18:17:26 -0800611{
Lee Thomason624d43f2012-10-12 10:58:48 -0700612 while( _firstChild ) {
613 XMLNode* node = _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700614 Unlink( node );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700615
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700616 DELETE_NODE( node );
617 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700618 _firstChild = _lastChild = 0;
Lee Thomasond923c672012-01-23 08:44:25 -0800619}
620
621
622void XMLNode::Unlink( XMLNode* child )
623{
Lee Thomason624d43f2012-10-12 10:58:48 -0700624 TIXMLASSERT( child->_parent == this );
625 if ( child == _firstChild ) {
626 _firstChild = _firstChild->_next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700627 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700628 if ( child == _lastChild ) {
629 _lastChild = _lastChild->_prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700630 }
Lee Thomasond923c672012-01-23 08:44:25 -0800631
Lee Thomason624d43f2012-10-12 10:58:48 -0700632 if ( child->_prev ) {
633 child->_prev->_next = child->_next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700634 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700635 if ( child->_next ) {
636 child->_next->_prev = child->_prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700637 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700638 child->_parent = 0;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800639}
640
641
U-Stream\Leeae25a442012-02-17 17:48:16 -0800642void XMLNode::DeleteChild( XMLNode* node )
643{
Lee Thomason624d43f2012-10-12 10:58:48 -0700644 TIXMLASSERT( node->_parent == this );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700645 DELETE_NODE( node );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800646}
647
648
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800649XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )
650{
Lee Thomason624d43f2012-10-12 10:58:48 -0700651 if ( _lastChild ) {
652 TIXMLASSERT( _firstChild );
653 TIXMLASSERT( _lastChild->_next == 0 );
654 _lastChild->_next = addThis;
655 addThis->_prev = _lastChild;
656 _lastChild = addThis;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800657
Lee Thomason624d43f2012-10-12 10:58:48 -0700658 addThis->_next = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700659 }
660 else {
Lee Thomason624d43f2012-10-12 10:58:48 -0700661 TIXMLASSERT( _firstChild == 0 );
662 _firstChild = _lastChild = addThis;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800663
Lee Thomason624d43f2012-10-12 10:58:48 -0700664 addThis->_prev = 0;
665 addThis->_next = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700666 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700667 addThis->_parent = this;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800668 addThis->_memPool->SetTracked();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700669 return addThis;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800670}
671
672
Lee Thomason1ff38e02012-02-14 18:18:16 -0800673XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis )
674{
Lee Thomason624d43f2012-10-12 10:58:48 -0700675 if ( _firstChild ) {
676 TIXMLASSERT( _lastChild );
677 TIXMLASSERT( _firstChild->_prev == 0 );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800678
Lee Thomason624d43f2012-10-12 10:58:48 -0700679 _firstChild->_prev = addThis;
680 addThis->_next = _firstChild;
681 _firstChild = addThis;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800682
Lee Thomason624d43f2012-10-12 10:58:48 -0700683 addThis->_prev = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700684 }
685 else {
Lee Thomason624d43f2012-10-12 10:58:48 -0700686 TIXMLASSERT( _lastChild == 0 );
687 _firstChild = _lastChild = addThis;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800688
Lee Thomason624d43f2012-10-12 10:58:48 -0700689 addThis->_prev = 0;
690 addThis->_next = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700691 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700692 addThis->_parent = this;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800693 addThis->_memPool->SetTracked();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700694 return addThis;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800695}
696
697
698XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )
699{
Lee Thomason624d43f2012-10-12 10:58:48 -0700700 TIXMLASSERT( afterThis->_parent == this );
701 if ( afterThis->_parent != this ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700702 return 0;
703 }
Lee Thomason1ff38e02012-02-14 18:18:16 -0800704
Lee Thomason624d43f2012-10-12 10:58:48 -0700705 if ( afterThis->_next == 0 ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700706 // The last node or the only node.
707 return InsertEndChild( addThis );
708 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700709 addThis->_prev = afterThis;
710 addThis->_next = afterThis->_next;
711 afterThis->_next->_prev = addThis;
712 afterThis->_next = addThis;
713 addThis->_parent = this;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800714 addThis->_memPool->SetTracked();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700715 return addThis;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800716}
717
718
719
720
Lee Thomason56bdd022012-02-09 18:16:58 -0800721const XMLElement* XMLNode::FirstChildElement( const char* value ) const
Lee Thomason2c85a712012-01-31 08:24:24 -0800722{
Lee Thomason624d43f2012-10-12 10:58:48 -0700723 for( XMLNode* node=_firstChild; node; node=node->_next ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700724 XMLElement* element = node->ToElement();
725 if ( element ) {
726 if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
727 return element;
728 }
729 }
730 }
731 return 0;
Lee Thomason2c85a712012-01-31 08:24:24 -0800732}
733
734
Lee Thomason56bdd022012-02-09 18:16:58 -0800735const XMLElement* XMLNode::LastChildElement( const char* value ) const
736{
Lee Thomason624d43f2012-10-12 10:58:48 -0700737 for( XMLNode* node=_lastChild; node; node=node->_prev ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700738 XMLElement* element = node->ToElement();
739 if ( element ) {
740 if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
741 return element;
742 }
743 }
744 }
745 return 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800746}
747
748
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800749const XMLElement* XMLNode::NextSiblingElement( const char* value ) const
750{
Lee Thomason624d43f2012-10-12 10:58:48 -0700751 for( XMLNode* element=this->_next; element; element = element->_next ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700752 if ( element->ToElement()
753 && (!value || XMLUtil::StringEqual( value, element->Value() ))) {
754 return element->ToElement();
755 }
756 }
757 return 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800758}
759
760
761const XMLElement* XMLNode::PreviousSiblingElement( const char* value ) const
762{
Lee Thomason624d43f2012-10-12 10:58:48 -0700763 for( XMLNode* element=_prev; element; element = element->_prev ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700764 if ( element->ToElement()
765 && (!value || XMLUtil::StringEqual( value, element->Value() ))) {
766 return element->ToElement();
767 }
768 }
769 return 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800770}
771
772
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800773char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
Lee Thomason67d61312012-01-24 16:01:51 -0800774{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700775 // This is a recursive method, but thinking about it "at the current level"
776 // it is a pretty simple flat list:
777 // <foo/>
778 // <!-- comment -->
779 //
780 // With a special case:
781 // <foo>
782 // </foo>
783 // <!-- comment -->
784 //
785 // Where the closing element (/foo) *must* be the next thing after the opening
786 // element, and the names must match. BUT the tricky bit is that the closing
787 // element will be read by the child.
788 //
789 // 'endTag' is the end tag for this node, it is returned by a call to a child.
790 // 'parentEnd' is the end tag for the parent, which is filled in and returned.
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800791
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700792 while( p && *p ) {
793 XMLNode* node = 0;
Lee Thomasond6277762012-02-22 16:00:12 -0800794
Lee Thomason624d43f2012-10-12 10:58:48 -0700795 p = _document->Identify( p, &node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700796 if ( p == 0 || node == 0 ) {
797 break;
798 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800799
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700800 StrPair endTag;
801 p = node->ParseDeep( p, &endTag );
802 if ( !p ) {
803 DELETE_NODE( node );
804 node = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700805 if ( !_document->Error() ) {
806 _document->SetError( XML_ERROR_PARSING, 0, 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700807 }
808 break;
809 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800810
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700811 // We read the end tag. Return it to the parent.
812 if ( node->ToElement() && node->ToElement()->ClosingType() == XMLElement::CLOSING ) {
813 if ( parentEnd ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700814 *parentEnd = static_cast<XMLElement*>(node)->_value;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700815 }
Lee Thomason5b0a6772012-11-19 13:54:42 -0800816 node->_memPool->SetTracked(); // created and then immediately deleted.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700817 DELETE_NODE( node );
818 return p;
819 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800820
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700821 // Handle an end tag returned to this level.
822 // And handle a bunch of annoying errors.
823 XMLElement* ele = node->ToElement();
824 if ( ele ) {
825 if ( endTag.Empty() && ele->ClosingType() == XMLElement::OPEN ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700826 _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700827 p = 0;
828 }
829 else if ( !endTag.Empty() && ele->ClosingType() != XMLElement::OPEN ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700830 _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700831 p = 0;
832 }
833 else if ( !endTag.Empty() ) {
834 if ( !XMLUtil::StringEqual( endTag.GetStr(), node->Value() )) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700835 _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700836 p = 0;
837 }
838 }
839 }
840 if ( p == 0 ) {
841 DELETE_NODE( node );
842 node = 0;
843 }
844 if ( node ) {
845 this->InsertEndChild( node );
846 }
847 }
848 return 0;
Lee Thomason67d61312012-01-24 16:01:51 -0800849}
850
Lee Thomason5492a1c2012-01-23 15:32:10 -0800851// --------- XMLText ---------- //
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800852char* XMLText::ParseDeep( char* p, StrPair* )
Lee Thomason5492a1c2012-01-23 15:32:10 -0800853{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700854 const char* start = p;
855 if ( this->CData() ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700856 p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700857 if ( !p ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700858 _document->SetError( XML_ERROR_PARSING_CDATA, start, 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700859 }
860 return p;
861 }
862 else {
Lee Thomason624d43f2012-10-12 10:58:48 -0700863 int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES;
864 if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700865 flags |= StrPair::COLLAPSE_WHITESPACE;
866 }
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -0700867
Lee Thomason624d43f2012-10-12 10:58:48 -0700868 p = _value.ParseText( p, "<", flags );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700869 if ( !p ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700870 _document->SetError( XML_ERROR_PARSING_TEXT, start, 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700871 }
872 if ( p && *p ) {
873 return p-1;
874 }
875 }
876 return 0;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800877}
878
879
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800880XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const
881{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700882 if ( !doc ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700883 doc = _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700884 }
885 XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern?
886 text->SetCData( this->CData() );
887 return text;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800888}
889
890
891bool XMLText::ShallowEqual( const XMLNode* compare ) const
892{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700893 return ( compare->ToText() && XMLUtil::StringEqual( compare->ToText()->Value(), Value() ));
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800894}
895
896
Lee Thomason56bdd022012-02-09 18:16:58 -0800897bool XMLText::Accept( XMLVisitor* visitor ) const
898{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700899 return visitor->Visit( *this );
Lee Thomason56bdd022012-02-09 18:16:58 -0800900}
901
902
Lee Thomason3f57d272012-01-11 15:30:03 -0800903// --------- XMLComment ---------- //
904
Lee Thomasone4422302012-01-20 17:59:50 -0800905XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc )
Lee Thomason3f57d272012-01-11 15:30:03 -0800906{
907}
908
909
Lee Thomasonce0763e2012-01-11 15:43:54 -0800910XMLComment::~XMLComment()
Lee Thomason3f57d272012-01-11 15:30:03 -0800911{
Lee Thomason3f57d272012-01-11 15:30:03 -0800912}
913
914
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800915char* XMLComment::ParseDeep( char* p, StrPair* )
Lee Thomason3f57d272012-01-11 15:30:03 -0800916{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700917 // Comment parses as text.
918 const char* start = p;
Lee Thomason624d43f2012-10-12 10:58:48 -0700919 p = _value.ParseText( p, "-->", StrPair::COMMENT );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700920 if ( p == 0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700921 _document->SetError( XML_ERROR_PARSING_COMMENT, start, 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700922 }
923 return p;
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800924}
925
926
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800927XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const
928{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700929 if ( !doc ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700930 doc = _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700931 }
932 XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern?
933 return comment;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800934}
935
936
937bool XMLComment::ShallowEqual( const XMLNode* compare ) const
938{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700939 return ( compare->ToComment() && XMLUtil::StringEqual( compare->ToComment()->Value(), Value() ));
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800940}
941
942
Lee Thomason751da522012-02-10 08:50:51 -0800943bool XMLComment::Accept( XMLVisitor* visitor ) const
944{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700945 return visitor->Visit( *this );
Lee Thomason751da522012-02-10 08:50:51 -0800946}
Lee Thomason56bdd022012-02-09 18:16:58 -0800947
948
Lee Thomason50f97b22012-02-11 16:33:40 -0800949// --------- XMLDeclaration ---------- //
950
951XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc )
952{
953}
954
955
956XMLDeclaration::~XMLDeclaration()
957{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700958 //printf( "~XMLDeclaration\n" );
Lee Thomason50f97b22012-02-11 16:33:40 -0800959}
960
961
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800962char* XMLDeclaration::ParseDeep( char* p, StrPair* )
Lee Thomason50f97b22012-02-11 16:33:40 -0800963{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700964 // Declaration parses as text.
965 const char* start = p;
Lee Thomason624d43f2012-10-12 10:58:48 -0700966 p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700967 if ( p == 0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700968 _document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700969 }
970 return p;
Lee Thomason50f97b22012-02-11 16:33:40 -0800971}
972
973
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800974XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const
975{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700976 if ( !doc ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700977 doc = _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700978 }
979 XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern?
980 return dec;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800981}
982
983
984bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const
985{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700986 return ( compare->ToDeclaration() && XMLUtil::StringEqual( compare->ToDeclaration()->Value(), Value() ));
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800987}
988
989
990
Lee Thomason50f97b22012-02-11 16:33:40 -0800991bool XMLDeclaration::Accept( XMLVisitor* visitor ) const
992{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700993 return visitor->Visit( *this );
Lee Thomason50f97b22012-02-11 16:33:40 -0800994}
995
996// --------- XMLUnknown ---------- //
997
998XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc )
999{
1000}
1001
1002
1003XMLUnknown::~XMLUnknown()
1004{
1005}
1006
1007
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -08001008char* XMLUnknown::ParseDeep( char* p, StrPair* )
Lee Thomason50f97b22012-02-11 16:33:40 -08001009{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001010 // Unknown parses as text.
1011 const char* start = p;
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001012
Lee Thomason624d43f2012-10-12 10:58:48 -07001013 p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001014 if ( !p ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001015 _document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001016 }
1017 return p;
Lee Thomason50f97b22012-02-11 16:33:40 -08001018}
1019
1020
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001021XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const
1022{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001023 if ( !doc ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001024 doc = _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001025 }
1026 XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern?
1027 return text;
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001028}
1029
1030
1031bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const
1032{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001033 return ( compare->ToUnknown() && XMLUtil::StringEqual( compare->ToUnknown()->Value(), Value() ));
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001034}
1035
1036
Lee Thomason50f97b22012-02-11 16:33:40 -08001037bool XMLUnknown::Accept( XMLVisitor* visitor ) const
1038{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001039 return visitor->Visit( *this );
Lee Thomason50f97b22012-02-11 16:33:40 -08001040}
1041
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001042// --------- XMLAttribute ---------- //
Lee Thomason6f381b72012-03-02 12:59:39 -08001043char* XMLAttribute::ParseDeep( char* p, bool processEntities )
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001044{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001045 // Parse using the name rules: bug fix, was using ParseText before
Lee Thomason624d43f2012-10-12 10:58:48 -07001046 p = _name.ParseName( p );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001047 if ( !p || !*p ) {
1048 return 0;
1049 }
Lee Thomason22aead12012-01-23 13:29:35 -08001050
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001051 // Skip white space before =
1052 p = XMLUtil::SkipWhiteSpace( p );
1053 if ( !p || *p != '=' ) {
1054 return 0;
1055 }
Lee Thomason78a773d2012-07-02 10:10:19 -07001056
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001057 ++p; // move up to opening quote
1058 p = XMLUtil::SkipWhiteSpace( p );
1059 if ( *p != '\"' && *p != '\'' ) {
1060 return 0;
1061 }
Lee Thomason78a773d2012-07-02 10:10:19 -07001062
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001063 char endTag[2] = { *p, 0 };
1064 ++p; // move past opening quote
Lee Thomason78a773d2012-07-02 10:10:19 -07001065
Lee Thomason624d43f2012-10-12 10:58:48 -07001066 p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001067 return p;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001068}
1069
1070
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001071void XMLAttribute::SetName( const char* n )
1072{
Lee Thomason624d43f2012-10-12 10:58:48 -07001073 _name.SetStr( n );
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001074}
1075
1076
Lee Thomason2fa81722012-11-09 12:37:46 -08001077XMLError XMLAttribute::QueryIntValue( int* value ) const
Lee Thomason1ff38e02012-02-14 18:18:16 -08001078{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001079 if ( XMLUtil::ToInt( Value(), value )) {
1080 return XML_NO_ERROR;
1081 }
1082 return XML_WRONG_ATTRIBUTE_TYPE;
Lee Thomason1ff38e02012-02-14 18:18:16 -08001083}
1084
1085
Lee Thomason2fa81722012-11-09 12:37:46 -08001086XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const
Lee Thomason1ff38e02012-02-14 18:18:16 -08001087{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001088 if ( XMLUtil::ToUnsigned( Value(), value )) {
1089 return XML_NO_ERROR;
1090 }
1091 return XML_WRONG_ATTRIBUTE_TYPE;
Lee Thomason1ff38e02012-02-14 18:18:16 -08001092}
1093
1094
Lee Thomason2fa81722012-11-09 12:37:46 -08001095XMLError XMLAttribute::QueryBoolValue( bool* value ) const
Lee Thomason1ff38e02012-02-14 18:18:16 -08001096{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001097 if ( XMLUtil::ToBool( Value(), value )) {
1098 return XML_NO_ERROR;
1099 }
1100 return XML_WRONG_ATTRIBUTE_TYPE;
Lee Thomason1ff38e02012-02-14 18:18:16 -08001101}
1102
1103
Lee Thomason2fa81722012-11-09 12:37:46 -08001104XMLError XMLAttribute::QueryFloatValue( float* value ) const
Lee Thomason1ff38e02012-02-14 18:18:16 -08001105{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001106 if ( XMLUtil::ToFloat( Value(), value )) {
1107 return XML_NO_ERROR;
1108 }
1109 return XML_WRONG_ATTRIBUTE_TYPE;
Lee Thomason21be8822012-07-15 17:27:22 -07001110}
1111
1112
Lee Thomason2fa81722012-11-09 12:37:46 -08001113XMLError XMLAttribute::QueryDoubleValue( double* value ) const
Lee Thomason21be8822012-07-15 17:27:22 -07001114{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001115 if ( XMLUtil::ToDouble( Value(), value )) {
1116 return XML_NO_ERROR;
1117 }
1118 return XML_WRONG_ATTRIBUTE_TYPE;
Lee Thomason1ff38e02012-02-14 18:18:16 -08001119}
1120
1121
1122void XMLAttribute::SetAttribute( const char* v )
1123{
Lee Thomason624d43f2012-10-12 10:58:48 -07001124 _value.SetStr( v );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001125}
1126
1127
Lee Thomason1ff38e02012-02-14 18:18:16 -08001128void XMLAttribute::SetAttribute( int v )
1129{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001130 char buf[BUF_SIZE];
1131 XMLUtil::ToStr( v, buf, BUF_SIZE );
Lee Thomason624d43f2012-10-12 10:58:48 -07001132 _value.SetStr( buf );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001133}
Lee Thomason1a1d4a72012-02-15 09:09:25 -08001134
1135
1136void XMLAttribute::SetAttribute( unsigned v )
1137{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001138 char buf[BUF_SIZE];
1139 XMLUtil::ToStr( v, buf, BUF_SIZE );
Lee Thomason624d43f2012-10-12 10:58:48 -07001140 _value.SetStr( buf );
Lee Thomason1a1d4a72012-02-15 09:09:25 -08001141}
1142
1143
1144void XMLAttribute::SetAttribute( bool v )
1145{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001146 char buf[BUF_SIZE];
1147 XMLUtil::ToStr( v, buf, BUF_SIZE );
Lee Thomason624d43f2012-10-12 10:58:48 -07001148 _value.SetStr( buf );
Lee Thomason1a1d4a72012-02-15 09:09:25 -08001149}
1150
1151void XMLAttribute::SetAttribute( double v )
1152{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001153 char buf[BUF_SIZE];
1154 XMLUtil::ToStr( v, buf, BUF_SIZE );
Lee Thomason624d43f2012-10-12 10:58:48 -07001155 _value.SetStr( buf );
Lee Thomason1a1d4a72012-02-15 09:09:25 -08001156}
1157
1158void XMLAttribute::SetAttribute( float v )
1159{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001160 char buf[BUF_SIZE];
1161 XMLUtil::ToStr( v, buf, BUF_SIZE );
Lee Thomason624d43f2012-10-12 10:58:48 -07001162 _value.SetStr( buf );
Lee Thomason1a1d4a72012-02-15 09:09:25 -08001163}
1164
Lee Thomasondadcdfa2012-01-18 17:55:48 -08001165
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001166// --------- XMLElement ---------- //
1167XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ),
Lee Thomason624d43f2012-10-12 10:58:48 -07001168 _closingType( 0 ),
1169 _rootAttribute( 0 )
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001170{
1171}
1172
1173
1174XMLElement::~XMLElement()
1175{
Lee Thomason624d43f2012-10-12 10:58:48 -07001176 while( _rootAttribute ) {
1177 XMLAttribute* next = _rootAttribute->_next;
1178 DELETE_ATTRIBUTE( _rootAttribute );
1179 _rootAttribute = next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001180 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001181}
1182
1183
Lee Thomason1a1d4a72012-02-15 09:09:25 -08001184XMLAttribute* XMLElement::FindAttribute( const char* name )
1185{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001186 XMLAttribute* a = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -07001187 for( a=_rootAttribute; a; a = a->_next ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001188 if ( XMLUtil::StringEqual( a->Name(), name ) ) {
1189 return a;
1190 }
1191 }
1192 return 0;
Lee Thomason1a1d4a72012-02-15 09:09:25 -08001193}
1194
1195
1196const XMLAttribute* XMLElement::FindAttribute( const char* name ) const
1197{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001198 XMLAttribute* a = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -07001199 for( a=_rootAttribute; a; a = a->_next ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001200 if ( XMLUtil::StringEqual( a->Name(), name ) ) {
1201 return a;
1202 }
1203 }
1204 return 0;
Lee Thomason1a1d4a72012-02-15 09:09:25 -08001205}
1206
1207
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001208const char* XMLElement::Attribute( const char* name, const char* value ) const
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001209{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001210 const XMLAttribute* a = FindAttribute( name );
1211 if ( !a ) {
1212 return 0;
1213 }
1214 if ( !value || XMLUtil::StringEqual( a->Value(), value )) {
1215 return a->Value();
1216 }
1217 return 0;
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001218}
1219
1220
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001221const char* XMLElement::GetText() const
1222{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001223 if ( FirstChild() && FirstChild()->ToText() ) {
1224 return FirstChild()->ToText()->Value();
1225 }
1226 return 0;
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001227}
1228
1229
MortenMacFly4ee49f12013-01-14 20:03:14 +01001230XMLError XMLElement::QueryIntText( int* ival ) const
Lee Thomason21be8822012-07-15 17:27:22 -07001231{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001232 if ( FirstChild() && FirstChild()->ToText() ) {
1233 const char* t = FirstChild()->ToText()->Value();
MortenMacFly4ee49f12013-01-14 20:03:14 +01001234 if ( XMLUtil::ToInt( t, ival ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001235 return XML_SUCCESS;
1236 }
1237 return XML_CAN_NOT_CONVERT_TEXT;
1238 }
1239 return XML_NO_TEXT_NODE;
Lee Thomason21be8822012-07-15 17:27:22 -07001240}
1241
1242
MortenMacFly4ee49f12013-01-14 20:03:14 +01001243XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const
Lee Thomason21be8822012-07-15 17:27:22 -07001244{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001245 if ( FirstChild() && FirstChild()->ToText() ) {
1246 const char* t = FirstChild()->ToText()->Value();
MortenMacFly4ee49f12013-01-14 20:03:14 +01001247 if ( XMLUtil::ToUnsigned( t, uval ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001248 return XML_SUCCESS;
1249 }
1250 return XML_CAN_NOT_CONVERT_TEXT;
1251 }
1252 return XML_NO_TEXT_NODE;
Lee Thomason21be8822012-07-15 17:27:22 -07001253}
1254
1255
MortenMacFly4ee49f12013-01-14 20:03:14 +01001256XMLError XMLElement::QueryBoolText( bool* bval ) const
Lee Thomason21be8822012-07-15 17:27:22 -07001257{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001258 if ( FirstChild() && FirstChild()->ToText() ) {
1259 const char* t = FirstChild()->ToText()->Value();
MortenMacFly4ee49f12013-01-14 20:03:14 +01001260 if ( XMLUtil::ToBool( t, bval ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001261 return XML_SUCCESS;
1262 }
1263 return XML_CAN_NOT_CONVERT_TEXT;
1264 }
1265 return XML_NO_TEXT_NODE;
Lee Thomason21be8822012-07-15 17:27:22 -07001266}
1267
1268
MortenMacFly4ee49f12013-01-14 20:03:14 +01001269XMLError XMLElement::QueryDoubleText( double* dval ) const
Lee Thomason21be8822012-07-15 17:27:22 -07001270{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001271 if ( FirstChild() && FirstChild()->ToText() ) {
1272 const char* t = FirstChild()->ToText()->Value();
MortenMacFly4ee49f12013-01-14 20:03:14 +01001273 if ( XMLUtil::ToDouble( t, dval ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001274 return XML_SUCCESS;
1275 }
1276 return XML_CAN_NOT_CONVERT_TEXT;
1277 }
1278 return XML_NO_TEXT_NODE;
Lee Thomason21be8822012-07-15 17:27:22 -07001279}
1280
1281
MortenMacFly4ee49f12013-01-14 20:03:14 +01001282XMLError XMLElement::QueryFloatText( float* fval ) const
Lee Thomason21be8822012-07-15 17:27:22 -07001283{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001284 if ( FirstChild() && FirstChild()->ToText() ) {
1285 const char* t = FirstChild()->ToText()->Value();
MortenMacFly4ee49f12013-01-14 20:03:14 +01001286 if ( XMLUtil::ToFloat( t, fval ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001287 return XML_SUCCESS;
1288 }
1289 return XML_CAN_NOT_CONVERT_TEXT;
1290 }
1291 return XML_NO_TEXT_NODE;
Lee Thomason21be8822012-07-15 17:27:22 -07001292}
1293
1294
1295
Lee Thomason1a1d4a72012-02-15 09:09:25 -08001296XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )
1297{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001298 XMLAttribute* last = 0;
1299 XMLAttribute* attrib = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -07001300 for( attrib = _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001301 attrib;
Lee Thomason624d43f2012-10-12 10:58:48 -07001302 last = attrib, attrib = attrib->_next ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001303 if ( XMLUtil::StringEqual( attrib->Name(), name ) ) {
1304 break;
1305 }
1306 }
1307 if ( !attrib ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001308 attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
1309 attrib->_memPool = &_document->_attributePool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001310 if ( last ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001311 last->_next = attrib;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001312 }
1313 else {
Lee Thomason624d43f2012-10-12 10:58:48 -07001314 _rootAttribute = attrib;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001315 }
1316 attrib->SetName( name );
Lee Thomason5b0a6772012-11-19 13:54:42 -08001317 attrib->_memPool->SetTracked(); // always created and linked.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001318 }
1319 return attrib;
Lee Thomason1a1d4a72012-02-15 09:09:25 -08001320}
1321
1322
U-Stream\Leeae25a442012-02-17 17:48:16 -08001323void XMLElement::DeleteAttribute( const char* name )
1324{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001325 XMLAttribute* prev = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -07001326 for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001327 if ( XMLUtil::StringEqual( name, a->Name() ) ) {
1328 if ( prev ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001329 prev->_next = a->_next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001330 }
1331 else {
Lee Thomason624d43f2012-10-12 10:58:48 -07001332 _rootAttribute = a->_next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001333 }
1334 DELETE_ATTRIBUTE( a );
1335 break;
1336 }
1337 prev = a;
1338 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001339}
1340
1341
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001342char* XMLElement::ParseAttributes( char* p )
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001343{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001344 const char* start = p;
1345 XMLAttribute* prevAttribute = 0;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001346
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001347 // Read the attributes.
1348 while( p ) {
1349 p = XMLUtil::SkipWhiteSpace( p );
1350 if ( !p || !(*p) ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001351 _document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001352 return 0;
1353 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001354
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001355 // attribute.
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +02001356 if (XMLUtil::IsNameStartChar( *p ) ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001357 XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
1358 attrib->_memPool = &_document->_attributePool;
Lee Thomason5b0a6772012-11-19 13:54:42 -08001359 attrib->_memPool->SetTracked();
Lee Thomasond1983222012-02-06 08:41:24 -08001360
Lee Thomason624d43f2012-10-12 10:58:48 -07001361 p = attrib->ParseDeep( p, _document->ProcessEntities() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001362 if ( !p || Attribute( attrib->Name() ) ) {
1363 DELETE_ATTRIBUTE( attrib );
Lee Thomason624d43f2012-10-12 10:58:48 -07001364 _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001365 return 0;
1366 }
1367 // There is a minor bug here: if the attribute in the source xml
1368 // document is duplicated, it will not be detected and the
1369 // attribute will be doubly added. However, tracking the 'prevAttribute'
1370 // avoids re-scanning the attribute list. Preferring performance for
1371 // now, may reconsider in the future.
1372 if ( prevAttribute ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001373 prevAttribute->_next = attrib;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001374 }
1375 else {
Lee Thomason624d43f2012-10-12 10:58:48 -07001376 _rootAttribute = attrib;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001377 }
1378 prevAttribute = attrib;
1379 }
1380 // end of the tag
1381 else if ( *p == '/' && *(p+1) == '>' ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001382 _closingType = CLOSED;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001383 return p+2; // done; sealed element.
1384 }
1385 // end of the tag
1386 else if ( *p == '>' ) {
1387 ++p;
1388 break;
1389 }
1390 else {
Lee Thomason624d43f2012-10-12 10:58:48 -07001391 _document->SetError( XML_ERROR_PARSING_ELEMENT, start, p );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001392 return 0;
1393 }
1394 }
1395 return p;
Lee Thomason67d61312012-01-24 16:01:51 -08001396}
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001397
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001398
Lee Thomason67d61312012-01-24 16:01:51 -08001399//
1400// <ele></ele>
1401// <ele>foo<b>bar</b></ele>
1402//
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -08001403char* XMLElement::ParseDeep( char* p, StrPair* strPair )
Lee Thomason67d61312012-01-24 16:01:51 -08001404{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001405 // Read the element name.
1406 p = XMLUtil::SkipWhiteSpace( p );
1407 if ( !p ) {
1408 return 0;
1409 }
Lee Thomason67d61312012-01-24 16:01:51 -08001410
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001411 // The closing element is the </element> form. It is
1412 // parsed just like a regular element then deleted from
1413 // the DOM.
1414 if ( *p == '/' ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001415 _closingType = CLOSING;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001416 ++p;
1417 }
Lee Thomason67d61312012-01-24 16:01:51 -08001418
Lee Thomason624d43f2012-10-12 10:58:48 -07001419 p = _value.ParseName( p );
1420 if ( _value.Empty() ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001421 return 0;
1422 }
Lee Thomason67d61312012-01-24 16:01:51 -08001423
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001424 p = ParseAttributes( p );
Lee Thomason624d43f2012-10-12 10:58:48 -07001425 if ( !p || !*p || _closingType ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001426 return p;
1427 }
Lee Thomason67d61312012-01-24 16:01:51 -08001428
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001429 p = XMLNode::ParseDeep( p, strPair );
1430 return p;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001431}
1432
1433
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001434
1435XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const
1436{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001437 if ( !doc ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001438 doc = _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001439 }
1440 XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern?
1441 for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) {
1442 element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern?
1443 }
1444 return element;
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001445}
1446
1447
1448bool XMLElement::ShallowEqual( const XMLNode* compare ) const
1449{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001450 const XMLElement* other = compare->ToElement();
1451 if ( other && XMLUtil::StringEqual( other->Value(), Value() )) {
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001452
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001453 const XMLAttribute* a=FirstAttribute();
1454 const XMLAttribute* b=other->FirstAttribute();
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001455
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001456 while ( a && b ) {
1457 if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) {
1458 return false;
1459 }
1460 a = a->Next();
1461 b = b->Next();
1462 }
1463 if ( a || b ) {
1464 // different count
1465 return false;
1466 }
1467 return true;
1468 }
1469 return false;
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001470}
1471
1472
Lee Thomason751da522012-02-10 08:50:51 -08001473bool XMLElement::Accept( XMLVisitor* visitor ) const
1474{
Lee Thomason624d43f2012-10-12 10:58:48 -07001475 if ( visitor->VisitEnter( *this, _rootAttribute ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001476 for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
1477 if ( !node->Accept( visitor ) ) {
1478 break;
1479 }
1480 }
1481 }
1482 return visitor->VisitExit( *this );
Lee Thomason751da522012-02-10 08:50:51 -08001483}
Lee Thomason56bdd022012-02-09 18:16:58 -08001484
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001485
Lee Thomason3f57d272012-01-11 15:30:03 -08001486// --------- XMLDocument ----------- //
Lee Thomason624d43f2012-10-12 10:58:48 -07001487XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) :
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001488 XMLNode( 0 ),
Lee Thomason624d43f2012-10-12 10:58:48 -07001489 _writeBOM( false ),
1490 _processEntities( processEntities ),
Lee Thomason2fa81722012-11-09 12:37:46 -08001491 _errorID( XML_NO_ERROR ),
Lee Thomason624d43f2012-10-12 10:58:48 -07001492 _whitespace( whitespace ),
1493 _errorStr1( 0 ),
1494 _errorStr2( 0 ),
1495 _charBuffer( 0 )
U-Lama\Lee560bd472011-12-28 19:42:49 -08001496{
Lee Thomason624d43f2012-10-12 10:58:48 -07001497 _document = this; // avoid warning about 'this' in initializer list
U-Lama\Lee560bd472011-12-28 19:42:49 -08001498}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001499
1500
Lee Thomason3f57d272012-01-11 15:30:03 -08001501XMLDocument::~XMLDocument()
1502{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001503 DeleteChildren();
Lee Thomason624d43f2012-10-12 10:58:48 -07001504 delete [] _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001505
Lee Thomason (grinliz)61cea672013-02-01 19:13:13 -08001506#if 0
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -08001507 _textPool.Trace( "text" );
1508 _elementPool.Trace( "element" );
1509 _commentPool.Trace( "comment" );
1510 _attributePool.Trace( "attribute" );
Lee Thomasone9ecdab2012-02-13 18:11:20 -08001511#endif
1512
Lee Thomason5b0a6772012-11-19 13:54:42 -08001513#ifdef DEBUG
1514 if ( Error() == false ) {
1515 TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() );
1516 TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );
1517 TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() );
1518 TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() );
1519 }
1520#endif
Lee Thomason3f57d272012-01-11 15:30:03 -08001521}
1522
1523
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001524void XMLDocument::Clear()
Lee Thomason18d68bd2012-01-26 18:17:26 -08001525{
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001526 DeleteChildren();
1527
Lee Thomason624d43f2012-10-12 10:58:48 -07001528 _errorID = XML_NO_ERROR;
1529 _errorStr1 = 0;
1530 _errorStr2 = 0;
Lee Thomason18d68bd2012-01-26 18:17:26 -08001531
Lee Thomason624d43f2012-10-12 10:58:48 -07001532 delete [] _charBuffer;
1533 _charBuffer = 0;
Lee Thomason18d68bd2012-01-26 18:17:26 -08001534}
1535
Lee Thomason3f57d272012-01-11 15:30:03 -08001536
Lee Thomason2c85a712012-01-31 08:24:24 -08001537XMLElement* XMLDocument::NewElement( const char* name )
1538{
Lee Thomason624d43f2012-10-12 10:58:48 -07001539 XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this );
1540 ele->_memPool = &_elementPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001541 ele->SetName( name );
1542 return ele;
Lee Thomason2c85a712012-01-31 08:24:24 -08001543}
1544
1545
Lee Thomason1ff38e02012-02-14 18:18:16 -08001546XMLComment* XMLDocument::NewComment( const char* str )
1547{
Lee Thomason624d43f2012-10-12 10:58:48 -07001548 XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this );
1549 comment->_memPool = &_commentPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001550 comment->SetValue( str );
1551 return comment;
Lee Thomason1ff38e02012-02-14 18:18:16 -08001552}
1553
1554
1555XMLText* XMLDocument::NewText( const char* str )
1556{
Lee Thomason624d43f2012-10-12 10:58:48 -07001557 XMLText* text = new (_textPool.Alloc()) XMLText( this );
1558 text->_memPool = &_textPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001559 text->SetValue( str );
1560 return text;
Lee Thomason1ff38e02012-02-14 18:18:16 -08001561}
1562
1563
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001564XMLDeclaration* XMLDocument::NewDeclaration( const char* str )
1565{
Lee Thomason624d43f2012-10-12 10:58:48 -07001566 XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this );
1567 dec->_memPool = &_commentPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001568 dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" );
1569 return dec;
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001570}
1571
1572
1573XMLUnknown* XMLDocument::NewUnknown( const char* str )
1574{
Lee Thomason624d43f2012-10-12 10:58:48 -07001575 XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this );
1576 unk->_memPool = &_commentPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001577 unk->SetValue( str );
1578 return unk;
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001579}
1580
1581
Lee Thomason2fa81722012-11-09 12:37:46 -08001582XMLError XMLDocument::LoadFile( const char* filename )
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001583{
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001584 Clear();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001585 FILE* fp = 0;
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001586
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001587#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
1588 errno_t err = fopen_s(&fp, filename, "rb" );
1589 if ( !fp || err) {
1590#else
1591 fp = fopen( filename, "rb" );
1592 if ( !fp) {
1593#endif
1594 SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -07001595 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001596 }
1597 LoadFile( fp );
1598 fclose( fp );
Lee Thomason624d43f2012-10-12 10:58:48 -07001599 return _errorID;
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001600}
1601
1602
Lee Thomason2fa81722012-11-09 12:37:46 -08001603XMLError XMLDocument::LoadFile( FILE* fp )
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001604{
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001605 Clear();
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001606
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001607 fseek( fp, 0, SEEK_END );
1608 size_t size = ftell( fp );
1609 fseek( fp, 0, SEEK_SET );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001610
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001611 if ( size == 0 ) {
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001612 SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -07001613 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001614 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001615
Lee Thomason624d43f2012-10-12 10:58:48 -07001616 _charBuffer = new char[size+1];
1617 size_t read = fread( _charBuffer, 1, size, fp );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001618 if ( read != size ) {
1619 SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -07001620 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001621 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001622
Lee Thomason624d43f2012-10-12 10:58:48 -07001623 _charBuffer[size] = 0;
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001624
Lee Thomason624d43f2012-10-12 10:58:48 -07001625 const char* p = _charBuffer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001626 p = XMLUtil::SkipWhiteSpace( p );
Lee Thomason624d43f2012-10-12 10:58:48 -07001627 p = XMLUtil::ReadBOM( p, &_writeBOM );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001628 if ( !p || !*p ) {
1629 SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -07001630 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001631 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001632
Lee Thomason624d43f2012-10-12 10:58:48 -07001633 ParseDeep( _charBuffer + (p-_charBuffer), 0 );
1634 return _errorID;
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001635}
1636
1637
Lee Thomason2fa81722012-11-09 12:37:46 -08001638XMLError XMLDocument::SaveFile( const char* filename, bool compact )
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001639{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001640 FILE* fp = 0;
1641#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
1642 errno_t err = fopen_s(&fp, filename, "w" );
1643 if ( !fp || err) {
1644#else
1645 fp = fopen( filename, "w" );
1646 if ( !fp) {
1647#endif
1648 SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -07001649 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001650 }
1651 SaveFile(fp, compact);
1652 fclose( fp );
Lee Thomason624d43f2012-10-12 10:58:48 -07001653 return _errorID;
Ken Miller81da1fb2012-04-09 23:32:26 -05001654}
1655
1656
Lee Thomason2fa81722012-11-09 12:37:46 -08001657XMLError XMLDocument::SaveFile( FILE* fp, bool compact )
Ken Miller81da1fb2012-04-09 23:32:26 -05001658{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001659 XMLPrinter stream( fp, compact );
1660 Print( &stream );
Lee Thomason624d43f2012-10-12 10:58:48 -07001661 return _errorID;
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001662}
1663
Lee Thomason1ff38e02012-02-14 18:18:16 -08001664
Lee Thomason2fa81722012-11-09 12:37:46 -08001665XMLError XMLDocument::Parse( const char* p, size_t len )
Lee Thomason3f57d272012-01-11 15:30:03 -08001666{
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001667 const char* start = p;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001668 Clear();
Lee Thomason18d68bd2012-01-26 18:17:26 -08001669
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001670 if ( !p || !*p ) {
1671 SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -07001672 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001673 }
1674 if ( len == (size_t)(-1) ) {
1675 len = strlen( p );
1676 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001677 _charBuffer = new char[ len+1 ];
1678 memcpy( _charBuffer, p, len );
1679 _charBuffer[len] = 0;
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001680
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001681 p = XMLUtil::SkipWhiteSpace( p );
Lee Thomason624d43f2012-10-12 10:58:48 -07001682 p = XMLUtil::ReadBOM( p, &_writeBOM );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001683 if ( !p || !*p ) {
1684 SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -07001685 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001686 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001687
Thomas Roß1470edc2013-05-10 15:44:12 +02001688 ptrdiff_t delta = p - start; // skip initial whitespace, BOM, etc.
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001689 ParseDeep( _charBuffer+delta, 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -07001690 return _errorID;
Lee Thomason3f57d272012-01-11 15:30:03 -08001691}
1692
1693
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001694void XMLDocument::Print( XMLPrinter* streamer )
Lee Thomason3f57d272012-01-11 15:30:03 -08001695{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001696 XMLPrinter stdStreamer( stdout );
1697 if ( !streamer ) {
1698 streamer = &stdStreamer;
1699 }
1700 Accept( streamer );
Lee Thomason3f57d272012-01-11 15:30:03 -08001701}
1702
1703
Lee Thomason2fa81722012-11-09 12:37:46 -08001704void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 )
Lee Thomason67d61312012-01-24 16:01:51 -08001705{
Lee Thomason624d43f2012-10-12 10:58:48 -07001706 _errorID = error;
1707 _errorStr1 = str1;
1708 _errorStr2 = str2;
Lee Thomason67d61312012-01-24 16:01:51 -08001709}
1710
Lee Thomason5cae8972012-01-24 18:03:07 -08001711
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001712void XMLDocument::PrintError() const
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001713{
Lee Thomason624d43f2012-10-12 10:58:48 -07001714 if ( _errorID ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001715 static const int LEN = 20;
1716 char buf1[LEN] = { 0 };
1717 char buf2[LEN] = { 0 };
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001718
Lee Thomason624d43f2012-10-12 10:58:48 -07001719 if ( _errorStr1 ) {
1720 TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr1 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001721 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001722 if ( _errorStr2 ) {
1723 TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001724 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001725
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001726 printf( "XMLDocument error id=%d str1=%s str2=%s\n",
Lee Thomason624d43f2012-10-12 10:58:48 -07001727 _errorID, buf1, buf2 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001728 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001729}
1730
1731
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001732XMLPrinter::XMLPrinter( FILE* file, bool compact ) :
Lee Thomason624d43f2012-10-12 10:58:48 -07001733 _elementJustOpened( false ),
1734 _firstElement( true ),
1735 _fp( file ),
1736 _depth( 0 ),
1737 _textDepth( -1 ),
1738 _processEntities( true ),
1739 _compactMode( compact )
Lee Thomason5cae8972012-01-24 18:03:07 -08001740{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001741 for( int i=0; i<ENTITY_RANGE; ++i ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001742 _entityFlag[i] = false;
1743 _restrictedEntityFlag[i] = false;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001744 }
1745 for( int i=0; i<NUM_ENTITIES; ++i ) {
1746 TIXMLASSERT( entities[i].value < ENTITY_RANGE );
1747 if ( entities[i].value < ENTITY_RANGE ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001748 _entityFlag[ (int)entities[i].value ] = true;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001749 }
1750 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001751 _restrictedEntityFlag[(int)'&'] = true;
1752 _restrictedEntityFlag[(int)'<'] = true;
1753 _restrictedEntityFlag[(int)'>'] = true; // not required, but consistency is nice
1754 _buffer.Push( 0 );
U-Stream\Leeae25a442012-02-17 17:48:16 -08001755}
1756
1757
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001758void XMLPrinter::Print( const char* format, ... )
U-Stream\Leeae25a442012-02-17 17:48:16 -08001759{
1760 va_list va;
1761 va_start( va, format );
1762
Lee Thomason624d43f2012-10-12 10:58:48 -07001763 if ( _fp ) {
1764 vfprintf( _fp, format, va );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001765 }
1766 else {
1767 // This seems brutally complex. Haven't figured out a better
1768 // way on windows.
1769#ifdef _MSC_VER
1770 int len = -1;
1771 int expand = 1000;
1772 while ( len < 0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001773 len = vsnprintf_s( _accumulator.Mem(), _accumulator.Capacity(), _TRUNCATE, format, va );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001774 if ( len < 0 ) {
1775 expand *= 3/2;
Lee Thomason1aa8fc42012-10-13 20:01:30 -07001776 _accumulator.PushArr( expand );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001777 }
1778 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001779 char* p = _buffer.PushArr( len ) - 1;
1780 memcpy( p, _accumulator.Mem(), len+1 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001781#else
1782 int len = vsnprintf( 0, 0, format, va );
1783 // Close out and re-start the va-args
1784 va_end( va );
1785 va_start( va, format );
Lee Thomason624d43f2012-10-12 10:58:48 -07001786 char* p = _buffer.PushArr( len ) - 1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001787 vsnprintf( p, len+1, format, va );
1788#endif
1789 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001790 va_end( va );
Lee Thomason5cae8972012-01-24 18:03:07 -08001791}
1792
1793
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001794void XMLPrinter::PrintSpace( int depth )
Lee Thomason5cae8972012-01-24 18:03:07 -08001795{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001796 for( int i=0; i<depth; ++i ) {
1797 Print( " " );
1798 }
Lee Thomason5cae8972012-01-24 18:03:07 -08001799}
1800
1801
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001802void XMLPrinter::PrintString( const char* p, bool restricted )
Lee Thomason857b8682012-01-25 17:50:25 -08001803{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001804 // Look for runs of bytes between entities to print.
1805 const char* q = p;
Lee Thomason624d43f2012-10-12 10:58:48 -07001806 const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag;
Lee Thomason857b8682012-01-25 17:50:25 -08001807
Lee Thomason624d43f2012-10-12 10:58:48 -07001808 if ( _processEntities ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001809 while ( *q ) {
1810 // Remember, char is sometimes signed. (How many times has that bitten me?)
1811 if ( *q > 0 && *q < ENTITY_RANGE ) {
1812 // Check for entities. If one is found, flush
1813 // the stream up until the entity, write the
1814 // entity, and keep looking.
1815 if ( flag[(unsigned)(*q)] ) {
1816 while ( p < q ) {
1817 Print( "%c", *p );
1818 ++p;
1819 }
1820 for( int i=0; i<NUM_ENTITIES; ++i ) {
1821 if ( entities[i].value == *q ) {
1822 Print( "&%s;", entities[i].pattern );
1823 break;
1824 }
1825 }
1826 ++p;
1827 }
1828 }
1829 ++q;
1830 }
1831 }
1832 // Flush the remaining string. This will be the entire
1833 // string if an entity wasn't found.
Lee Thomason624d43f2012-10-12 10:58:48 -07001834 if ( !_processEntities || (q-p > 0) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001835 Print( "%s", p );
1836 }
Lee Thomason857b8682012-01-25 17:50:25 -08001837}
1838
U-Stream\Leeae25a442012-02-17 17:48:16 -08001839
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001840void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001841{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001842 static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };
1843 if ( writeBOM ) {
1844 Print( "%s", bom );
1845 }
1846 if ( writeDec ) {
1847 PushDeclaration( "xml version=\"1.0\"" );
1848 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001849}
1850
1851
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001852void XMLPrinter::OpenElement( const char* name )
Lee Thomason5cae8972012-01-24 18:03:07 -08001853{
Lee Thomason624d43f2012-10-12 10:58:48 -07001854 if ( _elementJustOpened ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001855 SealElement();
1856 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001857 _stack.Push( name );
Lee Thomason56bdd022012-02-09 18:16:58 -08001858
Lee Thomason624d43f2012-10-12 10:58:48 -07001859 if ( _textDepth < 0 && !_firstElement && !_compactMode ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001860 Print( "\n" );
Lee Thomason624d43f2012-10-12 10:58:48 -07001861 PrintSpace( _depth );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001862 }
Lee Thomason5cae8972012-01-24 18:03:07 -08001863
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001864 Print( "<%s", name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001865 _elementJustOpened = true;
1866 _firstElement = false;
1867 ++_depth;
Lee Thomason5cae8972012-01-24 18:03:07 -08001868}
1869
1870
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001871void XMLPrinter::PushAttribute( const char* name, const char* value )
Lee Thomason5cae8972012-01-24 18:03:07 -08001872{
Lee Thomason624d43f2012-10-12 10:58:48 -07001873 TIXMLASSERT( _elementJustOpened );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001874 Print( " %s=\"", name );
1875 PrintString( value, false );
1876 Print( "\"" );
Lee Thomason5cae8972012-01-24 18:03:07 -08001877}
1878
1879
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001880void XMLPrinter::PushAttribute( const char* name, int v )
1881{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001882 char buf[BUF_SIZE];
1883 XMLUtil::ToStr( v, buf, BUF_SIZE );
1884 PushAttribute( name, buf );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001885}
1886
1887
1888void XMLPrinter::PushAttribute( const char* name, unsigned v )
1889{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001890 char buf[BUF_SIZE];
1891 XMLUtil::ToStr( v, buf, BUF_SIZE );
1892 PushAttribute( name, buf );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001893}
1894
1895
1896void XMLPrinter::PushAttribute( const char* name, bool v )
1897{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001898 char buf[BUF_SIZE];
1899 XMLUtil::ToStr( v, buf, BUF_SIZE );
1900 PushAttribute( name, buf );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001901}
1902
1903
1904void XMLPrinter::PushAttribute( const char* name, double v )
1905{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001906 char buf[BUF_SIZE];
1907 XMLUtil::ToStr( v, buf, BUF_SIZE );
1908 PushAttribute( name, buf );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001909}
1910
1911
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001912void XMLPrinter::CloseElement()
Lee Thomason5cae8972012-01-24 18:03:07 -08001913{
Lee Thomason624d43f2012-10-12 10:58:48 -07001914 --_depth;
1915 const char* name = _stack.Pop();
Lee Thomason5cae8972012-01-24 18:03:07 -08001916
Lee Thomason624d43f2012-10-12 10:58:48 -07001917 if ( _elementJustOpened ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001918 Print( "/>" );
1919 }
1920 else {
Lee Thomason624d43f2012-10-12 10:58:48 -07001921 if ( _textDepth < 0 && !_compactMode) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001922 Print( "\n" );
Lee Thomason624d43f2012-10-12 10:58:48 -07001923 PrintSpace( _depth );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001924 }
1925 Print( "</%s>", name );
1926 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001927
Lee Thomason624d43f2012-10-12 10:58:48 -07001928 if ( _textDepth == _depth ) {
1929 _textDepth = -1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001930 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001931 if ( _depth == 0 && !_compactMode) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001932 Print( "\n" );
1933 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001934 _elementJustOpened = false;
Lee Thomason5cae8972012-01-24 18:03:07 -08001935}
1936
1937
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001938void XMLPrinter::SealElement()
Lee Thomason5cae8972012-01-24 18:03:07 -08001939{
Lee Thomason624d43f2012-10-12 10:58:48 -07001940 _elementJustOpened = false;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001941 Print( ">" );
Lee Thomason5cae8972012-01-24 18:03:07 -08001942}
1943
1944
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001945void XMLPrinter::PushText( const char* text, bool cdata )
Lee Thomason5cae8972012-01-24 18:03:07 -08001946{
Lee Thomason624d43f2012-10-12 10:58:48 -07001947 _textDepth = _depth-1;
Lee Thomason56bdd022012-02-09 18:16:58 -08001948
Lee Thomason624d43f2012-10-12 10:58:48 -07001949 if ( _elementJustOpened ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001950 SealElement();
1951 }
1952 if ( cdata ) {
1953 Print( "<![CDATA[" );
1954 Print( "%s", text );
1955 Print( "]]>" );
1956 }
1957 else {
1958 PrintString( text, true );
1959 }
Lee Thomason5cae8972012-01-24 18:03:07 -08001960}
1961
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001962void XMLPrinter::PushText( int value )
Lee Thomason21be8822012-07-15 17:27:22 -07001963{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001964 char buf[BUF_SIZE];
1965 XMLUtil::ToStr( value, buf, BUF_SIZE );
1966 PushText( buf, false );
Lee Thomason21be8822012-07-15 17:27:22 -07001967}
1968
1969
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001970void XMLPrinter::PushText( unsigned value )
Lee Thomason21be8822012-07-15 17:27:22 -07001971{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001972 char buf[BUF_SIZE];
1973 XMLUtil::ToStr( value, buf, BUF_SIZE );
1974 PushText( buf, false );
Lee Thomason21be8822012-07-15 17:27:22 -07001975}
1976
1977
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001978void XMLPrinter::PushText( bool value )
Lee Thomason21be8822012-07-15 17:27:22 -07001979{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001980 char buf[BUF_SIZE];
1981 XMLUtil::ToStr( value, buf, BUF_SIZE );
1982 PushText( buf, false );
Lee Thomason21be8822012-07-15 17:27:22 -07001983}
1984
1985
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001986void XMLPrinter::PushText( float value )
Lee Thomason21be8822012-07-15 17:27:22 -07001987{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001988 char buf[BUF_SIZE];
1989 XMLUtil::ToStr( value, buf, BUF_SIZE );
1990 PushText( buf, false );
Lee Thomason21be8822012-07-15 17:27:22 -07001991}
1992
1993
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001994void XMLPrinter::PushText( double value )
Lee Thomason21be8822012-07-15 17:27:22 -07001995{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001996 char buf[BUF_SIZE];
1997 XMLUtil::ToStr( value, buf, BUF_SIZE );
1998 PushText( buf, false );
Lee Thomason21be8822012-07-15 17:27:22 -07001999}
2000
Lee Thomason5cae8972012-01-24 18:03:07 -08002001
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08002002void XMLPrinter::PushComment( const char* comment )
Lee Thomason5cae8972012-01-24 18:03:07 -08002003{
Lee Thomason624d43f2012-10-12 10:58:48 -07002004 if ( _elementJustOpened ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002005 SealElement();
2006 }
Lee Thomason624d43f2012-10-12 10:58:48 -07002007 if ( _textDepth < 0 && !_firstElement && !_compactMode) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002008 Print( "\n" );
Lee Thomason624d43f2012-10-12 10:58:48 -07002009 PrintSpace( _depth );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002010 }
Lee Thomason624d43f2012-10-12 10:58:48 -07002011 _firstElement = false;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002012 Print( "<!--%s-->", comment );
Lee Thomason5cae8972012-01-24 18:03:07 -08002013}
Lee Thomason751da522012-02-10 08:50:51 -08002014
2015
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08002016void XMLPrinter::PushDeclaration( const char* value )
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002017{
Lee Thomason624d43f2012-10-12 10:58:48 -07002018 if ( _elementJustOpened ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002019 SealElement();
2020 }
Lee Thomason624d43f2012-10-12 10:58:48 -07002021 if ( _textDepth < 0 && !_firstElement && !_compactMode) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002022 Print( "\n" );
Lee Thomason624d43f2012-10-12 10:58:48 -07002023 PrintSpace( _depth );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002024 }
Lee Thomason624d43f2012-10-12 10:58:48 -07002025 _firstElement = false;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002026 Print( "<?%s?>", value );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002027}
2028
2029
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08002030void XMLPrinter::PushUnknown( const char* value )
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002031{
Lee Thomason624d43f2012-10-12 10:58:48 -07002032 if ( _elementJustOpened ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002033 SealElement();
2034 }
Lee Thomason624d43f2012-10-12 10:58:48 -07002035 if ( _textDepth < 0 && !_firstElement && !_compactMode) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002036 Print( "\n" );
Lee Thomason624d43f2012-10-12 10:58:48 -07002037 PrintSpace( _depth );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002038 }
Lee Thomason624d43f2012-10-12 10:58:48 -07002039 _firstElement = false;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002040 Print( "<!%s>", value );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002041}
2042
2043
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08002044bool XMLPrinter::VisitEnter( const XMLDocument& doc )
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08002045{
Lee Thomason624d43f2012-10-12 10:58:48 -07002046 _processEntities = doc.ProcessEntities();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002047 if ( doc.HasBOM() ) {
2048 PushHeader( true, false );
2049 }
2050 return true;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08002051}
2052
2053
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08002054bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
Lee Thomason751da522012-02-10 08:50:51 -08002055{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002056 OpenElement( element.Name() );
2057 while ( attribute ) {
2058 PushAttribute( attribute->Name(), attribute->Value() );
2059 attribute = attribute->Next();
2060 }
2061 return true;
Lee Thomason751da522012-02-10 08:50:51 -08002062}
2063
2064
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08002065bool XMLPrinter::VisitExit( const XMLElement& )
Lee Thomason751da522012-02-10 08:50:51 -08002066{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002067 CloseElement();
2068 return true;
Lee Thomason751da522012-02-10 08:50:51 -08002069}
2070
2071
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08002072bool XMLPrinter::Visit( const XMLText& text )
Lee Thomason751da522012-02-10 08:50:51 -08002073{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002074 PushText( text.Value(), text.CData() );
2075 return true;
Lee Thomason751da522012-02-10 08:50:51 -08002076}
2077
2078
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08002079bool XMLPrinter::Visit( const XMLComment& comment )
Lee Thomason751da522012-02-10 08:50:51 -08002080{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002081 PushComment( comment.Value() );
2082 return true;
Lee Thomason751da522012-02-10 08:50:51 -08002083}
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002084
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08002085bool XMLPrinter::Visit( const XMLDeclaration& declaration )
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002086{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002087 PushDeclaration( declaration.Value() );
2088 return true;
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002089}
2090
2091
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08002092bool XMLPrinter::Visit( const XMLUnknown& unknown )
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002093{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002094 PushUnknown( unknown.Value() );
2095 return true;
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002096}
Kevin Wojniak04c22d22012-11-08 11:02:22 -08002097
Lee Thomason685b8952012-11-12 13:00:06 -08002098} // namespace tinyxml2
2099