Преглед изворни кода

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

Lee Thomason пре 14 година
родитељ
комит
e4422304e0
3 измењених фајлова са 78 додато и 66 уклоњено
  1. 68 60
      tinyxml2.cpp
  2. 10 6
      tinyxml2.h
  3. BIN
      tinyxml2.suo

+ 68 - 60
tinyxml2.cpp

@@ -7,10 +7,12 @@
 
 using namespace tinyxml2;
 
-static const char LINE_FEED				= (char)0x0a;				// all line endings are normalized to LF
+static const char LINE_FEED				= (char)0x0a;			// all line endings are normalized to LF
 static const char LF = LINE_FEED;
 static const char CARRIAGE_RETURN		= (char)0x0d;			// CR gets filtered out
 static const char CR = CARRIAGE_RETURN;
+static const char SINGLE_QUOTE			= '\'';
+static const char DOUBLE_QUOTE			= '\"';
 
 
 // --------- CharBuffer ----------- //
@@ -31,60 +33,66 @@ static const char CR = CARRIAGE_RETURN;
 }
 
 
+const char* StrPair::GetStr()
+{
+	if ( flags & NEEDS_FLUSH ) {
+		*end = 0;
+
+		if ( flags & ( NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION ) ) {
+			char* p = start;
+			char* q = start;
+
+			while( p < end ) {
+				if ( *p == CR ) {
+					// CR-LF pair becomes LF
+					// CR alone becomes LF
+					// LF-CR becomes LF
+					if ( *(p+1) == LF ) {
+						p += 2;
+					}
+					else {
+						++p;
+					}
+					*q = LF;
+				}
+				else if ( *p == LF ) {
+					if ( *(p+1) == CR ) {
+						p += 2;
+					}
+					else {
+						++p;
+					}
+					*q = LF;
+				}
+				else {
+					*q = *p;
+					++p;
+				}
+			}
+		}
+		flags = 0;
+	}
+	return start;
+}
+
+
 // --------- XMLBase ----------- //
-const char* XMLBase::ParseText( char* p, const char* endTag, char** next )
+char* XMLBase::ParseText( char* p, StrPair* pair, const char* endTag )
 {
 	TIXMLASSERT( endTag && *endTag );
 
 	char* start = p;
-	char* q = p;		// q (target) <= p (src) in same buffer.
 	char  endChar = *endTag;
 	int   length = strlen( endTag );	
-	char* nextTag = 0;
-	*next = 0;
 
 	// Inner loop of text parsing.
 	while ( *p ) {
 		if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
-			*q = 0;
-			nextTag = p + length;
+			pair->Set( start, p, StrPair::NEEDS_ENTITY_PROCESSING | StrPair::NEEDS_NEWLINE_NORMALIZATION );
 			break;
 		}
-		else if ( *p == CR ) {
-			// CR-LF pair becomes LF
-			// CR alone becomes LF
-			// LF-CR becomes LF
-			if ( *(p+1) == LF ) {
-				p += 2;
-			}
-			else {
-				++p;
-			}
-			*q = LF;
-		}
-		else if ( *p == LF ) {
-			if ( *(p+1) == CR ) {
-				p += 2;
-			}
-			else {
-				++p;
-			}
-			*q = LF;
-		}
-		else {
-			*q = *p;
-			++p;
-		}
-		++q;
 	}	
-
-	// Error? If we don't have a text tag, something went wrong. (Although 
-	// what the nextTag points at may be null.)
-	if ( nextTag == 0 ) {
-		return 0;
-	}
-	*next = nextTag;
-	return start;
+	return p;
 }
 
 
