Selaa lähdekoodia

better end element parsing

Lee Thomason (grinliz) 14 vuotta sitten
vanhempi
commit
7468f11413
2 muutettua tiedostoa jossa 54 lisäystä ja 60 poistoa
  1. 48 54
      tinyxml2.cpp
  2. 6 6
      tinyxml2.h

+ 48 - 54
tinyxml2.cpp

@@ -358,7 +358,7 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
 	p = XMLUtil::SkipWhiteSpace( p );
 	p = XMLUtil::SkipWhiteSpace( p );
 	if( !p || !*p )
 	if( !p || !*p )
 	{
 	{
-		return 0;
+		return p;
 	}
 	}
 
 
 	// What is this thing? 
 	// What is this thing? 
@@ -409,11 +409,6 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
 		returnNode = new (elementPool.Alloc()) XMLElement( this );
 		returnNode = new (elementPool.Alloc()) XMLElement( this );
 		returnNode->memPool = &elementPool;
 		returnNode->memPool = &elementPool;
 		p += elementHeaderLen;
 		p += elementHeaderLen;
-
-		p = XMLUtil::SkipWhiteSpace( p );
-		if ( p && *p == '/' ) {
-			((XMLElement*)returnNode)->closingType = XMLElement::CLOSING;
-		}
 	}
 	}
 	else {
 	else {
 		returnNode = new (textPool.Alloc()) XMLText( this );
 		returnNode = new (textPool.Alloc()) XMLText( this );
@@ -602,7 +597,7 @@ const XMLElement* XMLNode::LastChildElement( const char* value ) const
 }
 }
 
 
 
 
