1 /*
   2  * Copyright 2010 Inalogic�� Inc.
   3  *
   4  * This program is free software: you can redistribute it and/or modify it
   5  * under the terms of the GNU Lesser General Public License, as
   6  * published by the  Free Software Foundation; either version 2.1 or 3.0
   7  * of the License.
   8  *
   9  * This program is distributed in the hope that it will be useful, but
  10  * WITHOUT ANY WARRANTY; without even the implied warranties of
  11  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
  12  * PURPOSE.  See the applicable version of the GNU Lesser General Public
  13  * License for more details.
  14  *
  15  * You should have received a copy of both the GNU Lesser General Public
  16  * License along with this program. If not, see <http://www.gnu.org/licenses/>
  17  *
  18  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
  19  *
  20  */
  21 
  22 
  23 /*
  24 www.sourceforge.net/projects/tinyxml
  25 Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
  26 
  27 This software is provided 'as-is', without any express or implied
  28 warranty. In no event will the authors be held liable for any
  29 damages arising from the use of this software.
  30 
  31 Permission is granted to anyone to use this software for any
  32 purpose, including commercial applications, and to alter it and
  33 redistribute it freely, subject to the following restrictions:
  34 
  35 1. The origin of this software must not be misrepresented; you must
  36 not claim that you wrote the original software. If you use this
  37 software in a product, an acknowledgment in the product documentation
  38 would be appreciated but is not required.
  39 
  40 2. Altered source versions must be plainly marked as such, and
  41 must not be misrepresented as being the original software.
  42 
  43 3. This notice may not be removed or altered from any source
  44 distribution.
  45 */
  46 
  47 #include <ctype.h>
  48 
  49 #ifdef TIXML_USE_STL
  50 #include <sstream>
  51 #include <iostream>
  52 #endif
  53 
  54 #include "tinyxml.h"
  55 
  56 
  57 bool TiXmlBase::condenseWhiteSpace = true;
  58 
  59 // Microsoft compiler security
  60 FILE *TiXmlFOpen ( const char *filename, const char *mode )
  61 {
  62 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
  63   FILE *fp = 0;
  64   errno_t err = fopen_s ( &fp, filename, mode );
  65 
  66   if ( !err && fp )
  67     return fp;
  68 
  69   return 0;
  70 #else
  71   return fopen ( filename, mode );
  72 #endif
  73 }
  74 
  75 void TiXmlBase::EncodeString ( const TIXML_STRING &str, TIXML_STRING *outString )
  76 {
  77   int i = 0;
  78 
  79   while ( i < (int) str.length() )
  80   {
  81     unsigned char c = (unsigned char) str[i];
  82 
  83     if (    c == '&'
  84             && i < ( (int) str.length() - 2 )
  85             && str[i+1] == '#'
  86             && str[i+2] == 'x' )
  87     {
  88       // Hexadecimal character reference.
  89       // Pass through unchanged.
  90       // &#xA9;	-- copyright symbol, for example.
  91       //
  92       // The -1 is a bug fix from Rob Laveaux. It keeps
  93       // an overflow from happening if there is no ';'.
  94       // There are actually 2 ways to exit this loop -
  95       // while fails (error case) and break (semicolon found).
  96       // However, there is no mechanism (currently) for
  97       // this function to return an error.
  98       while ( i < (int) str.length() - 1 )
  99       {
 100         outString->append ( str.c_str() + i, 1 );
 101         ++i;
 102 
 103         if ( str[i] == ';' )
 104           break;
 105       }
 106     }
 107     else if ( c == '&' )
 108     {
 109       outString->append ( entity[0].str, entity[0].strLength );
 110       ++i;
 111     }
 112     else if ( c == '<' )
 113     {
 114       outString->append ( entity[1].str, entity[1].strLength );
 115       ++i;
 116     }
 117     else if ( c == '>' )
 118     {
 119       outString->append ( entity[2].str, entity[2].strLength );
 120       ++i;
 121     }
 122     else if ( c == '\"' )
 123     {
 124       outString->append ( entity[3].str, entity[3].strLength );
 125       ++i;
 126     }
 127     else if ( c == '\'' )
 128     {
 129       outString->append ( entity[4].str, entity[4].strLength );
 130       ++i;
 131     }
 132     else if ( c < 32 )
 133     {
 134       // Easy pass at non-alpha/numeric/symbol
 135       // Below 32 is symbolic.
 136       char buf[ 32 ];
 137 
 138 #if defined(TIXML_SNPRINTF)
 139       TIXML_SNPRINTF ( buf, sizeof (buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
 140 #else
 141       sprintf ( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
 142 #endif
 143 
 144       //*ME:	warning C4267: convert 'size_t' to 'int'
 145       //*ME:	Int-Cast to make compiler happy ...
 146       outString->append ( buf, (int) strlen ( buf ) );
 147       ++i;
 148     }
 149     else
 150     {
 151       //char realc = (char) c;
 152       //outString->append( &realc, 1 );
 153       *outString += (char) c;	// somewhat more efficient function call.
 154       ++i;
 155     }
 156   }
 157 }
 158 
 159 
 160 TiXmlNode::TiXmlNode ( NodeType _type ) : TiXmlBase()
 161 {
 162   parent = 0;
 163   type = _type;
 164   firstChild = 0;
 165   lastChild = 0;
 166   prev = 0;
 167   next = 0;
 168 }
 169 
 170 
 171 TiXmlNode::~TiXmlNode()
 172 {
 173   TiXmlNode *node = firstChild;
 174   TiXmlNode *temp = 0;
 175 
 176   while ( node )
 177   {
 178     temp = node;
 179     node = node->next;
 180     delete temp;
 181   }
 182 }
 183 
 184 
 185 void TiXmlNode::CopyTo ( TiXmlNode *target ) const
 186 {
 187   target->SetValue (value.c_str() );
 188   target->userData = userData;
 189 }
 190 
 191 
 192 void TiXmlNode::Clear()
 193 {
 194   TiXmlNode *node = firstChild;
 195   TiXmlNode *temp = 0;
 196 
 197   while ( node )
 198   {
 199     temp = node;
 200     node = node->next;
 201     delete temp;
 202   }
 203 
 204   firstChild = 0;
 205   lastChild = 0;
 206 }
 207 
 208 
 209 TiXmlNode *TiXmlNode::LinkEndChild ( TiXmlNode *node )
 210 {
 211   assert ( node->parent == 0 || node->parent == this );
 212   assert ( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
 213 
 214   if ( node->Type() == TiXmlNode::DOCUMENT )
 215   {
 216     delete node;
 217     node = 0;
 218 
 219     if ( GetDocument() ) GetDocument()->SetError ( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
 220 
 221     return 0;
 222   }
 223 
 224   node->parent = this;
 225 
 226   node->prev = lastChild;
 227   node->next = 0;
 228 
 229   if ( lastChild )
 230     lastChild->next = node;
 231   else
 232     firstChild = node;			// it was an empty list.
 233 
 234   lastChild = node;
 235   return node;
 236 }
 237 
 238 
 239 TiXmlNode *TiXmlNode::InsertEndChild ( const TiXmlNode &addThis )
 240 {
 241   if ( addThis.Type() == TiXmlNode::DOCUMENT )
 242   {
 243     if ( GetDocument() ) GetDocument()->SetError ( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
 244 
 245     return 0;
 246   }
 247 
 248   TiXmlNode *node = addThis.Clone();
 249 
 250   if ( !node )
 251     return 0;
 252 
 253   return LinkEndChild ( node );
 254 }
 255 
 256 
 257 TiXmlNode *TiXmlNode::InsertBeforeChild ( TiXmlNode *beforeThis, const TiXmlNode &addThis )
 258 {
 259   if ( !beforeThis || beforeThis->parent != this )
 260   {
 261     return 0;
 262   }
 263 
 264   if ( addThis.Type() == TiXmlNode::DOCUMENT )
 265   {
 266     if ( GetDocument() ) GetDocument()->SetError ( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
 267 
 268     return 0;
 269   }
 270 
 271   TiXmlNode *node = addThis.Clone();
 272 
 273   if ( !node )
 274     return 0;
 275 
 276   node->parent = this;
 277 
 278   node->next = beforeThis;
 279   node->prev = beforeThis->prev;
 280 
 281   if ( beforeThis->prev )
 282   {
 283     beforeThis->prev->next = node;
 284   }
 285   else
 286   {
 287     assert ( firstChild == beforeThis );
 288     firstChild = node;
 289   }
 290 
 291   beforeThis->prev = node;
 292   return node;
 293 }
 294 
 295 
 296 TiXmlNode *TiXmlNode::InsertAfterChild ( TiXmlNode *afterThis, const TiXmlNode &addThis )
 297 {
 298   if ( !afterThis || afterThis->parent != this )
 299   {
 300     return 0;
 301   }
 302 
 303   if ( addThis.Type() == TiXmlNode::DOCUMENT )
 304   {
 305     if ( GetDocument() ) GetDocument()->SetError ( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
 306 
 307     return 0;
 308   }
 309 
 310   TiXmlNode *node = addThis.Clone();
 311 
 312   if ( !node )
 313     return 0;
 314 
 315   node->parent = this;
 316 
 317   node->prev = afterThis;
 318   node->next = afterThis->next;
 319 
 320   if ( afterThis->next )
 321   {
 322     afterThis->next->prev = node;
 323   }
 324   else
 325   {
 326     assert ( lastChild == afterThis );
 327     lastChild = node;
 328   }
 329 
 330   afterThis->next = node;
 331   return node;
 332 }
 333 
 334 
 335 TiXmlNode *TiXmlNode::ReplaceChild ( TiXmlNode *replaceThis, const TiXmlNode &withThis )
 336 {
 337   if ( replaceThis->parent != this )
 338     return 0;
 339 
 340   TiXmlNode *node = withThis.Clone();
 341 
 342   if ( !node )
 343     return 0;
 344 
 345   node->next = replaceThis->next;
 346   node->prev = replaceThis->prev;
 347 
 348   if ( replaceThis->next )
 349     replaceThis->next->prev = node;
 350   else
 351     lastChild = node;
 352 
 353   if ( replaceThis->prev )
 354     replaceThis->prev->next = node;
 355   else
 356     firstChild = node;
 357 
 358   delete replaceThis;
 359   node->parent = this;
 360   return node;
 361 }
 362 
 363 
 364 bool TiXmlNode::RemoveChild ( TiXmlNode *removeThis )
 365 {
 366   if ( removeThis->parent != this )
 367   {
 368     assert ( 0 );
 369     return false;
 370   }
 371 
 372   if ( removeThis->next )
 373     removeThis->next->prev = removeThis->prev;
 374   else
 375     lastChild = removeThis->prev;
 376 
 377   if ( removeThis->prev )
 378     removeThis->prev->next = removeThis->next;
 379   else
 380     firstChild = removeThis->next;
 381 
 382   delete removeThis;
 383   return true;
 384 }
 385 
 386 const TiXmlNode *TiXmlNode::FirstChild ( const char *_value ) const
 387 {
 388   const TiXmlNode *node;
 389 
 390   for ( node = firstChild; node; node = node->next )
 391   {
 392     if ( strcmp ( node->Value(), _value ) == 0 )
 393       return node;
 394   }
 395 
 396   return 0;
 397 }
 398 
 399 
 400 const TiXmlNode *TiXmlNode::LastChild ( const char *_value ) const
 401 {
 402   const TiXmlNode *node;
 403 
 404   for ( node = lastChild; node; node = node->prev )
 405   {
 406     if ( strcmp ( node->Value(), _value ) == 0 )
 407       return node;
 408   }
 409 
 410   return 0;
 411 }
 412 
 413 
 414 const TiXmlNode *TiXmlNode::IterateChildren ( const TiXmlNode *previous ) const
 415 {
 416   if ( !previous )
 417   {
 418     return FirstChild();
 419   }
 420   else
 421   {
 422     assert ( previous->parent == this );
 423     return previous->NextSibling();
 424   }
 425 }
 426 
 427 
 428 const TiXmlNode *TiXmlNode::IterateChildren ( const char *val, const TiXmlNode *previous ) const
 429 {
 430   if ( !previous )
 431   {
 432     return FirstChild ( val );
 433   }
 434   else
 435   {
 436     assert ( previous->parent == this );
 437     return previous->NextSibling ( val );
 438   }
 439 }
 440 
 441 
 442 const TiXmlNode *TiXmlNode::NextSibling ( const char *_value ) const
 443 {
 444   const TiXmlNode *node;
 445 
 446   for ( node = next; node; node = node->next )
 447   {
 448     if ( strcmp ( node->Value(), _value ) == 0 )
 449       return node;
 450   }
 451 
 452   return 0;
 453 }
 454 
 455 
 456 const TiXmlNode *TiXmlNode::PreviousSibling ( const char *_value ) const
 457 {
 458   const TiXmlNode *node;
 459 
 460   for ( node = prev; node; node = node->prev )
 461   {
 462     if ( strcmp ( node->Value(), _value ) == 0 )
 463       return node;
 464   }
 465 
 466   return 0;
 467 }
 468 
 469 
 470 void TiXmlElement::RemoveAttribute ( const char *name )
 471 {
 472 #ifdef TIXML_USE_STL
 473   TIXML_STRING str ( name );
 474   TiXmlAttribute *node = attributeSet.Find ( str );
 475 #else
 476   TiXmlAttribute *node = attributeSet.Find ( name );
 477 #endif
 478 
 479   if ( node )
 480   {
 481     attributeSet.Remove ( node );
 482     delete node;
 483   }
 484 }
 485 
 486 const TiXmlElement *TiXmlNode::FirstChildElement() const
 487 {
 488   const TiXmlNode *node;
 489 
 490   for (	node = FirstChild();
 491         node;
 492         node = node->NextSibling() )
 493   {
 494     if ( node->ToElement() )
 495       return node->ToElement();
 496   }
 497 
 498   return 0;
 499 }
 500 
 501 
 502 const TiXmlElement *TiXmlNode::FirstChildElement ( const char *_value ) const
 503 {
 504   const TiXmlNode *node;
 505 
 506   for (	node = FirstChild ( _value );
 507         node;
 508         node = node->NextSibling ( _value ) )
 509   {
 510     if ( node->ToElement() )
 511       return node->ToElement();
 512   }
 513 
 514   return 0;
 515 }
 516 
 517 
 518 const TiXmlElement *TiXmlNode::NextSiblingElement() const
 519 {
 520   const TiXmlNode *node;
 521 
 522   for (	node = NextSibling();
 523         node;
 524         node = node->NextSibling() )
 525   {
 526     if ( node->ToElement() )
 527       return node->ToElement();
 528   }
 529 
 530   return 0;
 531 }
 532 
 533 
 534 const TiXmlElement *TiXmlNode::NextSiblingElement ( const char *_value ) const
 535 {
 536   const TiXmlNode *node;
 537 
 538   for (	node = NextSibling ( _value );
 539         node;
 540         node = node->NextSibling ( _value ) )
 541   {
 542     if ( node->ToElement() )
 543       return node->ToElement();
 544   }
 545 
 546   return 0;
 547 }
 548 
 549 
 550 const TiXmlDocument *TiXmlNode::GetDocument() const
 551 {
 552   const TiXmlNode *node;
 553 
 554   for ( node = this; node; node = node->parent )
 555   {
 556     if ( node->ToDocument() )
 557       return node->ToDocument();
 558   }
 559 
 560   return 0;
 561 }
 562 
 563 
 564 TiXmlElement::TiXmlElement (const char *_value)
 565   : TiXmlNode ( TiXmlNode::ELEMENT )
 566 {
 567   firstChild = lastChild = 0;
 568   value = _value;
 569 }
 570 
 571 
 572 #ifdef TIXML_USE_STL
 573 TiXmlElement::TiXmlElement ( const std::string &_value )
 574   : TiXmlNode ( TiXmlNode::ELEMENT )
 575 {
 576   firstChild = lastChild = 0;
 577   value = _value;
 578 }
 579 #endif
 580 
 581 
 582 TiXmlElement::TiXmlElement ( const TiXmlElement &copy)
 583   : TiXmlNode ( TiXmlNode::ELEMENT )
 584 {
 585   firstChild = lastChild = 0;
 586   copy.CopyTo ( this );
 587 }
 588 
 589 
 590 void TiXmlElement::operator= ( const TiXmlElement &base )
 591 {
 592   ClearThis();
 593   base.CopyTo ( this );
 594 }
 595 
 596 
 597 TiXmlElement::~TiXmlElement()
 598 {
 599   ClearThis();
 600 }
 601 
 602 
 603 void TiXmlElement::ClearThis()
 604 {
 605   Clear();
 606 
 607   while ( attributeSet.First() )
 608   {
 609     TiXmlAttribute *node = attributeSet.First();
 610     attributeSet.Remove ( node );
 611     delete node;
 612   }
 613 }
 614 
 615 
 616 const char *TiXmlElement::Attribute ( const char *name ) const
 617 {
 618   const TiXmlAttribute *node = attributeSet.Find ( name );
 619 
 620   if ( node )
 621     return node->Value();
 622 
 623   return 0;
 624 }
 625 
 626 
 627 #ifdef TIXML_USE_STL
 628 const std::string *TiXmlElement::Attribute ( const std::string &name ) const
 629 {
 630   const TiXmlAttribute *node = attributeSet.Find ( name );
 631 
 632   if ( node )
 633     return &node->ValueStr();
 634 
 635   return 0;
 636 }
 637 #endif
 638 
 639 
 640 const char *TiXmlElement::Attribute ( const char *name, int *i ) const
 641 {
 642   const char *s = Attribute ( name );
 643 
 644   if ( i )
 645   {
 646     if ( s )
 647     {
 648       *i = atoi ( s );
 649     }
 650     else
 651     {
 652       *i = 0;
 653     }
 654   }
 655 
 656   return s;
 657 }
 658 
 659 
 660 #ifdef TIXML_USE_STL
 661 const std::string *TiXmlElement::Attribute ( const std::string &name, int *i ) const
 662 {
 663   const std::string *s = Attribute ( name );
 664 
 665   if ( i )
 666   {
 667     if ( s )
 668     {
 669       *i = atoi ( s->c_str() );
 670     }
 671     else
 672     {
 673       *i = 0;
 674     }
 675   }
 676 
 677   return s;
 678 }
 679 #endif
 680 
 681 
 682 const char *TiXmlElement::Attribute ( const char *name, double *d ) const
 683 {
 684   const char *s = Attribute ( name );
 685 
 686   if ( d )
 687   {
 688     if ( s )
 689     {
 690       *d = atof ( s );
 691     }
 692     else
 693     {
 694       *d = 0;
 695     }
 696   }
 697 
 698   return s;
 699 }
 700 
 701 
 702 #ifdef TIXML_USE_STL
 703 const std::string *TiXmlElement::Attribute ( const std::string &name, double *d ) const
 704 {
 705   const std::string *s = Attribute ( name );
 706 
 707   if ( d )
 708   {
 709     if ( s )
 710     {
 711       *d = atof ( s->c_str() );
 712     }
 713     else
 714     {
 715       *d = 0;
 716     }
 717   }
 718 
 719   return s;
 720 }
 721 #endif
 722 
 723 
 724 int TiXmlElement::QueryIntAttribute ( const char *name, int *ival ) const
 725 {
 726   const TiXmlAttribute *node = attributeSet.Find ( name );
 727 
 728   if ( !node )
 729     return TIXML_NO_ATTRIBUTE;
 730 
 731   return node->QueryIntValue ( ival );
 732 }
 733 
 734 
 735 #ifdef TIXML_USE_STL
 736 int TiXmlElement::QueryIntAttribute ( const std::string &name, int *ival ) const
 737 {
 738   const TiXmlAttribute *node = attributeSet.Find ( name );
 739 
 740   if ( !node )
 741     return TIXML_NO_ATTRIBUTE;
 742 
 743   return node->QueryIntValue ( ival );
 744 }
 745 #endif
 746 
 747 
 748 int TiXmlElement::QueryDoubleAttribute ( const char *name, double *dval ) const
 749 {
 750   const TiXmlAttribute *node = attributeSet.Find ( name );
 751 
 752   if ( !node )
 753     return TIXML_NO_ATTRIBUTE;
 754 
 755   return node->QueryDoubleValue ( dval );
 756 }
 757 
 758 
 759 #ifdef TIXML_USE_STL
 760 int TiXmlElement::QueryDoubleAttribute ( const std::string &name, double *dval ) const
 761 {
 762   const TiXmlAttribute *node = attributeSet.Find ( name );
 763 
 764   if ( !node )
 765     return TIXML_NO_ATTRIBUTE;
 766 
 767   return node->QueryDoubleValue ( dval );
 768 }
 769 #endif
 770 
 771 
 772 void TiXmlElement::SetAttribute ( const char *name, int val )
 773 {
 774   char buf[64];
 775 #if defined(TIXML_SNPRINTF)
 776   TIXML_SNPRINTF ( buf, sizeof (buf), "%d", val );
 777 #else
 778   sprintf ( buf, "%d", val );
 779 #endif
 780   SetAttribute ( name, buf );
 781 }
 782 
 783 
 784 #ifdef TIXML_USE_STL
 785 void TiXmlElement::SetAttribute ( const std::string &name, int val )
 786 {
 787   std::ostringstream oss;
 788   oss << val;
 789   SetAttribute ( name, oss.str() );
 790 }
 791 #endif
 792 
 793 
 794 void TiXmlElement::SetDoubleAttribute ( const char *name, double val )
 795 {
 796   char buf[256];
 797 #if defined(TIXML_SNPRINTF)
 798   TIXML_SNPRINTF ( buf, sizeof (buf), "%f", val );
 799 #else
 800   sprintf ( buf, "%f", val );
 801 #endif
 802   SetAttribute ( name, buf );
 803 }
 804 
 805 
 806 void TiXmlElement::SetAttribute ( const char *cname, const char *cvalue )
 807 {
 808 #ifdef TIXML_USE_STL
 809   TIXML_STRING _name ( cname );
 810   TIXML_STRING _value ( cvalue );
 811 #else
 812   const char *_name = cname;
 813   const char *_value = cvalue;
 814 #endif
 815 
 816   TiXmlAttribute *node = attributeSet.Find ( _name );
 817 
 818   if ( node )
 819   {
 820     node->SetValue ( _value );
 821     return;
 822   }
 823 
 824   TiXmlAttribute *attrib = new TiXmlAttribute ( cname, cvalue );
 825 
 826   if ( attrib )
 827   {
 828     attributeSet.Add ( attrib );
 829   }
 830   else
 831   {
 832     TiXmlDocument *document = GetDocument();
 833 
 834     if ( document ) document->SetError ( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
 835   }
 836 }
 837 
 838 
 839 #ifdef TIXML_USE_STL
 840 void TiXmlElement::SetAttribute ( const std::string &name, const std::string &_value )
 841 {
 842   TiXmlAttribute *node = attributeSet.Find ( name );
 843 
 844   if ( node )
 845   {
 846     node->SetValue ( _value );
 847     return;
 848   }
 849 
 850   TiXmlAttribute *attrib = new TiXmlAttribute ( name, _value );
 851 
 852   if ( attrib )
 853   {
 854     attributeSet.Add ( attrib );
 855   }
 856   else
 857   {
 858     TiXmlDocument *document = GetDocument();
 859 
 860     if ( document ) document->SetError ( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
 861   }
 862 }
 863 #endif
 864 
 865 
 866 void TiXmlElement::Print ( FILE *cfile, int depth ) const
 867 {
 868   int i;
 869   assert ( cfile );
 870 
 871   for ( i = 0; i < depth; i++ )
 872   {
 873     fprintf ( cfile, "    " );
 874   }
 875 
 876   fprintf ( cfile, "<%s", value.c_str() );
 877 
 878   const TiXmlAttribute *attrib;
 879 
 880   for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
 881   {
 882     fprintf ( cfile, " " );
 883     attrib->Print ( cfile, depth );
 884   }
 885 
 886   // There are 3 different formatting approaches:
 887   // 1) An element without children is printed as a <foo /> node
 888   // 2) An element with only a text child is printed as <foo> text </foo>
 889   // 3) An element with children is printed on multiple lines.
 890   TiXmlNode *node;
 891 
 892   if ( !firstChild )
 893   {
 894     fprintf ( cfile, " />" );
 895   }
 896   else if ( firstChild == lastChild && firstChild->ToText() )
 897   {
 898     fprintf ( cfile, ">" );
 899     firstChild->Print ( cfile, depth + 1 );
 900     fprintf ( cfile, "</%s>", value.c_str() );
 901   }
 902   else
 903   {
 904     fprintf ( cfile, ">" );
 905 
 906     for ( node = firstChild; node; node = node->NextSibling() )
 907     {
 908       if ( !node->ToText() )
 909       {
 910         fprintf ( cfile, "\n" );
 911       }
 912 
 913       node->Print ( cfile, depth + 1 );
 914     }
 915 
 916     fprintf ( cfile, "\n" );
 917 
 918     for ( i = 0; i < depth; ++i )
 919     {
 920       fprintf ( cfile, "    " );
 921     }
 922 
 923     fprintf ( cfile, "</%s>", value.c_str() );
 924   }
 925 }
 926 
 927 
 928 void TiXmlElement::CopyTo ( TiXmlElement *target ) const
 929 {
 930   // superclass:
 931   TiXmlNode::CopyTo ( target );
 932 
 933   // Element class:
 934   // Clone the attributes, then clone the children.
 935   const TiXmlAttribute *attribute = 0;
 936 
 937   for (	attribute = attributeSet.First();
 938         attribute;
 939         attribute = attribute->Next() )
 940   {
 941     target->SetAttribute ( attribute->Name(), attribute->Value() );
 942   }
 943 
 944   TiXmlNode *node = 0;
 945 
 946   for ( node = firstChild; node; node = node->NextSibling() )
 947   {
 948     target->LinkEndChild ( node->Clone() );
 949   }
 950 }
 951 
 952 bool TiXmlElement::Accept ( TiXmlVisitor *visitor ) const
 953 {
 954   if ( visitor->VisitEnter ( *this, attributeSet.First() ) )
 955   {
 956     for ( const TiXmlNode *node = FirstChild(); node; node = node->NextSibling() )
 957     {
 958       if ( !node->Accept ( visitor ) )
 959         break;
 960     }
 961   }
 962 
 963   return visitor->VisitExit ( *this );
 964 }
 965 
 966 
 967 TiXmlNode *TiXmlElement::Clone() const
 968 {
 969   TiXmlElement *clone = new TiXmlElement ( Value() );
 970 
 971   if ( !clone )
 972     return 0;
 973 
 974   CopyTo ( clone );
 975   return clone;
 976 }
 977 
 978 
 979 const char *TiXmlElement::GetText() const
 980 {
 981   const TiXmlNode *child = this->FirstChild();
 982 
 983   if ( child )
 984   {
 985     const TiXmlText *childText = child->ToText();
 986 
 987     if ( childText )
 988     {
 989       return childText->Value();
 990     }
 991   }
 992 
 993   return 0;
 994 }
 995 
 996 
 997 TiXmlDocument::TiXmlDocument() : TiXmlNode ( TiXmlNode::DOCUMENT )
 998 {
 999   tabsize = 4;
1000   useMicrosoftBOM = false;
1001   ClearError();
1002 }
1003 
1004 TiXmlDocument::TiXmlDocument ( const char *documentName ) : TiXmlNode ( TiXmlNode::DOCUMENT )
1005 {
1006   tabsize = 4;
1007   useMicrosoftBOM = false;
1008   value = documentName;
1009   ClearError();
1010 }
1011 
1012 
1013 #ifdef TIXML_USE_STL
1014 TiXmlDocument::TiXmlDocument ( const std::string &documentName ) : TiXmlNode ( TiXmlNode::DOCUMENT )
1015 {
1016   tabsize = 4;
1017   useMicrosoftBOM = false;
1018   value = documentName;
1019   ClearError();
1020 }
1021 #endif
1022 
1023 
1024 TiXmlDocument::TiXmlDocument ( const TiXmlDocument &copy ) : TiXmlNode ( TiXmlNode::DOCUMENT )
1025 {
1026   copy.CopyTo ( this );
1027 }
1028 
1029 
1030 void TiXmlDocument::operator= ( const TiXmlDocument &copy )
1031 {
1032   Clear();
1033   copy.CopyTo ( this );
1034 }
1035 
1036 
1037 bool TiXmlDocument::LoadFile ( TiXmlEncoding encoding )
1038 {
1039   // See STL_STRING_BUG below.
1040   //StringToBuffer buf( value );
1041 
1042   return LoadFile ( Value(), encoding );
1043 }
1044 
1045 
1046 bool TiXmlDocument::SaveFile() const
1047 {
1048   // See STL_STRING_BUG below.
1049 //	StringToBuffer buf( value );
1050 //
1051 //	if ( buf.buffer && SaveFile( buf.buffer ) )
1052 //		return true;
1053 //
1054 //	return false;
1055   return SaveFile ( Value() );
1056 }
1057 
1058 bool TiXmlDocument::LoadFile ( const char *_filename, TiXmlEncoding encoding )
1059 {
1060   // There was a really terrifying little bug here. The code:
1061   //		value = filename
1062   // in the STL case, cause the assignment method of the std::string to
1063   // be called. What is strange, is that the std::string had the same
1064   // address as it's c_str() method, and so bad things happen. Looks
1065   // like a bug in the Microsoft STL implementation.
1066   // Add an extra string to avoid the crash.
1067   TIXML_STRING filename ( _filename );
1068   value = filename;
1069 
1070   // reading in binary mode so that tinyxml can normalize the EOL
1071   FILE *file = TiXmlFOpen ( value.c_str (), "rb" );
1072 
1073   if ( file )
1074   {
1075     bool result = LoadFile ( file, encoding );
1076     fclose ( file );
1077     return result;
1078   }
1079   else
1080   {
1081     SetError ( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1082     return false;
1083   }
1084 }
1085 
1086 bool TiXmlDocument::LoadFile ( FILE *file, TiXmlEncoding encoding )
1087 {
1088   if ( !file )
1089   {
1090     SetError ( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1091     return false;
1092   }
1093 
1094   // Delete the existing data:
1095   Clear();
1096   location.Clear();
1097 
1098   // Get the file size, so we can pre-allocate the string. HUGE speed impact.
1099   long length = 0;
1100   fseek ( file, 0, SEEK_END );
1101   length = ftell ( file );
1102   fseek ( file, 0, SEEK_SET );
1103 
1104   // Strange case, but good to handle up front.
1105   if ( length <= 0 )
1106   {
1107     SetError ( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
1108     return false;
1109   }
1110 
1111   // If we have a file, assume it is all one big XML file, and read it in.
1112   // The document parser may decide the document ends sooner than the entire file, however.
1113   TIXML_STRING data;
1114   data.reserve ( length );
1115 
1116   // Subtle bug here. TinyXml did use fgets. But from the XML spec:
1117   // 2.11 End-of-Line Handling
1118   // <snip>
1119   // <quote>
1120   // ...the XML processor MUST behave as if it normalized all line breaks in external
1121   // parsed entities (including the document entity) on input, before parsing, by translating
1122   // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
1123   // a single #xA character.
1124   // </quote>
1125   //
1126   // It is not clear fgets does that, and certainly isn't clear it works cross platform.
1127   // Generally, you expect fgets to translate from the convention of the OS to the c/unix
1128   // convention, and not work generally.
1129 
1130   /*
1131   while( fgets( buf, sizeof(buf), file ) )
1132   {
1133   	data += buf;
1134   }
1135   */
1136 
1137   char *buf = new char[ length+1 ];
1138   buf[0] = 0;
1139 
1140   if ( fread ( buf, length, 1, file ) != 1 )
1141   {
1142     delete [] buf;
1143     SetError ( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1144     return false;
1145   }
1146 
1147   const char *lastPos = buf;
1148 
1149   const char *p = buf;
1150 
1151   buf[length] = 0;
1152 
1153   while ( *p )
1154   {
1155     assert ( p < (buf + length) );
1156 
1157     if ( *p == 0xa )
1158     {
1159       // Newline character. No special rules for this. Append all the characters
1160       // since the last string, and include the newline.
1161       data.append ( lastPos, (p - lastPos + 1) );	// append, include the newline
1162       ++p;									// move past the newline
1163       lastPos = p;							// and point to the new buffer (may be 0)
1164       assert ( p <= (buf + length) );
1165     }
1166     else if ( *p == 0xd )
1167     {
1168       // Carriage return. Append what we have so far, then
1169       // handle moving forward in the buffer.
1170       if ( (p - lastPos) > 0 )
1171       {
1172         data.append ( lastPos, p - lastPos );	// do not add the CR
1173       }
1174 
1175       data += (char) 0xa;						// a proper newline
1176 
1177       if ( * (p + 1) == 0xa )
1178       {
1179         // Carriage return - new line sequence
1180         p += 2;
1181         lastPos = p;
1182         assert ( p <= (buf + length) );
1183       }
1184       else
1185       {
1186         // it was followed by something else...that is presumably characters again.
1187         ++p;
1188         lastPos = p;
1189         assert ( p <= (buf + length) );
1190       }
1191     }
1192     else
1193     {
1194       ++p;
1195     }
1196   }
1197 
1198   // Handle any left over characters.
1199   if ( p - lastPos )
1200   {
1201     data.append ( lastPos, p - lastPos );
1202   }
1203 
1204   delete [] buf;
1205   buf = 0;
1206 
1207   Parse ( data.c_str(), 0, encoding );
1208 
1209   if (  Error() )
1210     return false;
1211   else
1212     return true;
1213 }
1214 
1215 
1216 bool TiXmlDocument::SaveFile ( const char *filename ) const
1217 {
1218   // The old c stuff lives on...
1219   FILE *fp = TiXmlFOpen ( filename, "w" );
1220 
1221   if ( fp )
1222   {
1223     bool result = SaveFile ( fp );
1224     fclose ( fp );
1225     return result;
1226   }
1227 
1228   return false;
1229 }
1230 
1231 
1232 bool TiXmlDocument::SaveFile ( FILE *fp ) const
1233 {
1234   if ( useMicrosoftBOM )
1235   {
1236     const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
1237     const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
1238     const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
1239 
1240     fputc ( TIXML_UTF_LEAD_0, fp );
1241     fputc ( TIXML_UTF_LEAD_1, fp );
1242     fputc ( TIXML_UTF_LEAD_2, fp );
1243   }
1244 
1245   Print ( fp, 0 );
1246   return (ferror (fp) == 0);
1247 }
1248 
1249 
1250 void TiXmlDocument::CopyTo ( TiXmlDocument *target ) const
1251 {
1252   TiXmlNode::CopyTo ( target );
1253 
1254   target->error = error;
1255   target->errorId = errorId;
1256   target->errorDesc = errorDesc;
1257   target->tabsize = tabsize;
1258   target->errorLocation = errorLocation;
1259   target->useMicrosoftBOM = useMicrosoftBOM;
1260 
1261   TiXmlNode *node = 0;
1262 
1263   for ( node = firstChild; node; node = node->NextSibling() )
1264   {
1265     target->LinkEndChild ( node->Clone() );
1266   }
1267 }
1268 
1269 
1270 TiXmlNode *TiXmlDocument::Clone() const
1271 {
1272   TiXmlDocument *clone = new TiXmlDocument();
1273 
1274   if ( !clone )
1275     return 0;
1276 
1277   CopyTo ( clone );
1278   return clone;
1279 }
1280 
1281 
1282 void TiXmlDocument::Print ( FILE *cfile, int depth ) const
1283 {
1284   assert ( cfile );
1285 
1286   for ( const TiXmlNode *node = FirstChild(); node; node = node->NextSibling() )
1287   {
1288     node->Print ( cfile, depth );
1289     fprintf ( cfile, "\n" );
1290   }
1291 }
1292 
1293 
1294 bool TiXmlDocument::Accept ( TiXmlVisitor *visitor ) const
1295 {
1296   if ( visitor->VisitEnter ( *this ) )
1297   {
1298     for ( const TiXmlNode *node = FirstChild(); node; node = node->NextSibling() )
1299     {
1300       if ( !node->Accept ( visitor ) )
1301         break;
1302     }
1303   }
1304 
1305   return visitor->VisitExit ( *this );
1306 }
1307 
1308 
1309 const TiXmlAttribute *TiXmlAttribute::Next() const
1310 {
1311   // We are using knowledge of the sentinel. The sentinel
1312   // have a value or name.
1313   if ( next->value.empty() && next->name.empty() )
1314     return 0;
1315 
1316   return next;
1317 }
1318 
1319 /*
1320 TiXmlAttribute* TiXmlAttribute::Next()
1321 {
1322 	// We are using knowledge of the sentinel. The sentinel
1323 	// have a value or name.
1324 	if ( next->value.empty() && next->name.empty() )
1325 		return 0;
1326 	return next;
1327 }
1328 */
1329 
1330 const TiXmlAttribute *TiXmlAttribute::Previous() const
1331 {
1332   // We are using knowledge of the sentinel. The sentinel
1333   // have a value or name.
1334   if ( prev->value.empty() && prev->name.empty() )
1335     return 0;
1336 
1337   return prev;
1338 }
1339 
1340 /*
1341 TiXmlAttribute* TiXmlAttribute::Previous()
1342 {
1343 	// We are using knowledge of the sentinel. The sentinel
1344 	// have a value or name.
1345 	if ( prev->value.empty() && prev->name.empty() )
1346 		return 0;
1347 	return prev;
1348 }
1349 */
1350 
1351 void TiXmlAttribute::Print ( FILE *cfile, int /*depth*/, TIXML_STRING *str ) const
1352 {
1353   TIXML_STRING n, v;
1354 
1355   EncodeString ( name, &n );
1356   EncodeString ( value, &v );
1357 
1358   if (value.find ('\"') == TIXML_STRING::npos)
1359   {
1360     if ( cfile )
1361     {
1362       fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
1363     }
1364 
1365     if ( str )
1366     {
1367       (*str) += n;
1368       (*str) += "=\"";
1369       (*str) += v;
1370       (*str) += "\"";
1371     }
1372   }
1373   else
1374   {
1375     if ( cfile )
1376     {
1377       fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
1378     }
1379 
1380     if ( str )
1381     {
1382       (*str) += n;
1383       (*str) += "='";
1384       (*str) += v;
1385       (*str) += "'";
1386     }
1387   }
1388 }
1389 
1390 
1391 int TiXmlAttribute::QueryIntValue ( int *ival ) const
1392 {
1393   if ( TIXML_SSCANF ( value.c_str(), "%d", ival ) == 1 )
1394     return TIXML_SUCCESS;
1395 
1396   return TIXML_WRONG_TYPE;
1397 }
1398 
1399 int TiXmlAttribute::QueryDoubleValue ( double *dval ) const
1400 {
1401   if ( TIXML_SSCANF ( value.c_str(), "%lf", dval ) == 1 )
1402     return TIXML_SUCCESS;
1403 
1404   return TIXML_WRONG_TYPE;
1405 }
1406 
1407 void TiXmlAttribute::SetIntValue ( int _value )
1408 {
1409   char buf [64];
1410 #if defined(TIXML_SNPRINTF)
1411   TIXML_SNPRINTF (buf, sizeof (buf), "%d", _value);
1412 #else
1413   sprintf (buf, "%d", _value);
1414 #endif
1415   SetValue (buf);
1416 }
1417 
1418 void TiXmlAttribute::SetDoubleValue ( double _value )
1419 {
1420   char buf [256];
1421 #if defined(TIXML_SNPRINTF)
1422   TIXML_SNPRINTF ( buf, sizeof (buf), "%lf", _value);
1423 #else
1424   sprintf (buf, "%lf", _value);
1425 #endif
1426   SetValue (buf);
1427 }
1428 
1429 int TiXmlAttribute::IntValue() const
1430 {
1431   return atoi (value.c_str () );
1432 }
1433 
1434 double  TiXmlAttribute::DoubleValue() const
1435 {
1436   return atof (value.c_str () );
1437 }
1438 
1439 
1440 TiXmlComment::TiXmlComment ( const TiXmlComment &copy ) : TiXmlNode ( TiXmlNode::COMMENT )
1441 {
1442   copy.CopyTo ( this );
1443 }
1444 
1445 
1446 void TiXmlComment::operator= ( const TiXmlComment &base )
1447 {
1448   Clear();
1449   base.CopyTo ( this );
1450 }
1451 
1452 
1453 void TiXmlComment::Print ( FILE *cfile, int depth ) const
1454 {
1455   assert ( cfile );
1456 
1457   for ( int i = 0; i < depth; i++ )
1458   {
1459     fprintf ( cfile,  "    " );
1460   }
1461 
1462   fprintf ( cfile, "<!--%s-->", value.c_str() );
1463 }
1464 
1465 
1466 void TiXmlComment::CopyTo ( TiXmlComment *target ) const
1467 {
1468   TiXmlNode::CopyTo ( target );
1469 }
1470 
1471 
1472 bool TiXmlComment::Accept ( TiXmlVisitor *visitor ) const
1473 {
1474   return visitor->Visit ( *this );
1475 }
1476 
1477 
1478 TiXmlNode *TiXmlComment::Clone() const
1479 {
1480   TiXmlComment *clone = new TiXmlComment();
1481 
1482   if ( !clone )
1483     return 0;
1484 
1485   CopyTo ( clone );
1486   return clone;
1487 }
1488 
1489 
1490 void TiXmlText::Print ( FILE *cfile, int depth ) const
1491 {
1492   assert ( cfile );
1493 
1494   if ( cdata )
1495   {
1496     int i;
1497     fprintf ( cfile, "\n" );
1498 
1499     for ( i = 0; i < depth; i++ )
1500     {
1501       fprintf ( cfile, "    " );
1502     }
1503 
1504     fprintf ( cfile, "<![CDATA[%s]]>\n", value.c_str() );	// unformatted output
1505   }
1506   else
1507   {
1508     TIXML_STRING buffer;
1509     EncodeString ( value, &buffer );
1510     fprintf ( cfile, "%s", buffer.c_str() );
1511   }
1512 }
1513 
1514 
1515 void TiXmlText::CopyTo ( TiXmlText *target ) const
1516 {
1517   TiXmlNode::CopyTo ( target );
1518   target->cdata = cdata;
1519 }
1520 
1521 
1522 bool TiXmlText::Accept ( TiXmlVisitor *visitor ) const
1523 {
1524   return visitor->Visit ( *this );
1525 }
1526 
1527 
1528 TiXmlNode *TiXmlText::Clone() const
1529 {
1530   TiXmlText *clone = 0;
1531   clone = new TiXmlText ( "" );
1532 
1533   if ( !clone )
1534     return 0;
1535 
1536   CopyTo ( clone );
1537   return clone;
1538 }
1539 
1540 
1541 TiXmlDeclaration::TiXmlDeclaration ( const char *_version,
1542                                      const char *_encoding,
1543                                      const char *_standalone )
1544   : TiXmlNode ( TiXmlNode::DECLARATION )
1545 {
1546   version = _version;
1547   encoding = _encoding;
1548   standalone = _standalone;
1549 }
1550 
1551 
1552 #ifdef TIXML_USE_STL
1553 TiXmlDeclaration::TiXmlDeclaration (	const std::string &_version,
1554                                       const std::string &_encoding,
1555                                       const std::string &_standalone )
1556   : TiXmlNode ( TiXmlNode::DECLARATION )
1557 {
1558   version = _version;
1559   encoding = _encoding;
1560   standalone = _standalone;
1561 }
1562 #endif
1563 
1564 
1565 TiXmlDeclaration::TiXmlDeclaration ( const TiXmlDeclaration &copy )
1566   : TiXmlNode ( TiXmlNode::DECLARATION )
1567 {
1568   copy.CopyTo ( this );
1569 }
1570 
1571 
1572 void TiXmlDeclaration::operator= ( const TiXmlDeclaration &copy )
CID 10639 - ASSIGN_NOT_RETURNING_STAR_THIS
Assignment operator with void return type.
1573 {
1574   Clear();
1575   copy.CopyTo ( this );
1576 }
1577 
1578 
1579 void TiXmlDeclaration::Print ( FILE *cfile, int /*depth*/, TIXML_STRING *str ) const
1580 {
1581   if ( cfile ) fprintf ( cfile, "<?xml " );
1582 
1583   if ( str )	 (*str) += "<?xml ";
1584 
1585   if ( !version.empty() )
1586   {
1587     if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str () );
1588 
1589     if ( str )
1590     {
1591       (*str) += "version=\"";
1592       (*str) += version;
1593       (*str) += "\" ";
1594     }
1595   }
1596 
1597   if ( !encoding.empty() )
1598   {
1599     if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str () );
1600 
1601     if ( str )
1602     {
1603       (*str) += "encoding=\"";
1604       (*str) += encoding;
1605       (*str) += "\" ";
1606     }
1607   }
1608 
1609   if ( !standalone.empty() )
1610   {
1611     if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str () );
1612 
1613     if ( str )
1614     {
1615       (*str) += "standalone=\"";
1616       (*str) += standalone;
1617       (*str) += "\" ";
1618     }
1619   }
1620 
1621   if ( cfile ) fprintf ( cfile, "?>" );
1622 
1623   if ( str )	 (*str) += "?>";
1624 }
1625 
1626 
1627 void TiXmlDeclaration::CopyTo ( TiXmlDeclaration *target ) const
1628 {
1629   TiXmlNode::CopyTo ( target );
1630 
1631   target->version = version;
1632   target->encoding = encoding;
1633   target->standalone = standalone;
1634 }
1635 
1636 
1637 bool TiXmlDeclaration::Accept ( TiXmlVisitor *visitor ) const
1638 {
1639   return visitor->Visit ( *this );
1640 }
1641 
1642 
1643 TiXmlNode *TiXmlDeclaration::Clone() const
1644 {
1645   TiXmlDeclaration *clone = new TiXmlDeclaration();
1646 
1647   if ( !clone )
1648     return 0;
1649 
1650   CopyTo ( clone );
1651   return clone;
1652 }
1653 
1654 
1655 void TiXmlUnknown::Print ( FILE *cfile, int depth ) const
1656 {
1657   for ( int i = 0; i < depth; i++ )
1658     fprintf ( cfile, "    " );
1659 
1660   fprintf ( cfile, "<%s>", value.c_str() );
1661 }
1662 
1663 
1664 void TiXmlUnknown::CopyTo ( TiXmlUnknown *target ) const
1665 {
1666   TiXmlNode::CopyTo ( target );
1667 }
1668 
1669 
1670 bool TiXmlUnknown::Accept ( TiXmlVisitor *visitor ) const
1671 {
1672   return visitor->Visit ( *this );
1673 }
1674 
1675 
1676 TiXmlNode *TiXmlUnknown::Clone() const
1677 {
1678   TiXmlUnknown *clone = new TiXmlUnknown();
1679 
1680   if ( !clone )
1681     return 0;
1682 
1683   CopyTo ( clone );
1684   return clone;
1685 }
1686 
1687 
1688 TiXmlAttributeSet::TiXmlAttributeSet()
1689 {
1690   sentinel.next = &sentinel;
1691   sentinel.prev = &sentinel;
1692 }
1693 
1694 
1695 TiXmlAttributeSet::~TiXmlAttributeSet()
1696 {
1697   assert ( sentinel.next == &sentinel );
1698   assert ( sentinel.prev == &sentinel );
1699 }
1700 
1701 
1702 void TiXmlAttributeSet::Add ( TiXmlAttribute *addMe )
1703 {
1704 #ifdef TIXML_USE_STL
1705   assert ( !Find ( TIXML_STRING ( addMe->Name() ) ) );	// Shouldn't be multiply adding to the set.
1706 #else
1707   assert ( !Find ( addMe->Name() ) );	// Shouldn't be multiply adding to the set.
1708 #endif
1709 
1710   addMe->next = &sentinel;
1711   addMe->prev = sentinel.prev;
1712 
1713   sentinel.prev->next = addMe;
1714   sentinel.prev      = addMe;
1715 }
1716 
1717 void TiXmlAttributeSet::Remove ( TiXmlAttribute *removeMe )
1718 {
1719   TiXmlAttribute *node;
1720 
1721   for ( node = sentinel.next; node != &sentinel; node = node->next )
1722   {
1723     if ( node == removeMe )
1724     {
1725       node->prev->next = node->next;
1726       node->next->prev = node->prev;
1727       node->next = 0;
1728       node->prev = 0;
1729       return;
1730     }
1731   }
1732 
1733   assert ( 0 );		// we tried to remove a non-linked attribute.
1734 }
1735 
1736 
1737 #ifdef TIXML_USE_STL
1738 const TiXmlAttribute *TiXmlAttributeSet::Find ( const std::string &name ) const
1739 {
1740   for ( const TiXmlAttribute *node = sentinel.next; node != &sentinel; node = node->next )
1741   {
1742     if ( node->name == name )
1743       return node;
1744   }
1745 
1746   return 0;
1747 }
1748 
1749 /*
1750 TiXmlAttribute*	TiXmlAttributeSet::Find( const std::string& name )
1751 {
1752 	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1753 	{
1754 		if ( node->name == name )
1755 			return node;
1756 	}
1757 	return 0;
1758 }
1759 */
1760 #endif
1761 
1762 
1763 const TiXmlAttribute *TiXmlAttributeSet::Find ( const char *name ) const
1764 {
1765   for ( const TiXmlAttribute *node = sentinel.next; node != &sentinel; node = node->next )
1766   {
1767     if ( strcmp ( node->name.c_str(), name ) == 0 )
1768       return node;
1769   }
1770 
1771   return 0;
1772 }
1773 
1774 /*
1775 TiXmlAttribute*	TiXmlAttributeSet::Find( const char* name )
1776 {
1777 	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1778 	{
1779 		if ( strcmp( node->name.c_str(), name ) == 0 )
1780 			return node;
1781 	}
1782 	return 0;
1783 }
1784 */
1785 
1786 #ifdef TIXML_USE_STL
1787 std::istream &operator>> (std::istream &in, TiXmlNode &base)
1788 {
1789   TIXML_STRING tag;
1790   tag.reserve ( 8 * 1000 );
1791   base.StreamIn ( &in, &tag );
1792 
1793   base.Parse ( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
1794   return in;
1795 }
1796 #endif
1797 
1798 
1799 #ifdef TIXML_USE_STL
1800 std::ostream &operator<< (std::ostream &out, const TiXmlNode &base)
1801 {
1802   TiXmlPrinter printer;
1803   printer.SetStreamPrinting();
1804   base.Accept ( &printer );
1805   out << printer.Str();
1806 
1807   return out;
1808 }
1809 
1810 
1811 std::string &operator<< (std::string &out, const TiXmlNode &base )
1812 {
1813   TiXmlPrinter printer;
1814   printer.SetStreamPrinting();
1815   base.Accept ( &printer );
1816   out.append ( printer.Str() );
1817 
1818   return out;
1819 }
1820 #endif
1821 
1822 
1823 TiXmlHandle TiXmlHandle::FirstChild() const
1824 {
1825   if ( node )
1826   {
1827     TiXmlNode *child = node->FirstChild();
1828 
1829     if ( child )
1830       return TiXmlHandle ( child );
1831   }
1832 
1833   return TiXmlHandle ( 0 );
1834 }
1835 
1836 
1837 TiXmlHandle TiXmlHandle::FirstChild ( const char *value ) const
1838 {
1839   if ( node )
1840   {
1841     TiXmlNode *child = node->FirstChild ( value );
1842 
1843     if ( child )
1844       return TiXmlHandle ( child );
1845   }
1846 
1847   return TiXmlHandle ( 0 );
1848 }
1849 
1850 
1851 TiXmlHandle TiXmlHandle::FirstChildElement() const
1852 {
1853   if ( node )
1854   {
1855     TiXmlElement *child = node->FirstChildElement();
1856 
1857     if ( child )
1858       return TiXmlHandle ( child );
1859   }
1860 
1861   return TiXmlHandle ( 0 );
1862 }
1863 
1864 
1865 TiXmlHandle TiXmlHandle::FirstChildElement ( const char *value ) const
1866 {
1867   if ( node )
1868   {
1869     TiXmlElement *child = node->FirstChildElement ( value );
1870 
1871     if ( child )
1872       return TiXmlHandle ( child );
1873   }
1874 
1875   return TiXmlHandle ( 0 );
1876 }
1877 
1878 
1879 TiXmlHandle TiXmlHandle::Child ( int count ) const
1880 {
1881   if ( node )
1882   {
1883     int i;
1884     TiXmlNode *child = node->FirstChild();
1885 
1886     for (	i = 0;
1887           child && i < count;
1888           child = child->NextSibling(), ++i )
1889     {
1890       // nothing
1891     }
1892 
1893     if ( child )
1894       return TiXmlHandle ( child );
1895   }
1896 
1897   return TiXmlHandle ( 0 );
1898 }
1899 
1900 
1901 TiXmlHandle TiXmlHandle::Child ( const char *value, int count ) const
1902 {
1903   if ( node )
1904   {
1905     int i;
1906     TiXmlNode *child = node->FirstChild ( value );
1907 
1908     for (	i = 0;
1909           child && i < count;
1910           child = child->NextSibling ( value ), ++i )
1911     {
1912       // nothing
1913     }
1914 
1915     if ( child )
1916       return TiXmlHandle ( child );
1917   }
1918 
1919   return TiXmlHandle ( 0 );
1920 }
1921 
1922 
1923 TiXmlHandle TiXmlHandle::ChildElement ( int count ) const
1924 {
1925   if ( node )
1926   {
1927     int i;
1928     TiXmlElement *child = node->FirstChildElement();
1929 
1930     for (	i = 0;
1931           child && i < count;
1932           child = child->NextSiblingElement(), ++i )
1933     {
1934       // nothing
1935     }
1936 
1937     if ( child )
1938       return TiXmlHandle ( child );
1939   }
1940 
1941   return TiXmlHandle ( 0 );
1942 }
1943 
1944 
1945 TiXmlHandle TiXmlHandle::ChildElement ( const char *value, int count ) const
1946 {
1947   if ( node )
1948   {
1949     int i;
1950     TiXmlElement *child = node->FirstChildElement ( value );
1951 
1952     for (	i = 0;
1953           child && i < count;
1954           child = child->NextSiblingElement ( value ), ++i )
1955     {
1956       // nothing
1957     }
1958 
1959     if ( child )
1960       return TiXmlHandle ( child );
1961   }
1962 
1963   return TiXmlHandle ( 0 );
1964 }
1965 
1966 
1967 bool TiXmlPrinter::VisitEnter ( const TiXmlDocument & )
1968 {
1969   return true;
1970 }
1971 
1972 bool TiXmlPrinter::VisitExit ( const TiXmlDocument & )
1973 {
1974   return true;
1975 }
1976 
1977 bool TiXmlPrinter::VisitEnter ( const TiXmlElement &element, const TiXmlAttribute *firstAttribute )
1978 {
1979   DoIndent();
1980   buffer += "<";
1981   buffer += element.Value();
1982 
1983   for ( const TiXmlAttribute *attrib = firstAttribute; attrib; attrib = attrib->Next() )
1984   {
1985     buffer += " ";
1986     attrib->Print ( 0, 0, &buffer );
1987   }
1988 
1989   if ( !element.FirstChild() )
1990   {
1991     buffer += " />";
1992     DoLineBreak();
1993   }
1994   else
1995   {
1996     buffer += ">";
1997 
1998     if (    element.FirstChild()->ToText()
1999             && element.LastChild() == element.FirstChild()
2000             && element.FirstChild()->ToText()->CDATA() == false )
2001     {
2002       simpleTextPrint = true;
2003       // no DoLineBreak()!
2004     }
2005     else
2006     {
2007       DoLineBreak();
2008     }
2009   }
2010 
2011   ++depth;
2012   return true;
2013 }
2014 
2015 
2016 bool TiXmlPrinter::VisitExit ( const TiXmlElement &element )
2017 {
2018   --depth;
2019 
2020   if ( !element.FirstChild() )
2021   {
2022     // nothing.
2023   }
2024   else
2025   {
2026     if ( simpleTextPrint )
2027     {
2028       simpleTextPrint = false;
2029     }
2030     else
2031     {
2032       DoIndent();
2033     }
2034 
2035     buffer += "</";
2036     buffer += element.Value();
2037     buffer += ">";
2038     DoLineBreak();
2039   }
2040 
2041   return true;
2042 }
2043 
2044 
2045 bool TiXmlPrinter::Visit ( const TiXmlText &text )
2046 {
2047   if ( text.CDATA() )
2048   {
2049     DoIndent();
2050     buffer += "<![CDATA[";
2051     buffer += text.Value();
2052     buffer += "]]>";
2053     DoLineBreak();
2054   }
2055   else if ( simpleTextPrint )
2056   {
2057     TIXML_STRING str;
2058     TiXmlBase::EncodeString ( text.ValueTStr(), &str );
2059     buffer += str;
2060   }
2061   else
2062   {
2063     DoIndent();
2064     TIXML_STRING str;
2065     TiXmlBase::EncodeString ( text.ValueTStr(), &str );
2066     buffer += str;
2067     DoLineBreak();
2068   }
2069 
2070   return true;
2071 }
2072 
2073 
2074 bool TiXmlPrinter::Visit ( const TiXmlDeclaration &declaration )
2075 {
2076   DoIndent();
2077   declaration.Print ( 0, 0, &buffer );
2078   DoLineBreak();
2079   return true;
2080 }
2081 
2082 
2083 bool TiXmlPrinter::Visit ( const TiXmlComment &comment )
2084 {
2085   DoIndent();
2086   buffer += "<!--";
2087   buffer += comment.Value();
2088   buffer += "-->";
2089   DoLineBreak();
2090   return true;
2091 }
2092 
2093 
2094 bool TiXmlPrinter::Visit ( const TiXmlUnknown &unknown )
2095 {
2096   DoIndent();
2097   buffer += "<";
2098   buffer += unknown.Value();
2099   buffer += ">";
2100   DoLineBreak();
2101   return true;
2102 }