mirror of https://github.com/AxioDL/tinyxml2.git
refactored logic to use the StrPair. Still cleaning up bugs.
This commit is contained in:
parent
d34f52c43b
commit
e4422304e0
94
tinyxml2.cpp
94
tinyxml2.cpp
|
@ -11,6 +11,8 @@ static const char LINE_FEED = (char)0x0a; // all line endings are normaliz
|
||||||
static const char LF = LINE_FEED;
|
static const char LF = LINE_FEED;
|
||||||
static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out
|
static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out
|
||||||
static const char CR = CARRIAGE_RETURN;
|
static const char CR = CARRIAGE_RETURN;
|
||||||
|
static const char SINGLE_QUOTE = '\'';
|
||||||
|
static const char DOUBLE_QUOTE = '\"';
|
||||||
|
|
||||||
|
|
||||||
// --------- CharBuffer ----------- //
|
// --------- CharBuffer ----------- //
|
||||||
|
@ -31,26 +33,17 @@ static const char CR = CARRIAGE_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --------- XMLBase ----------- //
|
const char* StrPair::GetStr()
|
||||||
const char* XMLBase::ParseText( char* p, const char* endTag, char** next )
|
|
||||||
{
|
{
|
||||||
TIXMLASSERT( endTag && *endTag );
|
if ( flags & NEEDS_FLUSH ) {
|
||||||
|
*end = 0;
|
||||||
|
|
||||||
char* start = p;
|
if ( flags & ( NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION ) ) {
|
||||||
char* q = p; // q (target) <= p (src) in same buffer.
|
char* p = start;
|
||||||
char endChar = *endTag;
|
char* q = start;
|
||||||
int length = strlen( endTag );
|
|
||||||
char* nextTag = 0;
|
|
||||||
*next = 0;
|
|
||||||
|
|
||||||
// Inner loop of text parsing.
|
while( p < end ) {
|
||||||
while ( *p ) {
|
if ( *p == CR ) {
|
||||||
if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
|
|
||||||
*q = 0;
|
|
||||||
nextTag = p + length;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if ( *p == CR ) {
|
|
||||||
// CR-LF pair becomes LF
|
// CR-LF pair becomes LF
|
||||||
// CR alone becomes LF
|
// CR alone becomes LF
|
||||||
// LF-CR becomes LF
|
// LF-CR becomes LF
|
||||||
|
@ -75,16 +68,31 @@ const char* XMLBase::ParseText( char* p, const char* endTag, char** next )
|
||||||
*q = *p;
|
*q = *p;
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
++q;
|
}
|
||||||
|
}
|
||||||
|
flags = 0;
|
||||||
|
}
|
||||||
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error? If we don't have a text tag, something went wrong. (Although
|
|
||||||
// what the nextTag points at may be null.)
|
// --------- XMLBase ----------- //
|
||||||
if ( nextTag == 0 ) {
|
char* XMLBase::ParseText( char* p, StrPair* pair, const char* endTag )
|
||||||
return 0;
|
{
|
||||||
|
TIXMLASSERT( endTag && *endTag );
|
||||||
|
|
||||||
|
char* start = p;
|
||||||
|
char endChar = *endTag;
|
||||||
|
int length = strlen( endTag );
|
||||||
|
|
||||||
|
// Inner loop of text parsing.
|
||||||
|
while ( *p ) {
|
||||||
|
if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
|
||||||
|
pair->Set( start, p, StrPair::NEEDS_ENTITY_PROCESSING | StrPair::NEEDS_NEWLINE_NORMALIZATION );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
*next = nextTag;
|
}
|
||||||
return start;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,7 +100,6 @@ char* XMLBase::ParseName( char* p, StrPair* pair )
|
||||||
{
|
{
|
||||||
char* start = p;
|
char* start = p;
|
||||||
char* nextTag = 0;
|
char* nextTag = 0;
|
||||||
*next = 0;
|
|
||||||
|
|
||||||
start = p;
|
start = p;
|
||||||
if ( !start || !(*start) ) {
|
if ( !start || !(*start) ) {
|
||||||
|
@ -112,11 +119,10 @@ char* XMLBase::ParseName( char* p, StrPair* pair )
|
||||||
{
|
{
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
*p = 0;
|
|
||||||
|
|
||||||
if ( p > start ) {
|
if ( p > start ) {
|
||||||
*next = p+1;
|
pair->Set( start, p, 0 );
|
||||||
return start;
|
return p;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -241,7 +247,7 @@ void XMLNode::PrintSpace( FILE* fp, int depth )
|
||||||
|
|
||||||
// --------- XMLComment ---------- //
|
// --------- XMLComment ---------- //
|
||||||
|
|
||||||
XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc ), value( 0 )
|
XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,8 +267,7 @@ void XMLComment::Print( FILE* fp, int depth )
|
||||||
char* XMLComment::ParseDeep( char* p )
|
char* XMLComment::ParseDeep( char* p )
|
||||||
{
|
{
|
||||||
// Comment parses as text.
|
// Comment parses as text.
|
||||||
value = ParseText( p, "-->", &p );
|
return ParseText( p, &value, "-->" );
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -271,8 +276,8 @@ char* XMLAttribute::ParseDeep( char* p )
|
||||||
{
|
{
|
||||||
char endTag[2] = { *p, 0 };
|
char endTag[2] = { *p, 0 };
|
||||||
++p;
|
++p;
|
||||||
value = ParseText( p, endTag, &p );
|
p = ParseText( p, &value, endTag );
|
||||||
if ( !value ) return 0;
|
if ( value.Empty() ) return 0;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,7 +290,6 @@ void XMLAttribute::Print( FILE* cfile )
|
||||||
|
|
||||||
// --------- XMLElement ---------- //
|
// --------- XMLElement ---------- //
|
||||||
XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ),
|
XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ),
|
||||||
name( 0 ),
|
|
||||||
closing( false ),
|
closing( false ),
|
||||||
rootAttribute( 0 ),
|
rootAttribute( 0 ),
|
||||||
lastAttribute( 0 )
|
lastAttribute( 0 )
|
||||||
|
@ -326,25 +330,24 @@ char* XMLElement::ParseDeep( char* p )
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = ParseName( p, &p );
|
p = ParseName( p, &name );
|
||||||
if ( !name ) return 0;
|
if ( name.Empty() ) return 0;
|
||||||
|
|
||||||
// Read the attributes.
|
// Read the attributes.
|
||||||
while( p ) {
|
while( p ) {
|
||||||
p = SkipWhiteSpace( p );
|
p = SkipWhiteSpace( p );
|
||||||
if ( !p || !(*p) ) {
|
if ( !p || !(*p) ) {
|
||||||
document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, name );
|
document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, name.GetStr() );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const char* saveP = p;
|
|
||||||
|
|
||||||
// attribute.
|
// attribute.
|
||||||
if ( *p == '\'' || *p == '\"' ) {
|
if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) {
|
||||||
XMLAttribute* attrib = new XMLAttribute( this );
|
XMLAttribute* attrib = new XMLAttribute( this );
|
||||||
p = attrib->ParseDeep( p );
|
p = attrib->ParseDeep( p );
|
||||||
if ( !p ) {
|
if ( !p ) {
|
||||||
delete attrib;
|
delete attrib;
|
||||||
document->SetError( XMLDocument::ERROR_PARSING_ATTRIBUTE, start, saveP );
|
document->SetError( XMLDocument::ERROR_PARSING_ATTRIBUTE, start, p );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ( rootAttribute ) {
|
if ( rootAttribute ) {
|
||||||
|
@ -356,36 +359,41 @@ char* XMLElement::ParseDeep( char* p )
|
||||||
rootAttribute = lastAttribute = attrib;
|
rootAttribute = lastAttribute = attrib;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// end of the tag
|
||||||
else if ( *p == '/' && *(p+1) == '>' ) {
|
else if ( *p == '/' && *(p+1) == '>' ) {
|
||||||
// end tag.
|
|
||||||
if ( closing ) {
|
if ( closing ) {
|
||||||
document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, p );
|
document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, p );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return p+2; // done; sealed element.
|
return p+2; // done; sealed element.
|
||||||
}
|
}
|
||||||
|
// end of the tag
|
||||||
else if ( *p == '>' ) {
|
else if ( *p == '>' ) {
|
||||||
++p;
|
++p;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, p );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while( p && *p ) {
|
while( p && *p ) {
|
||||||
XMLNode* node = 0;
|
XMLNode* node = 0;
|
||||||
p = Identify( document, p, &node );
|
p = Identify( document, p, &node );
|
||||||
if ( p && node ) {
|
if ( p && node ) {
|
||||||
node->ParseDeep( p );
|
p = node->ParseDeep( p );
|
||||||
|
|
||||||
XMLElement* element = node->ToElement();
|
XMLElement* element = node->ToElement();
|
||||||
if ( element && element->Closing() ) {
|
if ( element && element->Closing() ) {
|
||||||
if ( StringEqual( element->Name(), this->Name() ) ) {
|
if ( StringEqual( element->Name(), this->Name() ) ) {
|
||||||
// All good, this is closing tag.
|
// All good, this is closing tag.
|
||||||
delete node;
|
delete node;
|
||||||
p = 0;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, p );
|
document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, p );
|
||||||
delete node;
|
delete node;
|
||||||
|
p = 0;
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
16
tinyxml2.h
16
tinyxml2.h
|
@ -50,21 +50,25 @@ class StrPair
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
NEEDS_FLUSH = 0x01,
|
NEEDS_ENTITY_PROCESSING = 0x01,
|
||||||
NEEDS_ENTITY_PROCESSING = 0x02,
|
NEEDS_NEWLINE_NORMALIZATION = 0x02
|
||||||
NEEDS_NEWLINE_NORMALIZATION = 0x04
|
|
||||||
};
|
};
|
||||||
|
|
||||||
StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
|
StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
|
||||||
void Init( const char* start, char* end, int flags ) {
|
void Set( char* start, char* end, int flags ) {
|
||||||
this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
|
this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
|
||||||
}
|
}
|
||||||
const char* GetStr();
|
const char* GetStr();
|
||||||
|
bool Empty() const { return start == end; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum {
|
||||||
|
NEEDS_FLUSH = 0x100
|
||||||
|
};
|
||||||
|
|
||||||
// After parsing, if *end != 0, it can be set to zero.
|
// After parsing, if *end != 0, it can be set to zero.
|
||||||
int flags;
|
int flags;
|
||||||
const char* start;
|
char* start;
|
||||||
char* end;
|
char* end;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -96,7 +100,7 @@ protected:
|
||||||
inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalnum( anyByte ) : 1; }
|
inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalnum( anyByte ) : 1; }
|
||||||
inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalpha( anyByte ) : 1; }
|
inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalpha( anyByte ) : 1; }
|
||||||
|
|
||||||
const char* ParseText( char* in, const char* endTag, char** next );
|
char* ParseText( char* in, StrPair* pair, const char* endTag );
|
||||||
char* ParseName( char* in, StrPair* pair );
|
char* ParseName( char* in, StrPair* pair );
|
||||||
char* Identify( XMLDocument* document, char* p, XMLNode** node );
|
char* Identify( XMLDocument* document, char* p, XMLNode** node );
|
||||||
};
|
};
|
||||||
|
|
BIN
tinyxml2.suo
BIN
tinyxml2.suo
Binary file not shown.
Loading…
Reference in New Issue