-char* XMLNode::ParseDeep( char* p )
+char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
 {
 {
 	// This is a recursive method, but thinking about it "at the current level"
 	// This is a recursive method, but thinking about it "at the current level"
 	// it is a pretty simple flat list:
 	// it is a pretty simple flat list:
@@ -617,69 +612,67 @@ char* XMLNode::ParseDeep( char* p )
 	// Where the closing element (/foo) *must* be the next thing after the opening
 	// Where the closing element (/foo) *must* be the next thing after the opening
 	// element, and the names must match. BUT the tricky bit is that the closing
 	// element, and the names must match. BUT the tricky bit is that the closing
 	// element will be read by the child.
 	// element will be read by the child.
+	// 
+	// 'endTag' is the end tag for this node, it is returned by a call to a child.
+	// 'parentEnd' is the end tag for the parent, which is filled in and returned.
 
 
 	while( p && *p ) {
 	while( p && *p ) {
 		XMLNode* node = 0;
 		XMLNode* node = 0;
-		char* mark = p;
 
 
 		p = document->Identify( p, &node );
 		p = document->Identify( p, &node );
-		if ( p == 0 ) {
+		if ( p == 0 || node == 0 ) {
 			break;
 			break;
 		}
 		}
 
 
-		// We read the end tag. Back up and return.
-		if ( node && node->ToElement() && node->ToElement()->ClosingType() == XMLElement::CLOSING ) {
+		StrPair endTag;
+		p = node->ParseDeep( p, &endTag );
+		if ( !p ) {
 			DELETE_NODE( node );
 			DELETE_NODE( node );
-			return mark;
+			node = 0;
+			break;
 		}
 		}
 
 
-		if ( node ) {
-			p = node->ParseDeep( p );
-			if ( !p ) {
-				DELETE_NODE( node );
-				node = 0;
-				break;
+		// We read the end tag. Return it to the parent.
+		if ( node->ToElement() && node->ToElement()->ClosingType() == XMLElement::CLOSING ) {
+			if ( parentEnd ) {
+				*parentEnd = ((XMLElement*)node)->value;
 			}
 			}
-	
-			XMLElement* ele = node->ToElement();
-			if ( ele && ele->ClosingType() == XMLElement::OPEN ) {
-				XMLNode* closingNode = 0;
-				p = document->Identify( p, &closingNode );
-				XMLElement* closingEle = closingNode ? closingNode->ToElement() : 0;
+			DELETE_NODE( node );
+			return p;
+		}
 
 
-				if ( closingEle == 0 ) {
-					document->SetError( ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
-					p = 0;
-				}
-				else if ( closingEle->ClosingType() != XMLElement::CLOSING ) {
+		// Handle an end tag returned to this level.
+		// And handle a bunch of annoying errors.
+		XMLElement* ele = node->ToElement();
+		if ( ele ) {
+			if ( endTag.Empty() && ele->ClosingType() == XMLElement::OPEN ) {
+				document->SetError( ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
+				p = 0;
+			}
+			else if ( !endTag.Empty() && ele->ClosingType() != XMLElement::OPEN ) {
+				document->SetError( ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
+				p = 0;
+			}
+			else if ( !endTag.Empty() ) {
+				if ( !XMLUtil::StringEqual( endTag.GetStr(), node->Value() )) { 
 					document->SetError( ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
 					document->SetError( ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
 					p = 0;
 					p = 0;
 				}
 				}
-				else 
-				{
-					p = closingEle->ParseDeep( p );
-					if ( !XMLUtil::StringEqual( closingEle->Value(), node->Value() )) { 
-						document->SetError( ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
-						p = 0;
-					}
-				}
-				// Else everything is fine, but we need to throw away the node.
-				DELETE_NODE( closingNode );
-				if ( p == 0 ) {
-					DELETE_NODE( node );
-					node = 0;
-				}
-			}
-			if ( node ) {
-				this->InsertEndChild( node );
 			}
 			}
 		}
 		}
+		if ( p == 0 ) {
+			DELETE_NODE( node );
+			node = 0;
+		}
+		if ( node ) {
+			this->InsertEndChild( node );
+		}
 	}
 	}
 	return 0;
 	return 0;
 }
 }
 
 
 // --------- XMLText ---------- //
 // --------- XMLText ---------- //
-char* XMLText::ParseDeep( char* p )
+char* XMLText::ParseDeep( char* p, StrPair* )
 {
 {
 	const char* start = p;
 	const char* start = p;
 	if ( this->CData() ) {
 	if ( this->CData() ) {
@@ -721,7 +714,7 @@ XMLComment::~XMLComment()
 }
 }
 
 
 
 
-char* XMLComment::ParseDeep( char* p )
+char* XMLComment::ParseDeep( char* p, StrPair* )
 {
 {
 	// Comment parses as text.
 	// Comment parses as text.
 	const char* start = p;
 	const char* start = p;
@@ -752,7 +745,7 @@ XMLDeclaration::~XMLDeclaration()
 }
 }
 
 
 
 
-char* XMLDeclaration::ParseDeep( char* p )
+char* XMLDeclaration::ParseDeep( char* p, StrPair* )
 {
 {
 	// Declaration parses as text.
 	// Declaration parses as text.
 	const char* start = p;
 	const char* start = p;
@@ -781,7 +774,7 @@ XMLUnknown::~XMLUnknown()
 }
 }
 
 
 
 
-char* XMLUnknown::ParseDeep( char* p )
+char* XMLUnknown::ParseDeep( char* p, StrPair* )
 {
 {
 	// Unknown parses as text.
 	// Unknown parses as text.
 	const char* start = p;
 	const char* start = p;
@@ -1056,7 +1049,7 @@ char* XMLElement::ParseAttributes( char* p )
 //	<ele></ele>
 //	<ele></ele>
 //	<ele>foo<b>bar</b></ele>
 //	<ele>foo<b>bar</b></ele>
 //
 //
-char* XMLElement::ParseDeep( char* p )
+char* XMLElement::ParseDeep( char* p, StrPair* strPair )
 {
 {
 	// Read the element name.
 	// Read the element name.
 	p = XMLUtil::SkipWhiteSpace( p );
 	p = XMLUtil::SkipWhiteSpace( p );
@@ -1079,7 +1072,8 @@ char* XMLElement::ParseDeep( char* p )
 	if ( !p || !*p || closingType ) 
 	if ( !p || !*p || closingType ) 
 		return p;
 		return p;
 
 
-	p = XMLNode::ParseDeep( p );
+	p = XMLNode::ParseDeep( p, strPair );
+	// FIXME: proces end tage here??
 	return p;
 	return p;
 }
 }
 
 
@@ -1207,7 +1201,7 @@ int XMLDocument::LoadFile( FILE* fp )
 		return errorID;
 		return errorID;
 	}
 	}
 
 
-	ParseDeep( charBuffer + (p-charBuffer) );
+	ParseDeep( charBuffer + (p-charBuffer), 0 );
 	return errorID;
 	return errorID;
 }
 }
 
 
@@ -1242,7 +1236,7 @@ int XMLDocument::Parse( const char* p )
 	memcpy( charBuffer, p, len+1 );
 	memcpy( charBuffer, p, len+1 );
 
 
 	
 	
-	ParseDeep( charBuffer );
+	ParseDeep( charBuffer, 0 );
 	return errorID;
 	return errorID;
 }
 }
 
 

+ 6 - 6
tinyxml2.h

@@ -462,7 +462,7 @@ public:
 
 
 	virtual bool Accept( XMLVisitor* visitor ) const = 0;
 	virtual bool Accept( XMLVisitor* visitor ) const = 0;
 
 
-	virtual char* ParseDeep( char* );
+	virtual char* ParseDeep( char*, StrPair* );
 
 
 protected:
 protected:
 	XMLNode( XMLDocument* );
 	XMLNode( XMLDocument* );
@@ -499,7 +499,7 @@ public:
 	void SetCData( bool value )				{ isCData = true; }
 	void SetCData( bool value )				{ isCData = true; }
 	bool CData() const						{ return isCData; }
 	bool CData() const						{ return isCData; }
 
 
-	char* ParseDeep( char* );
+	char* ParseDeep( char*, StrPair* endTag );
 
 
 protected:
 protected:
 	XMLText( XMLDocument* doc )	: XMLNode( doc ), isCData( false )	{}
 	XMLText( XMLDocument* doc )	: XMLNode( doc ), isCData( false )	{}
@@ -521,7 +521,7 @@ public:
 
 
 	virtual bool Accept( XMLVisitor* visitor ) const;
 	virtual bool Accept( XMLVisitor* visitor ) const;
 
 
-	char* ParseDeep( char* );
+	char* ParseDeep( char*, StrPair* endTag );
 
 
 protected:
 protected:
 	XMLComment( XMLDocument* doc );
 	XMLComment( XMLDocument* doc );
@@ -542,7 +542,7 @@ public:
 
 
 	virtual bool Accept( XMLVisitor* visitor ) const;
 	virtual bool Accept( XMLVisitor* visitor ) const;
 
 
-	char* ParseDeep( char* );
+	char* ParseDeep( char*, StrPair* endTag );
 
 
 protected:
 protected:
 	XMLDeclaration( XMLDocument* doc );
 	XMLDeclaration( XMLDocument* doc );
@@ -561,7 +561,7 @@ public:
 
 
 	virtual bool Accept( XMLVisitor* visitor ) const;
 	virtual bool Accept( XMLVisitor* visitor ) const;
 
 
-	char* ParseDeep( char* );
+	char* ParseDeep( char*, StrPair* endTag );
 
 
 protected:
 protected:
 	XMLUnknown( XMLDocument* doc );
 	XMLUnknown( XMLDocument* doc );
@@ -686,7 +686,7 @@ public:
 		CLOSING		// </foo>
 		CLOSING		// </foo>
 	};
 	};
 	int ClosingType() const { return closingType; }
 	int ClosingType() const { return closingType; }
-	char* ParseDeep( char* p );
+	char* ParseDeep( char* p, StrPair* endTag );
 
 
 private:
 private:
 	XMLElement( XMLDocument* doc );
 	XMLElement( XMLDocument* doc );