refactored logic to use the StrPair. Still cleaning up bugs.

This commit is contained in:
Lee Thomason 2012-01-20 17:59:50 -08:00
parent d34f52c43b
commit e4422304e0
3 changed files with 78 additions and 66 deletions

View File

@ -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;
} }

View File

@ -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 );
}; };

Binary file not shown.