@@ -92,7 +100,6 @@ char* XMLBase::ParseName( char* p, StrPair* pair )
 {
 	char* start = p;
 	char* nextTag = 0;
-	*next = 0;
 
 	start = p;
 	if ( !start || !(*start) ) {
@@ -112,11 +119,10 @@ char* XMLBase::ParseName( char* p, StrPair* pair )
 	{
 		++p;
 	}
-	*p = 0;
 
 	if ( p > start ) {
-		*next = p+1;
-		return start;
+		pair->Set( start, p, 0 );
+		return p;
 	}
 	return 0;
 }
@@ -241,7 +247,7 @@ void XMLNode::PrintSpace( FILE* fp, int depth )
 
 // --------- 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 )
 {
 	// Comment parses as text.
-	value = ParseText( p, "-->", &p );
-	return p;
+	return ParseText( p, &value, "-->" );
 }
 
 
@@ -271,8 +276,8 @@ char* XMLAttribute::ParseDeep( char* p )
 {
 	char endTag[2] = { *p, 0 };
 	++p;
-	value = ParseText( p, endTag, &p );
-	if ( !value ) return 0;
+	p = ParseText( p, &value, endTag );
+	if ( value.Empty() ) return 0;
 	return p;
 }
 
@@ -285,7 +290,6 @@ void XMLAttribute::Print( FILE* cfile )
 
 // --------- XMLElement ---------- //
 XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ),
-	name( 0 ),
 	closing( false ),
 	rootAttribute( 0 ),
 	lastAttribute( 0 )
@@ -326,25 +330,24 @@ char* XMLElement::ParseDeep( char* p )
 		++p;
 	}
 
-	name = ParseName( p, &p );
-	if ( !name ) return 0;
+	p = ParseName( p, &name );
+	if ( name.Empty() ) return 0;
 
 	// Read the attributes.
 	while( p ) {
 		p = SkipWhiteSpace( p );
 		if ( !p || !(*p) ) {
-			document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, name );
+			document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, name.GetStr() );
 			return 0;
 		}
-		const char* saveP = p;
 
 		// attribute.
-		if ( *p == '\'' || *p == '\"' ) {
+		if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) {
 			XMLAttribute* attrib = new XMLAttribute( this );
 			p = attrib->ParseDeep( p );
 			if ( !p ) {
 				delete attrib;
-				document->SetError( XMLDocument::ERROR_PARSING_ATTRIBUTE, start, saveP );
+				document->SetError( XMLDocument::ERROR_PARSING_ATTRIBUTE, start, p );
 				return 0;
 			}
 			if ( rootAttribute ) {
@@ -356,36 +359,41 @@ char* XMLElement::ParseDeep( char* p )
 				rootAttribute = lastAttribute = attrib;
 			}
 		}
+		// end of the tag
 		else if ( *p == '/' && *(p+1) == '>' ) {
-			// end tag.
 			if ( closing ) {
 				document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, p );
 				return 0;
 			}
 			return p+2;	// done; sealed element.
 		}
+		// end of the tag
 		else if ( *p == '>' ) {
 			++p;
 			break;
 		}
+		else {
+			document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, p );
+			return 0;
+		}
 	}
 
 	while( p && *p ) {
 		XMLNode* node = 0;
 		p = Identify( document, p, &node );
 		if ( p && node ) {
-			node->ParseDeep( p );
+			p = node->ParseDeep( p );
 
 			XMLElement* element = node->ToElement();
 			if ( element && element->Closing() ) {
 				if ( StringEqual( element->Name(), this->Name() ) ) {
 					// All good, this is closing tag.
 					delete node;
-					p = 0;
 				}
 				else {
 					document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, p );
 					delete node;
+					p = 0;
 				}
 				return p;
 			}

+ 10 - 6
tinyxml2.h

@@ -50,21 +50,25 @@ class StrPair
 {
 public:
 	enum {
-		NEEDS_FLUSH = 0x01,
-		NEEDS_ENTITY_PROCESSING = 0x02,
-		NEEDS_NEWLINE_NORMALIZATION = 0x04
+		NEEDS_ENTITY_PROCESSING			= 0x01,
+		NEEDS_NEWLINE_NORMALIZATION		= 0x02
 	};
 
 	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;
 	}
 	const char* GetStr();
+	bool Empty() const { return start == end; }
 
 private:
+	enum {
+		NEEDS_FLUSH = 0x100
+	};
+
 	// After parsing, if *end != 0, it can be set to zero.
 	int flags;
-	const char* start;	
+	char* start;	
 	char* end;
 };
 
@@ -96,7 +100,7 @@ protected:
 	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; }
 
-	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* Identify( XMLDocument* document, char* p, XMLNode** node );
 };