00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <ctype.h>
00026
00027 #ifdef TIXML_USE_STL
00028 #include <sstream>
00029 #include <iostream>
00030 #endif
00031
00032 #include "tinyxml.h"
00033
00034 bool TiXmlBase::condenseWhiteSpace = true;
00035
00036
00037 FILE* TiXmlFOpen(const char* filename, const char* mode) {
00038 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
00039 FILE* fp = 0;
00040 errno_t err = fopen_s( &fp, filename, mode );
00041 if ( !err && fp )
00042 return fp;
00043 return 0;
00044 #else
00045 return fopen(filename, mode);
00046 #endif
00047 }
00048
00049 void TiXmlBase::EncodeString(const TIXML_STRING& str, TIXML_STRING* outString) {
00050 int i = 0;
00051
00052 while (i < (int) str.length()) {
00053 unsigned char c = (unsigned char) str[i];
00054
00055 if (c == '&' && i < ((int) str.length() - 2) && str[i + 1] == '#'
00056 && str[i + 2] == 'x') {
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 while (i < (int) str.length() - 1) {
00068 outString->append(str.c_str() + i, 1);
00069 ++i;
00070 if (str[i] == ';')
00071 break;
00072 }
00073 } else if (c == '&') {
00074 outString->append(entity[0].str, entity[0].strLength);
00075 ++i;
00076 } else if (c == '<') {
00077 outString->append(entity[1].str, entity[1].strLength);
00078 ++i;
00079 } else if (c == '>') {
00080 outString->append(entity[2].str, entity[2].strLength);
00081 ++i;
00082 } else if (c == '\"') {
00083 outString->append(entity[3].str, entity[3].strLength);
00084 ++i;
00085 } else if (c == '\'') {
00086 outString->append(entity[4].str, entity[4].strLength);
00087 ++i;
00088 } else if (c < 32) {
00089
00090
00091 char buf[32];
00092
00093 #if defined(TIXML_SNPRINTF)
00094 TIXML_SNPRINTF(buf, sizeof(buf), "&#x%02X;", (unsigned) (c & 0xff));
00095 #else
00096 sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
00097 #endif
00098
00099
00100
00101 outString->append(buf, (int) strlen(buf));
00102 ++i;
00103 } else {
00104
00105
00106 *outString += (char) c;
00107 ++i;
00108 }
00109 }
00110 }
00111
00112 TiXmlNode::TiXmlNode(NodeType _type) :
00113 TiXmlBase() {
00114 parent = 0;
00115 type = _type;
00116 firstChild = 0;
00117 lastChild = 0;
00118 prev = 0;
00119 next = 0;
00120 }
00121
00122 TiXmlNode::~TiXmlNode() {
00123 TiXmlNode* node = firstChild;
00124 TiXmlNode* temp = 0;
00125
00126 while (node) {
00127 temp = node;
00128 node = node->next;
00129 delete temp;
00130 }
00131 }
00132
00133 void TiXmlNode::CopyTo(TiXmlNode* target) const {
00134 target->SetValue(value.c_str());
00135 target->userData = userData;
00136 }
00137
00138 void TiXmlNode::Clear() {
00139 TiXmlNode* node = firstChild;
00140 TiXmlNode* temp = 0;
00141
00142 while (node) {
00143 temp = node;
00144 node = node->next;
00145 delete temp;
00146 }
00147
00148 firstChild = 0;
00149 lastChild = 0;
00150 }
00151
00152 TiXmlNode* TiXmlNode::LinkEndChild(TiXmlNode* node) {
00153 assert( node->parent == 0 || node->parent == this );
00154 assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
00155
00156 if (node->Type() == TiXmlNode::DOCUMENT) {
00157 delete node;
00158 if (GetDocument())
00159 GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0,
00160 TIXML_ENCODING_UNKNOWN);
00161 return 0;
00162 }
00163
00164 node->parent = this;
00165
00166 node->prev = lastChild;
00167 node->next = 0;
00168
00169 if (lastChild)
00170 lastChild->next = node;
00171 else
00172 firstChild = node;
00173
00174 lastChild = node;
00175 return node;
00176 }
00177
00178 TiXmlNode* TiXmlNode::InsertEndChild(const TiXmlNode& addThis) {
00179 if (addThis.Type() == TiXmlNode::DOCUMENT) {
00180 if (GetDocument())
00181 GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0,
00182 TIXML_ENCODING_UNKNOWN);
00183 return 0;
00184 }
00185 TiXmlNode* node = addThis.Clone();
00186 if (!node)
00187 return 0;
00188
00189 return LinkEndChild(node);
00190 }
00191
00192 TiXmlNode* TiXmlNode::InsertBeforeChild(TiXmlNode* beforeThis,
00193 const TiXmlNode& addThis) {
00194 if (!beforeThis || beforeThis->parent != this) {
00195 return 0;
00196 }
00197 if (addThis.Type() == TiXmlNode::DOCUMENT) {
00198 if (GetDocument())
00199 GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0,
00200 TIXML_ENCODING_UNKNOWN);
00201 return 0;
00202 }
00203
00204 TiXmlNode* node = addThis.Clone();
00205 if (!node)
00206 return 0;
00207 node->parent = this;
00208
00209 node->next = beforeThis;
00210 node->prev = beforeThis->prev;
00211 if (beforeThis->prev) {
00212 beforeThis->prev->next = node;
00213 } else {
00214 assert( firstChild == beforeThis );
00215 firstChild = node;
00216 }
00217 beforeThis->prev = node;
00218 return node;
00219 }
00220
00221 TiXmlNode* TiXmlNode::InsertAfterChild(TiXmlNode* afterThis,
00222 const TiXmlNode& addThis) {
00223 if (!afterThis || afterThis->parent != this) {
00224 return 0;
00225 }
00226 if (addThis.Type() == TiXmlNode::DOCUMENT) {
00227 if (GetDocument())
00228 GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0,
00229 TIXML_ENCODING_UNKNOWN);
00230 return 0;
00231 }
00232
00233 TiXmlNode* node = addThis.Clone();
00234 if (!node)
00235 return 0;
00236 node->parent = this;
00237
00238 node->prev = afterThis;
00239 node->next = afterThis->next;
00240 if (afterThis->next) {
00241 afterThis->next->prev = node;
00242 } else {
00243 assert( lastChild == afterThis );
00244 lastChild = node;
00245 }
00246 afterThis->next = node;
00247 return node;
00248 }
00249
00250 TiXmlNode* TiXmlNode::ReplaceChild(TiXmlNode* replaceThis,
00251 const TiXmlNode& withThis) {
00252 if (replaceThis->parent != this)
00253 return 0;
00254
00255 TiXmlNode* node = withThis.Clone();
00256 if (!node)
00257 return 0;
00258
00259 node->next = replaceThis->next;
00260 node->prev = replaceThis->prev;
00261
00262 if (replaceThis->next)
00263 replaceThis->next->prev = node;
00264 else
00265 lastChild = node;
00266
00267 if (replaceThis->prev)
00268 replaceThis->prev->next = node;
00269 else
00270 firstChild = node;
00271
00272 delete replaceThis;
00273 node->parent = this;
00274 return node;
00275 }
00276
00277 bool TiXmlNode::RemoveChild(TiXmlNode* removeThis) {
00278 if (removeThis->parent != this) {
00279 assert( 0 );
00280 return false;
00281 }
00282
00283 if (removeThis->next)
00284 removeThis->next->prev = removeThis->prev;
00285 else
00286 lastChild = removeThis->prev;
00287
00288 if (removeThis->prev)
00289 removeThis->prev->next = removeThis->next;
00290 else
00291 firstChild = removeThis->next;
00292
00293 delete removeThis;
00294 return true;
00295 }
00296
00297 const TiXmlNode* TiXmlNode::FirstChild(const char * _value) const {
00298 const TiXmlNode* node;
00299 for (node = firstChild; node; node = node->next) {
00300 if (strcmp(node->Value(), _value) == 0)
00301 return node;
00302 }
00303 return 0;
00304 }
00305
00306 const TiXmlNode* TiXmlNode::LastChild(const char * _value) const {
00307 const TiXmlNode* node;
00308 for (node = lastChild; node; node = node->prev) {
00309 if (strcmp(node->Value(), _value) == 0)
00310 return node;
00311 }
00312 return 0;
00313 }
00314
00315 const TiXmlNode* TiXmlNode::IterateChildren(const TiXmlNode* previous) const {
00316 if (!previous) {
00317 return FirstChild();
00318 } else {
00319 assert( previous->parent == this );
00320 return previous->NextSibling();
00321 }
00322 }
00323
00324 const TiXmlNode* TiXmlNode::IterateChildren(const char * val,
00325 const TiXmlNode* previous) const {
00326 if (!previous) {
00327 return FirstChild(val);
00328 } else {
00329 assert( previous->parent == this );
00330 return previous->NextSibling(val);
00331 }
00332 }
00333
00334 const TiXmlNode* TiXmlNode::NextSibling(const char * _value) const {
00335 const TiXmlNode* node;
00336 for (node = next; node; node = node->next) {
00337 if (strcmp(node->Value(), _value) == 0)
00338 return node;
00339 }
00340 return 0;
00341 }
00342
00343 const TiXmlNode* TiXmlNode::PreviousSibling(const char * _value) const {
00344 const TiXmlNode* node;
00345 for (node = prev; node; node = node->prev) {
00346 if (strcmp(node->Value(), _value) == 0)
00347 return node;
00348 }
00349 return 0;
00350 }
00351
00352 void TiXmlElement::RemoveAttribute(const char * name) {
00353 #ifdef TIXML_USE_STL
00354 TIXML_STRING str( name );
00355 TiXmlAttribute* node = attributeSet.Find( str );
00356 #else
00357 TiXmlAttribute* node = attributeSet.Find(name);
00358 #endif
00359 if (node) {
00360 attributeSet.Remove(node);
00361 delete node;
00362 }
00363 }
00364
00365 const TiXmlElement* TiXmlNode::FirstChildElement() const {
00366 const TiXmlNode* node;
00367
00368 for (node = FirstChild(); node; node = node->NextSibling()) {
00369 if (node->ToElement())
00370 return node->ToElement();
00371 }
00372 return 0;
00373 }
00374
00375 const TiXmlElement* TiXmlNode::FirstChildElement(const char * _value) const {
00376 const TiXmlNode* node;
00377
00378 for (node = FirstChild(_value); node; node = node->NextSibling(_value)) {
00379 if (node->ToElement())
00380 return node->ToElement();
00381 }
00382 return 0;
00383 }
00384
00385 const TiXmlElement* TiXmlNode::NextSiblingElement() const {
00386 const TiXmlNode* node;
00387
00388 for (node = NextSibling(); node; node = node->NextSibling()) {
00389 if (node->ToElement())
00390 return node->ToElement();
00391 }
00392 return 0;
00393 }
00394
00395 const TiXmlElement* TiXmlNode::NextSiblingElement(const char * _value) const {
00396 const TiXmlNode* node;
00397
00398 for (node = NextSibling(_value); node; node = node->NextSibling(_value)) {
00399 if (node->ToElement())
00400 return node->ToElement();
00401 }
00402 return 0;
00403 }
00404
00405 const TiXmlDocument* TiXmlNode::GetDocument() const {
00406 const TiXmlNode* node;
00407
00408 for (node = this; node; node = node->parent) {
00409 if (node->ToDocument())
00410 return node->ToDocument();
00411 }
00412 return 0;
00413 }
00414
00415 TiXmlElement::TiXmlElement(const char * _value) :
00416 TiXmlNode(TiXmlNode::ELEMENT) {
00417 firstChild = lastChild = 0;
00418 value = _value;
00419 }
00420
00421 #ifdef TIXML_USE_STL
00422 TiXmlElement::TiXmlElement( const std::string& _value )
00423 : TiXmlNode( TiXmlNode::ELEMENT )
00424 {
00425 firstChild = lastChild = 0;
00426 value = _value;
00427 }
00428 #endif
00429
00430 TiXmlElement::TiXmlElement(const TiXmlElement& copy) :
00431 TiXmlNode(TiXmlNode::ELEMENT) {
00432 firstChild = lastChild = 0;
00433 copy.CopyTo(this);
00434 }
00435
00436 void TiXmlElement::operator=(const TiXmlElement& base) {
00437 ClearThis();
00438 base.CopyTo(this);
00439 }
00440
00441 TiXmlElement::~TiXmlElement() {
00442 ClearThis();
00443 }
00444
00445 void TiXmlElement::ClearThis() {
00446 Clear();
00447 while (attributeSet.First()) {
00448 TiXmlAttribute* node = attributeSet.First();
00449 attributeSet.Remove(node);
00450 delete node;
00451 }
00452 }
00453
00454 const char* TiXmlElement::Attribute(const char* name) const {
00455 const TiXmlAttribute* node = attributeSet.Find(name);
00456 if (node)
00457 return node->Value();
00458 return 0;
00459 }
00460
00461 #ifdef TIXML_USE_STL
00462 const std::string* TiXmlElement::Attribute( const std::string& name ) const
00463 {
00464 const TiXmlAttribute* node = attributeSet.Find( name );
00465 if ( node )
00466 return &node->ValueStr();
00467 return 0;
00468 }
00469 #endif
00470
00471 const char* TiXmlElement::Attribute(const char* name, int* i) const {
00472 const char* s = Attribute(name);
00473 if (i) {
00474 if (s) {
00475 *i = atoi(s);
00476 } else {
00477 *i = 0;
00478 }
00479 }
00480 return s;
00481 }
00482
00483 #ifdef TIXML_USE_STL
00484 const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
00485 {
00486 const std::string* s = Attribute( name );
00487 if ( i )
00488 {
00489 if ( s ) {
00490 *i = atoi( s->c_str() );
00491 }
00492 else {
00493 *i = 0;
00494 }
00495 }
00496 return s;
00497 }
00498 #endif
00499
00500 const char* TiXmlElement::Attribute(const char* name, double* d) const {
00501 const char* s = Attribute(name);
00502 if (d) {
00503 if (s) {
00504 *d = atof(s);
00505 } else {
00506 *d = 0;
00507 }
00508 }
00509 return s;
00510 }
00511
00512 #ifdef TIXML_USE_STL
00513 const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
00514 {
00515 const std::string* s = Attribute( name );
00516 if ( d )
00517 {
00518 if ( s ) {
00519 *d = atof( s->c_str() );
00520 }
00521 else {
00522 *d = 0;
00523 }
00524 }
00525 return s;
00526 }
00527 #endif
00528
00529 int TiXmlElement::QueryIntAttribute(const char* name, int* ival) const {
00530 const TiXmlAttribute* node = attributeSet.Find(name);
00531 if (!node)
00532 return TIXML_NO_ATTRIBUTE;
00533 return node->QueryIntValue(ival);
00534 }
00535
00536 #ifdef TIXML_USE_STL
00537 int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
00538 {
00539 const TiXmlAttribute* node = attributeSet.Find( name );
00540 if ( !node )
00541 return TIXML_NO_ATTRIBUTE;
00542 return node->QueryIntValue( ival );
00543 }
00544 #endif
00545
00546 int TiXmlElement::QueryDoubleAttribute(const char* name, double* dval) const {
00547 const TiXmlAttribute* node = attributeSet.Find(name);
00548 if (!node)
00549 return TIXML_NO_ATTRIBUTE;
00550 return node->QueryDoubleValue(dval);
00551 }
00552
00553 #ifdef TIXML_USE_STL
00554 int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
00555 {
00556 const TiXmlAttribute* node = attributeSet.Find( name );
00557 if ( !node )
00558 return TIXML_NO_ATTRIBUTE;
00559 return node->QueryDoubleValue( dval );
00560 }
00561 #endif
00562
00563 void TiXmlElement::SetAttribute(const char * name, int val) {
00564 char buf[64];
00565 #if defined(TIXML_SNPRINTF)
00566 TIXML_SNPRINTF(buf, sizeof(buf), "%d", val);
00567 #else
00568 sprintf( buf, "%d", val );
00569 #endif
00570 SetAttribute(name, buf);
00571 }
00572
00573 #ifdef TIXML_USE_STL
00574 void TiXmlElement::SetAttribute( const std::string& name, int val )
00575 {
00576 std::ostringstream oss;
00577 oss << val;
00578 SetAttribute( name, oss.str() );
00579 }
00580 #endif
00581
00582 void TiXmlElement::SetDoubleAttribute(const char * name, double val) {
00583 char buf[256];
00584 #if defined(TIXML_SNPRINTF)
00585 TIXML_SNPRINTF(buf, sizeof(buf), "%f", val);
00586 #else
00587 sprintf( buf, "%f", val );
00588 #endif
00589 SetAttribute(name, buf);
00590 }
00591
00592 void TiXmlElement::SetAttribute(const char * cname, const char * cvalue) {
00593 #ifdef TIXML_USE_STL
00594 TIXML_STRING _name( cname );
00595 TIXML_STRING _value( cvalue );
00596 #else
00597 const char* _name = cname;
00598 const char* _value = cvalue;
00599 #endif
00600
00601 TiXmlAttribute* node = attributeSet.Find(_name);
00602 if (node) {
00603 node->SetValue(_value);
00604 return;
00605 }
00606
00607 TiXmlAttribute* attrib = new TiXmlAttribute(cname, cvalue);
00608 if (attrib) {
00609 attributeSet.Add(attrib);
00610 } else {
00611 TiXmlDocument* document = GetDocument();
00612 if (document)
00613 document->SetError(TIXML_ERROR_OUT_OF_MEMORY, 0, 0,
00614 TIXML_ENCODING_UNKNOWN);
00615 }
00616 }
00617
00618 #ifdef TIXML_USE_STL
00619 void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
00620 {
00621 TiXmlAttribute* node = attributeSet.Find( name );
00622 if ( node )
00623 {
00624 node->SetValue( _value );
00625 return;
00626 }
00627
00628 TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
00629 if ( attrib )
00630 {
00631 attributeSet.Add( attrib );
00632 }
00633 else
00634 {
00635 TiXmlDocument* document = GetDocument();
00636 if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
00637 }
00638 }
00639 #endif
00640
00641 void TiXmlElement::Print(FILE* cfile, int depth) const {
00642 int i;
00643 assert( cfile );
00644 for (i = 0; i < depth; i++) {
00645 fprintf(cfile, " ");
00646 }
00647
00648 fprintf(cfile, "<%s", value.c_str());
00649
00650 const TiXmlAttribute* attrib;
00651 for (attrib = attributeSet.First(); attrib; attrib = attrib->Next()) {
00652 fprintf(cfile, " ");
00653 attrib->Print(cfile, depth);
00654 }
00655
00656
00657
00658
00659
00660 TiXmlNode* node;
00661 if (!firstChild) {
00662 fprintf(cfile, " />");
00663 } else if (firstChild == lastChild && firstChild->ToText()) {
00664 fprintf(cfile, ">");
00665 firstChild->Print(cfile, depth + 1);
00666 fprintf(cfile, "</%s>", value.c_str());
00667 } else {
00668 fprintf(cfile, ">");
00669
00670 for (node = firstChild; node; node = node->NextSibling()) {
00671 if (!node->ToText()) {
00672 fprintf(cfile, "\n");
00673 }
00674 node->Print(cfile, depth + 1);
00675 }
00676 fprintf(cfile, "\n");
00677 for (i = 0; i < depth; ++i) {
00678 fprintf(cfile, " ");
00679 }
00680 fprintf(cfile, "</%s>", value.c_str());
00681 }
00682 }
00683
00684 void TiXmlElement::CopyTo(TiXmlElement* target) const {
00685
00686 TiXmlNode::CopyTo(target);
00687
00688
00689
00690 const TiXmlAttribute* attribute = 0;
00691 for (attribute = attributeSet.First(); attribute; attribute
00692 = attribute->Next()) {
00693 target->SetAttribute(attribute->Name(), attribute->Value());
00694 }
00695
00696 TiXmlNode* node = 0;
00697 for (node = firstChild; node; node = node->NextSibling()) {
00698 target->LinkEndChild(node->Clone());
00699 }
00700 }
00701
00702 bool TiXmlElement::Accept(TiXmlVisitor* visitor) const {
00703 if (visitor->VisitEnter(*this, attributeSet.First())) {
00704 for (const TiXmlNode* node = FirstChild(); node; node
00705 = node->NextSibling()) {
00706 if (!node->Accept(visitor))
00707 break;
00708 }
00709 }
00710 return visitor->VisitExit(*this);
00711 }
00712
00713 TiXmlNode* TiXmlElement::Clone() const {
00714 TiXmlElement* clone = new TiXmlElement(Value());
00715 if (!clone)
00716 return 0;
00717
00718 CopyTo(clone);
00719 return clone;
00720 }
00721
00722 const char* TiXmlElement::GetText() const {
00723 const TiXmlNode* child = this->FirstChild();
00724 if (child) {
00725 const TiXmlText* childText = child->ToText();
00726 if (childText) {
00727 return childText->Value();
00728 }
00729 }
00730 return 0;
00731 }
00732
00733 TiXmlDocument::TiXmlDocument() :
00734 TiXmlNode(TiXmlNode::DOCUMENT) {
00735 tabsize = 4;
00736 useMicrosoftBOM = false;
00737 ClearError();
00738 }
00739
00740 TiXmlDocument::TiXmlDocument(const char * documentName) :
00741 TiXmlNode(TiXmlNode::DOCUMENT) {
00742 tabsize = 4;
00743 useMicrosoftBOM = false;
00744 value = documentName;
00745 ClearError();
00746 }
00747
00748 #ifdef TIXML_USE_STL
00749 TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
00750 {
00751 tabsize = 4;
00752 useMicrosoftBOM = false;
00753 value = documentName;
00754 ClearError();
00755 }
00756 #endif
00757
00758 TiXmlDocument::TiXmlDocument(const TiXmlDocument& copy) :
00759 TiXmlNode(TiXmlNode::DOCUMENT) {
00760 copy.CopyTo(this);
00761 }
00762
00763 void TiXmlDocument::operator=(const TiXmlDocument& copy) {
00764 Clear();
00765 copy.CopyTo(this);
00766 }
00767
00768 bool TiXmlDocument::LoadFile(TiXmlEncoding encoding) {
00769
00770
00771
00772 return LoadFile(Value(), encoding);
00773 }
00774
00775 bool TiXmlDocument::SaveFile() const {
00776
00777
00778
00779
00780
00781
00782
00783 return SaveFile(Value());
00784 }
00785
00786 bool TiXmlDocument::LoadFile(const char* _filename, TiXmlEncoding encoding) {
00787
00788
00789
00790
00791
00792
00793
00794 TIXML_STRING filename(_filename);
00795 value = filename;
00796
00797
00798 FILE* file = TiXmlFOpen(value.c_str(), "rb");
00799
00800 if (file) {
00801 bool result = LoadFile(file, encoding);
00802 fclose(file);
00803 return result;
00804 } else {
00805 SetError(TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN);
00806 return false;
00807 }
00808 }
00809
00810 bool TiXmlDocument::LoadFile(FILE* file, TiXmlEncoding encoding) {
00811 if (!file) {
00812 SetError(TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN);
00813 return false;
00814 }
00815
00816
00817 Clear();
00818 location.Clear();
00819
00820
00821 long length = 0;
00822 fseek(file, 0, SEEK_END );
00823 length = ftell(file);
00824 fseek(file, 0, SEEK_SET );
00825
00826
00827 if (length <= 0) {
00828 SetError(TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN);
00829 return false;
00830 }
00831
00832
00833 TIXML_STRING data;
00834 data.reserve(length);
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857 char* buf = new char[length + 1];
00858 buf[0] = 0;
00859
00860 if (fread(buf, length, 1, file) != 1) {
00861 delete[] buf;
00862 SetError(TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN);
00863 return false;
00864 }
00865
00866 const char* lastPos = buf;
00867 const char* p = buf;
00868
00869 buf[length] = 0;
00870 while (*p) {
00871 assert( p < (buf+length) );
00872 if (*p == 0xa) {
00873
00874
00875 data.append(lastPos, (p - lastPos + 1));
00876 ++p;
00877 lastPos = p;
00878 assert( p <= (buf+length) );
00879 } else if (*p == 0xd) {
00880
00881
00882 if ((p - lastPos) > 0) {
00883 data.append(lastPos, p - lastPos);
00884 }
00885 data += (char) 0xa;
00886
00887 if (*(p + 1) == 0xa) {
00888
00889 p += 2;
00890 lastPos = p;
00891 assert( p <= (buf+length) );
00892 } else {
00893
00894 ++p;
00895 lastPos = p;
00896 assert( p <= (buf+length) );
00897 }
00898 } else {
00899 ++p;
00900 }
00901 }
00902
00903 if (p - lastPos) {
00904 data.append(lastPos, p - lastPos);
00905 }
00906 delete[] buf;
00907 buf = 0;
00908
00909 Parse(data.c_str(), 0, encoding);
00910
00911 if (Error())
00912 return false;
00913 else
00914 return true;
00915 }
00916
00917 bool TiXmlDocument::SaveFile(const char * filename) const {
00918
00919 FILE* fp = TiXmlFOpen(filename, "w");
00920 if (fp) {
00921 bool result = SaveFile(fp);
00922 fclose(fp);
00923 return result;
00924 }
00925 return false;
00926 }
00927
00928 bool TiXmlDocument::SaveFile(FILE* fp) const {
00929 if (useMicrosoftBOM) {
00930 const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
00931 const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
00932 const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
00933
00934 fputc(TIXML_UTF_LEAD_0, fp);
00935 fputc(TIXML_UTF_LEAD_1, fp);
00936 fputc(TIXML_UTF_LEAD_2, fp);
00937 }
00938 Print(fp, 0);
00939 return (ferror(fp) == 0);
00940 }
00941
00942 void TiXmlDocument::CopyTo(TiXmlDocument* target) const {
00943 TiXmlNode::CopyTo(target);
00944
00945 target->error = error;
00946 target->errorId = errorId;
00947 target->errorDesc = errorDesc;
00948 target->tabsize = tabsize;
00949 target->errorLocation = errorLocation;
00950 target->useMicrosoftBOM = useMicrosoftBOM;
00951
00952 TiXmlNode* node = 0;
00953 for (node = firstChild; node; node = node->NextSibling()) {
00954 target->LinkEndChild(node->Clone());
00955 }
00956 }
00957
00958 TiXmlNode* TiXmlDocument::Clone() const {
00959 TiXmlDocument* clone = new TiXmlDocument();
00960 if (!clone)
00961 return 0;
00962
00963 CopyTo(clone);
00964 return clone;
00965 }
00966
00967 void TiXmlDocument::Print(FILE* cfile, int depth) const {
00968 assert( cfile );
00969 for (const TiXmlNode* node = FirstChild(); node; node = node->NextSibling()) {
00970 node->Print(cfile, depth);
00971 fprintf(cfile, "\n");
00972 }
00973 }
00974
00975 bool TiXmlDocument::Accept(TiXmlVisitor* visitor) const {
00976 if (visitor->VisitEnter(*this)) {
00977 for (const TiXmlNode* node = FirstChild(); node; node
00978 = node->NextSibling()) {
00979 if (!node->Accept(visitor))
00980 break;
00981 }
00982 }
00983 return visitor->VisitExit(*this);
00984 }
00985
00986 const TiXmlAttribute* TiXmlAttribute::Next() const {
00987
00988
00989 if (next->value.empty() && next->name.empty())
00990 return 0;
00991 return next;
00992 }
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005 const TiXmlAttribute* TiXmlAttribute::Previous() const {
01006
01007
01008 if (prev->value.empty() && prev->name.empty())
01009 return 0;
01010 return prev;
01011 }
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024 void TiXmlAttribute::Print(FILE* cfile, int , TIXML_STRING* str) const {
01025 TIXML_STRING n, v;
01026
01027 EncodeString(name, &n);
01028 EncodeString(value, &v);
01029
01030 if (value.find('\"') == TIXML_STRING::npos) {
01031 if (cfile) {
01032 fprintf(cfile, "%s=\"%s\"", n.c_str(), v.c_str());
01033 }
01034 if (str) {
01035 (*str) += n;
01036 (*str) += "=\"";
01037 (*str) += v;
01038 (*str) += "\"";
01039 }
01040 } else {
01041 if (cfile) {
01042 fprintf(cfile, "%s='%s'", n.c_str(), v.c_str());
01043 }
01044 if (str) {
01045 (*str) += n;
01046 (*str) += "='";
01047 (*str) += v;
01048 (*str) += "'";
01049 }
01050 }
01051 }
01052
01053 int TiXmlAttribute::QueryIntValue(int* ival) const {
01054 if (TIXML_SSCANF(value.c_str(), "%d", ival) == 1)
01055 return TIXML_SUCCESS;
01056 return TIXML_WRONG_TYPE;
01057 }
01058
01059 int TiXmlAttribute::QueryDoubleValue(double* dval) const {
01060 if (TIXML_SSCANF(value.c_str(), "%lf", dval) == 1)
01061 return TIXML_SUCCESS;
01062 return TIXML_WRONG_TYPE;
01063 }
01064
01065 void TiXmlAttribute::SetIntValue(int _value) {
01066 char buf[64];
01067 #if defined(TIXML_SNPRINTF)
01068 TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
01069 #else
01070 sprintf (buf, "%d", _value);
01071 #endif
01072 SetValue(buf);
01073 }
01074
01075 void TiXmlAttribute::SetDoubleValue(double _value) {
01076 char buf[256];
01077 #if defined(TIXML_SNPRINTF)
01078 TIXML_SNPRINTF(buf, sizeof(buf), "%lf", _value);
01079 #else
01080 sprintf (buf, "%lf", _value);
01081 #endif
01082 SetValue(buf);
01083 }
01084
01085 int TiXmlAttribute::IntValue() const {
01086 return atoi(value.c_str());
01087 }
01088
01089 double TiXmlAttribute::DoubleValue() const {
01090 return atof(value.c_str());
01091 }
01092
01093 TiXmlComment::TiXmlComment(const TiXmlComment& copy) :
01094 TiXmlNode(TiXmlNode::COMMENT) {
01095 copy.CopyTo(this);
01096 }
01097
01098 void TiXmlComment::operator=(const TiXmlComment& base) {
01099 Clear();
01100 base.CopyTo(this);
01101 }
01102
01103 void TiXmlComment::Print(FILE* cfile, int depth) const {
01104 assert( cfile );
01105 for (int i = 0; i < depth; i++) {
01106 fprintf(cfile, " ");
01107 }
01108 fprintf(cfile, "<!--%s-->", value.c_str());
01109 }
01110
01111 void TiXmlComment::CopyTo(TiXmlComment* target) const {
01112 TiXmlNode::CopyTo(target);
01113 }
01114
01115 bool TiXmlComment::Accept(TiXmlVisitor* visitor) const {
01116 return visitor->Visit(*this);
01117 }
01118
01119 TiXmlNode* TiXmlComment::Clone() const {
01120 TiXmlComment* clone = new TiXmlComment();
01121
01122 if (!clone)
01123 return 0;
01124
01125 CopyTo(clone);
01126 return clone;
01127 }
01128
01129 void TiXmlText::Print(FILE* cfile, int depth) const {
01130 assert( cfile );
01131 if (cdata) {
01132 int i;
01133 fprintf(cfile, "\n");
01134 for (i = 0; i < depth; i++) {
01135 fprintf(cfile, " ");
01136 }
01137 fprintf(cfile, "<![CDATA[%s]]>\n", value.c_str());
01138 } else {
01139 TIXML_STRING buffer;
01140 EncodeString(value, &buffer);
01141 fprintf(cfile, "%s", buffer.c_str());
01142 }
01143 }
01144
01145 void TiXmlText::CopyTo(TiXmlText* target) const {
01146 TiXmlNode::CopyTo(target);
01147 target->cdata = cdata;
01148 }
01149
01150 bool TiXmlText::Accept(TiXmlVisitor* visitor) const {
01151 return visitor->Visit(*this);
01152 }
01153
01154 TiXmlNode* TiXmlText::Clone() const {
01155 TiXmlText* clone = 0;
01156 clone = new TiXmlText("");
01157
01158 if (!clone)
01159 return 0;
01160
01161 CopyTo(clone);
01162 return clone;
01163 }
01164
01165 TiXmlDeclaration::TiXmlDeclaration(const char * _version,
01166 const char * _encoding, const char * _standalone) :
01167 TiXmlNode(TiXmlNode::DECLARATION) {
01168 version = _version;
01169 encoding = _encoding;
01170 standalone = _standalone;
01171 }
01172
01173 #ifdef TIXML_USE_STL
01174 TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
01175 const std::string& _encoding,
01176 const std::string& _standalone )
01177 : TiXmlNode( TiXmlNode::DECLARATION )
01178 {
01179 version = _version;
01180 encoding = _encoding;
01181 standalone = _standalone;
01182 }
01183 #endif
01184
01185 TiXmlDeclaration::TiXmlDeclaration(const TiXmlDeclaration& copy) :
01186 TiXmlNode(TiXmlNode::DECLARATION) {
01187 copy.CopyTo(this);
01188 }
01189
01190 void TiXmlDeclaration::operator=(const TiXmlDeclaration& copy) {
01191 Clear();
01192 copy.CopyTo(this);
01193 }
01194
01195 void TiXmlDeclaration::Print(FILE* cfile, int , TIXML_STRING* str) const {
01196 if (cfile)
01197 fprintf(cfile, "<?xml ");
01198 if (str)
01199 (*str) += "<?xml ";
01200
01201 if (!version.empty()) {
01202 if (cfile)
01203 fprintf(cfile, "version=\"%s\" ", version.c_str());
01204 if (str) {
01205 (*str) += "version=\"";
01206 (*str) += version;
01207 (*str) += "\" ";
01208 }
01209 }
01210 if (!encoding.empty()) {
01211 if (cfile)
01212 fprintf(cfile, "encoding=\"%s\" ", encoding.c_str());
01213 if (str) {
01214 (*str) += "encoding=\"";
01215 (*str) += encoding;
01216 (*str) += "\" ";
01217 }
01218 }
01219 if (!standalone.empty()) {
01220 if (cfile)
01221 fprintf(cfile, "standalone=\"%s\" ", standalone.c_str());
01222 if (str) {
01223 (*str) += "standalone=\"";
01224 (*str) += standalone;
01225 (*str) += "\" ";
01226 }
01227 }
01228 if (cfile)
01229 fprintf(cfile, "?>");
01230 if (str)
01231 (*str) += "?>";
01232 }
01233
01234 void TiXmlDeclaration::CopyTo(TiXmlDeclaration* target) const {
01235 TiXmlNode::CopyTo(target);
01236
01237 target->version = version;
01238 target->encoding = encoding;
01239 target->standalone = standalone;
01240 }
01241
01242 bool TiXmlDeclaration::Accept(TiXmlVisitor* visitor) const {
01243 return visitor->Visit(*this);
01244 }
01245
01246 TiXmlNode* TiXmlDeclaration::Clone() const {
01247 TiXmlDeclaration* clone = new TiXmlDeclaration();
01248
01249 if (!clone)
01250 return 0;
01251
01252 CopyTo(clone);
01253 return clone;
01254 }
01255
01256 void TiXmlUnknown::Print(FILE* cfile, int depth) const {
01257 for (int i = 0; i < depth; i++)
01258 fprintf(cfile, " ");
01259 fprintf(cfile, "<%s>", value.c_str());
01260 }
01261
01262 void TiXmlUnknown::CopyTo(TiXmlUnknown* target) const {
01263 TiXmlNode::CopyTo(target);
01264 }
01265
01266 bool TiXmlUnknown::Accept(TiXmlVisitor* visitor) const {
01267 return visitor->Visit(*this);
01268 }
01269
01270 TiXmlNode* TiXmlUnknown::Clone() const {
01271 TiXmlUnknown* clone = new TiXmlUnknown();
01272
01273 if (!clone)
01274 return 0;
01275
01276 CopyTo(clone);
01277 return clone;
01278 }
01279
01280 TiXmlAttributeSet::TiXmlAttributeSet() {
01281 sentinel.next = &sentinel;
01282 sentinel.prev = &sentinel;
01283 }
01284
01285 TiXmlAttributeSet::~TiXmlAttributeSet() {
01286 assert( sentinel.next == &sentinel );
01287 assert( sentinel.prev == &sentinel );
01288 }
01289
01290 void TiXmlAttributeSet::Add(TiXmlAttribute* addMe) {
01291 #ifdef TIXML_USE_STL
01292 assert( !Find( TIXML_STRING( addMe->Name() ) ) );
01293 #else
01294 assert( !Find( addMe->Name() ) );
01295 #endif
01296
01297 addMe->next = &sentinel;
01298 addMe->prev = sentinel.prev;
01299
01300 sentinel.prev->next = addMe;
01301 sentinel.prev = addMe;
01302 }
01303
01304 void TiXmlAttributeSet::Remove(TiXmlAttribute* removeMe) {
01305 TiXmlAttribute* node;
01306
01307 for (node = sentinel.next; node != &sentinel; node = node->next) {
01308 if (node == removeMe) {
01309 node->prev->next = node->next;
01310 node->next->prev = node->prev;
01311 node->next = 0;
01312 node->prev = 0;
01313 return;
01314 }
01315 }
01316 assert( 0 );
01317 }
01318
01319 #ifdef TIXML_USE_STL
01320 const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
01321 {
01322 for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
01323 {
01324 if ( node->name == name )
01325 return node;
01326 }
01327 return 0;
01328 }
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341 #endif
01342
01343 const TiXmlAttribute* TiXmlAttributeSet::Find(const char* name) const {
01344 for (const TiXmlAttribute* node = sentinel.next; node != &sentinel; node
01345 = node->next) {
01346 if (strcmp(node->name.c_str(), name) == 0)
01347 return node;
01348 }
01349 return 0;
01350 }
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364 #ifdef TIXML_USE_STL
01365 std::istream& operator>> (std::istream & in, TiXmlNode & base)
01366 {
01367 TIXML_STRING tag;
01368 tag.reserve( 8 * 1000 );
01369 base.StreamIn( &in, &tag );
01370
01371 base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
01372 return in;
01373 }
01374 #endif
01375
01376 #ifdef TIXML_USE_STL
01377 std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
01378 {
01379 TiXmlPrinter printer;
01380 printer.SetStreamPrinting();
01381 base.Accept( &printer );
01382 out << printer.Str();
01383
01384 return out;
01385 }
01386
01387 std::string& operator<< (std::string& out, const TiXmlNode& base )
01388 {
01389 TiXmlPrinter printer;
01390 printer.SetStreamPrinting();
01391 base.Accept( &printer );
01392 out.append( printer.Str() );
01393
01394 return out;
01395 }
01396 #endif
01397
01398 TiXmlHandle TiXmlHandle::FirstChild() const {
01399 if (node) {
01400 TiXmlNode* child = node->FirstChild();
01401 if (child)
01402 return TiXmlHandle(child);
01403 }
01404 return TiXmlHandle(0);
01405 }
01406
01407 TiXmlHandle TiXmlHandle::FirstChild(const char * value) const {
01408 if (node) {
01409 TiXmlNode* child = node->FirstChild(value);
01410 if (child)
01411 return TiXmlHandle(child);
01412 }
01413 return TiXmlHandle(0);
01414 }
01415
01416 TiXmlHandle TiXmlHandle::FirstChildElement() const {
01417 if (node) {
01418 TiXmlElement* child = node->FirstChildElement();
01419 if (child)
01420 return TiXmlHandle(child);
01421 }
01422 return TiXmlHandle(0);
01423 }
01424
01425 TiXmlHandle TiXmlHandle::FirstChildElement(const char * value) const {
01426 if (node) {
01427 TiXmlElement* child = node->FirstChildElement(value);
01428 if (child)
01429 return TiXmlHandle(child);
01430 }
01431 return TiXmlHandle(0);
01432 }
01433
01434 TiXmlHandle TiXmlHandle::Child(int count) const {
01435 if (node) {
01436 int i;
01437 TiXmlNode* child = node->FirstChild();
01438 for (i = 0; child && i < count; child = child->NextSibling(), ++i) {
01439
01440 }
01441 if (child)
01442 return TiXmlHandle(child);
01443 }
01444 return TiXmlHandle(0);
01445 }
01446
01447 TiXmlHandle TiXmlHandle::Child(const char* value, int count) const {
01448 if (node) {
01449 int i;
01450 TiXmlNode* child = node->FirstChild(value);
01451 for (i = 0; child && i < count; child = child->NextSibling(value), ++i) {
01452
01453 }
01454 if (child)
01455 return TiXmlHandle(child);
01456 }
01457 return TiXmlHandle(0);
01458 }
01459
01460 TiXmlHandle TiXmlHandle::ChildElement(int count) const {
01461 if (node) {
01462 int i;
01463 TiXmlElement* child = node->FirstChildElement();
01464 for (i = 0; child && i < count; child = child->NextSiblingElement(), ++i) {
01465
01466 }
01467 if (child)
01468 return TiXmlHandle(child);
01469 }
01470 return TiXmlHandle(0);
01471 }
01472
01473 TiXmlHandle TiXmlHandle::ChildElement(const char* value, int count) const {
01474 if (node) {
01475 int i;
01476 TiXmlElement* child = node->FirstChildElement(value);
01477 for (i = 0; child && i < count; child
01478 = child->NextSiblingElement(value), ++i) {
01479
01480 }
01481 if (child)
01482 return TiXmlHandle(child);
01483 }
01484 return TiXmlHandle(0);
01485 }
01486
01487 bool TiXmlPrinter::VisitEnter(const TiXmlDocument&) {
01488 return true;
01489 }
01490
01491 bool TiXmlPrinter::VisitExit(const TiXmlDocument&) {
01492 return true;
01493 }
01494
01495 bool TiXmlPrinter::VisitEnter(const TiXmlElement& element,
01496 const TiXmlAttribute* firstAttribute) {
01497 DoIndent();
01498 buffer += "<";
01499 buffer += element.Value();
01500
01501 for (const TiXmlAttribute* attrib = firstAttribute; attrib; attrib
01502 = attrib->Next()) {
01503 buffer += " ";
01504 attrib->Print(0, 0, &buffer);
01505 }
01506
01507 if (!element.FirstChild()) {
01508 buffer += " />";
01509 DoLineBreak();
01510 } else {
01511 buffer += ">";
01512 if (element.FirstChild()->ToText() && element.LastChild()
01513 == element.FirstChild()
01514 && element.FirstChild()->ToText()->CDATA() == false) {
01515 simpleTextPrint = true;
01516
01517 } else {
01518 DoLineBreak();
01519 }
01520 }
01521 ++depth;
01522 return true;
01523 }
01524
01525 bool TiXmlPrinter::VisitExit(const TiXmlElement& element) {
01526 --depth;
01527 if (!element.FirstChild()) {
01528
01529 } else {
01530 if (simpleTextPrint) {
01531 simpleTextPrint = false;
01532 } else {
01533 DoIndent();
01534 }
01535 buffer += "</";
01536 buffer += element.Value();
01537 buffer += ">";
01538 DoLineBreak();
01539 }
01540 return true;
01541 }
01542
01543 bool TiXmlPrinter::Visit(const TiXmlText& text) {
01544 if (text.CDATA()) {
01545 DoIndent();
01546 buffer += "<![CDATA[";
01547 buffer += text.Value();
01548 buffer += "]]>";
01549 DoLineBreak();
01550 } else if (simpleTextPrint) {
01551 TIXML_STRING str;
01552 TiXmlBase::EncodeString(text.ValueTStr(), &str);
01553 buffer += str;
01554 } else {
01555 DoIndent();
01556 TIXML_STRING str;
01557 TiXmlBase::EncodeString(text.ValueTStr(), &str);
01558 buffer += str;
01559 DoLineBreak();
01560 }
01561 return true;
01562 }
01563
01564 bool TiXmlPrinter::Visit(const TiXmlDeclaration& declaration) {
01565 DoIndent();
01566 declaration.Print(0, 0, &buffer);
01567 DoLineBreak();
01568 return true;
01569 }
01570
01571 bool TiXmlPrinter::Visit(const TiXmlComment& comment) {
01572 DoIndent();
01573 buffer += "<!--";
01574 buffer += comment.Value();
01575 buffer += "-->";
01576 DoLineBreak();
01577 return true;
01578 }
01579
01580 bool TiXmlPrinter::Visit(const TiXmlUnknown& unknown) {
01581 DoIndent();
01582 buffer += "<";
01583 buffer += unknown.Value();
01584 buffer += ">";
01585 DoLineBreak();
01586 return true;
01587 }
01588