nux-1.16.0
|
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 // © -- 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 ©) 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 © ) : TiXmlNode ( TiXmlNode::DOCUMENT ) 01025 { 01026 copy.CopyTo ( this ); 01027 } 01028 01029 01030 void TiXmlDocument::operator= ( const TiXmlDocument © ) 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 © ) : 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 © ) 01566 : TiXmlNode ( TiXmlNode::DECLARATION ) 01567 { 01568 copy.CopyTo ( this ); 01569 } 01570 01571 01572 void TiXmlDeclaration::operator= ( const TiXmlDeclaration © ) 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