File indexing completed on 2026-07-17 07:52:47
0001 #ifndef DDCORE_SRC_XML_TINYXMLPARSER_INL_H
0002 #define DDCORE_SRC_XML_TINYXMLPARSER_INL_H
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #include <ctype.h>
0033 #include <stddef.h>
0034
0035 #include <XML/tinyxml.h>
0036
0037
0038 #if defined( DEBUG_PARSER )
0039 # if defined( DEBUG ) && defined( _MSC_VER )
0040 # include <windows.h>
0041 # define TIXML_LOG OutputDebugString
0042 # else
0043 # define TIXML_LOG printf
0044 # endif
0045 #endif
0046
0047
0048
0049
0050
0051
0052 TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] =
0053 {
0054
0055
0056 { "&", 1, '&' },
0057
0058
0059 { "<", 4, '<' },
0060 { ">", 4, '>' },
0061 { """, 6, '\"' },
0062 { "'", 6, '\'' }
0063 };
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075 const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
0076 const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
0077 const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
0078
0079 const int TiXmlBase::utf8ByteTable[256] =
0080 {
0081
0082 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0083 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0084 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0085 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0086 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0087 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0088 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0089 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0090 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0091 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0092 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0093 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0094 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
0095 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
0096 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
0097 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
0098 };
0099
0100
0101 void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
0102 {
0103 const unsigned long BYTE_MASK = 0xBF;
0104 const unsigned long BYTE_MARK = 0x80;
0105 const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
0106
0107 if (input < 0x80)
0108 *length = 1;
0109 else if ( input < 0x800 )
0110 *length = 2;
0111 else if ( input < 0x10000 )
0112 *length = 3;
0113 else if ( input < 0x200000 )
0114 *length = 4;
0115 else
0116 { *length = 0; return; }
0117
0118 output += *length;
0119
0120
0121 switch (*length)
0122 {
0123 case 4:
0124 --output;
0125 *output = (char)((input | BYTE_MARK) & BYTE_MASK);
0126 input >>= 6;
0127 [[fallthrough]];
0128 case 3:
0129 --output;
0130 *output = (char)((input | BYTE_MARK) & BYTE_MASK);
0131 input >>= 6;
0132 [[fallthrough]];
0133 case 2:
0134 --output;
0135 *output = (char)((input | BYTE_MARK) & BYTE_MASK);
0136 input >>= 6;
0137 [[fallthrough]];
0138 case 1:
0139 --output;
0140 *output = (char)(input | FIRST_BYTE_MARK[*length]);
0141 [[fallthrough]];
0142 default:
0143 break;
0144 }
0145 }
0146
0147
0148 int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding )
0149 {
0150
0151
0152
0153
0154
0155
0156
0157 if ( anyByte < 127 )
0158 return isalpha( anyByte );
0159 else
0160 return 1;
0161
0162
0163
0164
0165
0166 }
0167
0168
0169 int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding )
0170 {
0171
0172
0173
0174
0175
0176
0177
0178 if ( anyByte < 127 )
0179 return isalnum( anyByte );
0180 else
0181 return 1;
0182
0183
0184
0185
0186
0187 }
0188
0189
0190 class TiXmlParsingData
0191 {
0192 friend class TiXmlDocument;
0193 public:
0194 void Stamp( const char* now, TiXmlEncoding encoding );
0195
0196 const TiXmlCursor& Cursor() { return cursor; }
0197
0198 private:
0199
0200 TiXmlParsingData( const char* start, int _tabsize, int row, int col )
0201 {
0202 assert( start );
0203 stamp = start;
0204 tabsize = _tabsize;
0205 cursor.row = row;
0206 cursor.col = col;
0207 }
0208
0209 TiXmlCursor cursor;
0210 const char* stamp;
0211 int tabsize;
0212 };
0213
0214
0215 void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding )
0216 {
0217 assert( now );
0218
0219
0220 if ( tabsize < 1 )
0221 {
0222 return;
0223 }
0224
0225
0226 int row = cursor.row;
0227 int col = cursor.col;
0228 const char* p = stamp;
0229 assert( p );
0230
0231 while ( p < now )
0232 {
0233
0234 const unsigned char* pU = (const unsigned char*)p;
0235
0236
0237 switch (*pU) {
0238 case 0:
0239
0240
0241 return;
0242
0243 case '\r':
0244
0245 ++row;
0246 col = 0;
0247
0248 ++p;
0249
0250
0251 if (*p == '\n') {
0252 ++p;
0253 }
0254 break;
0255
0256 case '\n':
0257
0258 ++row;
0259 col = 0;
0260
0261
0262 ++p;
0263
0264
0265
0266
0267 if (*p == '\r') {
0268 ++p;
0269 }
0270 break;
0271
0272 case '\t':
0273
0274 ++p;
0275
0276
0277 col = (col / tabsize + 1) * tabsize;
0278 break;
0279
0280 case TIXML_UTF_LEAD_0:
0281 if ( encoding == TIXML_ENCODING_UTF8 )
0282 {
0283 if ( *(p+1) && *(p+2) )
0284 {
0285
0286
0287 if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 )
0288 p += 3;
0289 else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU )
0290 p += 3;
0291 else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU )
0292 p += 3;
0293 else
0294 { p +=3; ++col; }
0295 }
0296 }
0297 else
0298 {
0299 ++p;
0300 ++col;
0301 }
0302 break;
0303
0304 default:
0305 if ( encoding == TIXML_ENCODING_UTF8 )
0306 {
0307
0308 int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)];
0309 if ( step == 0 )
0310 step = 1;
0311 p += step;
0312
0313
0314 ++col;
0315 }
0316 else
0317 {
0318 ++p;
0319 ++col;
0320 }
0321 break;
0322 }
0323 }
0324 cursor.row = row;
0325 cursor.col = col;
0326 assert( cursor.row >= -1 );
0327 assert( cursor.col >= -1 );
0328 stamp = p;
0329 assert( stamp );
0330 }
0331
0332
0333 const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding )
0334 {
0335 if ( !p || !*p )
0336 {
0337 return 0;
0338 }
0339 if ( encoding == TIXML_ENCODING_UTF8 )
0340 {
0341 while ( *p )
0342 {
0343 const unsigned char* pU = (const unsigned char*)p;
0344
0345
0346 if ( *(pU+0)==TIXML_UTF_LEAD_0
0347 && *(pU+1)==TIXML_UTF_LEAD_1
0348 && *(pU+2)==TIXML_UTF_LEAD_2 )
0349 {
0350 p += 3;
0351 continue;
0352 }
0353 else if(*(pU+0)==TIXML_UTF_LEAD_0
0354 && *(pU+1)==0xbfU
0355 && *(pU+2)==0xbeU )
0356 {
0357 p += 3;
0358 continue;
0359 }
0360 else if(*(pU+0)==TIXML_UTF_LEAD_0
0361 && *(pU+1)==0xbfU
0362 && *(pU+2)==0xbfU )
0363 {
0364 p += 3;
0365 continue;
0366 }
0367
0368 if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' )
0369 ++p;
0370 else
0371 break;
0372 }
0373 }
0374 else
0375 {
0376 while ( ( *p && IsWhiteSpace( *p ) ) || *p == '\n' || *p =='\r' )
0377 ++p;
0378 }
0379
0380 return p;
0381 }
0382
0383 #ifdef TIXML_USE_STL
0384 bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag )
0385 {
0386 for( ;; )
0387 {
0388 if ( !in->good() ) return false;
0389
0390 int c = in->peek();
0391
0392 if ( !IsWhiteSpace( c ) || c <= 0 )
0393 return true;
0394
0395 *tag += (char) in->get();
0396 }
0397 }
0398
0399 bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag )
0400 {
0401
0402 while ( in->good() )
0403 {
0404 int c = in->peek();
0405 if ( c == character )
0406 return true;
0407 if ( c <= 0 )
0408 return false;
0409
0410 in->get();
0411 *tag += (char) c;
0412 }
0413 return false;
0414 }
0415 #endif
0416
0417
0418
0419
0420 const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding )
0421 {
0422
0423
0424
0425 *name = "";
0426 assert( p );
0427
0428
0429
0430
0431
0432
0433
0434
0435 if ( p && *p
0436 && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) )
0437 {
0438 const char* start = p;
0439 while( p && *p
0440 && ( IsAlphaNum( (unsigned char ) *p, encoding )
0441 || *p == '_'
0442 || *p == '-'
0443 || *p == '.'
0444 || *p == ':' ) )
0445 {
0446
0447 ++p;
0448 }
0449 if ( p-start > 0 ) {
0450 name->assign( start, p-start );
0451 }
0452 return p;
0453 }
0454 return 0;
0455 }
0456
0457 const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding )
0458 {
0459
0460 TIXML_STRING ent;
0461 int i;
0462 *length = 0;
0463
0464 if ( *(p+1) && *(p+1) == '#' && *(p+2) )
0465 {
0466 unsigned long ucs = 0;
0467 ptrdiff_t delta = 0;
0468 unsigned mult = 1;
0469
0470 if ( *(p+2) == 'x' )
0471 {
0472
0473 if ( !*(p+3) ) return 0;
0474
0475 const char* q = p+3;
0476 q = strchr( q, ';' );
0477
0478 if ( !q || !*q ) return 0;
0479
0480 delta = q-p;
0481 --q;
0482
0483 while ( *q != 'x' )
0484 {
0485 if ( *q >= '0' && *q <= '9' )
0486 ucs += mult * (*q - '0');
0487 else if ( *q >= 'a' && *q <= 'f' )
0488 ucs += mult * (*q - 'a' + 10);
0489 else if ( *q >= 'A' && *q <= 'F' )
0490 ucs += mult * (*q - 'A' + 10 );
0491 else
0492 return 0;
0493 mult *= 16;
0494 --q;
0495 }
0496 }
0497 else
0498 {
0499
0500 if ( !*(p+2) ) return 0;
0501
0502 const char* q = p+2;
0503 q = strchr( q, ';' );
0504
0505 if ( !q || !*q ) return 0;
0506
0507 delta = q-p;
0508 --q;
0509
0510 while ( *q != '#' )
0511 {
0512 if ( *q >= '0' && *q <= '9' )
0513 ucs += mult * (*q - '0');
0514 else
0515 return 0;
0516 mult *= 10;
0517 --q;
0518 }
0519 }
0520 if ( encoding == TIXML_ENCODING_UTF8 )
0521 {
0522
0523 ConvertUTF32ToUTF8( ucs, value, length );
0524 }
0525 else
0526 {
0527 *value = (char)ucs;
0528 *length = 1;
0529 }
0530 return p + delta + 1;
0531 }
0532
0533
0534 for( i=0; i<NUM_ENTITY; ++i )
0535 {
0536 if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 )
0537 {
0538 assert( strlen( entity[i].str ) == entity[i].strLength );
0539 *value = entity[i].chr;
0540 *length = 1;
0541 return ( p + entity[i].strLength );
0542 }
0543 }
0544
0545
0546 *value = *p;
0547
0548
0549 return p+1;
0550 }
0551
0552
0553 bool TiXmlBase::StringEqual( const char* p,
0554 const char* tag,
0555 bool ignoreCase,
0556 TiXmlEncoding encoding )
0557 {
0558 assert( p );
0559 assert( tag );
0560 if ( !p || !*p )
0561 {
0562 assert( 0 );
0563 return false;
0564 }
0565
0566 const char* q = p;
0567
0568 if ( ignoreCase )
0569 {
0570 while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) )
0571 {
0572 ++q;
0573 ++tag;
0574 }
0575
0576 if ( *tag == 0 )
0577 return true;
0578 }
0579 else
0580 {
0581 while ( *q && *tag && *q == *tag )
0582 {
0583 ++q;
0584 ++tag;
0585 }
0586
0587 if ( *tag == 0 )
0588 return true;
0589 }
0590 return false;
0591 }
0592
0593 const char* TiXmlBase::ReadText( const char* p,
0594 TIXML_STRING * text,
0595 bool trimWhiteSpace,
0596 const char* endTag,
0597 bool caseInsensitive,
0598 TiXmlEncoding encoding )
0599 {
0600 *text = "";
0601 if ( !trimWhiteSpace
0602 || !condenseWhiteSpace )
0603 {
0604
0605 while ( p && *p
0606 && !StringEqual( p, endTag, caseInsensitive, encoding )
0607 )
0608 {
0609 int len;
0610 char cArr[4] = { 0, 0, 0, 0 };
0611 p = GetChar( p, cArr, &len, encoding );
0612 text->append( cArr, len );
0613 }
0614 }
0615 else
0616 {
0617 bool whitespace = false;
0618
0619
0620 p = SkipWhiteSpace( p, encoding );
0621 while ( p && *p
0622 && !StringEqual( p, endTag, caseInsensitive, encoding ) )
0623 {
0624 if ( *p == '\r' || *p == '\n' )
0625 {
0626 whitespace = true;
0627 ++p;
0628 }
0629 else if ( IsWhiteSpace( *p ) )
0630 {
0631 whitespace = true;
0632 ++p;
0633 }
0634 else
0635 {
0636
0637
0638 if ( whitespace )
0639 {
0640 (*text) += ' ';
0641 whitespace = false;
0642 }
0643 int len;
0644 char cArr[4] = { 0, 0, 0, 0 };
0645 p = GetChar( p, cArr, &len, encoding );
0646 if ( len == 1 )
0647 (*text) += cArr[0];
0648 else
0649 text->append( cArr, len );
0650 }
0651 }
0652 }
0653 if ( p )
0654 p += strlen( endTag );
0655 return p;
0656 }
0657
0658 #ifdef TIXML_USE_STL
0659
0660 void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag )
0661 {
0662
0663
0664
0665
0666
0667
0668
0669 if ( !StreamTo( in, '<', tag ) )
0670 {
0671 SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
0672 return;
0673 }
0674
0675 while ( in->good() )
0676 {
0677 int tagIndex = (int) tag->length();
0678 while ( in->good() && in->peek() != '>' )
0679 {
0680 int c = in->get();
0681 if ( c <= 0 )
0682 {
0683 SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
0684 break;
0685 }
0686 (*tag) += (char) c;
0687 }
0688
0689 if ( in->good() )
0690 {
0691
0692
0693
0694 TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING );
0695
0696 if ( node )
0697 {
0698 node->StreamIn( in, tag );
0699 bool isElement = node->ToElement() != 0;
0700 delete node;
0701 node = 0;
0702
0703
0704
0705 if ( isElement )
0706 {
0707 return;
0708 }
0709 }
0710 else
0711 {
0712 SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
0713 return;
0714 }
0715 }
0716 }
0717
0718 SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
0719 }
0720
0721 #endif
0722
0723 const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding )
0724 {
0725 ClearError();
0726
0727
0728
0729
0730 if ( !p || !*p )
0731 {
0732 SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
0733 return 0;
0734 }
0735
0736
0737
0738
0739 location.Clear();
0740 if ( prevData )
0741 {
0742 location.row = prevData->cursor.row;
0743 location.col = prevData->cursor.col;
0744 }
0745 else
0746 {
0747 location.row = 0;
0748 location.col = 0;
0749 }
0750 TiXmlParsingData data( p, TabSize(), location.row, location.col );
0751 location = data.Cursor();
0752
0753 if ( encoding == TIXML_ENCODING_UNKNOWN )
0754 {
0755
0756 const unsigned char* pU = (const unsigned char*)p;
0757 if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0
0758 && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1
0759 && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 )
0760 {
0761 encoding = TIXML_ENCODING_UTF8;
0762 useMicrosoftBOM = true;
0763 }
0764 }
0765
0766 p = SkipWhiteSpace( p, encoding );
0767 if ( !p )
0768 {
0769 SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
0770 return 0;
0771 }
0772
0773 while ( p && *p )
0774 {
0775 TiXmlNode* node = Identify( p, encoding );
0776 if ( node )
0777 {
0778 p = node->Parse( p, &data, encoding );
0779 LinkEndChild( node );
0780 }
0781 else
0782 {
0783 break;
0784 }
0785
0786
0787 if ( encoding == TIXML_ENCODING_UNKNOWN
0788 && node->ToDeclaration() )
0789 {
0790 TiXmlDeclaration* dec = node->ToDeclaration();
0791 const char* enc = dec->Encoding();
0792 assert( enc );
0793
0794 if ( *enc == 0 )
0795 encoding = TIXML_ENCODING_UTF8;
0796 else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) )
0797 encoding = TIXML_ENCODING_UTF8;
0798 else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) )
0799 encoding = TIXML_ENCODING_UTF8;
0800 else
0801 encoding = TIXML_ENCODING_LEGACY;
0802 }
0803
0804 p = SkipWhiteSpace( p, encoding );
0805 }
0806
0807
0808 if ( !firstChild ) {
0809 SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding );
0810 return 0;
0811 }
0812
0813
0814 return p;
0815 }
0816
0817 void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding )
0818 {
0819
0820 if ( error )
0821 return;
0822
0823 assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
0824 error = true;
0825 errorId = err;
0826 errorDesc = errorString[ errorId ];
0827
0828 errorLocation.Clear();
0829 if ( pError && data )
0830 {
0831 data->Stamp( pError, encoding );
0832 errorLocation = data->Cursor();
0833 }
0834 }
0835
0836
0837 TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding )
0838 {
0839 TiXmlNode* returnNode = 0;
0840
0841 p = SkipWhiteSpace( p, encoding );
0842 if( !p || !*p || *p != '<' )
0843 {
0844 return 0;
0845 }
0846
0847 TiXmlDocument* doc = GetDocument();
0848 p = SkipWhiteSpace( p, encoding );
0849
0850 if ( !p || !*p )
0851 {
0852 return 0;
0853 }
0854
0855
0856
0857
0858
0859
0860
0861
0862 const char* xmlHeader = { "<?xml" };
0863 const char* commentHeader = { "<!--" };
0864 const char* dtdHeader = { "<!" };
0865 const char* cdataHeader = { "<![CDATA[" };
0866
0867 if ( StringEqual( p, xmlHeader, true, encoding ) )
0868 {
0869 #ifdef DEBUG_PARSER
0870 TIXML_LOG( "XML parsing Declaration\n" );
0871 #endif
0872 returnNode = new TiXmlDeclaration();
0873 }
0874 else if ( StringEqual( p, commentHeader, false, encoding ) )
0875 {
0876 #ifdef DEBUG_PARSER
0877 TIXML_LOG( "XML parsing Comment\n" );
0878 #endif
0879 returnNode = new TiXmlComment();
0880 }
0881 else if ( StringEqual( p, cdataHeader, false, encoding ) )
0882 {
0883 #ifdef DEBUG_PARSER
0884 TIXML_LOG( "XML parsing CDATA\n" );
0885 #endif
0886 TiXmlText* text = new TiXmlText( "" );
0887 text->SetCDATA( true );
0888 returnNode = text;
0889 }
0890 else if ( StringEqual( p, dtdHeader, false, encoding ) )
0891 {
0892 #ifdef DEBUG_PARSER
0893 TIXML_LOG( "XML parsing Unknown(1)\n" );
0894 #endif
0895 returnNode = new TiXmlUnknown();
0896 }
0897 else if ( IsAlpha( *(p+1), encoding )
0898 || *(p+1) == '_' )
0899 {
0900 #ifdef DEBUG_PARSER
0901 TIXML_LOG( "XML parsing Element\n" );
0902 #endif
0903 returnNode = new TiXmlElement( "" );
0904 }
0905 else
0906 {
0907 #ifdef DEBUG_PARSER
0908 TIXML_LOG( "XML parsing Unknown(2)\n" );
0909 #endif
0910 returnNode = new TiXmlUnknown();
0911 }
0912
0913 if ( returnNode )
0914 {
0915
0916 returnNode->parent = this;
0917 }
0918 else
0919 {
0920 if ( doc )
0921 doc->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
0922 }
0923 return returnNode;
0924 }
0925
0926 #ifdef TIXML_USE_STL
0927
0928 void TiXmlElement::StreamIn (std::istream * in, TIXML_STRING * tag)
0929 {
0930
0931
0932 while( in->good() )
0933 {
0934 int c = in->get();
0935 if ( c <= 0 )
0936 {
0937 TiXmlDocument* document = GetDocument();
0938 if ( document )
0939 document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
0940 return;
0941 }
0942 (*tag) += (char) c ;
0943
0944 if ( c == '>' )
0945 break;
0946 }
0947
0948 if ( tag->length() < 3 ) return;
0949
0950
0951
0952
0953 if ( tag->at( tag->length() - 1 ) == '>'
0954 && tag->at( tag->length() - 2 ) == '/' )
0955 {
0956
0957 return;
0958 }
0959 else if ( tag->at( tag->length() - 1 ) == '>' )
0960 {
0961
0962
0963
0964
0965
0966 for ( ;; )
0967 {
0968 StreamWhiteSpace( in, tag );
0969
0970
0971 if ( in->good() && in->peek() != '<' )
0972 {
0973
0974 TiXmlText text( "" );
0975 text.StreamIn( in, tag );
0976
0977
0978
0979 continue;
0980 }
0981
0982
0983
0984 if ( !in->good() ) return;
0985 assert( in->peek() == '<' );
0986 int tagIndex = (int) tag->length();
0987
0988 bool closingTag = false;
0989 bool firstCharFound = false;
0990
0991 for( ;; )
0992 {
0993 if ( !in->good() )
0994 return;
0995
0996 int c = in->peek();
0997 if ( c <= 0 )
0998 {
0999 TiXmlDocument* document = GetDocument();
1000 if ( document )
1001 document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
1002 return;
1003 }
1004
1005 if ( c == '>' )
1006 break;
1007
1008 *tag += (char) c;
1009 in->get();
1010
1011
1012 if ( c == '[' && tag->size() >= 9 )
1013 {
1014 size_t len = tag->size();
1015 const char* start = tag->c_str() + len - 9;
1016 if ( strcmp( start, "<![CDATA[" ) == 0 ) {
1017 assert( !closingTag );
1018 break;
1019 }
1020 }
1021
1022 if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) )
1023 {
1024 firstCharFound = true;
1025 if ( c == '/' )
1026 closingTag = true;
1027 }
1028 }
1029
1030
1031 if ( closingTag )
1032 {
1033 if ( !in->good() )
1034 return;
1035
1036 int c = in->get();
1037 if ( c <= 0 )
1038 {
1039 TiXmlDocument* document = GetDocument();
1040 if ( document )
1041 document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
1042 return;
1043 }
1044 assert( c == '>' );
1045 *tag += (char) c;
1046
1047
1048 return;
1049 }
1050 else
1051 {
1052
1053 const char* tagloc = tag->c_str() + tagIndex;
1054 TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING );
1055 if ( !node )
1056 return;
1057 node->StreamIn( in, tag );
1058 delete node;
1059 node = 0;
1060
1061
1062 }
1063 }
1064 }
1065 }
1066 #endif
1067
1068 const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1069 {
1070 p = SkipWhiteSpace( p, encoding );
1071 TiXmlDocument* document = GetDocument();
1072
1073 if ( !p || !*p )
1074 {
1075 if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding );
1076 return 0;
1077 }
1078
1079 if ( data )
1080 {
1081 data->Stamp( p, encoding );
1082 location = data->Cursor();
1083 }
1084
1085 if ( *p != '<' )
1086 {
1087 if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding );
1088 return 0;
1089 }
1090
1091 p = SkipWhiteSpace( p+1, encoding );
1092
1093
1094 const char* pErr = p;
1095
1096 p = ReadName( p, &value, encoding );
1097 if ( !p || !*p )
1098 {
1099 if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding );
1100 return 0;
1101 }
1102
1103 TIXML_STRING endTag ("</");
1104 endTag += value;
1105 endTag += ">";
1106
1107
1108
1109 while ( p && *p )
1110 {
1111 pErr = p;
1112 p = SkipWhiteSpace( p, encoding );
1113 if ( !p || !*p )
1114 {
1115 if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
1116 return 0;
1117 }
1118 if ( *p == '/' )
1119 {
1120 ++p;
1121
1122 if ( *p != '>' )
1123 {
1124 if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding );
1125 return 0;
1126 }
1127 return (p+1);
1128 }
1129 else if ( *p == '>' )
1130 {
1131
1132
1133
1134 ++p;
1135 p = ReadValue( p, data, encoding );
1136 if ( !p || !*p )
1137 return 0;
1138
1139
1140 if ( StringEqual( p, endTag.c_str(), false, encoding ) )
1141 {
1142 p += endTag.length();
1143 return p;
1144 }
1145 else
1146 {
1147 if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
1148 return 0;
1149 }
1150 }
1151 else
1152 {
1153
1154 TiXmlAttribute* attrib = new TiXmlAttribute();
1155 if ( !attrib )
1156 {
1157 if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, pErr, data, encoding );
1158 return 0;
1159 }
1160
1161 attrib->SetDocument( document );
1162 pErr = p;
1163 p = attrib->Parse( p, data, encoding );
1164
1165 if ( !p || !*p )
1166 {
1167 if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
1168 delete attrib;
1169 return 0;
1170 }
1171
1172
1173 #ifdef TIXML_USE_STL
1174 TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() );
1175 #else
1176 TiXmlAttribute* node = attributeSet.Find( attrib->Name() );
1177 #endif
1178 if ( node )
1179 {
1180 node->SetValue( attrib->Value() );
1181 delete attrib;
1182 return 0;
1183 }
1184
1185 attributeSet.Add( attrib );
1186 }
1187 }
1188 return p;
1189 }
1190
1191
1192 const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1193 {
1194 TiXmlDocument* document = GetDocument();
1195
1196
1197 const char* pWithWhiteSpace = p;
1198 p = SkipWhiteSpace( p, encoding );
1199
1200 while ( p && *p )
1201 {
1202 if ( *p != '<' )
1203 {
1204
1205 TiXmlText* textNode = new TiXmlText( "" );
1206
1207 if ( !textNode )
1208 {
1209 if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, encoding );
1210 return 0;
1211 }
1212
1213 if ( TiXmlBase::IsWhiteSpaceCondensed() )
1214 {
1215 p = textNode->Parse( p, data, encoding );
1216 }
1217 else
1218 {
1219
1220
1221 p = textNode->Parse( pWithWhiteSpace, data, encoding );
1222 }
1223
1224 if ( !textNode->Blank() )
1225 LinkEndChild( textNode );
1226 else
1227 delete textNode;
1228 }
1229 else
1230 {
1231
1232
1233
1234 if ( StringEqual( p, "</", false, encoding ) )
1235 {
1236 return p;
1237 }
1238 else
1239 {
1240 TiXmlNode* node = Identify( p, encoding );
1241 if ( node )
1242 {
1243 p = node->Parse( p, data, encoding );
1244 LinkEndChild( node );
1245 }
1246 else
1247 {
1248 return 0;
1249 }
1250 }
1251 }
1252 pWithWhiteSpace = p;
1253 p = SkipWhiteSpace( p, encoding );
1254 }
1255
1256 if ( !p )
1257 {
1258 if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding );
1259 }
1260 return p;
1261 }
1262
1263
1264 #ifdef TIXML_USE_STL
1265 void TiXmlUnknown::StreamIn( std::istream * in, TIXML_STRING * tag )
1266 {
1267 while ( in->good() )
1268 {
1269 int c = in->get();
1270 if ( c <= 0 )
1271 {
1272 TiXmlDocument* document = GetDocument();
1273 if ( document )
1274 document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
1275 return;
1276 }
1277 (*tag) += (char) c;
1278
1279 if ( c == '>' )
1280 {
1281
1282 return;
1283 }
1284 }
1285 }
1286 #endif
1287
1288
1289 const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1290 {
1291 TiXmlDocument* document = GetDocument();
1292 p = SkipWhiteSpace( p, encoding );
1293
1294 if ( data )
1295 {
1296 data->Stamp( p, encoding );
1297 location = data->Cursor();
1298 }
1299 if ( !p || !*p || *p != '<' )
1300 {
1301 if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding );
1302 return 0;
1303 }
1304 ++p;
1305 value = "";
1306
1307 while ( p && *p && *p != '>' )
1308 {
1309 value += *p;
1310 ++p;
1311 }
1312
1313 if ( !p )
1314 {
1315 if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
1316 }
1317 if ( *p == '>' )
1318 return p+1;
1319 return p;
1320 }
1321
1322 #ifdef TIXML_USE_STL
1323 void TiXmlComment::StreamIn( std::istream * in, TIXML_STRING * tag )
1324 {
1325 while ( in->good() )
1326 {
1327 int c = in->get();
1328 if ( c <= 0 )
1329 {
1330 TiXmlDocument* document = GetDocument();
1331 if ( document )
1332 document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
1333 return;
1334 }
1335
1336 (*tag) += (char) c;
1337
1338 if ( c == '>'
1339 && tag->at( tag->length() - 2 ) == '-'
1340 && tag->at( tag->length() - 3 ) == '-' )
1341 {
1342
1343 return;
1344 }
1345 }
1346 }
1347 #endif
1348
1349
1350 const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1351 {
1352 TiXmlDocument* document = GetDocument();
1353 value = "";
1354
1355 p = SkipWhiteSpace( p, encoding );
1356
1357 if ( data )
1358 {
1359 data->Stamp( p, encoding );
1360 location = data->Cursor();
1361 }
1362 const char* startTag = "<!--";
1363 const char* endTag = "-->";
1364
1365 if ( !StringEqual( p, startTag, false, encoding ) )
1366 {
1367 document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding );
1368 return 0;
1369 }
1370 p += strlen( startTag );
1371 p = ReadText( p, &value, false, endTag, false, encoding );
1372 return p;
1373 }
1374
1375
1376 const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1377 {
1378 p = SkipWhiteSpace( p, encoding );
1379 if ( !p || !*p ) return 0;
1380
1381
1382
1383
1384
1385 if ( data )
1386 {
1387 data->Stamp( p, encoding );
1388 location = data->Cursor();
1389 }
1390
1391 const char* pErr = p;
1392 p = ReadName( p, &name, encoding );
1393 if ( !p || !*p )
1394 {
1395 if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
1396 return 0;
1397 }
1398 p = SkipWhiteSpace( p, encoding );
1399 if ( !p || !*p || *p != '=' )
1400 {
1401 if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
1402 return 0;
1403 }
1404
1405 ++p;
1406 p = SkipWhiteSpace( p, encoding );
1407 if ( !p || !*p )
1408 {
1409 if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
1410 return 0;
1411 }
1412
1413 const char* end;
1414 const char SINGLE_QUOTE = '\'';
1415 const char DOUBLE_QUOTE = '\"';
1416
1417 if ( *p == SINGLE_QUOTE )
1418 {
1419 ++p;
1420 end = "\'";
1421 p = ReadText( p, &value, false, end, false, encoding );
1422 }
1423 else if ( *p == DOUBLE_QUOTE )
1424 {
1425 ++p;
1426 end = "\"";
1427 p = ReadText( p, &value, false, end, false, encoding );
1428 }
1429 else
1430 {
1431
1432
1433
1434 value = "";
1435 while ( p && *p
1436 && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r'
1437 && *p != '/' && *p != '>' )
1438 {
1439 if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) {
1440
1441
1442
1443 if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
1444 return 0;
1445 }
1446 value += *p;
1447 ++p;
1448 }
1449 }
1450 return p;
1451 }
1452
1453 #ifdef TIXML_USE_STL
1454 void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag )
1455 {
1456 while ( in->good() )
1457 {
1458 int c = in->peek();
1459 if ( !cdata && (c == '<' ) )
1460 {
1461 return;
1462 }
1463 if ( c <= 0 )
1464 {
1465 TiXmlDocument* document = GetDocument();
1466 if ( document )
1467 document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
1468 return;
1469 }
1470
1471 (*tag) += (char) c;
1472 in->get();
1473
1474 if ( cdata && c == '>' && tag->size() >= 3 ) {
1475 size_t len = tag->size();
1476 if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) {
1477
1478 return;
1479 }
1480 }
1481 }
1482 }
1483 #endif
1484
1485 const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1486 {
1487 value = "";
1488 TiXmlDocument* document = GetDocument();
1489
1490 if ( data )
1491 {
1492 data->Stamp( p, encoding );
1493 location = data->Cursor();
1494 }
1495
1496 const char* const startTag = "<![CDATA[";
1497 const char* const endTag = "]]>";
1498
1499 if ( cdata || StringEqual( p, startTag, false, encoding ) )
1500 {
1501 cdata = true;
1502
1503 if ( !StringEqual( p, startTag, false, encoding ) )
1504 {
1505 document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding );
1506 return 0;
1507 }
1508 p += strlen( startTag );
1509
1510
1511 while ( p && *p
1512 && !StringEqual( p, endTag, false, encoding )
1513 )
1514 {
1515 value += *p;
1516 ++p;
1517 }
1518
1519 TIXML_STRING dummy;
1520 p = ReadText( p, &dummy, false, endTag, false, encoding );
1521 return p;
1522 }
1523 else
1524 {
1525 bool ignoreWhite = true;
1526
1527 const char* end = "<";
1528 p = ReadText( p, &value, ignoreWhite, end, false, encoding );
1529 if ( p )
1530 return p-1;
1531 return 0;
1532 }
1533 }
1534
1535 #ifdef TIXML_USE_STL
1536 void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag )
1537 {
1538 while ( in->good() )
1539 {
1540 int c = in->get();
1541 if ( c <= 0 )
1542 {
1543 TiXmlDocument* document = GetDocument();
1544 if ( document )
1545 document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
1546 return;
1547 }
1548 (*tag) += (char) c;
1549
1550 if ( c == '>' )
1551 {
1552
1553 return;
1554 }
1555 }
1556 }
1557 #endif
1558
1559 const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding )
1560 {
1561 p = SkipWhiteSpace( p, _encoding );
1562
1563
1564 TiXmlDocument* document = GetDocument();
1565 if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) )
1566 {
1567 if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding );
1568 return 0;
1569 }
1570 if ( data )
1571 {
1572 data->Stamp( p, _encoding );
1573 location = data->Cursor();
1574 }
1575 p += 5;
1576
1577 version = "";
1578 encoding = "";
1579 standalone = "";
1580
1581 while ( p && *p )
1582 {
1583 if ( *p == '>' )
1584 {
1585 ++p;
1586 return p;
1587 }
1588
1589 p = SkipWhiteSpace( p, _encoding );
1590 if ( StringEqual( p, "version", true, _encoding ) )
1591 {
1592 TiXmlAttribute attrib;
1593 p = attrib.Parse( p, data, _encoding );
1594 version = attrib.Value();
1595 }
1596 else if ( StringEqual( p, "encoding", true, _encoding ) )
1597 {
1598 TiXmlAttribute attrib;
1599 p = attrib.Parse( p, data, _encoding );
1600 encoding = attrib.Value();
1601 }
1602 else if ( StringEqual( p, "standalone", true, _encoding ) )
1603 {
1604 TiXmlAttribute attrib;
1605 p = attrib.Parse( p, data, _encoding );
1606 standalone = attrib.Value();
1607 }
1608 else
1609 {
1610
1611 while( p && *p && *p != '>' && !IsWhiteSpace( *p ) )
1612 ++p;
1613 }
1614 }
1615 return 0;
1616 }
1617
1618 bool TiXmlText::Blank() const
1619 {
1620 for ( unsigned i=0; i<value.length(); i++ )
1621 if ( !IsWhiteSpace( value[i] ) )
1622 return false;
1623 return true;
1624 }
1625
1626
1627 #endif