00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "tinyxml2.h"
00025
00026 #include <new>
00027 # ifdef ANDROID_NDK
00028 # include <stddef.h>
00029 #else
00030 # include <cstddef>
00031 #endif
00032
00033 static const char LINE_FEED = (char)0x0a;
00034 static const char LF = LINE_FEED;
00035 static const char CARRIAGE_RETURN = (char)0x0d;
00036 static const char CR = CARRIAGE_RETURN;
00037 static const char SINGLE_QUOTE = '\'';
00038 static const char DOUBLE_QUOTE = '\"';
00039
00040
00041
00042
00043
00044 static const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
00045 static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
00046 static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
00047
00048
00049 #define DELETE_NODE( node ) { \
00050 if ( node ) { \
00051 MemPool* pool = node->_memPool; \
00052 node->~XMLNode(); \
00053 pool->Free( node ); \
00054 } \
00055 }
00056 #define DELETE_ATTRIBUTE( attrib ) { \
00057 if ( attrib ) { \
00058 MemPool* pool = attrib->_memPool; \
00059 attrib->~XMLAttribute(); \
00060 pool->Free( attrib ); \
00061 } \
00062 }
00063
00064 namespace tinyxml2
00065 {
00066
00067 struct Entity {
00068 const char* pattern;
00069 int length;
00070 char value;
00071 };
00072
00073 static const int NUM_ENTITIES = 5;
00074 static const Entity entities[NUM_ENTITIES] = {
00075 { "quot", 4, DOUBLE_QUOTE },
00076 { "amp", 3, '&' },
00077 { "apos", 4, SINGLE_QUOTE },
00078 { "lt", 2, '<' },
00079 { "gt", 2, '>' }
00080 };
00081
00082
00083 StrPair::~StrPair()
00084 {
00085 Reset();
00086 }
00087
00088
00089 void StrPair::Reset()
00090 {
00091 if ( _flags & NEEDS_DELETE ) {
00092 delete [] _start;
00093 }
00094 _flags = 0;
00095 _start = 0;
00096 _end = 0;
00097 }
00098
00099
00100 void StrPair::SetStr( const char* str, int flags )
00101 {
00102 Reset();
00103 size_t len = strlen( str );
00104 _start = new char[ len+1 ];
00105 memcpy( _start, str, len+1 );
00106 _end = _start + len;
00107 _flags = flags | NEEDS_DELETE;
00108 }
00109
00110
00111 char* StrPair::ParseText( char* p, const char* endTag, int strFlags )
00112 {
00113 TIXMLASSERT( endTag && *endTag );
00114
00115 char* start = p;
00116 char endChar = *endTag;
00117 size_t length = strlen( endTag );
00118
00119
00120 while ( *p ) {
00121 if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
00122 Set( start, p, strFlags );
00123 return p + length;
00124 }
00125 ++p;
00126 }
00127 return 0;
00128 }
00129
00130
00131 char* StrPair::ParseName( char* p )
00132 {
00133 char* start = p;
00134
00135 if ( !start || !(*start) ) {
00136 return 0;
00137 }
00138
00139 while( *p && (
00140 XMLUtil::IsAlphaNum( (unsigned char) *p )
00141 || *p == '_'
00142 || *p == ':'
00143 || (*p == '-' && p>start )
00144 || (*p == '.' && p>start ) )) {
00145 ++p;
00146 }
00147
00148 if ( p > start ) {
00149 Set( start, p, 0 );
00150 return p;
00151 }
00152 return 0;
00153 }
00154
00155
00156 void StrPair::CollapseWhitespace()
00157 {
00158
00159 _start = XMLUtil::SkipWhiteSpace( _start );
00160
00161 if ( _start && *_start ) {
00162 char* p = _start;
00163 char* q = _start;
00164
00165 while( *p ) {
00166 if ( XMLUtil::IsWhiteSpace( *p )) {
00167 p = XMLUtil::SkipWhiteSpace( p );
00168 if ( *p == 0 ) {
00169 break;
00170 }
00171 *q = ' ';
00172 ++q;
00173 }
00174 *q = *p;
00175 ++q;
00176 ++p;
00177 }
00178 *q = 0;
00179 }
00180 }
00181
00182
00183 const char* StrPair::GetStr()
00184 {
00185 if ( _flags & NEEDS_FLUSH ) {
00186 *_end = 0;
00187 _flags ^= NEEDS_FLUSH;
00188
00189 if ( _flags ) {
00190 char* p = _start;
00191 char* q = _start;
00192
00193 while( p < _end ) {
00194 if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) {
00195
00196
00197
00198 if ( *(p+1) == LF ) {
00199 p += 2;
00200 }
00201 else {
00202 ++p;
00203 }
00204 *q++ = LF;
00205 }
00206 else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {
00207 if ( *(p+1) == CR ) {
00208 p += 2;
00209 }
00210 else {
00211 ++p;
00212 }
00213 *q++ = LF;
00214 }
00215 else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {
00216
00217
00218
00219
00220
00221 if ( *(p+1) == '#' ) {
00222 char buf[10] = { 0 };
00223 int len;
00224 p = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );
00225 for( int i=0; i<len; ++i ) {
00226 *q++ = buf[i];
00227 }
00228 TIXMLASSERT( q <= p );
00229 }
00230 else {
00231 int i=0;
00232 for(; i<NUM_ENTITIES; ++i ) {
00233 if ( strncmp( p+1, entities[i].pattern, entities[i].length ) == 0
00234 && *(p+entities[i].length+1) == ';' ) {
00235
00236 *q = entities[i].value;
00237 ++q;
00238 p += entities[i].length + 2;
00239 break;
00240 }
00241 }
00242 if ( i == NUM_ENTITIES ) {
00243
00244 ++p;
00245 ++q;
00246 }
00247 }
00248 }
00249 else {
00250 *q = *p;
00251 ++p;
00252 ++q;
00253 }
00254 }
00255 *q = 0;
00256 }
00257
00258
00259 if ( _flags & COLLAPSE_WHITESPACE ) {
00260 CollapseWhitespace();
00261 }
00262 _flags = (_flags & NEEDS_DELETE);
00263 }
00264 return _start;
00265 }
00266
00267
00268
00269
00270
00271
00272 const char* XMLUtil::ReadBOM( const char* p, bool* bom )
00273 {
00274 *bom = false;
00275 const unsigned char* pu = reinterpret_cast<const unsigned char*>(p);
00276
00277 if ( *(pu+0) == TIXML_UTF_LEAD_0
00278 && *(pu+1) == TIXML_UTF_LEAD_1
00279 && *(pu+2) == TIXML_UTF_LEAD_2 ) {
00280 *bom = true;
00281 p += 3;
00282 }
00283 return p;
00284 }
00285
00286
00287 void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
00288 {
00289 const unsigned long BYTE_MASK = 0xBF;
00290 const unsigned long BYTE_MARK = 0x80;
00291 const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
00292
00293 if (input < 0x80) {
00294 *length = 1;
00295 }
00296 else if ( input < 0x800 ) {
00297 *length = 2;
00298 }
00299 else if ( input < 0x10000 ) {
00300 *length = 3;
00301 }
00302 else if ( input < 0x200000 ) {
00303 *length = 4;
00304 }
00305 else {
00306 *length = 0;
00307 return;
00308 }
00309
00310 output += *length;
00311
00312
00313 switch (*length) {
00314 case 4:
00315 --output;
00316 *output = (char)((input | BYTE_MARK) & BYTE_MASK);
00317 input >>= 6;
00318 case 3:
00319 --output;
00320 *output = (char)((input | BYTE_MARK) & BYTE_MASK);
00321 input >>= 6;
00322 case 2:
00323 --output;
00324 *output = (char)((input | BYTE_MARK) & BYTE_MASK);
00325 input >>= 6;
00326 case 1:
00327 --output;
00328 *output = (char)(input | FIRST_BYTE_MARK[*length]);
00329 default:
00330 break;
00331 }
00332 }
00333
00334
00335 const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )
00336 {
00337
00338 *length = 0;
00339
00340 if ( *(p+1) == '#' && *(p+2) ) {
00341 unsigned long ucs = 0;
00342 ptrdiff_t delta = 0;
00343 unsigned mult = 1;
00344
00345 if ( *(p+2) == 'x' ) {
00346
00347 if ( !*(p+3) ) {
00348 return 0;
00349 }
00350
00351 const char* q = p+3;
00352 q = strchr( q, ';' );
00353
00354 if ( !q || !*q ) {
00355 return 0;
00356 }
00357
00358 delta = q-p;
00359 --q;
00360
00361 while ( *q != 'x' ) {
00362 if ( *q >= '0' && *q <= '9' ) {
00363 ucs += mult * (*q - '0');
00364 }
00365 else if ( *q >= 'a' && *q <= 'f' ) {
00366 ucs += mult * (*q - 'a' + 10);
00367 }
00368 else if ( *q >= 'A' && *q <= 'F' ) {
00369 ucs += mult * (*q - 'A' + 10 );
00370 }
00371 else {
00372 return 0;
00373 }
00374 mult *= 16;
00375 --q;
00376 }
00377 }
00378 else {
00379
00380 if ( !*(p+2) ) {
00381 return 0;
00382 }
00383
00384 const char* q = p+2;
00385 q = strchr( q, ';' );
00386
00387 if ( !q || !*q ) {
00388 return 0;
00389 }
00390
00391 delta = q-p;
00392 --q;
00393
00394 while ( *q != '#' ) {
00395 if ( *q >= '0' && *q <= '9' ) {
00396 ucs += mult * (*q - '0');
00397 }
00398 else {
00399 return 0;
00400 }
00401 mult *= 10;
00402 --q;
00403 }
00404 }
00405
00406 ConvertUTF32ToUTF8( ucs, value, length );
00407 return p + delta + 1;
00408 }
00409 return p+1;
00410 }
00411
00412
00413 void XMLUtil::ToStr( int v, char* buffer, int bufferSize )
00414 {
00415 TIXML_SNPRINTF( buffer, bufferSize, "%d", v );
00416 }
00417
00418
00419 void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize )
00420 {
00421 TIXML_SNPRINTF( buffer, bufferSize, "%u", v );
00422 }
00423
00424
00425 void XMLUtil::ToStr( bool v, char* buffer, int bufferSize )
00426 {
00427 TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 );
00428 }
00429
00430
00431 void XMLUtil::ToStr( float v, char* buffer, int bufferSize )
00432 {
00433 TIXML_SNPRINTF( buffer, bufferSize, "%g", v );
00434 }
00435
00436
00437 void XMLUtil::ToStr( double v, char* buffer, int bufferSize )
00438 {
00439 TIXML_SNPRINTF( buffer, bufferSize, "%g", v );
00440 }
00441
00442
00443 bool XMLUtil::ToInt( const char* str, int* value )
00444 {
00445 if ( TIXML_SSCANF( str, "%d", value ) == 1 ) {
00446 return true;
00447 }
00448 return false;
00449 }
00450
00451 bool XMLUtil::ToUnsigned( const char* str, unsigned *value )
00452 {
00453 if ( TIXML_SSCANF( str, "%u", value ) == 1 ) {
00454 return true;
00455 }
00456 return false;
00457 }
00458
00459 bool XMLUtil::ToBool( const char* str, bool* value )
00460 {
00461 int ival = 0;
00462 if ( ToInt( str, &ival )) {
00463 *value = (ival==0) ? false : true;
00464 return true;
00465 }
00466 if ( StringEqual( str, "true" ) ) {
00467 *value = true;
00468 return true;
00469 }
00470 else if ( StringEqual( str, "false" ) ) {
00471 *value = false;
00472 return true;
00473 }
00474 return false;
00475 }
00476
00477
00478 bool XMLUtil::ToFloat( const char* str, float* value )
00479 {
00480 if ( TIXML_SSCANF( str, "%f", value ) == 1 ) {
00481 return true;
00482 }
00483 return false;
00484 }
00485
00486 bool XMLUtil::ToDouble( const char* str, double* value )
00487 {
00488 if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) {
00489 return true;
00490 }
00491 return false;
00492 }
00493
00494
00495 char* XMLDocument::Identify( char* p, XMLNode** node )
00496 {
00497 XMLNode* returnNode = 0;
00498 char* start = p;
00499 p = XMLUtil::SkipWhiteSpace( p );
00500 if( !p || !*p ) {
00501 return p;
00502 }
00503
00504
00505
00506
00507
00508
00509
00510
00511 static const char* xmlHeader = { "<?" };
00512 static const char* commentHeader = { "<!--" };
00513 static const char* dtdHeader = { "<!" };
00514 static const char* cdataHeader = { "<![CDATA[" };
00515 static const char* elementHeader = { "<" };
00516
00517 static const int xmlHeaderLen = 2;
00518 static const int commentHeaderLen = 4;
00519 static const int dtdHeaderLen = 2;
00520 static const int cdataHeaderLen = 9;
00521 static const int elementHeaderLen = 1;
00522
00523 #if defined(_MSC_VER)
00524 #pragma warning ( push )
00525 #pragma warning ( disable : 4127 )
00526 #endif
00527 TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) );
00528 TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) );
00529 #if defined(_MSC_VER)
00530 #pragma warning (pop)
00531 #endif
00532 if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
00533 returnNode = new (_commentPool.Alloc()) XMLDeclaration( this );
00534 returnNode->_memPool = &_commentPool;
00535 p += xmlHeaderLen;
00536 }
00537 else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) {
00538 returnNode = new (_commentPool.Alloc()) XMLComment( this );
00539 returnNode->_memPool = &_commentPool;
00540 p += commentHeaderLen;
00541 }
00542 else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) {
00543 XMLText* text = new (_textPool.Alloc()) XMLText( this );
00544 returnNode = text;
00545 returnNode->_memPool = &_textPool;
00546 p += cdataHeaderLen;
00547 text->SetCData( true );
00548 }
00549 else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) {
00550 returnNode = new (_commentPool.Alloc()) XMLUnknown( this );
00551 returnNode->_memPool = &_commentPool;
00552 p += dtdHeaderLen;
00553 }
00554 else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {
00555 returnNode = new (_elementPool.Alloc()) XMLElement( this );
00556 returnNode->_memPool = &_elementPool;
00557 p += elementHeaderLen;
00558 }
00559 else {
00560 returnNode = new (_textPool.Alloc()) XMLText( this );
00561 returnNode->_memPool = &_textPool;
00562 p = start;
00563 }
00564
00565 *node = returnNode;
00566 return p;
00567 }
00568
00569
00570 bool XMLDocument::Accept( XMLVisitor* visitor ) const
00571 {
00572 if ( visitor->VisitEnter( *this ) ) {
00573 for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
00574 if ( !node->Accept( visitor ) ) {
00575 break;
00576 }
00577 }
00578 }
00579 return visitor->VisitExit( *this );
00580 }
00581
00582
00583
00584
00585 XMLNode::XMLNode( XMLDocument* doc ) :
00586 _document( doc ),
00587 _parent( 0 ),
00588 _firstChild( 0 ), _lastChild( 0 ),
00589 _prev( 0 ), _next( 0 )
00590 {
00591 }
00592
00593
00594 XMLNode::~XMLNode()
00595 {
00596 DeleteChildren();
00597 if ( _parent ) {
00598 _parent->Unlink( this );
00599 }
00600 }
00601
00602
00603 void XMLNode::SetValue( const char* str, bool staticMem )
00604 {
00605 if ( staticMem ) {
00606 _value.SetInternedStr( str );
00607 }
00608 else {
00609 _value.SetStr( str );
00610 }
00611 }
00612
00613
00614 void XMLNode::DeleteChildren()
00615 {
00616 while( _firstChild ) {
00617 XMLNode* node = _firstChild;
00618 Unlink( node );
00619
00620 DELETE_NODE( node );
00621 }
00622 _firstChild = _lastChild = 0;
00623 }
00624
00625
00626 void XMLNode::Unlink( XMLNode* child )
00627 {
00628 TIXMLASSERT( child->_parent == this );
00629 if ( child == _firstChild ) {
00630 _firstChild = _firstChild->_next;
00631 }
00632 if ( child == _lastChild ) {
00633 _lastChild = _lastChild->_prev;
00634 }
00635
00636 if ( child->_prev ) {
00637 child->_prev->_next = child->_next;
00638 }
00639 if ( child->_next ) {
00640 child->_next->_prev = child->_prev;
00641 }
00642 child->_parent = 0;
00643 }
00644
00645
00646 void XMLNode::DeleteChild( XMLNode* node )
00647 {
00648 TIXMLASSERT( node->_parent == this );
00649 DELETE_NODE( node );
00650 }
00651
00652
00653 XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )
00654 {
00655 if ( _lastChild ) {
00656 TIXMLASSERT( _firstChild );
00657 TIXMLASSERT( _lastChild->_next == 0 );
00658 _lastChild->_next = addThis;
00659 addThis->_prev = _lastChild;
00660 _lastChild = addThis;
00661
00662 addThis->_next = 0;
00663 }
00664 else {
00665 TIXMLASSERT( _firstChild == 0 );
00666 _firstChild = _lastChild = addThis;
00667
00668 addThis->_prev = 0;
00669 addThis->_next = 0;
00670 }
00671 addThis->_parent = this;
00672 addThis->_memPool->SetTracked();
00673 return addThis;
00674 }
00675
00676
00677 XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis )
00678 {
00679 if ( _firstChild ) {
00680 TIXMLASSERT( _lastChild );
00681 TIXMLASSERT( _firstChild->_prev == 0 );
00682
00683 _firstChild->_prev = addThis;
00684 addThis->_next = _firstChild;
00685 _firstChild = addThis;
00686
00687 addThis->_prev = 0;
00688 }
00689 else {
00690 TIXMLASSERT( _lastChild == 0 );
00691 _firstChild = _lastChild = addThis;
00692
00693 addThis->_prev = 0;
00694 addThis->_next = 0;
00695 }
00696 addThis->_parent = this;
00697 addThis->_memPool->SetTracked();
00698 return addThis;
00699 }
00700
00701
00702 XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )
00703 {
00704 TIXMLASSERT( afterThis->_parent == this );
00705 if ( afterThis->_parent != this ) {
00706 return 0;
00707 }
00708
00709 if ( afterThis->_next == 0 ) {
00710
00711 return InsertEndChild( addThis );
00712 }
00713 addThis->_prev = afterThis;
00714 addThis->_next = afterThis->_next;
00715 afterThis->_next->_prev = addThis;
00716 afterThis->_next = addThis;
00717 addThis->_parent = this;
00718 addThis->_memPool->SetTracked();
00719 return addThis;
00720 }
00721
00722
00723
00724
00725 const XMLElement* XMLNode::FirstChildElement( const char* value ) const
00726 {
00727 for( XMLNode* node=_firstChild; node; node=node->_next ) {
00728 XMLElement* element = node->ToElement();
00729 if ( element ) {
00730 if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
00731 return element;
00732 }
00733 }
00734 }
00735 return 0;
00736 }
00737
00738
00739 const XMLElement* XMLNode::LastChildElement( const char* value ) const
00740 {
00741 for( XMLNode* node=_lastChild; node; node=node->_prev ) {
00742 XMLElement* element = node->ToElement();
00743 if ( element ) {
00744 if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
00745 return element;
00746 }
00747 }
00748 }
00749 return 0;
00750 }
00751
00752
00753 const XMLElement* XMLNode::NextSiblingElement( const char* value ) const
00754 {
00755 for( XMLNode* element=this->_next; element; element = element->_next ) {
00756 if ( element->ToElement()
00757 && (!value || XMLUtil::StringEqual( value, element->Value() ))) {
00758 return element->ToElement();
00759 }
00760 }
00761 return 0;
00762 }
00763
00764
00765 const XMLElement* XMLNode::PreviousSiblingElement( const char* value ) const
00766 {
00767 for( XMLNode* element=_prev; element; element = element->_prev ) {
00768 if ( element->ToElement()
00769 && (!value || XMLUtil::StringEqual( value, element->Value() ))) {
00770 return element->ToElement();
00771 }
00772 }
00773 return 0;
00774 }
00775
00776
00777 char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
00778 {
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796 while( p && *p ) {
00797 XMLNode* node = 0;
00798
00799 p = _document->Identify( p, &node );
00800 if ( p == 0 || node == 0 ) {
00801 break;
00802 }
00803
00804 StrPair endTag;
00805 p = node->ParseDeep( p, &endTag );
00806 if ( !p ) {
00807 DELETE_NODE( node );
00808 node = 0;
00809 if ( !_document->Error() ) {
00810 _document->SetError( XML_ERROR_PARSING, 0, 0 );
00811 }
00812 break;
00813 }
00814
00815
00816 if ( node->ToElement() && node->ToElement()->ClosingType() == XMLElement::CLOSING ) {
00817 if ( parentEnd ) {
00818 *parentEnd = static_cast<XMLElement*>(node)->_value;
00819 }
00820 node->_memPool->SetTracked();
00821 DELETE_NODE( node );
00822 return p;
00823 }
00824
00825
00826
00827 XMLElement* ele = node->ToElement();
00828 if ( ele ) {
00829 if ( endTag.Empty() && ele->ClosingType() == XMLElement::OPEN ) {
00830 _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
00831 p = 0;
00832 }
00833 else if ( !endTag.Empty() && ele->ClosingType() != XMLElement::OPEN ) {
00834 _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
00835 p = 0;
00836 }
00837 else if ( !endTag.Empty() ) {
00838 if ( !XMLUtil::StringEqual( endTag.GetStr(), node->Value() )) {
00839 _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
00840 p = 0;
00841 }
00842 }
00843 }
00844 if ( p == 0 ) {
00845 DELETE_NODE( node );
00846 node = 0;
00847 }
00848 if ( node ) {
00849 this->InsertEndChild( node );
00850 }
00851 }
00852 return 0;
00853 }
00854
00855
00856 char* XMLText::ParseDeep( char* p, StrPair* )
00857 {
00858 const char* start = p;
00859 if ( this->CData() ) {
00860 p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
00861 if ( !p ) {
00862 _document->SetError( XML_ERROR_PARSING_CDATA, start, 0 );
00863 }
00864 return p;
00865 }
00866 else {
00867 int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES;
00868 if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) {
00869 flags |= StrPair::COLLAPSE_WHITESPACE;
00870 }
00871
00872 p = _value.ParseText( p, "<", flags );
00873 if ( !p ) {
00874 _document->SetError( XML_ERROR_PARSING_TEXT, start, 0 );
00875 }
00876 if ( p && *p ) {
00877 return p-1;
00878 }
00879 }
00880 return 0;
00881 }
00882
00883
00884 XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const
00885 {
00886 if ( !doc ) {
00887 doc = _document;
00888 }
00889 XMLText* text = doc->NewText( Value() );
00890 text->SetCData( this->CData() );
00891 return text;
00892 }
00893
00894
00895 bool XMLText::ShallowEqual( const XMLNode* compare ) const
00896 {
00897 return ( compare->ToText() && XMLUtil::StringEqual( compare->ToText()->Value(), Value() ));
00898 }
00899
00900
00901 bool XMLText::Accept( XMLVisitor* visitor ) const
00902 {
00903 return visitor->Visit( *this );
00904 }
00905
00906
00907
00908
00909 XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc )
00910 {
00911 }
00912
00913
00914 XMLComment::~XMLComment()
00915 {
00916 }
00917
00918
00919 char* XMLComment::ParseDeep( char* p, StrPair* )
00920 {
00921
00922 const char* start = p;
00923 p = _value.ParseText( p, "-->", StrPair::COMMENT );
00924 if ( p == 0 ) {
00925 _document->SetError( XML_ERROR_PARSING_COMMENT, start, 0 );
00926 }
00927 return p;
00928 }
00929
00930
00931 XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const
00932 {
00933 if ( !doc ) {
00934 doc = _document;
00935 }
00936 XMLComment* comment = doc->NewComment( Value() );
00937 return comment;
00938 }
00939
00940
00941 bool XMLComment::ShallowEqual( const XMLNode* compare ) const
00942 {
00943 return ( compare->ToComment() && XMLUtil::StringEqual( compare->ToComment()->Value(), Value() ));
00944 }
00945
00946
00947 bool XMLComment::Accept( XMLVisitor* visitor ) const
00948 {
00949 return visitor->Visit( *this );
00950 }
00951
00952
00953
00954
00955 XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc )
00956 {
00957 }
00958
00959
00960 XMLDeclaration::~XMLDeclaration()
00961 {
00962
00963 }
00964
00965
00966 char* XMLDeclaration::ParseDeep( char* p, StrPair* )
00967 {
00968
00969 const char* start = p;
00970 p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
00971 if ( p == 0 ) {
00972 _document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0 );
00973 }
00974 return p;
00975 }
00976
00977
00978 XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const
00979 {
00980 if ( !doc ) {
00981 doc = _document;
00982 }
00983 XMLDeclaration* dec = doc->NewDeclaration( Value() );
00984 return dec;
00985 }
00986
00987
00988 bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const
00989 {
00990 return ( compare->ToDeclaration() && XMLUtil::StringEqual( compare->ToDeclaration()->Value(), Value() ));
00991 }
00992
00993
00994
00995 bool XMLDeclaration::Accept( XMLVisitor* visitor ) const
00996 {
00997 return visitor->Visit( *this );
00998 }
00999
01000
01001
01002 XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc )
01003 {
01004 }
01005
01006
01007 XMLUnknown::~XMLUnknown()
01008 {
01009 }
01010
01011
01012 char* XMLUnknown::ParseDeep( char* p, StrPair* )
01013 {
01014
01015 const char* start = p;
01016
01017 p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION );
01018 if ( !p ) {
01019 _document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 );
01020 }
01021 return p;
01022 }
01023
01024
01025 XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const
01026 {
01027 if ( !doc ) {
01028 doc = _document;
01029 }
01030 XMLUnknown* text = doc->NewUnknown( Value() );
01031 return text;
01032 }
01033
01034
01035 bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const
01036 {
01037 return ( compare->ToUnknown() && XMLUtil::StringEqual( compare->ToUnknown()->Value(), Value() ));
01038 }
01039
01040
01041 bool XMLUnknown::Accept( XMLVisitor* visitor ) const
01042 {
01043 return visitor->Visit( *this );
01044 }
01045
01046
01047 char* XMLAttribute::ParseDeep( char* p, bool processEntities )
01048 {
01049
01050 p = _name.ParseName( p );
01051 if ( !p || !*p ) {
01052 return 0;
01053 }
01054
01055
01056 p = XMLUtil::SkipWhiteSpace( p );
01057 if ( !p || *p != '=' ) {
01058 return 0;
01059 }
01060
01061 ++p;
01062 p = XMLUtil::SkipWhiteSpace( p );
01063 if ( *p != '\"' && *p != '\'' ) {
01064 return 0;
01065 }
01066
01067 char endTag[2] = { *p, 0 };
01068 ++p;
01069
01070 p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES );
01071 return p;
01072 }
01073
01074
01075 void XMLAttribute::SetName( const char* n )
01076 {
01077 _name.SetStr( n );
01078 }
01079
01080
01081 XMLError XMLAttribute::QueryIntValue( int* value ) const
01082 {
01083 if ( XMLUtil::ToInt( Value(), value )) {
01084 return XML_NO_ERROR;
01085 }
01086 return XML_WRONG_ATTRIBUTE_TYPE;
01087 }
01088
01089
01090 XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const
01091 {
01092 if ( XMLUtil::ToUnsigned( Value(), value )) {
01093 return XML_NO_ERROR;
01094 }
01095 return XML_WRONG_ATTRIBUTE_TYPE;
01096 }
01097
01098
01099 XMLError XMLAttribute::QueryBoolValue( bool* value ) const
01100 {
01101 if ( XMLUtil::ToBool( Value(), value )) {
01102 return XML_NO_ERROR;
01103 }
01104 return XML_WRONG_ATTRIBUTE_TYPE;
01105 }
01106
01107
01108 XMLError XMLAttribute::QueryFloatValue( float* value ) const
01109 {
01110 if ( XMLUtil::ToFloat( Value(), value )) {
01111 return XML_NO_ERROR;
01112 }
01113 return XML_WRONG_ATTRIBUTE_TYPE;
01114 }
01115
01116
01117 XMLError XMLAttribute::QueryDoubleValue( double* value ) const
01118 {
01119 if ( XMLUtil::ToDouble( Value(), value )) {
01120 return XML_NO_ERROR;
01121 }
01122 return XML_WRONG_ATTRIBUTE_TYPE;
01123 }
01124
01125
01126 void XMLAttribute::SetAttribute( const char* v )
01127 {
01128 _value.SetStr( v );
01129 }
01130
01131
01132 void XMLAttribute::SetAttribute( int v )
01133 {
01134 char buf[BUF_SIZE];
01135 XMLUtil::ToStr( v, buf, BUF_SIZE );
01136 _value.SetStr( buf );
01137 }
01138
01139
01140 void XMLAttribute::SetAttribute( unsigned v )
01141 {
01142 char buf[BUF_SIZE];
01143 XMLUtil::ToStr( v, buf, BUF_SIZE );
01144 _value.SetStr( buf );
01145 }
01146
01147
01148 void XMLAttribute::SetAttribute( bool v )
01149 {
01150 char buf[BUF_SIZE];
01151 XMLUtil::ToStr( v, buf, BUF_SIZE );
01152 _value.SetStr( buf );
01153 }
01154
01155 void XMLAttribute::SetAttribute( double v )
01156 {
01157 char buf[BUF_SIZE];
01158 XMLUtil::ToStr( v, buf, BUF_SIZE );
01159 _value.SetStr( buf );
01160 }
01161
01162 void XMLAttribute::SetAttribute( float v )
01163 {
01164 char buf[BUF_SIZE];
01165 XMLUtil::ToStr( v, buf, BUF_SIZE );
01166 _value.SetStr( buf );
01167 }
01168
01169
01170
01171 XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ),
01172 _closingType( 0 ),
01173 _rootAttribute( 0 )
01174 {
01175 }
01176
01177
01178 XMLElement::~XMLElement()
01179 {
01180 while( _rootAttribute ) {
01181 XMLAttribute* next = _rootAttribute->_next;
01182 DELETE_ATTRIBUTE( _rootAttribute );
01183 _rootAttribute = next;
01184 }
01185 }
01186
01187
01188 XMLAttribute* XMLElement::FindAttribute( const char* name )
01189 {
01190 XMLAttribute* a = 0;
01191 for( a=_rootAttribute; a; a = a->_next ) {
01192 if ( XMLUtil::StringEqual( a->Name(), name ) ) {
01193 return a;
01194 }
01195 }
01196 return 0;
01197 }
01198
01199
01200 const XMLAttribute* XMLElement::FindAttribute( const char* name ) const
01201 {
01202 XMLAttribute* a = 0;
01203 for( a=_rootAttribute; a; a = a->_next ) {
01204 if ( XMLUtil::StringEqual( a->Name(), name ) ) {
01205 return a;
01206 }
01207 }
01208 return 0;
01209 }
01210
01211
01212 const char* XMLElement::Attribute( const char* name, const char* value ) const
01213 {
01214 const XMLAttribute* a = FindAttribute( name );
01215 if ( !a ) {
01216 return 0;
01217 }
01218 if ( !value || XMLUtil::StringEqual( a->Value(), value )) {
01219 return a->Value();
01220 }
01221 return 0;
01222 }
01223
01224
01225 const char* XMLElement::GetText() const
01226 {
01227 if ( FirstChild() && FirstChild()->ToText() ) {
01228 return FirstChild()->ToText()->Value();
01229 }
01230 return 0;
01231 }
01232
01233
01234 XMLError XMLElement::QueryIntText( int* ival ) const
01235 {
01236 if ( FirstChild() && FirstChild()->ToText() ) {
01237 const char* t = FirstChild()->ToText()->Value();
01238 if ( XMLUtil::ToInt( t, ival ) ) {
01239 return XML_SUCCESS;
01240 }
01241 return XML_CAN_NOT_CONVERT_TEXT;
01242 }
01243 return XML_NO_TEXT_NODE;
01244 }
01245
01246
01247 XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const
01248 {
01249 if ( FirstChild() && FirstChild()->ToText() ) {
01250 const char* t = FirstChild()->ToText()->Value();
01251 if ( XMLUtil::ToUnsigned( t, uval ) ) {
01252 return XML_SUCCESS;
01253 }
01254 return XML_CAN_NOT_CONVERT_TEXT;
01255 }
01256 return XML_NO_TEXT_NODE;
01257 }
01258
01259
01260 XMLError XMLElement::QueryBoolText( bool* bval ) const
01261 {
01262 if ( FirstChild() && FirstChild()->ToText() ) {
01263 const char* t = FirstChild()->ToText()->Value();
01264 if ( XMLUtil::ToBool( t, bval ) ) {
01265 return XML_SUCCESS;
01266 }
01267 return XML_CAN_NOT_CONVERT_TEXT;
01268 }
01269 return XML_NO_TEXT_NODE;
01270 }
01271
01272
01273 XMLError XMLElement::QueryDoubleText( double* dval ) const
01274 {
01275 if ( FirstChild() && FirstChild()->ToText() ) {
01276 const char* t = FirstChild()->ToText()->Value();
01277 if ( XMLUtil::ToDouble( t, dval ) ) {
01278 return XML_SUCCESS;
01279 }
01280 return XML_CAN_NOT_CONVERT_TEXT;
01281 }
01282 return XML_NO_TEXT_NODE;
01283 }
01284
01285
01286 XMLError XMLElement::QueryFloatText( float* fval ) const
01287 {
01288 if ( FirstChild() && FirstChild()->ToText() ) {
01289 const char* t = FirstChild()->ToText()->Value();
01290 if ( XMLUtil::ToFloat( t, fval ) ) {
01291 return XML_SUCCESS;
01292 }
01293 return XML_CAN_NOT_CONVERT_TEXT;
01294 }
01295 return XML_NO_TEXT_NODE;
01296 }
01297
01298
01299
01300 XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )
01301 {
01302 XMLAttribute* last = 0;
01303 XMLAttribute* attrib = 0;
01304 for( attrib = _rootAttribute;
01305 attrib;
01306 last = attrib, attrib = attrib->_next ) {
01307 if ( XMLUtil::StringEqual( attrib->Name(), name ) ) {
01308 break;
01309 }
01310 }
01311 if ( !attrib ) {
01312 attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
01313 attrib->_memPool = &_document->_attributePool;
01314 if ( last ) {
01315 last->_next = attrib;
01316 }
01317 else {
01318 _rootAttribute = attrib;
01319 }
01320 attrib->SetName( name );
01321 attrib->_memPool->SetTracked();
01322 }
01323 return attrib;
01324 }
01325
01326
01327 void XMLElement::DeleteAttribute( const char* name )
01328 {
01329 XMLAttribute* prev = 0;
01330 for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) {
01331 if ( XMLUtil::StringEqual( name, a->Name() ) ) {
01332 if ( prev ) {
01333 prev->_next = a->_next;
01334 }
01335 else {
01336 _rootAttribute = a->_next;
01337 }
01338 DELETE_ATTRIBUTE( a );
01339 break;
01340 }
01341 prev = a;
01342 }
01343 }
01344
01345
01346 char* XMLElement::ParseAttributes( char* p )
01347 {
01348 const char* start = p;
01349 XMLAttribute* prevAttribute = 0;
01350
01351
01352 while( p ) {
01353 p = XMLUtil::SkipWhiteSpace( p );
01354 if ( !p || !(*p) ) {
01355 _document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() );
01356 return 0;
01357 }
01358
01359
01360 if ( XMLUtil::IsAlpha( *p ) ) {
01361 XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
01362 attrib->_memPool = &_document->_attributePool;
01363 attrib->_memPool->SetTracked();
01364
01365 p = attrib->ParseDeep( p, _document->ProcessEntities() );
01366 if ( !p || Attribute( attrib->Name() ) ) {
01367 DELETE_ATTRIBUTE( attrib );
01368 _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p );
01369 return 0;
01370 }
01371
01372
01373
01374
01375
01376 if ( prevAttribute ) {
01377 prevAttribute->_next = attrib;
01378 }
01379 else {
01380 _rootAttribute = attrib;
01381 }
01382 prevAttribute = attrib;
01383 }
01384
01385 else if ( *p == '/' && *(p+1) == '>' ) {
01386 _closingType = CLOSED;
01387 return p+2;
01388 }
01389
01390 else if ( *p == '>' ) {
01391 ++p;
01392 break;
01393 }
01394 else {
01395 _document->SetError( XML_ERROR_PARSING_ELEMENT, start, p );
01396 return 0;
01397 }
01398 }
01399 return p;
01400 }
01401
01402
01403
01404
01405
01406
01407 char* XMLElement::ParseDeep( char* p, StrPair* strPair )
01408 {
01409
01410 p = XMLUtil::SkipWhiteSpace( p );
01411 if ( !p ) {
01412 return 0;
01413 }
01414
01415
01416
01417
01418 if ( *p == '/' ) {
01419 _closingType = CLOSING;
01420 ++p;
01421 }
01422
01423 p = _value.ParseName( p );
01424 if ( _value.Empty() ) {
01425 return 0;
01426 }
01427
01428 p = ParseAttributes( p );
01429 if ( !p || !*p || _closingType ) {
01430 return p;
01431 }
01432
01433 p = XMLNode::ParseDeep( p, strPair );
01434 return p;
01435 }
01436
01437
01438
01439 XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const
01440 {
01441 if ( !doc ) {
01442 doc = _document;
01443 }
01444 XMLElement* element = doc->NewElement( Value() );
01445 for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) {
01446 element->SetAttribute( a->Name(), a->Value() );
01447 }
01448 return element;
01449 }
01450
01451
01452 bool XMLElement::ShallowEqual( const XMLNode* compare ) const
01453 {
01454 const XMLElement* other = compare->ToElement();
01455 if ( other && XMLUtil::StringEqual( other->Value(), Value() )) {
01456
01457 const XMLAttribute* a=FirstAttribute();
01458 const XMLAttribute* b=other->FirstAttribute();
01459
01460 while ( a && b ) {
01461 if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) {
01462 return false;
01463 }
01464 a = a->Next();
01465 b = b->Next();
01466 }
01467 if ( a || b ) {
01468
01469 return false;
01470 }
01471 return true;
01472 }
01473 return false;
01474 }
01475
01476
01477 bool XMLElement::Accept( XMLVisitor* visitor ) const
01478 {
01479 if ( visitor->VisitEnter( *this, _rootAttribute ) ) {
01480 for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
01481 if ( !node->Accept( visitor ) ) {
01482 break;
01483 }
01484 }
01485 }
01486 return visitor->VisitExit( *this );
01487 }
01488
01489
01490
01491 XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) :
01492 XMLNode( 0 ),
01493 _writeBOM( false ),
01494 _processEntities( processEntities ),
01495 _errorID( XML_NO_ERROR ),
01496 _whitespace( whitespace ),
01497 _errorStr1( 0 ),
01498 _errorStr2( 0 ),
01499 _charBuffer( 0 )
01500 {
01501 _document = this;
01502 }
01503
01504
01505 XMLDocument::~XMLDocument()
01506 {
01507 DeleteChildren();
01508 delete [] _charBuffer;
01509
01510 #if 0
01511 textPool.Trace( "text" );
01512 elementPool.Trace( "element" );
01513 commentPool.Trace( "comment" );
01514 attributePool.Trace( "attribute" );
01515 #endif
01516
01517 #ifdef DEBUG
01518 if ( Error() == false ) {
01519 TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() );
01520 TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );
01521 TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() );
01522 TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() );
01523 }
01524 #endif
01525 }
01526
01527
01528 void XMLDocument::InitDocument()
01529 {
01530 _errorID = XML_NO_ERROR;
01531 _errorStr1 = 0;
01532 _errorStr2 = 0;
01533
01534 delete [] _charBuffer;
01535 _charBuffer = 0;
01536 }
01537
01538
01539 XMLElement* XMLDocument::NewElement( const char* name )
01540 {
01541 XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this );
01542 ele->_memPool = &_elementPool;
01543 ele->SetName( name );
01544 return ele;
01545 }
01546
01547
01548 XMLComment* XMLDocument::NewComment( const char* str )
01549 {
01550 XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this );
01551 comment->_memPool = &_commentPool;
01552 comment->SetValue( str );
01553 return comment;
01554 }
01555
01556
01557 XMLText* XMLDocument::NewText( const char* str )
01558 {
01559 XMLText* text = new (_textPool.Alloc()) XMLText( this );
01560 text->_memPool = &_textPool;
01561 text->SetValue( str );
01562 return text;
01563 }
01564
01565
01566 XMLDeclaration* XMLDocument::NewDeclaration( const char* str )
01567 {
01568 XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this );
01569 dec->_memPool = &_commentPool;
01570 dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" );
01571 return dec;
01572 }
01573
01574
01575 XMLUnknown* XMLDocument::NewUnknown( const char* str )
01576 {
01577 XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this );
01578 unk->_memPool = &_commentPool;
01579 unk->SetValue( str );
01580 return unk;
01581 }
01582
01583
01584 XMLError XMLDocument::LoadFile( const char* filename )
01585 {
01586 DeleteChildren();
01587 InitDocument();
01588 FILE* fp = 0;
01589
01590 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
01591 errno_t err = fopen_s(&fp, filename, "rb" );
01592 if ( !fp || err) {
01593 #else
01594 fp = fopen( filename, "rb" );
01595 if ( !fp) {
01596 #endif
01597 SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 );
01598 return _errorID;
01599 }
01600 LoadFile( fp );
01601 fclose( fp );
01602 return _errorID;
01603 }
01604
01605
01606 XMLError XMLDocument::LoadFile( FILE* fp )
01607 {
01608 DeleteChildren();
01609 InitDocument();
01610
01611 fseek( fp, 0, SEEK_END );
01612 size_t size = ftell( fp );
01613 fseek( fp, 0, SEEK_SET );
01614
01615 if ( size == 0 ) {
01616 return _errorID;
01617 }
01618
01619 _charBuffer = new char[size+1];
01620 size_t read = fread( _charBuffer, 1, size, fp );
01621 if ( read != size ) {
01622 SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
01623 return _errorID;
01624 }
01625
01626 _charBuffer[size] = 0;
01627
01628 const char* p = _charBuffer;
01629 p = XMLUtil::SkipWhiteSpace( p );
01630 p = XMLUtil::ReadBOM( p, &_writeBOM );
01631 if ( !p || !*p ) {
01632 SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
01633 return _errorID;
01634 }
01635
01636 ParseDeep( _charBuffer + (p-_charBuffer), 0 );
01637 return _errorID;
01638 }
01639
01640
01641 XMLError XMLDocument::SaveFile( const char* filename, bool compact )
01642 {
01643 FILE* fp = 0;
01644 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
01645 errno_t err = fopen_s(&fp, filename, "w" );
01646 if ( !fp || err) {
01647 #else
01648 fp = fopen( filename, "w" );
01649 if ( !fp) {
01650 #endif
01651 SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 );
01652 return _errorID;
01653 }
01654 SaveFile(fp, compact);
01655 fclose( fp );
01656 return _errorID;
01657 }
01658
01659
01660 XMLError XMLDocument::SaveFile( FILE* fp, bool compact )
01661 {
01662 XMLPrinter stream( fp, compact );
01663 Print( &stream );
01664 return _errorID;
01665 }
01666
01667
01668 XMLError XMLDocument::Parse( const char* p, size_t len )
01669 {
01670 DeleteChildren();
01671 InitDocument();
01672
01673 if ( !p || !*p ) {
01674 SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
01675 return _errorID;
01676 }
01677 if ( len == (size_t)(-1) ) {
01678 len = strlen( p );
01679 }
01680 _charBuffer = new char[ len+1 ];
01681 memcpy( _charBuffer, p, len );
01682 _charBuffer[len] = 0;
01683
01684 p = XMLUtil::SkipWhiteSpace( p );
01685 p = XMLUtil::ReadBOM( p, &_writeBOM );
01686 if ( !p || !*p ) {
01687 SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
01688 return _errorID;
01689 }
01690
01691 ParseDeep( _charBuffer, 0 );
01692 return _errorID;
01693 }
01694
01695
01696 void XMLDocument::Print( XMLPrinter* streamer )
01697 {
01698 XMLPrinter stdStreamer( stdout );
01699 if ( !streamer ) {
01700 streamer = &stdStreamer;
01701 }
01702 Accept( streamer );
01703 }
01704
01705
01706 void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 )
01707 {
01708 _errorID = error;
01709 _errorStr1 = str1;
01710 _errorStr2 = str2;
01711 }
01712
01713
01714 void XMLDocument::PrintError() const
01715 {
01716 if ( _errorID ) {
01717 static const int LEN = 20;
01718 char buf1[LEN] = { 0 };
01719 char buf2[LEN] = { 0 };
01720
01721 if ( _errorStr1 ) {
01722 TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr1 );
01723 }
01724 if ( _errorStr2 ) {
01725 TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 );
01726 }
01727
01728 printf( "XMLDocument error id=%d str1=%s str2=%s\n",
01729 _errorID, buf1, buf2 );
01730 }
01731 }
01732
01733
01734 XMLPrinter::XMLPrinter( FILE* file, bool compact ) :
01735 _elementJustOpened( false ),
01736 _firstElement( true ),
01737 _fp( file ),
01738 _depth( 0 ),
01739 _textDepth( -1 ),
01740 _processEntities( true ),
01741 _compactMode( compact )
01742 {
01743 for( int i=0; i<ENTITY_RANGE; ++i ) {
01744 _entityFlag[i] = false;
01745 _restrictedEntityFlag[i] = false;
01746 }
01747 for( int i=0; i<NUM_ENTITIES; ++i ) {
01748 TIXMLASSERT( entities[i].value < ENTITY_RANGE );
01749 if ( entities[i].value < ENTITY_RANGE ) {
01750 _entityFlag[ (int)entities[i].value ] = true;
01751 }
01752 }
01753 _restrictedEntityFlag[(int)'&'] = true;
01754 _restrictedEntityFlag[(int)'<'] = true;
01755 _restrictedEntityFlag[(int)'>'] = true;
01756 _buffer.Push( 0 );
01757 }
01758
01759
01760 void XMLPrinter::Print( const char* format, ... )
01761 {
01762 va_list va;
01763 va_start( va, format );
01764
01765 if ( _fp ) {
01766 vfprintf( _fp, format, va );
01767 }
01768 else {
01769
01770
01771 #ifdef _MSC_VER
01772 int len = -1;
01773 int expand = 1000;
01774 while ( len < 0 ) {
01775 len = vsnprintf_s( _accumulator.Mem(), _accumulator.Capacity(), _TRUNCATE, format, va );
01776 if ( len < 0 ) {
01777 expand *= 3/2;
01778 _accumulator.PushArr( expand );
01779 }
01780 }
01781 char* p = _buffer.PushArr( len ) - 1;
01782 memcpy( p, _accumulator.Mem(), len+1 );
01783 #else
01784 int len = vsnprintf( 0, 0, format, va );
01785
01786 va_end( va );
01787 va_start( va, format );
01788 char* p = _buffer.PushArr( len ) - 1;
01789 vsnprintf( p, len+1, format, va );
01790 #endif
01791 }
01792 va_end( va );
01793 }
01794
01795
01796 void XMLPrinter::PrintSpace( int depth )
01797 {
01798 for( int i=0; i<depth; ++i ) {
01799 Print( " " );
01800 }
01801 }
01802
01803
01804 void XMLPrinter::PrintString( const char* p, bool restricted )
01805 {
01806
01807 const char* q = p;
01808 const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag;
01809
01810 if ( _processEntities ) {
01811 while ( *q ) {
01812
01813 if ( *q > 0 && *q < ENTITY_RANGE ) {
01814
01815
01816
01817 if ( flag[(unsigned)(*q)] ) {
01818 while ( p < q ) {
01819 Print( "%c", *p );
01820 ++p;
01821 }
01822 for( int i=0; i<NUM_ENTITIES; ++i ) {
01823 if ( entities[i].value == *q ) {
01824 Print( "&%s;", entities[i].pattern );
01825 break;
01826 }
01827 }
01828 ++p;
01829 }
01830 }
01831 ++q;
01832 }
01833 }
01834
01835
01836 if ( !_processEntities || (q-p > 0) ) {
01837 Print( "%s", p );
01838 }
01839 }
01840
01841
01842 void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
01843 {
01844 static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };
01845 if ( writeBOM ) {
01846 Print( "%s", bom );
01847 }
01848 if ( writeDec ) {
01849 PushDeclaration( "xml version=\"1.0\"" );
01850 }
01851 }
01852
01853
01854 void XMLPrinter::OpenElement( const char* name )
01855 {
01856 if ( _elementJustOpened ) {
01857 SealElement();
01858 }
01859 _stack.Push( name );
01860
01861 if ( _textDepth < 0 && !_firstElement && !_compactMode ) {
01862 Print( "\n" );
01863 PrintSpace( _depth );
01864 }
01865
01866 Print( "<%s", name );
01867 _elementJustOpened = true;
01868 _firstElement = false;
01869 ++_depth;
01870 }
01871
01872
01873 void XMLPrinter::PushAttribute( const char* name, const char* value )
01874 {
01875 TIXMLASSERT( _elementJustOpened );
01876 Print( " %s=\"", name );
01877 PrintString( value, false );
01878 Print( "\"" );
01879 }
01880
01881
01882 void XMLPrinter::PushAttribute( const char* name, int v )
01883 {
01884 char buf[BUF_SIZE];
01885 XMLUtil::ToStr( v, buf, BUF_SIZE );
01886 PushAttribute( name, buf );
01887 }
01888
01889
01890 void XMLPrinter::PushAttribute( const char* name, unsigned v )
01891 {
01892 char buf[BUF_SIZE];
01893 XMLUtil::ToStr( v, buf, BUF_SIZE );
01894 PushAttribute( name, buf );
01895 }
01896
01897
01898 void XMLPrinter::PushAttribute( const char* name, bool v )
01899 {
01900 char buf[BUF_SIZE];
01901 XMLUtil::ToStr( v, buf, BUF_SIZE );
01902 PushAttribute( name, buf );
01903 }
01904
01905
01906 void XMLPrinter::PushAttribute( const char* name, double v )
01907 {
01908 char buf[BUF_SIZE];
01909 XMLUtil::ToStr( v, buf, BUF_SIZE );
01910 PushAttribute( name, buf );
01911 }
01912
01913
01914 void XMLPrinter::CloseElement()
01915 {
01916 --_depth;
01917 const char* name = _stack.Pop();
01918
01919 if ( _elementJustOpened ) {
01920 Print( "/>" );
01921 }
01922 else {
01923 if ( _textDepth < 0 && !_compactMode) {
01924 Print( "\n" );
01925 PrintSpace( _depth );
01926 }
01927 Print( "</%s>", name );
01928 }
01929
01930 if ( _textDepth == _depth ) {
01931 _textDepth = -1;
01932 }
01933 if ( _depth == 0 && !_compactMode) {
01934 Print( "\n" );
01935 }
01936 _elementJustOpened = false;
01937 }
01938
01939
01940 void XMLPrinter::SealElement()
01941 {
01942 _elementJustOpened = false;
01943 Print( ">" );
01944 }
01945
01946
01947 void XMLPrinter::PushText( const char* text, bool cdata )
01948 {
01949 _textDepth = _depth-1;
01950
01951 if ( _elementJustOpened ) {
01952 SealElement();
01953 }
01954 if ( cdata ) {
01955 Print( "<![CDATA[" );
01956 Print( "%s", text );
01957 Print( "]]>" );
01958 }
01959 else {
01960 PrintString( text, true );
01961 }
01962 }
01963
01964 void XMLPrinter::PushText( int value )
01965 {
01966 char buf[BUF_SIZE];
01967 XMLUtil::ToStr( value, buf, BUF_SIZE );
01968 PushText( buf, false );
01969 }
01970
01971
01972 void XMLPrinter::PushText( unsigned value )
01973 {
01974 char buf[BUF_SIZE];
01975 XMLUtil::ToStr( value, buf, BUF_SIZE );
01976 PushText( buf, false );
01977 }
01978
01979
01980 void XMLPrinter::PushText( bool value )
01981 {
01982 char buf[BUF_SIZE];
01983 XMLUtil::ToStr( value, buf, BUF_SIZE );
01984 PushText( buf, false );
01985 }
01986
01987
01988 void XMLPrinter::PushText( float value )
01989 {
01990 char buf[BUF_SIZE];
01991 XMLUtil::ToStr( value, buf, BUF_SIZE );
01992 PushText( buf, false );
01993 }
01994
01995
01996 void XMLPrinter::PushText( double value )
01997 {
01998 char buf[BUF_SIZE];
01999 XMLUtil::ToStr( value, buf, BUF_SIZE );
02000 PushText( buf, false );
02001 }
02002
02003
02004 void XMLPrinter::PushComment( const char* comment )
02005 {
02006 if ( _elementJustOpened ) {
02007 SealElement();
02008 }
02009 if ( _textDepth < 0 && !_firstElement && !_compactMode) {
02010 Print( "\n" );
02011 PrintSpace( _depth );
02012 }
02013 _firstElement = false;
02014 Print( "<!--%s-->", comment );
02015 }
02016
02017
02018 void XMLPrinter::PushDeclaration( const char* value )
02019 {
02020 if ( _elementJustOpened ) {
02021 SealElement();
02022 }
02023 if ( _textDepth < 0 && !_firstElement && !_compactMode) {
02024 Print( "\n" );
02025 PrintSpace( _depth );
02026 }
02027 _firstElement = false;
02028 Print( "<?%s?>", value );
02029 }
02030
02031
02032 void XMLPrinter::PushUnknown( const char* value )
02033 {
02034 if ( _elementJustOpened ) {
02035 SealElement();
02036 }
02037 if ( _textDepth < 0 && !_firstElement && !_compactMode) {
02038 Print( "\n" );
02039 PrintSpace( _depth );
02040 }
02041 _firstElement = false;
02042 Print( "<!%s>", value );
02043 }
02044
02045
02046 bool XMLPrinter::VisitEnter( const XMLDocument& doc )
02047 {
02048 _processEntities = doc.ProcessEntities();
02049 if ( doc.HasBOM() ) {
02050 PushHeader( true, false );
02051 }
02052 return true;
02053 }
02054
02055
02056 bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
02057 {
02058 OpenElement( element.Name() );
02059 while ( attribute ) {
02060 PushAttribute( attribute->Name(), attribute->Value() );
02061 attribute = attribute->Next();
02062 }
02063 return true;
02064 }
02065
02066
02067 bool XMLPrinter::VisitExit( const XMLElement& )
02068 {
02069 CloseElement();
02070 return true;
02071 }
02072
02073
02074 bool XMLPrinter::Visit( const XMLText& text )
02075 {
02076 PushText( text.Value(), text.CData() );
02077 return true;
02078 }
02079
02080
02081 bool XMLPrinter::Visit( const XMLComment& comment )
02082 {
02083 PushComment( comment.Value() );
02084 return true;
02085 }
02086
02087 bool XMLPrinter::Visit( const XMLDeclaration& declaration )
02088 {
02089 PushDeclaration( declaration.Value() );
02090 return true;
02091 }
02092
02093
02094 bool XMLPrinter::Visit( const XMLUnknown& unknown )
02095 {
02096 PushUnknown( unknown.Value() );
02097 return true;
02098 }
02099
02100 }
02101