CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/FWCore/Utilities/src/tinyxml.cc

Go to the documentation of this file.
00001 /*
00002 www.sourceforge.net/projects/tinyxml
00003 Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
00004 
00005 This software is provided 'as-is', without any express or implied
00006 warranty. In no event will the authors be held liable for any
00007 damages arising from the use of this software.
00008 
00009 Permission is granted to anyone to use this software for any
00010 purpose, including commercial applications, and to alter it and
00011 redistribute it freely, subject to the following restrictions:
00012 
00013 1. The origin of this software must not be misrepresented; you must
00014 not claim that you wrote the original software. If you use this
00015 software in a product, an acknowledgment in the product documentation
00016 would be appreciated but is not required.
00017 
00018 2. Altered source versions must be plainly marked as such, and
00019 must not be misrepresented as being the original software.
00020 
00021 3. This notice may not be removed or altered from any source
00022 distribution.
00023 */
00024 /*
00025  * THIS FILE WAS ALTERED BY Eric Vaandering, 25 August 2009.
00026  * THIS FILE WAS ALTERED BY Bill Tanenbaum, 2 September 2011.
00027  * Coverity complains about sprintf, so converted to snprintf.
00028  * THIS FILE WAS ALTERED BY Bill Tanenbaum, 10 November 2011.
00029  * Coverity complains about assignment operators returning void,
00030  * so fixed them to return a reference to the object.
00031  */
00032 #define TIXML_USE_STL
00033 
00034 #ifdef TIXML_USE_STL
00035 #include <sstream>
00036 #include <iostream>
00037 #endif
00038 
00039 #include "FWCore/Utilities/interface/tinyxml.h"
00040 
00041 #include <boost/lexical_cast.hpp>
00042 
00043 bool TiXmlBase::condenseWhiteSpace = true;
00044 
00045 // Microsoft compiler security
00046 FILE* TiXmlFOpen( const char* filename, const char* mode )
00047 {
00048         #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
00049                 FILE* fp = 0;
00050                 errno_t err = fopen_s( &fp, filename, mode );
00051                 if ( !err && fp )
00052                         return fp;
00053                 return 0;
00054         #else
00055                 return fopen( filename, mode );
00056         #endif
00057 }
00058 
00059 void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
00060 {
00061         int i=0;
00062 
00063         while( i<(int)str.length() )
00064         {
00065                 unsigned char c = (unsigned char) str[i];
00066 
00067                 if (    c == '&'
00068                      && i < ( (int)str.length() - 2 )
00069                          && str[i+1] == '#'
00070                          && str[i+2] == 'x' )
00071                 {
00072                         // Hexadecimal character reference.
00073                         // Pass through unchanged.
00074                         // &#xA9;       -- copyright symbol, for example.
00075                         //
00076                         // The -1 is a bug fix from Rob Laveaux. It keeps
00077                         // an overflow from happening if there is no ';'.
00078                         // There are actually 2 ways to exit this loop -
00079                         // while fails (error case) and break (semicolon found).
00080                         // However, there is no mechanism (currently) for
00081                         // this function to return an error.
00082                         while ( i<(int)str.length()-1 )
00083                         {
00084                                 outString->append( str.c_str() + i, 1 );
00085                                 ++i;
00086                                 if ( str[i] == ';' )
00087                                         break;
00088                         }
00089                 }
00090                 else if ( c == '&' )
00091                 {
00092                         outString->append( entity[0].str, entity[0].strLength );
00093                         ++i;
00094                 }
00095                 else if ( c == '<' )
00096                 {
00097                         outString->append( entity[1].str, entity[1].strLength );
00098                         ++i;
00099                 }
00100                 else if ( c == '>' )
00101                 {
00102                         outString->append( entity[2].str, entity[2].strLength );
00103                         ++i;
00104                 }
00105                 else if ( c == '\"' )
00106                 {
00107                         outString->append( entity[3].str, entity[3].strLength );
00108                         ++i;
00109                 }
00110                 else if ( c == '\'' )
00111                 {
00112                         outString->append( entity[4].str, entity[4].strLength );
00113                         ++i;
00114                 }
00115                 else if ( c < 32 )
00116                 {
00117                         // Easy pass at non-alpha/numeric/symbol
00118                         // Below 32 is symbolic.
00119                         char buf[ 32 ];
00120 
00121                         #if defined(TIXML_SNPRINTF)
00122                                 TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
00123                         #else
00124                                 snprintf( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
00125                         #endif
00126 
00127                         //*ME:  warning C4267: convert 'size_t' to 'int'
00128                         //*ME:  Int-Cast to make compiler happy ...
00129                         outString->append( buf, (int)strlen( buf ) );
00130                         ++i;
00131                 }
00132                 else
00133                 {
00134                         //char realc = (char) c;
00135                         //outString->append( &realc, 1 );
00136                         *outString += (char) c; // somewhat more efficient function call.
00137                         ++i;
00138                 }
00139         }
00140 }
00141 
00142 
00143 TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
00144 {
00145         parent = 0;
00146         type = _type;
00147         firstChild = 0;
00148         lastChild = 0;
00149         prev = 0;
00150         next = 0;
00151 }
00152 
00153 
00154 TiXmlNode::~TiXmlNode()
00155 {
00156         TiXmlNode* node = firstChild;
00157         TiXmlNode* temp = 0;
00158 
00159         while ( node )
00160         {
00161                 temp = node;
00162                 node = node->next;
00163                 delete temp;
00164         }
00165 }
00166 
00167 
00168 void TiXmlNode::CopyTo( TiXmlNode* target ) const
00169 {
00170         target->SetValue (value.c_str() );
00171         target->userData = userData;
00172 }
00173 
00174 
00175 void TiXmlNode::Clear()
00176 {
00177         TiXmlNode* node = firstChild;
00178         TiXmlNode* temp = 0;
00179 
00180         while ( node )
00181         {
00182                 temp = node;
00183                 node = node->next;
00184                 delete temp;
00185         }
00186 
00187         firstChild = 0;
00188         lastChild = 0;
00189 }
00190 
00191 
00192 TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
00193 {
00194         assert( node->parent == 0 || node->parent == this );
00195         assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
00196 
00197         if ( node->Type() == TiXmlNode::DOCUMENT )
00198         {
00199                 delete node;
00200                 if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
00201                 return 0;
00202         }
00203 
00204         node->parent = this;
00205 
00206         node->prev = lastChild;
00207         node->next = 0;
00208 
00209         if ( lastChild )
00210                 lastChild->next = node;
00211         else
00212                 firstChild = node;                      // it was an empty list.
00213 
00214         lastChild = node;
00215         return node;
00216 }
00217 
00218 
00219 TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
00220 {
00221         if ( addThis.Type() == TiXmlNode::DOCUMENT )
00222         {
00223                 if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
00224                 return 0;
00225         }
00226         TiXmlNode* node = addThis.Clone();
00227         if ( !node )
00228                 return 0;
00229 
00230         return LinkEndChild( node );
00231 }
00232 
00233 
00234 TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
00235 {
00236         if ( !beforeThis || beforeThis->parent != this ) {
00237                 return 0;
00238         }
00239         if ( addThis.Type() == TiXmlNode::DOCUMENT )
00240         {
00241                 if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
00242                 return 0;
00243         }
00244 
00245         TiXmlNode* node = addThis.Clone();
00246         if ( !node )
00247                 return 0;
00248         node->parent = this;
00249 
00250         node->next = beforeThis;
00251         node->prev = beforeThis->prev;
00252         if ( beforeThis->prev )
00253         {
00254                 beforeThis->prev->next = node;
00255         }
00256         else
00257         {
00258                 assert( firstChild == beforeThis );
00259                 firstChild = node;
00260         }
00261         beforeThis->prev = node;
00262         return node;
00263 }
00264 
00265 
00266 TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
00267 {
00268         if ( !afterThis || afterThis->parent != this ) {
00269                 return 0;
00270         }
00271         if ( addThis.Type() == TiXmlNode::DOCUMENT )
00272         {
00273                 if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
00274                 return 0;
00275         }
00276 
00277         TiXmlNode* node = addThis.Clone();
00278         if ( !node )
00279                 return 0;
00280         node->parent = this;
00281 
00282         node->prev = afterThis;
00283         node->next = afterThis->next;
00284         if ( afterThis->next )
00285         {
00286                 afterThis->next->prev = node;
00287         }
00288         else
00289         {
00290                 assert( lastChild == afterThis );
00291                 lastChild = node;
00292         }
00293         afterThis->next = node;
00294         return node;
00295 }
00296 
00297 
00298 TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
00299 {
00300         if ( replaceThis->parent != this )
00301                 return 0;
00302 
00303         TiXmlNode* node = withThis.Clone();
00304         if ( !node )
00305                 return 0;
00306 
00307         node->next = replaceThis->next;
00308         node->prev = replaceThis->prev;
00309 
00310         if ( replaceThis->next )
00311                 replaceThis->next->prev = node;
00312         else
00313                 lastChild = node;
00314 
00315         if ( replaceThis->prev )
00316                 replaceThis->prev->next = node;
00317         else
00318                 firstChild = node;
00319 
00320         delete replaceThis;
00321         node->parent = this;
00322         return node;
00323 }
00324 
00325 
00326 bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
00327 {
00328         if ( removeThis->parent != this )
00329         {
00330                 assert( 0 );
00331                 return false;
00332         }
00333 
00334         if ( removeThis->next )
00335                 removeThis->next->prev = removeThis->prev;
00336         else
00337                 lastChild = removeThis->prev;
00338 
00339         if ( removeThis->prev )
00340                 removeThis->prev->next = removeThis->next;
00341         else
00342                 firstChild = removeThis->next;
00343 
00344         delete removeThis;
00345         return true;
00346 }
00347 
00348 const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
00349 {
00350         const TiXmlNode* node;
00351         for ( node = firstChild; node; node = node->next )
00352         {
00353                 if ( strcmp( node->Value(), _value ) == 0 )
00354                         return node;
00355         }
00356         return 0;
00357 }
00358 
00359 
00360 const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
00361 {
00362         const TiXmlNode* node;
00363         for ( node = lastChild; node; node = node->prev )
00364         {
00365                 if ( strcmp( node->Value(), _value ) == 0 )
00366                         return node;
00367         }
00368         return 0;
00369 }
00370 
00371 
00372 const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
00373 {
00374         if ( !previous )
00375         {
00376                 return FirstChild();
00377         }
00378         else
00379         {
00380                 assert( previous->parent == this );
00381                 return previous->NextSibling();
00382         }
00383 }
00384 
00385 
00386 const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
00387 {
00388         if ( !previous )
00389         {
00390                 return FirstChild( val );
00391         }
00392         else
00393         {
00394                 assert( previous->parent == this );
00395                 return previous->NextSibling( val );
00396         }
00397 }
00398 
00399 
00400 const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
00401 {
00402         const TiXmlNode* node;
00403         for ( node = next; node; node = node->next )
00404         {
00405                 if ( strcmp( node->Value(), _value ) == 0 )
00406                         return node;
00407         }
00408         return 0;
00409 }
00410 
00411 
00412 const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
00413 {
00414         const TiXmlNode* node;
00415         for ( node = prev; node; node = node->prev )
00416         {
00417                 if ( strcmp( node->Value(), _value ) == 0 )
00418                         return node;
00419         }
00420         return 0;
00421 }
00422 
00423 
00424 void TiXmlElement::RemoveAttribute( const char * name )
00425 {
00426     #ifdef TIXML_USE_STL
00427         TIXML_STRING str( name );
00428         TiXmlAttribute* node = attributeSet.Find( str );
00429         #else
00430         TiXmlAttribute* node = attributeSet.Find( name );
00431         #endif
00432         if ( node )
00433         {
00434                 attributeSet.Remove( node );
00435                 delete node;
00436         }
00437 }
00438 
00439 const TiXmlElement* TiXmlNode::FirstChildElement() const
00440 {
00441         const TiXmlNode* node;
00442 
00443         for (   node = FirstChild();
00444                         node;
00445                         node = node->NextSibling() )
00446         {
00447                 if ( node->ToElement() )
00448                         return node->ToElement();
00449         }
00450         return 0;
00451 }
00452 
00453 
00454 const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
00455 {
00456         const TiXmlNode* node;
00457 
00458         for (   node = FirstChild( _value );
00459                         node;
00460                         node = node->NextSibling( _value ) )
00461         {
00462                 if ( node->ToElement() )
00463                         return node->ToElement();
00464         }
00465         return 0;
00466 }
00467 
00468 
00469 const TiXmlElement* TiXmlNode::NextSiblingElement() const
00470 {
00471         const TiXmlNode* node;
00472 
00473         for (   node = NextSibling();
00474                         node;
00475                         node = node->NextSibling() )
00476         {
00477                 if ( node->ToElement() )
00478                         return node->ToElement();
00479         }
00480         return 0;
00481 }
00482 
00483 
00484 const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
00485 {
00486         const TiXmlNode* node;
00487 
00488         for (   node = NextSibling( _value );
00489                         node;
00490                         node = node->NextSibling( _value ) )
00491         {
00492                 if ( node->ToElement() )
00493                         return node->ToElement();
00494         }
00495         return 0;
00496 }
00497 
00498 
00499 const TiXmlDocument* TiXmlNode::GetDocument() const
00500 {
00501         const TiXmlNode* node;
00502 
00503         for( node = this; node; node = node->parent )
00504         {
00505                 if ( node->ToDocument() )
00506                         return node->ToDocument();
00507         }
00508         return 0;
00509 }
00510 
00511 
00512 TiXmlElement::TiXmlElement (const char * _value)
00513         : TiXmlNode( TiXmlNode::ELEMENT )
00514 {
00515         firstChild = lastChild = 0;
00516         value = _value;
00517 }
00518 
00519 
00520 #ifdef TIXML_USE_STL
00521 TiXmlElement::TiXmlElement( const std::string& _value )
00522         : TiXmlNode( TiXmlNode::ELEMENT )
00523 {
00524         firstChild = lastChild = 0;
00525         value = _value;
00526 }
00527 #endif
00528 
00529 
00530 TiXmlElement::TiXmlElement( const TiXmlElement& copy)
00531         : TiXmlNode( TiXmlNode::ELEMENT )
00532 {
00533         firstChild = lastChild = 0;
00534         copy.CopyTo( this );
00535 }
00536 
00537 
00538 TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base )
00539 {
00540         ClearThis();
00541         base.CopyTo( this );
00542         return *this;
00543 }
00544 
00545 
00546 TiXmlElement::~TiXmlElement()
00547 {
00548         ClearThis();
00549 }
00550 
00551 
00552 void TiXmlElement::ClearThis()
00553 {
00554         Clear();
00555         while( attributeSet.First() )
00556         {
00557                 TiXmlAttribute* node = attributeSet.First();
00558                 attributeSet.Remove( node );
00559                 delete node;
00560         }
00561 }
00562 
00563 
00564 const char* TiXmlElement::Attribute( const char* name ) const
00565 {
00566         const TiXmlAttribute* node = attributeSet.Find( name );
00567         if ( node )
00568                 return node->Value();
00569         return 0;
00570 }
00571 
00572 
00573 #ifdef TIXML_USE_STL
00574 const std::string* TiXmlElement::Attribute( const std::string& name ) const
00575 {
00576         const TiXmlAttribute* node = attributeSet.Find( name );
00577         if ( node )
00578                 return &node->ValueStr();
00579         return 0;
00580 }
00581 #endif
00582 
00583 
00584 const char* TiXmlElement::Attribute( const char* name, int* i ) const
00585 {
00586         const char* s = Attribute( name );
00587         if ( i )
00588         {
00589                 if ( s ) {
00590                         *i = atoi( s );
00591                 }
00592                 else {
00593                         *i = 0;
00594                 }
00595         }
00596         return s;
00597 }
00598 
00599 
00600 #ifdef TIXML_USE_STL
00601 const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
00602 {
00603         const std::string* s = Attribute( name );
00604         if ( i )
00605         {
00606                 if ( s ) {
00607                         *i = atoi( s->c_str() );
00608                 }
00609                 else {
00610                         *i = 0;
00611                 }
00612         }
00613         return s;
00614 }
00615 #endif
00616 
00617 
00618 const char* TiXmlElement::Attribute( const char* name, double* d ) const
00619 {
00620         const char* s = Attribute( name );
00621         if ( d )
00622         {
00623                 if ( s ) {
00624                         *d = atof( s );
00625                 }
00626                 else {
00627                         *d = 0;
00628                 }
00629         }
00630         return s;
00631 }
00632 
00633 
00634 #ifdef TIXML_USE_STL
00635 const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
00636 {
00637         const std::string* s = Attribute( name );
00638         if ( d )
00639         {
00640                 if ( s ) {
00641                         *d = atof( s->c_str() );
00642                 }
00643                 else {
00644                         *d = 0;
00645                 }
00646         }
00647         return s;
00648 }
00649 #endif
00650 
00651 
00652 int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
00653 {
00654         const TiXmlAttribute* node = attributeSet.Find( name );
00655         if ( !node )
00656                 return TIXML_NO_ATTRIBUTE;
00657         return node->QueryIntValue( ival );
00658 }
00659 
00660 
00661 #ifdef TIXML_USE_STL
00662 int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
00663 {
00664         const TiXmlAttribute* node = attributeSet.Find( name );
00665         if ( !node )
00666                 return TIXML_NO_ATTRIBUTE;
00667         return node->QueryIntValue( ival );
00668 }
00669 #endif
00670 
00671 
00672 int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
00673 {
00674         const TiXmlAttribute* node = attributeSet.Find( name );
00675         if ( !node )
00676                 return TIXML_NO_ATTRIBUTE;
00677         return node->QueryDoubleValue( dval );
00678 }
00679 
00680 
00681 #ifdef TIXML_USE_STL
00682 int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
00683 {
00684         const TiXmlAttribute* node = attributeSet.Find( name );
00685         if ( !node )
00686                 return TIXML_NO_ATTRIBUTE;
00687         return node->QueryDoubleValue( dval );
00688 }
00689 #endif
00690 
00691 
00692 void TiXmlElement::SetAttribute( const char * name, int val )
00693 {
00694         char buf[64];
00695         #if defined(TIXML_SNPRINTF)
00696                 TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
00697         #else
00698                 snprintf( buf, sizeof(buf), "%d", val );
00699         #endif
00700         SetAttribute( name, buf );
00701 }
00702 
00703 
00704 #ifdef TIXML_USE_STL
00705 void TiXmlElement::SetAttribute( const std::string& name, int val )
00706 {
00707    std::ostringstream oss;
00708    oss << val;
00709    SetAttribute( name, oss.str() );
00710 }
00711 #endif
00712 
00713 
00714 void TiXmlElement::SetDoubleAttribute( const char * name, double val )
00715 {
00716         char buf[256];
00717         #if defined(TIXML_SNPRINTF)
00718                 TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
00719         #else
00720                 snprintf( buf, sizeof(buf), "%f", val );
00721         #endif
00722         SetAttribute( name, buf );
00723 }
00724 
00725 
00726 void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
00727 {
00728     #ifdef TIXML_USE_STL
00729         TIXML_STRING _name( cname );
00730         TIXML_STRING _value( cvalue );
00731         #else
00732         const char* _name = cname;
00733         const char* _value = cvalue;
00734         #endif
00735 
00736         TiXmlAttribute* node = attributeSet.Find( _name );
00737         if ( node )
00738         {
00739                 node->SetValue( _value );
00740                 return;
00741         }
00742 
00743         TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue );
00744         if ( attrib )
00745         {
00746                 attributeSet.Add( attrib );
00747         }
00748         else
00749         {
00750                 TiXmlDocument* document = GetDocument();
00751                 if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
00752         }
00753 }
00754 
00755 
00756 #ifdef TIXML_USE_STL
00757 void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
00758 {
00759         TiXmlAttribute* node = attributeSet.Find( name );
00760         if ( node )
00761         {
00762                 node->SetValue( _value );
00763                 return;
00764         }
00765 
00766         TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
00767         if ( attrib )
00768         {
00769                 attributeSet.Add( attrib );
00770         }
00771         else
00772         {
00773                 TiXmlDocument* document = GetDocument();
00774                 if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
00775         }
00776 }
00777 #endif
00778 
00779 
00780 void TiXmlElement::Print( FILE* cfile, int depth ) const
00781 {
00782         int i;
00783         assert( cfile );
00784         for ( i=0; i<depth; i++ ) {
00785                 fprintf( cfile, "    " );
00786         }
00787 
00788         fprintf( cfile, "<%s", value.c_str() );
00789 
00790         const TiXmlAttribute* attrib;
00791         for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
00792         {
00793                 fprintf( cfile, " " );
00794                 attrib->Print( cfile, depth );
00795         }
00796 
00797         // There are 3 different formatting approaches:
00798         // 1) An element without children is printed as a <foo /> node
00799         // 2) An element with only a text child is printed as <foo> text </foo>
00800         // 3) An element with children is printed on multiple lines.
00801         TiXmlNode* node;
00802         if ( !firstChild )
00803         {
00804                 fprintf( cfile, " />" );
00805         }
00806         else if ( firstChild == lastChild && firstChild->ToText() )
00807         {
00808                 fprintf( cfile, ">" );
00809                 firstChild->Print( cfile, depth + 1 );
00810                 fprintf( cfile, "</%s>", value.c_str() );
00811         }
00812         else
00813         {
00814                 fprintf( cfile, ">" );
00815 
00816                 for ( node = firstChild; node; node=node->NextSibling() )
00817                 {
00818                         if ( !node->ToText() )
00819                         {
00820                                 fprintf( cfile, "\n" );
00821                         }
00822                         node->Print( cfile, depth+1 );
00823                 }
00824                 fprintf( cfile, "\n" );
00825                 for( i=0; i<depth; ++i ) {
00826                         fprintf( cfile, "    " );
00827                 }
00828                 fprintf( cfile, "</%s>", value.c_str() );
00829         }
00830 }
00831 
00832 
00833 void TiXmlElement::CopyTo( TiXmlElement* target ) const
00834 {
00835         // superclass:
00836         TiXmlNode::CopyTo( target );
00837 
00838         // Element class:
00839         // Clone the attributes, then clone the children.
00840         const TiXmlAttribute* attribute = 0;
00841         for(    attribute = attributeSet.First();
00842         attribute;
00843         attribute = attribute->Next() )
00844         {
00845                 target->SetAttribute( attribute->Name(), attribute->Value() );
00846         }
00847 
00848         TiXmlNode* node = 0;
00849         for ( node = firstChild; node; node = node->NextSibling() )
00850         {
00851                 target->LinkEndChild( node->Clone() );
00852         }
00853 }
00854 
00855 bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
00856 {
00857         if ( visitor->VisitEnter( *this, attributeSet.First() ) )
00858         {
00859                 for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
00860                 {
00861                         if ( !node->Accept( visitor ) )
00862                                 break;
00863                 }
00864         }
00865         return visitor->VisitExit( *this );
00866 }
00867 
00868 
00869 TiXmlNode* TiXmlElement::Clone() const
00870 {
00871         TiXmlElement* clone = new TiXmlElement( Value() );
00872         if ( !clone )
00873                 return 0;
00874 
00875         CopyTo( clone );
00876         return clone;
00877 }
00878 
00879 
00880 const char* TiXmlElement::GetText() const
00881 {
00882         const TiXmlNode* child = this->FirstChild();
00883         if ( child ) {
00884                 const TiXmlText* childText = child->ToText();
00885                 if ( childText ) {
00886                         return childText->Value();
00887                 }
00888         }
00889         return 0;
00890 }
00891 
00892 
00893 TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
00894 {
00895         tabsize = 4;
00896         useMicrosoftBOM = false;
00897         ClearError();
00898 }
00899 
00900 TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
00901 {
00902         tabsize = 4;
00903         useMicrosoftBOM = false;
00904         value = documentName;
00905         ClearError();
00906 }
00907 
00908 
00909 #ifdef TIXML_USE_STL
00910 TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
00911 {
00912         tabsize = 4;
00913         useMicrosoftBOM = false;
00914     value = documentName;
00915         ClearError();
00916 }
00917 #endif
00918 
00919 
00920 TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
00921 {
00922         copy.CopyTo( this );
00923 }
00924 
00925 
00926 TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy )
00927 {
00928         Clear();
00929         copy.CopyTo( this );
00930         return *this;
00931 }
00932 
00933 
00934 bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
00935 {
00936         // See STL_STRING_BUG below.
00937         //StringToBuffer buf( value );
00938 
00939         return LoadFile( Value(), encoding );
00940 }
00941 
00942 
00943 bool TiXmlDocument::SaveFile() const
00944 {
00945         // See STL_STRING_BUG below.
00946 //      StringToBuffer buf( value );
00947 //
00948 //      if ( buf.buffer && SaveFile( buf.buffer ) )
00949 //              return true;
00950 //
00951 //      return false;
00952         return SaveFile( Value() );
00953 }
00954 
00955 bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
00956 {
00957         // There was a really terrifying little bug here. The code:
00958         //              value = filename
00959         // in the STL case, cause the assignment method of the std::string to
00960         // be called. What is strange, is that the std::string had the same
00961         // address as it's c_str() method, and so bad things happen. Looks
00962         // like a bug in the Microsoft STL implementation.
00963         // Add an extra string to avoid the crash.
00964         TIXML_STRING filename( _filename );
00965         value = filename;
00966 
00967         // reading in binary mode so that tinyxml can normalize the EOL
00968         FILE* file = TiXmlFOpen( value.c_str (), "rb" );
00969 
00970         if ( file )
00971         {
00972                 bool result = LoadFile( file, encoding );
00973                 fclose( file );
00974                 return result;
00975         }
00976         else
00977         {
00978                 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
00979                 return false;
00980         }
00981 }
00982 
00983 bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
00984 {
00985         if ( !file )
00986         {
00987                 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
00988                 return false;
00989         }
00990 
00991         // Delete the existing data:
00992         Clear();
00993         location.Clear();
00994 
00995         // Get the file size, so we can pre-allocate the string. HUGE speed impact.
00996         long length = 0;
00997         fseek( file, 0, SEEK_END );
00998         length = ftell( file );
00999         fseek( file, 0, SEEK_SET );
01000 
01001         // Strange case, but good to handle up front.
01002         if ( length <= 0 )
01003         {
01004                 SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
01005                 return false;
01006         }
01007 
01008         // If we have a file, assume it is all one big XML file, and read it in.
01009         // The document parser may decide the document ends sooner than the entire file, however.
01010         TIXML_STRING data;
01011         data.reserve( length );
01012 
01013         // Subtle bug here. TinyXml did use fgets. But from the XML spec:
01014         // 2.11 End-of-Line Handling
01015         // <snip>
01016         // <quote>
01017         // ...the XML processor MUST behave as if it normalized all line breaks in external
01018         // parsed entities (including the document entity) on input, before parsing, by translating
01019         // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
01020         // a single #xA character.
01021         // </quote>
01022         //
01023         // It is not clear fgets does that, and certainly isn't clear it works cross platform.
01024         // Generally, you expect fgets to translate from the convention of the OS to the c/unix
01025         // convention, and not work generally.
01026 
01027         /*
01028         while( fgets( buf, sizeof(buf), file ) )
01029         {
01030                 data += buf;
01031         }
01032         */
01033 
01034         char* buf = new char[ length+1 ];
01035         buf[0] = 0;
01036 
01037         if ( fread( buf, length, 1, file ) != 1 ) {
01038                 delete [] buf;
01039                 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
01040                 return false;
01041         }
01042 
01043         const char* lastPos = buf;
01044         const char* p = buf;
01045 
01046         buf[length] = 0;
01047         while( *p ) {
01048                 assert( p < (buf+length) );
01049                 if ( *p == 0xa ) {
01050                         // Newline character. No special rules for this. Append all the characters
01051                         // since the last string, and include the newline.
01052                         data.append( lastPos, (p-lastPos+1) );  // append, include the newline
01053                         ++p;                                                                    // move past the newline
01054                         lastPos = p;                                                    // and point to the new buffer (may be 0)
01055                         assert( p <= (buf+length) );
01056                 }
01057                 else if ( *p == 0xd ) {
01058                         // Carriage return. Append what we have so far, then
01059                         // handle moving forward in the buffer.
01060                         if ( (p-lastPos) > 0 ) {
01061                                 data.append( lastPos, p-lastPos );      // do not add the CR
01062                         }
01063                         data += (char)0xa;                                              // a proper newline
01064 
01065                         if ( *(p+1) == 0xa ) {
01066                                 // Carriage return - new line sequence
01067                                 p += 2;
01068                                 lastPos = p;
01069                                 assert( p <= (buf+length) );
01070                         }
01071                         else {
01072                                 // it was followed by something else...that is presumably characters again.
01073                                 ++p;
01074                                 lastPos = p;
01075                                 assert( p <= (buf+length) );
01076                         }
01077                 }
01078                 else {
01079                         ++p;
01080                 }
01081         }
01082         // Handle any left over characters.
01083         if ( p-lastPos ) {
01084                 data.append( lastPos, p-lastPos );
01085         }
01086         delete [] buf;
01087         buf = 0;
01088 
01089         Parse( data.c_str(), 0, encoding );
01090 
01091         if (  Error() )
01092         return false;
01093     else
01094                 return true;
01095 }
01096 
01097 
01098 bool TiXmlDocument::SaveFile( const char * filename ) const
01099 {
01100         // The old c stuff lives on...
01101         FILE* fp = TiXmlFOpen( filename, "w" );
01102         if ( fp )
01103         {
01104                 bool result = SaveFile( fp );
01105                 fclose( fp );
01106                 return result;
01107         }
01108         return false;
01109 }
01110 
01111 
01112 bool TiXmlDocument::SaveFile( FILE* fp ) const
01113 {
01114         if ( useMicrosoftBOM )
01115         {
01116                 const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
01117                 const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
01118                 const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
01119 
01120                 fputc( TIXML_UTF_LEAD_0, fp );
01121                 fputc( TIXML_UTF_LEAD_1, fp );
01122                 fputc( TIXML_UTF_LEAD_2, fp );
01123         }
01124         Print( fp, 0 );
01125         return (ferror(fp) == 0);
01126 }
01127 
01128 
01129 void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
01130 {
01131         TiXmlNode::CopyTo( target );
01132 
01133         target->error = error;
01134         target->errorId = errorId;
01135         target->errorDesc = errorDesc;
01136         target->tabsize = tabsize;
01137         target->errorLocation = errorLocation;
01138         target->useMicrosoftBOM = useMicrosoftBOM;
01139 
01140         TiXmlNode* node = 0;
01141         for ( node = firstChild; node; node = node->NextSibling() )
01142         {
01143                 target->LinkEndChild( node->Clone() );
01144         }
01145 }
01146 
01147 
01148 TiXmlNode* TiXmlDocument::Clone() const
01149 {
01150         TiXmlDocument* clone = new TiXmlDocument();
01151         if ( !clone )
01152                 return 0;
01153 
01154         CopyTo( clone );
01155         return clone;
01156 }
01157 
01158 
01159 void TiXmlDocument::Print( FILE* cfile, int depth ) const
01160 {
01161         assert( cfile );
01162         for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
01163         {
01164                 node->Print( cfile, depth );
01165                 fprintf( cfile, "\n" );
01166         }
01167 }
01168 
01169 
01170 bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
01171 {
01172         if ( visitor->VisitEnter( *this ) )
01173         {
01174                 for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
01175                 {
01176                         if ( !node->Accept( visitor ) )
01177                                 break;
01178                 }
01179         }
01180         return visitor->VisitExit( *this );
01181 }
01182 
01183 
01184 const TiXmlAttribute* TiXmlAttribute::Next() const
01185 {
01186         // We are using knowledge of the sentinel. The sentinel
01187         // have a value or name.
01188         if ( next->value.empty() && next->name.empty() )
01189                 return 0;
01190         return next;
01191 }
01192 
01193 /*
01194 TiXmlAttribute* TiXmlAttribute::Next()
01195 {
01196         // We are using knowledge of the sentinel. The sentinel
01197         // have a value or name.
01198         if ( next->value.empty() && next->name.empty() )
01199                 return 0;
01200         return next;
01201 }
01202 */
01203 
01204 const TiXmlAttribute* TiXmlAttribute::Previous() const
01205 {
01206         // We are using knowledge of the sentinel. The sentinel
01207         // have a value or name.
01208         if ( prev->value.empty() && prev->name.empty() )
01209                 return 0;
01210         return prev;
01211 }
01212 
01213 /*
01214 TiXmlAttribute* TiXmlAttribute::Previous()
01215 {
01216         // We are using knowledge of the sentinel. The sentinel
01217         // have a value or name.
01218         if ( prev->value.empty() && prev->name.empty() )
01219                 return 0;
01220         return prev;
01221 }
01222 */
01223 
01224 void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
01225 {
01226         TIXML_STRING n, v;
01227 
01228         EncodeString( name, &n );
01229         EncodeString( value, &v );
01230 
01231         if (value.find ('\"') == TIXML_STRING::npos) {
01232                 if ( cfile ) {
01233                 fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
01234                 }
01235                 if ( str ) {
01236                         (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
01237                 }
01238         }
01239         else {
01240                 if ( cfile ) {
01241                 fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
01242                 }
01243                 if ( str ) {
01244                         (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
01245                 }
01246         }
01247 }
01248 
01249 
01250 int TiXmlAttribute::QueryIntValue( int* ival ) const
01251 {
01252         try {
01253           *ival = boost::lexical_cast<int>(value);
01254         } catch(boost::bad_lexical_cast const&) {
01255           return TIXML_WRONG_TYPE;
01256         }
01257         return TIXML_SUCCESS;
01258 }
01259 
01260 int TiXmlAttribute::QueryDoubleValue( double* dval ) const
01261 {
01262         try {
01263           *dval = boost::lexical_cast<double>(value);
01264         } catch(boost::bad_lexical_cast const&) {
01265           return TIXML_WRONG_TYPE;
01266         }
01267         return TIXML_SUCCESS;
01268 }
01269 
01270 void TiXmlAttribute::SetIntValue( int _value )
01271 {
01272         char buf [64];
01273         #if defined(TIXML_SNPRINTF)
01274                 TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
01275         #else
01276                 snprintf (buf, sizeof(buf), "%d", _value);
01277         #endif
01278         SetValue (buf);
01279 }
01280 
01281 void TiXmlAttribute::SetDoubleValue( double _value )
01282 {
01283         char buf [256];
01284         #if defined(TIXML_SNPRINTF)
01285                 TIXML_SNPRINTF( buf, sizeof(buf), "%f", _value);
01286         #else
01287                 snprintf (buf, sizeof(buf), "%f", _value);
01288         #endif
01289         SetValue (buf);
01290 }
01291 
01292 int TiXmlAttribute::IntValue() const
01293 {
01294         return atoi (value.c_str ());
01295 }
01296 
01297 double  TiXmlAttribute::DoubleValue() const
01298 {
01299         return atof (value.c_str ());
01300 }
01301 
01302 
01303 TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
01304 {
01305         copy.CopyTo( this );
01306 }
01307 
01308 
01309 TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base )
01310 {
01311         Clear();
01312         base.CopyTo( this );
01313         return *this;
01314 }
01315 
01316 
01317 void TiXmlComment::Print( FILE* cfile, int depth ) const
01318 {
01319         assert( cfile );
01320         for ( int i=0; i<depth; i++ )
01321         {
01322                 fprintf( cfile,  "    " );
01323         }
01324         fprintf( cfile, "<!--%s-->", value.c_str() );
01325 }
01326 
01327 
01328 void TiXmlComment::CopyTo( TiXmlComment* target ) const
01329 {
01330         TiXmlNode::CopyTo( target );
01331 }
01332 
01333 
01334 bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
01335 {
01336         return visitor->Visit( *this );
01337 }
01338 
01339 
01340 TiXmlNode* TiXmlComment::Clone() const
01341 {
01342         TiXmlComment* clone = new TiXmlComment();
01343 
01344         if ( !clone )
01345                 return 0;
01346 
01347         CopyTo( clone );
01348         return clone;
01349 }
01350 
01351 
01352 void TiXmlText::Print( FILE* cfile, int depth ) const
01353 {
01354         assert( cfile );
01355         if ( cdata )
01356         {
01357                 int i;
01358                 fprintf( cfile, "\n" );
01359                 for ( i=0; i<depth; i++ ) {
01360                         fprintf( cfile, "    " );
01361                 }
01362                 fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() );    // unformatted output
01363         }
01364         else
01365         {
01366                 TIXML_STRING buffer;
01367                 EncodeString( value, &buffer );
01368                 fprintf( cfile, "%s", buffer.c_str() );
01369         }
01370 }
01371 
01372 
01373 void TiXmlText::CopyTo( TiXmlText* target ) const
01374 {
01375         TiXmlNode::CopyTo( target );
01376         target->cdata = cdata;
01377 }
01378 
01379 
01380 bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
01381 {
01382         return visitor->Visit( *this );
01383 }
01384 
01385 
01386 TiXmlNode* TiXmlText::Clone() const
01387 {
01388         TiXmlText* clone = 0;
01389         clone = new TiXmlText( "" );
01390 
01391         if ( !clone )
01392                 return 0;
01393 
01394         CopyTo( clone );
01395         return clone;
01396 }
01397 
01398 
01399 TiXmlDeclaration::TiXmlDeclaration( const char * _version,
01400                                                                         const char * _encoding,
01401                                                                         const char * _standalone )
01402         : TiXmlNode( TiXmlNode::DECLARATION )
01403 {
01404         version = _version;
01405         encoding = _encoding;
01406         standalone = _standalone;
01407 }
01408 
01409 
01410 #ifdef TIXML_USE_STL
01411 TiXmlDeclaration::TiXmlDeclaration(     const std::string& _version,
01412                                                                         const std::string& _encoding,
01413                                                                         const std::string& _standalone )
01414         : TiXmlNode( TiXmlNode::DECLARATION )
01415 {
01416         version = _version;
01417         encoding = _encoding;
01418         standalone = _standalone;
01419 }
01420 #endif
01421 
01422 
01423 TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
01424         : TiXmlNode( TiXmlNode::DECLARATION )
01425 {
01426         copy.CopyTo( this );
01427 }
01428 
01429 
01430 TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
01431 {
01432         Clear();
01433         copy.CopyTo( this );
01434         return *this;
01435 }
01436 
01437 
01438 void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
01439 {
01440         if ( cfile ) fprintf( cfile, "<?xml " );
01441         if ( str )       (*str) += "<?xml ";
01442 
01443         if ( !version.empty() ) {
01444                 if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
01445                 if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
01446         }
01447         if ( !encoding.empty() ) {
01448                 if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
01449                 if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
01450         }
01451         if ( !standalone.empty() ) {
01452                 if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
01453                 if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
01454         }
01455         if ( cfile ) fprintf( cfile, "?>" );
01456         if ( str )       (*str) += "?>";
01457 }
01458 
01459 
01460 void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
01461 {
01462         TiXmlNode::CopyTo( target );
01463 
01464         target->version = version;
01465         target->encoding = encoding;
01466         target->standalone = standalone;
01467 }
01468 
01469 
01470 bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
01471 {
01472         return visitor->Visit( *this );
01473 }
01474 
01475 
01476 TiXmlNode* TiXmlDeclaration::Clone() const
01477 {
01478         TiXmlDeclaration* clone = new TiXmlDeclaration();
01479 
01480         if ( !clone )
01481                 return 0;
01482 
01483         CopyTo( clone );
01484         return clone;
01485 }
01486 
01487 
01488 void TiXmlUnknown::Print( FILE* cfile, int depth ) const
01489 {
01490         for ( int i=0; i<depth; i++ )
01491                 fprintf( cfile, "    " );
01492         fprintf( cfile, "<%s>", value.c_str() );
01493 }
01494 
01495 
01496 void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
01497 {
01498         TiXmlNode::CopyTo( target );
01499 }
01500 
01501 
01502 bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
01503 {
01504         return visitor->Visit( *this );
01505 }
01506 
01507 
01508 TiXmlNode* TiXmlUnknown::Clone() const
01509 {
01510         TiXmlUnknown* clone = new TiXmlUnknown();
01511 
01512         if ( !clone )
01513                 return 0;
01514 
01515         CopyTo( clone );
01516         return clone;
01517 }
01518 
01519 
01520 TiXmlAttributeSet::TiXmlAttributeSet()
01521 {
01522         sentinel.next = &sentinel;
01523         sentinel.prev = &sentinel;
01524 }
01525 
01526 
01527 TiXmlAttributeSet::~TiXmlAttributeSet()
01528 {
01529         assert( sentinel.next == &sentinel );
01530         assert( sentinel.prev == &sentinel );
01531 }
01532 
01533 
01534 void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
01535 {
01536     #ifdef TIXML_USE_STL
01537         assert( !Find( TIXML_STRING( addMe->Name() ) ) );       // Shouldn't be multiply adding to the set.
01538         #else
01539         assert( !Find( addMe->Name() ) );       // Shouldn't be multiply adding to the set.
01540         #endif
01541 
01542         addMe->next = &sentinel;
01543         addMe->prev = sentinel.prev;
01544 
01545         sentinel.prev->next = addMe;
01546         sentinel.prev      = addMe;
01547 }
01548 
01549 void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
01550 {
01551         TiXmlAttribute* node;
01552 
01553         for( node = sentinel.next; node != &sentinel; node = node->next )
01554         {
01555                 if ( node == removeMe )
01556                 {
01557                         node->prev->next = node->next;
01558                         node->next->prev = node->prev;
01559                         node->next = 0;
01560                         node->prev = 0;
01561                         return;
01562                 }
01563         }
01564         assert( 0 );            // we tried to remove a non-linked attribute.
01565 }
01566 
01567 
01568 #ifdef TIXML_USE_STL
01569 const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
01570 {
01571         for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
01572         {
01573                 if ( node->name == name )
01574                         return node;
01575         }
01576         return 0;
01577 }
01578 
01579 /*
01580 TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name )
01581 {
01582         for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
01583         {
01584                 if ( node->name == name )
01585                         return node;
01586         }
01587         return 0;
01588 }
01589 */
01590 #endif
01591 
01592 
01593 const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
01594 {
01595         for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
01596         {
01597                 if ( strcmp( node->name.c_str(), name ) == 0 )
01598                         return node;
01599         }
01600         return 0;
01601 }
01602 
01603 /*
01604 TiXmlAttribute* TiXmlAttributeSet::Find( const char* name )
01605 {
01606         for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
01607         {
01608                 if ( strcmp( node->name.c_str(), name ) == 0 )
01609                         return node;
01610         }
01611         return 0;
01612 }
01613 */
01614 
01615 #ifdef TIXML_USE_STL
01616 std::istream& operator>> (std::istream & in, TiXmlNode & base)
01617 {
01618         TIXML_STRING tag;
01619         tag.reserve( 8 * 1000 );
01620         base.StreamIn( &in, &tag );
01621 
01622         base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
01623         return in;
01624 }
01625 #endif
01626 
01627 
01628 #ifdef TIXML_USE_STL
01629 std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
01630 {
01631         TiXmlPrinter printer;
01632         printer.SetStreamPrinting();
01633         base.Accept( &printer );
01634         out << printer.Str();
01635 
01636         return out;
01637 }
01638 
01639 
01640 std::string& operator<< (std::string& out, const TiXmlNode& base )
01641 {
01642         TiXmlPrinter printer;
01643         printer.SetStreamPrinting();
01644         base.Accept( &printer );
01645         out.append( printer.Str() );
01646 
01647         return out;
01648 }
01649 #endif
01650 
01651 
01652 TiXmlHandle TiXmlHandle::FirstChild() const
01653 {
01654         if ( node )
01655         {
01656                 TiXmlNode* child = node->FirstChild();
01657                 if ( child )
01658                         return TiXmlHandle( child );
01659         }
01660         return TiXmlHandle( 0 );
01661 }
01662 
01663 
01664 TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
01665 {
01666         if ( node )
01667         {
01668                 TiXmlNode* child = node->FirstChild( value );
01669                 if ( child )
01670                         return TiXmlHandle( child );
01671         }
01672         return TiXmlHandle( 0 );
01673 }
01674 
01675 
01676 TiXmlHandle TiXmlHandle::FirstChildElement() const
01677 {
01678         if ( node )
01679         {
01680                 TiXmlElement* child = node->FirstChildElement();
01681                 if ( child )
01682                         return TiXmlHandle( child );
01683         }
01684         return TiXmlHandle( 0 );
01685 }
01686 
01687 
01688 TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
01689 {
01690         if ( node )
01691         {
01692                 TiXmlElement* child = node->FirstChildElement( value );
01693                 if ( child )
01694                         return TiXmlHandle( child );
01695         }
01696         return TiXmlHandle( 0 );
01697 }
01698 
01699 
01700 TiXmlHandle TiXmlHandle::Child( int count ) const
01701 {
01702         if ( node )
01703         {
01704                 int i;
01705                 TiXmlNode* child = node->FirstChild();
01706                 for (   i=0;
01707                                 child && i<count;
01708                                 child = child->NextSibling(), ++i )
01709                 {
01710                         // nothing
01711                 }
01712                 if ( child )
01713                         return TiXmlHandle( child );
01714         }
01715         return TiXmlHandle( 0 );
01716 }
01717 
01718 
01719 TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
01720 {
01721         if ( node )
01722         {
01723                 int i;
01724                 TiXmlNode* child = node->FirstChild( value );
01725                 for (   i=0;
01726                                 child && i<count;
01727                                 child = child->NextSibling( value ), ++i )
01728                 {
01729                         // nothing
01730                 }
01731                 if ( child )
01732                         return TiXmlHandle( child );
01733         }
01734         return TiXmlHandle( 0 );
01735 }
01736 
01737 
01738 TiXmlHandle TiXmlHandle::ChildElement( int count ) const
01739 {
01740         if ( node )
01741         {
01742                 int i;
01743                 TiXmlElement* child = node->FirstChildElement();
01744                 for (   i=0;
01745                                 child && i<count;
01746                                 child = child->NextSiblingElement(), ++i )
01747                 {
01748                         // nothing
01749                 }
01750                 if ( child )
01751                         return TiXmlHandle( child );
01752         }
01753         return TiXmlHandle( 0 );
01754 }
01755 
01756 
01757 TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
01758 {
01759         if ( node )
01760         {
01761                 int i;
01762                 TiXmlElement* child = node->FirstChildElement( value );
01763                 for (   i=0;
01764                                 child && i<count;
01765                                 child = child->NextSiblingElement( value ), ++i )
01766                 {
01767                         // nothing
01768                 }
01769                 if ( child )
01770                         return TiXmlHandle( child );
01771         }
01772         return TiXmlHandle( 0 );
01773 }
01774 
01775 
01776 bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
01777 {
01778         return true;
01779 }
01780 
01781 bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
01782 {
01783         return true;
01784 }
01785 
01786 bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
01787 {
01788         DoIndent();
01789         buffer += "<";
01790         buffer += element.Value();
01791 
01792         for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
01793         {
01794                 buffer += " ";
01795                 attrib->Print( 0, 0, &buffer );
01796         }
01797 
01798         if ( !element.FirstChild() )
01799         {
01800                 buffer += " />";
01801                 DoLineBreak();
01802         }
01803         else
01804         {
01805                 buffer += ">";
01806                 if (    element.FirstChild()->ToText()
01807                           && element.LastChild() == element.FirstChild()
01808                           && element.FirstChild()->ToText()->CDATA() == false )
01809                 {
01810                         simpleTextPrint = true;
01811                         // no DoLineBreak()!
01812                 }
01813                 else
01814                 {
01815                         DoLineBreak();
01816                 }
01817         }
01818         ++depth;
01819         return true;
01820 }
01821 
01822 
01823 bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
01824 {
01825         --depth;
01826         if ( !element.FirstChild() )
01827         {
01828                 // nothing.
01829         }
01830         else
01831         {
01832                 if ( simpleTextPrint )
01833                 {
01834                         simpleTextPrint = false;
01835                 }
01836                 else
01837                 {
01838                         DoIndent();
01839                 }
01840                 buffer += "</";
01841                 buffer += element.Value();
01842                 buffer += ">";
01843                 DoLineBreak();
01844         }
01845         return true;
01846 }
01847 
01848 
01849 bool TiXmlPrinter::Visit( const TiXmlText& text )
01850 {
01851         if ( text.CDATA() )
01852         {
01853                 DoIndent();
01854                 buffer += "<![CDATA[";
01855                 buffer += text.Value();
01856                 buffer += "]]>";
01857                 DoLineBreak();
01858         }
01859         else if ( simpleTextPrint )
01860         {
01861                 TIXML_STRING str;
01862                 TiXmlBase::EncodeString( text.ValueTStr(), &str );
01863                 buffer += str;
01864         }
01865         else
01866         {
01867                 DoIndent();
01868                 TIXML_STRING str;
01869                 TiXmlBase::EncodeString( text.ValueTStr(), &str );
01870                 buffer += str;
01871                 DoLineBreak();
01872         }
01873         return true;
01874 }
01875 
01876 
01877 bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
01878 {
01879         DoIndent();
01880         declaration.Print( 0, 0, &buffer );
01881         DoLineBreak();
01882         return true;
01883 }
01884 
01885 
01886 bool TiXmlPrinter::Visit( const TiXmlComment& comment )
01887 {
01888         DoIndent();
01889         buffer += "<!--";
01890         buffer += comment.Value();
01891         buffer += "-->";
01892         DoLineBreak();
01893         return true;
01894 }
01895 
01896 
01897 bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
01898 {
01899         DoIndent();
01900         buffer += "<";
01901         buffer += unknown.Value();
01902         buffer += ">";
01903         DoLineBreak();
01904         return true;
01905 }
01906