ovr_sdk

annotate 3rdParty/TinyXml/tinyxml2.cpp @ 0:1b39a1b46319

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