goat3d

annotate libs/tinyxml2/tinyxml2.cpp @ 19:b35427826b60

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