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