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 "stdafx.h"
00026
#include "tinyxml.h"
00027
#include <ctype.h>
00028
00029
00030
00031
00032
00033
00034 TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] =
00035 {
00036 {
"&", 5,
'&' },
00037 {
"<", 4,
'<' },
00038 {
">", 4,
'>' },
00039 {
""", 6,
'\"' },
00040 {
"'", 6,
'\'' }
00041 };
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
const int TiXmlBase::utf8ByteTable[256] =
00056 {
00057
00058 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00059 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00060 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00061 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00062 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00063 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00064 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00065 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00066 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00067 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00068 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00069 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00070 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
00071 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
00072 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
00073 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
00074 };
00075
00076
00077
void TiXmlBase::ConvertUTF32ToUTF8(
unsigned long input,
char* output,
int* length )
00078 {
00079
const unsigned long BYTE_MASK = 0xBF;
00080
const unsigned long BYTE_MARK = 0x80;
00081
const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
00082
00083
if (input < 0x80)
00084 *length = 1;
00085
else if ( input < 0x800 )
00086 *length = 2;
00087
else if ( input < 0x10000 )
00088 *length = 3;
00089
else if ( input < 0x200000 )
00090 *length = 4;
00091
else
00092 { *length = 0;
return; }
00093
00094 output += *length;
00095
00096
00097
switch (*length)
00098 {
00099
case 4:
00100 --output;
00101 *output = (
char)((input | BYTE_MARK) & BYTE_MASK);
00102 input >>= 6;
00103
case 3:
00104 --output;
00105 *output = (
char)((input | BYTE_MARK) & BYTE_MASK);
00106 input >>= 6;
00107
case 2:
00108 --output;
00109 *output = (
char)((input | BYTE_MARK) & BYTE_MASK);
00110 input >>= 6;
00111
case 1:
00112 --output;
00113 *output = (
char)(input | FIRST_BYTE_MARK[*length]);
00114 }
00115 }
00116
00117
00118
int TiXmlBase::IsAlpha(
unsigned char anyByte, TiXmlEncoding encoding )
00119 {
00120
00121
00122
00123
00124
00125
00126
00127
if ( anyByte < 127 )
00128
return isalpha( anyByte );
00129
else
00130
return 1;
00131
00132
00133
00134
00135
00136 }
00137
00138
00139
int TiXmlBase::IsAlphaNum(
unsigned char anyByte, TiXmlEncoding encoding )
00140 {
00141
00142
00143
00144
00145
00146
00147
00148
if ( anyByte < 127 )
00149
return isalnum( anyByte );
00150
else
00151
return 1;
00152
00153
00154
00155
00156
00157 }
00158
00159
00160
class TiXmlParsingData
00161 {
00162
friend class TiXmlDocument;
00163
public:
00164
void Stamp(
const char* now, TiXmlEncoding encoding );
00165
00166
const TiXmlCursor& Cursor() {
return cursor; }
00167
00168
private:
00169
00170 TiXmlParsingData(
const char* start,
int _tabsize,
int row,
int col )
00171 {
00172 assert( start );
00173 stamp = start;
00174 tabsize = _tabsize;
00175 cursor.row = row;
00176 cursor.col = col;
00177 }
00178
00179 TiXmlCursor cursor;
00180
const char* stamp;
00181
int tabsize;
00182 };
00183
00184
00185
void TiXmlParsingData::Stamp(
const char* now, TiXmlEncoding encoding )
00186 {
00187 assert( now );
00188
00189
00190
if ( tabsize < 1 )
00191 {
00192
return;
00193 }
00194
00195
00196
int row = cursor.row;
00197
int col = cursor.col;
00198
const char* p = stamp;
00199 assert( p );
00200
00201
while ( p < now )
00202 {
00203
00204
switch (*p) {
00205
case 0:
00206
00207
00208
return;
00209
00210
case '\r':
00211
00212 ++row;
00213 col = 0;
00214
00215 ++p;
00216
00217
00218
if (*p ==
'\n') {
00219 ++p;
00220 }
00221
break;
00222
00223
case '\n':
00224
00225 ++row;
00226 col = 0;
00227
00228
00229 ++p;
00230
00231
00232
00233
00234
if (*p ==
'\r') {
00235 ++p;
00236 }
00237
break;
00238
00239
case '\t':
00240
00241 ++p;
00242
00243
00244 col = (col / tabsize + 1) * tabsize;
00245
break;
00246
00247
case (
char)(0xef):
00248
if ( encoding == TIXML_ENCODING_UTF8 )
00249 {
00250
if ( *(p+1) && *(p+2) )
00251 {
00252
00253
00254
if ( *(p+1)==(
char)(0xbb) && *(p+2)==(
char)(0xbf) )
00255 p += 3;
00256
else if ( *(p+1)==(
char)(0xbf) && *(p+2)==(
char)(0xbe) )
00257 p += 3;
00258
else if ( *(p+1)==(
char)(0xbf) && *(p+2)==(
char)(0xbf) )
00259 p += 3;
00260
else
00261 { p +=3; ++col; }
00262 }
00263 }
00264
else
00265 {
00266 ++p;
00267 ++col;
00268 }
00269
break;
00270
00271
default:
00272
if ( encoding == TIXML_ENCODING_UTF8 )
00273 {
00274
00275
int step = TiXmlBase::utf8ByteTable[*((
unsigned char*)p)];
00276
if ( step == 0 )
00277 step = 1;
00278 p += step;
00279
00280
00281 ++col;
00282 }
00283
else
00284 {
00285 ++p;
00286 ++col;
00287 }
00288
break;
00289 }
00290 }
00291 cursor.row = row;
00292 cursor.col = col;
00293 assert( cursor.row >= -1 );
00294 assert( cursor.col >= -1 );
00295 stamp = p;
00296 assert( stamp );
00297 }
00298
00299
00300
const char* TiXmlBase::SkipWhiteSpace(
const char* p, TiXmlEncoding encoding )
00301 {
00302
if ( !p || !*p )
00303 {
00304
return 0;
00305 }
00306
if ( encoding == TIXML_ENCODING_UTF8 )
00307 {
00308
while ( *p )
00309 {
00310
00311
if ( *(p+0)==(
char) 0xef
00312 && *(p+1)==(
char) 0xbb
00313 && *(p+2)==(
char) 0xbf )
00314 {
00315 p += 3;
00316
continue;
00317 }
00318
else if(*(p+0)==(
char) 0xef
00319 && *(p+1)==(
char) 0xbf
00320 && *(p+2)==(
char) 0xbe )
00321 {
00322 p += 3;
00323
continue;
00324 }
00325
else if(*(p+0)==(
char) 0xef
00326 && *(p+1)==(
char) 0xbf
00327 && *(p+2)==(
char) 0xbf )
00328 {
00329 p += 3;
00330
continue;
00331 }
00332
00333
if ( IsWhiteSpace( *p ) || *p ==
'\n' || *p ==
'\r' )
00334 ++p;
00335
else
00336
break;
00337 }
00338 }
00339
else
00340 {
00341
while ( *p && IsWhiteSpace( *p ) || *p ==
'\n' || *p ==
'\r' )
00342 ++p;
00343 }
00344
00345
return p;
00346 }
00347
00348
#ifdef TIXML_USE_STL
00349
bool TiXmlBase::StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag )
00350 {
00351
for( ;; )
00352 {
00353
if ( !in->good() )
return false;
00354
00355
int c = in->peek();
00356
00357
if ( !IsWhiteSpace( c ) || c <= 0 )
00358
return true;
00359
00360 *tag += (
char) in->get();
00361 }
00362 }
00363
00364
bool TiXmlBase::StreamTo( TIXML_ISTREAM * in,
int character, TIXML_STRING * tag )
00365 {
00366
00367
while ( in->good() )
00368 {
00369
int c = in->peek();
00370
if ( c == character )
00371
return true;
00372
if ( c <= 0 )
00373
return false;
00374
00375 in->get();
00376 *tag += (
char) c;
00377 }
00378
return false;
00379 }
00380
#endif
00381
00382
const char* TiXmlBase::ReadName(
const char* p, TIXML_STRING * name, TiXmlEncoding encoding )
00383 {
00384 *name =
"";
00385 assert( p );
00386
00387
00388
00389
00390
00391
00392
00393
00394
if ( p && *p
00395 && ( IsAlpha( (
unsigned char) *p, encoding ) || *p ==
'_' ) )
00396 {
00397
while( p && *p
00398 && ( IsAlphaNum( (
unsigned char ) *p, encoding )
00399 || *p ==
'_'
00400 || *p ==
'-'
00401 || *p ==
'.'
00402 || *p ==
':' ) )
00403 {
00404 (*name) += *p;
00405 ++p;
00406 }
00407
return p;
00408 }
00409
return 0;
00410 }
00411
00412
const char* TiXmlBase::GetEntity(
const char* p,
char* value,
int* length, TiXmlEncoding encoding )
00413 {
00414
00415 TIXML_STRING ent;
00416
int i;
00417 *length = 0;
00418
00419
if ( *(p+1) && *(p+1) ==
'#' && *(p+2) )
00420 {
00421
unsigned long ucs = 0;
00422
unsigned delta = 0;
00423
unsigned mult = 1;
00424
00425
if ( *(p+2) ==
'x' )
00426 {
00427
00428
if ( !*(p+3) )
return 0;
00429
00430
const char* q = p+3;
00431 q = strchr( q,
';' );
00432
00433
if ( !q || !*q )
return 0;
00434
00435 delta = q-p;
00436 --q;
00437
00438
while ( *q !=
'x' )
00439 {
00440
if ( *q >=
'0' && *q <=
'9' )
00441 ucs += mult * (*q -
'0');
00442
else if ( *q >=
'a' && *q <=
'f' )
00443 ucs += mult * (*q -
'a' + 10);
00444
else if ( *q >=
'A' && *q <=
'F' )
00445 ucs += mult * (*q -
'A' + 10 );
00446
else
00447
return 0;
00448 mult *= 16;
00449 --q;
00450 }
00451 }
00452
else
00453 {
00454
00455
if ( !*(p+2) )
return 0;
00456
00457
const char* q = p+2;
00458 q = strchr( q,
';' );
00459
00460
if ( !q || !*q )
return 0;
00461
00462 delta = q-p;
00463 --q;
00464
00465
while ( *q !=
'#' )
00466 {
00467
if ( *q >=
'0' && *q <=
'9' )
00468 ucs += mult * (*q -
'0');
00469
else
00470
return 0;
00471 mult *= 10;
00472 --q;
00473 }
00474 }
00475
if ( encoding == TIXML_ENCODING_UTF8 )
00476 {
00477
00478 ConvertUTF32ToUTF8( ucs, value, length );
00479 }
00480
else
00481 {
00482 *value = (
char)ucs;
00483 *length = 1;
00484 }
00485
return p + delta + 1;
00486 }
00487
00488
00489
for( i=0; i<NUM_ENTITY; ++i )
00490 {
00491
if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 )
00492 {
00493 assert( strlen( entity[i].str ) == entity[i].strLength );
00494 *value = entity[i].chr;
00495 *length = 1;
00496
return ( p + entity[i].strLength );
00497 }
00498 }
00499
00500
00501 *value = *p;
00502
return p+1;
00503 }
00504
00505
00506
bool TiXmlBase::StringEqual(
const char* p,
00507
const char* tag,
00508
bool ignoreCase,
00509 TiXmlEncoding encoding )
00510 {
00511 assert( p );
00512 assert( tag );
00513
if ( !p || !*p )
00514 {
00515 assert( 0 );
00516
return false;
00517 }
00518
00519
const char* q = p;
00520
00521
if ( ignoreCase )
00522 {
00523
while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) )
00524 {
00525 ++q;
00526 ++tag;
00527 }
00528
00529
if ( *tag == 0 )
00530
return true;
00531 }
00532
else
00533 {
00534
while ( *q && *tag && *q == *tag )
00535 {
00536 ++q;
00537 ++tag;
00538 }
00539
00540
if ( *tag == 0 )
00541
return true;
00542 }
00543
return false;
00544 }
00545
00546
const char* TiXmlBase::ReadText(
const char* p,
00547 TIXML_STRING * text,
00548
bool trimWhiteSpace,
00549
const char* endTag,
00550
bool caseInsensitive,
00551 TiXmlEncoding encoding )
00552 {
00553 *text =
"";
00554
if ( !trimWhiteSpace
00555 || !condenseWhiteSpace )
00556 {
00557
00558
while ( p && *p
00559 && !StringEqual( p, endTag, caseInsensitive, encoding )
00560 )
00561 {
00562
int len;
00563
char cArr[4] = { 0, 0, 0, 0 };
00564 p = GetChar( p, cArr, &len, encoding );
00565 text->Append( cArr, len );
00566 }
00567 }
00568
else
00569 {
00570
bool whitespace =
false;
00571
00572
00573 p = SkipWhiteSpace( p, encoding );
00574
while ( p && *p
00575 && !StringEqual( p, endTag, caseInsensitive, encoding ) )
00576 {
00577
if ( *p ==
'\r' || *p ==
'\n' )
00578 {
00579 whitespace =
true;
00580 ++p;
00581 }
00582
else if ( IsWhiteSpace( *p ) )
00583 {
00584 whitespace =
true;
00585 ++p;
00586 }
00587
else
00588 {
00589
00590
00591
if ( whitespace )
00592 {
00593 (*text) +=
' ';
00594 whitespace =
false;
00595 }
00596
int len;
00597
char cArr[4] = { 0, 0, 0, 0 };
00598 p = GetChar( p, cArr, &len, encoding );
00599
if ( len == 1 )
00600 (*text) += cArr[0];
00601
else
00602 text->Append( cArr, len );
00603 }
00604 }
00605 }
00606
return p + strlen( endTag );
00607 }
00608
00609
#ifdef TIXML_USE_STL
00610
00611
void TiXmlDocument::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
00612 {
00613
00614
00615
00616
00617
00618
00619
00620
if ( !StreamTo( in,
'<', tag ) )
00621 {
00622 SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
00623
return;
00624 }
00625
00626
while ( in->good() )
00627 {
00628
int tagIndex = (
int) tag->length();
00629
while ( in->good() && in->peek() !=
'>' )
00630 {
00631
int c = in->get();
00632
if ( c <= 0 )
00633 {
00634 SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
00635
break;
00636 }
00637 (*tag) += (
char) c;
00638 }
00639
00640
if ( in->good() )
00641 {
00642
00643
00644
00645
TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING );
00646
00647
if ( node )
00648 {
00649 node->StreamIn( in, tag );
00650
bool isElement = node->
ToElement() != 0;
00651
delete node;
00652 node = 0;
00653
00654
00655
00656
if ( isElement )
00657 {
00658
return;
00659 }
00660 }
00661
else
00662 {
00663 SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
00664
return;
00665 }
00666 }
00667 }
00668
00669 SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
00670 }
00671
00672
#endif
00673
00674 const char*
TiXmlDocument::Parse(
const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding )
00675 {
00676
ClearError();
00677
00678
00679
00680
00681
if ( !p || !*p )
00682 {
00683 SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
00684
return 0;
00685 }
00686
00687
00688
00689
00690 location.Clear();
00691
if ( prevData )
00692 {
00693 location.row = prevData->cursor.row;
00694 location.col = prevData->cursor.col;
00695 }
00696
else
00697 {
00698 location.row = 0;
00699 location.col = 0;
00700 }
00701 TiXmlParsingData data( p, TabSize(), location.row, location.col );
00702 location = data.Cursor();
00703
00704
if ( encoding == TIXML_ENCODING_UNKNOWN )
00705 {
00706
00707
if ( *(p+0) && *(p+0) == (
char)(0xef)
00708 && *(p+1) && *(p+1) == (
char)(0xbb)
00709 && *(p+2) && *(p+2) == (
char)(0xbf) )
00710 {
00711 encoding = TIXML_ENCODING_UTF8;
00712 }
00713 }
00714
00715 p = SkipWhiteSpace( p, encoding );
00716
if ( !p )
00717 {
00718 SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
00719
return 0;
00720 }
00721
00722
while ( p && *p )
00723 {
00724
TiXmlNode* node = Identify( p, encoding );
00725
if ( node )
00726 {
00727 p = node->
Parse( p, &data, encoding );
00728
LinkEndChild( node );
00729 }
00730
else
00731 {
00732
break;
00733 }
00734
00735
00736
if ( encoding == TIXML_ENCODING_UNKNOWN
00737 && node->
ToDeclaration() )
00738 {
00739
TiXmlDeclaration* dec = node->
ToDeclaration();
00740
const char* enc = dec->
Encoding();
00741 assert( enc );
00742
00743
if ( *enc == 0 )
00744 encoding = TIXML_ENCODING_UTF8;
00745
else if ( StringEqual( enc,
"UTF-8",
true, TIXML_ENCODING_UNKNOWN ) )
00746 encoding = TIXML_ENCODING_UTF8;
00747
else if ( StringEqual( enc,
"UTF8",
true, TIXML_ENCODING_UNKNOWN ) )
00748 encoding = TIXML_ENCODING_UTF8;
00749
else
00750 encoding = TIXML_ENCODING_LEGACY;
00751 }
00752
00753 p = SkipWhiteSpace( p, encoding );
00754 }
00755
00756
00757
return p;
00758 }
00759
00760
void TiXmlDocument::SetError(
int err,
const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding )
00761 {
00762
00763
if ( error )
00764
return;
00765
00766 assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
00767 error =
true;
00768 errorId = err;
00769 errorDesc = errorString[ errorId ];
00770
00771 errorLocation.Clear();
00772
if ( pError && data )
00773 {
00774
00775 data->Stamp( pError, encoding );
00776 errorLocation = data->Cursor();
00777 }
00778 }
00779
00780
00781
TiXmlNode* TiXmlNode::Identify(
const char* p, TiXmlEncoding encoding )
00782 {
00783
TiXmlNode* returnNode = 0;
00784
00785 p = SkipWhiteSpace( p, encoding );
00786
if( !p || !*p || *p !=
'<' )
00787 {
00788
return 0;
00789 }
00790
00791
TiXmlDocument* doc =
GetDocument();
00792 p = SkipWhiteSpace( p, encoding );
00793
00794
if ( !p || !*p )
00795 {
00796
return 0;
00797 }
00798
00799
00800
00801
00802
00803
00804
00805
00806
const char* xmlHeader = {
"<?xml" };
00807
const char* commentHeader = {
"<!--" };
00808
const char* dtdHeader = {
"<!" };
00809
00810
if ( StringEqual( p, xmlHeader,
true, encoding ) )
00811 {
00812
#ifdef DEBUG_PARSER
00813
TIXML_LOG(
"XML parsing Declaration\n" );
00814
#endif
00815
returnNode =
new TiXmlDeclaration();
00816 }
00817
else if ( StringEqual( p, commentHeader,
false, encoding ) )
00818 {
00819
#ifdef DEBUG_PARSER
00820
TIXML_LOG(
"XML parsing Comment\n" );
00821
#endif
00822
returnNode =
new TiXmlComment();
00823 }
00824
else if ( StringEqual( p, dtdHeader,
false, encoding ) )
00825 {
00826
#ifdef DEBUG_PARSER
00827
TIXML_LOG(
"XML parsing Unknown(1)\n" );
00828
#endif
00829
returnNode =
new TiXmlUnknown();
00830 }
00831
else if ( IsAlpha( *(p+1), encoding )
00832 || *(p+1) ==
'_' )
00833 {
00834
#ifdef DEBUG_PARSER
00835
TIXML_LOG(
"XML parsing Element\n" );
00836
#endif
00837
returnNode =
new TiXmlElement(
"" );
00838 }
00839
else
00840 {
00841
#ifdef DEBUG_PARSER
00842
TIXML_LOG(
"XML parsing Unknown(2)\n" );
00843
#endif
00844
returnNode =
new TiXmlUnknown();
00845 }
00846
00847
if ( returnNode )
00848 {
00849
00850 returnNode->
parent =
this;
00851 }
00852
else
00853 {
00854
if ( doc )
00855 doc->
SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
00856 }
00857
return returnNode;
00858 }
00859
00860
#ifdef TIXML_USE_STL
00861
00862
void TiXmlElement::StreamIn (TIXML_ISTREAM * in, TIXML_STRING * tag)
00863 {
00864
00865
00866
while( in->good() )
00867 {
00868
int c = in->get();
00869
if ( c <= 0 )
00870 {
00871
TiXmlDocument* document =
GetDocument();
00872
if ( document )
00873 document->
SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
00874
return;
00875 }
00876 (*tag) += (
char) c ;
00877
00878
if ( c ==
'>' )
00879
break;
00880 }
00881
00882
if ( tag->length() < 3 )
return;
00883
00884
00885
00886
00887
if ( tag->at( tag->length() - 1 ) ==
'>'
00888 && tag->at( tag->length() - 2 ) ==
'/' )
00889 {
00890
00891
return;
00892 }
00893
else if ( tag->at( tag->length() - 1 ) ==
'>' )
00894 {
00895
00896
00897
00898
00899
for ( ;; )
00900 {
00901 StreamWhiteSpace( in, tag );
00902
00903
00904
if ( in->good() && in->peek() !=
'<' )
00905 {
00906
00907
TiXmlText text(
"" );
00908 text.StreamIn( in, tag );
00909
00910
00911
00912
continue;
00913 }
00914
00915
00916
00917
if ( !in->good() )
return;
00918 assert( in->peek() ==
'<' );
00919
int tagIndex = tag->length();
00920
00921
bool closingTag =
false;
00922
bool firstCharFound =
false;
00923
00924
for( ;; )
00925 {
00926
if ( !in->good() )
00927
return;
00928
00929
int c = in->peek();
00930
if ( c <= 0 )
00931 {
00932
TiXmlDocument* document =
GetDocument();
00933
if ( document )
00934 document->
SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
00935
return;
00936 }
00937
00938
if ( c ==
'>' )
00939
break;
00940
00941 *tag += (
char) c;
00942 in->get();
00943
00944
if ( !firstCharFound && c !=
'<' && !IsWhiteSpace( c ) )
00945 {
00946 firstCharFound =
true;
00947
if ( c ==
'/' )
00948 closingTag =
true;
00949 }
00950 }
00951
00952
00953
if ( closingTag )
00954 {
00955
if ( !in->good() )
00956
return;
00957
00958
int c = in->get();
00959
if ( c <= 0 )
00960 {
00961
TiXmlDocument* document =
GetDocument();
00962
if ( document )
00963 document->
SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
00964
return;
00965 }
00966 assert( c ==
'>' );
00967 *tag += (
char) c;
00968
00969
00970
return;
00971 }
00972
else
00973 {
00974
00975
const char* tagloc = tag->c_str() + tagIndex;
00976
TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING );
00977
if ( !node )
00978
return;
00979 node->StreamIn( in, tag );
00980
delete node;
00981 node = 0;
00982
00983
00984 }
00985 }
00986 }
00987 }
00988
#endif
00989
00990
const char* TiXmlElement::Parse(
const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
00991 {
00992 p = SkipWhiteSpace( p, encoding );
00993
TiXmlDocument* document =
GetDocument();
00994
00995
if ( !p || !*p )
00996 {
00997
if ( document ) document->
SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding );
00998
return 0;
00999 }
01000
01001
01002
if ( data )
01003 {
01004 data->Stamp( p, encoding );
01005 location = data->Cursor();
01006 }
01007
01008
if ( *p !=
'<' )
01009 {
01010
if ( document ) document->
SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding );
01011
return 0;
01012 }
01013
01014 p = SkipWhiteSpace( p+1, encoding );
01015
01016
01017
const char* pErr = p;
01018
01019 p = ReadName( p, &value, encoding );
01020
if ( !p || !*p )
01021 {
01022
if ( document ) document->
SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding );
01023
return 0;
01024 }
01025
01026 TIXML_STRING endTag (
"</");
01027 endTag += value;
01028 endTag +=
">";
01029
01030
01031
01032
while ( p && *p )
01033 {
01034 pErr = p;
01035 p = SkipWhiteSpace( p, encoding );
01036
if ( !p || !*p )
01037 {
01038
if ( document ) document->
SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
01039
return 0;
01040 }
01041
if ( *p ==
'/' )
01042 {
01043 ++p;
01044
01045
if ( *p !=
'>' )
01046 {
01047
if ( document ) document->
SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding );
01048
return 0;
01049 }
01050
return (p+1);
01051 }
01052
else if ( *p ==
'>' )
01053 {
01054
01055
01056
01057 ++p;
01058 p = ReadValue( p, data, encoding );
01059
if ( !p || !*p )
01060
return 0;
01061
01062
01063
if ( StringEqual( p, endTag.c_str(),
false, encoding ) )
01064 {
01065 p += endTag.length();
01066
return p;
01067 }
01068
else
01069 {
01070
if ( document ) document->
SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
01071
return 0;
01072 }
01073 }
01074
else
01075 {
01076
01077
TiXmlAttribute* attrib =
new TiXmlAttribute();
01078
if ( !attrib )
01079 {
01080
if ( document ) document->
SetError( TIXML_ERROR_OUT_OF_MEMORY, pErr, data, encoding );
01081
return 0;
01082 }
01083
01084 attrib->
SetDocument( document );
01085
const char* pErr = p;
01086 p = attrib->
Parse( p, data, encoding );
01087
01088
if ( !p || !*p )
01089 {
01090
if ( document ) document->
SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
01091
delete attrib;
01092
return 0;
01093 }
01094
01095
01096
TiXmlAttribute* node = attributeSet.Find( attrib->
strName() );
01097
if ( node )
01098 {
01099 node->
SetValue( attrib->
pcValue() );
01100
delete attrib;
01101
return 0;
01102 }
01103
01104 attributeSet.Add( attrib );
01105 }
01106 }
01107
return p;
01108 }
01109
01110
01111
const char* TiXmlElement::ReadValue(
const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
01112 {
01113
TiXmlDocument* document =
GetDocument();
01114
01115
const char* pWithWhiteSpace = p;
01116
01117 p = SkipWhiteSpace( p, encoding );
01118
while ( p && *p )
01119 {
01120
if ( *p !=
'<' )
01121 {
01122
01123
TiXmlText* textNode =
new TiXmlText(
"" );
01124
01125
if ( !textNode )
01126 {
01127
if ( document ) document->
SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, encoding );
01128
return 0;
01129 }
01130
01131
if (
TiXmlBase::IsWhiteSpaceCondensed() )
01132 {
01133 p = textNode->
Parse( p, data, encoding );
01134 }
01135
else
01136 {
01137
01138
01139 p = textNode->
Parse( pWithWhiteSpace, data, encoding );
01140 }
01141
01142
if ( !textNode->
Blank() )
01143
LinkEndChild( textNode );
01144
else
01145
delete textNode;
01146 }
01147
else
01148 {
01149
01150
01151
if ( StringEqual( p,
"</",
false, encoding ) )
01152 {
01153
return p;
01154 }
01155
else
01156 {
01157
TiXmlNode* node = Identify( p, encoding );
01158
if ( node )
01159 {
01160 p = node->
Parse( p, data, encoding );
01161
LinkEndChild( node );
01162 }
01163
else
01164 {
01165
return 0;
01166 }
01167 }
01168 }
01169 p = SkipWhiteSpace( p, encoding );
01170 }
01171
01172
if ( !p )
01173 {
01174
if ( document ) document->
SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding );
01175 }
01176
return p;
01177 }
01178
01179
01180
#ifdef TIXML_USE_STL
01181
void TiXmlUnknown::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
01182 {
01183
while ( in->good() )
01184 {
01185
int c = in->get();
01186
if ( c <= 0 )
01187 {
01188
TiXmlDocument* document =
GetDocument();
01189
if ( document )
01190 document->
SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
01191
return;
01192 }
01193 (*tag) += (
char) c;
01194
01195
if ( c ==
'>' )
01196 {
01197
01198
return;
01199 }
01200 }
01201 }
01202
#endif
01203
01204
01205
const char* TiXmlUnknown::Parse(
const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
01206 {
01207
TiXmlDocument* document =
GetDocument();
01208 p = SkipWhiteSpace( p, encoding );
01209
01210
01211
if ( data )
01212 {
01213 data->Stamp( p, encoding );
01214 location = data->Cursor();
01215 }
01216
if ( !p || !*p || *p !=
'<' )
01217 {
01218
if ( document ) document->
SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding );
01219
return 0;
01220 }
01221 ++p;
01222 value =
"";
01223
01224
while ( p && *p && *p !=
'>' )
01225 {
01226 value += *p;
01227 ++p;
01228 }
01229
01230
if ( !p )
01231 {
01232
if ( document ) document->
SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
01233 }
01234
if ( *p ==
'>' )
01235
return p+1;
01236
return p;
01237 }
01238
01239
#ifdef TIXML_USE_STL
01240
void TiXmlComment::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
01241 {
01242
while ( in->good() )
01243 {
01244
int c = in->get();
01245
if ( c <= 0 )
01246 {
01247
TiXmlDocument* document =
GetDocument();
01248
if ( document )
01249 document->
SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
01250
return;
01251 }
01252
01253 (*tag) += (
char) c;
01254
01255
if ( c ==
'>'
01256 && tag->at( tag->length() - 2 ) ==
'-'
01257 && tag->at( tag->length() - 3 ) ==
'-' )
01258 {
01259
01260
return;
01261 }
01262 }
01263 }
01264
#endif
01265
01266
01267
const char* TiXmlComment::Parse(
const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
01268 {
01269
TiXmlDocument* document =
GetDocument();
01270 value =
"";
01271
01272 p = SkipWhiteSpace( p, encoding );
01273
01274
01275
if ( data )
01276 {
01277 data->Stamp( p, encoding );
01278 location = data->Cursor();
01279 }
01280
const char* startTag =
"<!--";
01281
const char* endTag =
"-->";
01282
01283
if ( !StringEqual( p, startTag,
false, encoding ) )
01284 {
01285 document->
SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding );
01286
return 0;
01287 }
01288 p += strlen( startTag );
01289 p = ReadText( p, &value,
false, endTag,
false, encoding );
01290
return p;
01291 }
01292
01293
01294
const char* TiXmlAttribute::Parse(
const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
01295 {
01296 p = SkipWhiteSpace( p, encoding );
01297
if ( !p || !*p )
return 0;
01298
01299
int tabsize = 4;
01300
if ( document )
01301 tabsize = document->
TabSize();
01302
01303
01304
if ( data )
01305 {
01306 data->Stamp( p, encoding );
01307 location = data->Cursor();
01308 }
01309
01310
const char* pErr = p;
01311 p = ReadName( p, &name, encoding );
01312
if ( !p || !*p )
01313 {
01314
if ( document ) document->
SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
01315
return 0;
01316 }
01317 p = SkipWhiteSpace( p, encoding );
01318
if ( !p || !*p || *p !=
'=' )
01319 {
01320
if ( document ) document->
SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
01321
return 0;
01322 }
01323
01324 ++p;
01325 p = SkipWhiteSpace( p, encoding );
01326
if ( !p || !*p )
01327 {
01328
if ( document ) document->
SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
01329
return 0;
01330 }
01331
01332
const char* end;
01333
01334
if ( *p ==
'\'' )
01335 {
01336 ++p;
01337 end =
"\'";
01338 p = ReadText( p, &value,
false, end,
false, encoding );
01339 }
01340
else if ( *p ==
'"' )
01341 {
01342 ++p;
01343 end =
"\"";
01344 p = ReadText( p, &value,
false, end,
false, encoding );
01345 }
01346
else
01347 {
01348
01349
01350
01351 value =
"";
01352
while ( p && *p
01353 && !IsWhiteSpace( *p ) && *p !=
'\n' && *p !=
'\r'
01354 && *p !=
'/' && *p !=
'>' )
01355 {
01356 value += *p;
01357 ++p;
01358 }
01359 }
01360
return p;
01361 }
01362
01363
#ifdef TIXML_USE_STL
01364
void TiXmlText::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
01365 {
01366
while ( in->good() )
01367 {
01368
int c = in->peek();
01369
if ( c ==
'<' )
01370
return;
01371
if ( c <= 0 )
01372 {
01373
TiXmlDocument* document =
GetDocument();
01374
if ( document )
01375 document->
SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
01376
return;
01377 }
01378
01379 (*tag) += (
char) c;
01380 in->get();
01381 }
01382 }
01383
#endif
01384
01385
const char* TiXmlText::Parse(
const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
01386 {
01387 value =
"";
01388
01389
if ( data )
01390 {
01391 data->Stamp( p, encoding );
01392 location = data->Cursor();
01393 }
01394
bool ignoreWhite =
true;
01395
01396
const char* end =
"<";
01397 p = ReadText( p, &value, ignoreWhite, end,
false, encoding );
01398
if ( p )
01399
return p-1;
01400
return 0;
01401 }
01402
01403
#ifdef TIXML_USE_STL
01404
void TiXmlDeclaration::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
01405 {
01406
while ( in->good() )
01407 {
01408
int c = in->get();
01409
if ( c <= 0 )
01410 {
01411
TiXmlDocument* document =
GetDocument();
01412
if ( document )
01413 document->
SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
01414
return;
01415 }
01416 (*tag) += (
char) c;
01417
01418
if ( c ==
'>' )
01419 {
01420
01421
return;
01422 }
01423 }
01424 }
01425
#endif
01426
01427
const char* TiXmlDeclaration::Parse(
const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding )
01428 {
01429 p = SkipWhiteSpace( p, _encoding );
01430
01431
01432
TiXmlDocument* document =
GetDocument();
01433
if ( !p || !*p || !StringEqual( p,
"<?xml",
true, _encoding ) )
01434 {
01435
if ( document ) document->
SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding );
01436
return 0;
01437 }
01438
01439
if ( data )
01440 {
01441 data->Stamp( p, _encoding );
01442 location = data->Cursor();
01443 }
01444 p += 5;
01445
01446 version =
"";
01447 encoding =
"";
01448 standalone =
"";
01449
01450
while ( p && *p )
01451 {
01452
if ( *p ==
'>' )
01453 {
01454 ++p;
01455
return p;
01456 }
01457
01458 p = SkipWhiteSpace( p, _encoding );
01459
if ( StringEqual( p,
"version",
true, _encoding ) )
01460 {
01461
TiXmlAttribute attrib;
01462 p = attrib.
Parse( p, data, _encoding );
01463 version = attrib.
pcValue();
01464 }
01465
else if ( StringEqual( p,
"encoding",
true, _encoding ) )
01466 {
01467
TiXmlAttribute attrib;
01468 p = attrib.
Parse( p, data, _encoding );
01469 encoding = attrib.
pcValue();
01470 }
01471
else if ( StringEqual( p,
"standalone",
true, _encoding ) )
01472 {
01473
TiXmlAttribute attrib;
01474 p = attrib.
Parse( p, data, _encoding );
01475 standalone = attrib.
pcValue();
01476 }
01477
else
01478 {
01479
01480
while( p && *p && *p !=
'>' && !IsWhiteSpace( *p ) )
01481 ++p;
01482 }
01483 }
01484
return 0;
01485 }
01486
01487
bool TiXmlText::Blank()
const
01488
{
01489
for (
unsigned i=0; i<value.length(); i++ )
01490
if ( !IsWhiteSpace( value[i] ) )
01491
return false;
01492
return true;
01493 }
01494