Back to index

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