From 7468f11413a6f19cd3e5d5f566ec305c1111c9cf Mon Sep 17 00:00:00 2001 From: "Lee Thomason (grinliz)" Date: Fri, 24 Feb 2012 08:56:50 -0800 Subject: [PATCH] better end element parsing --- tinyxml2.cpp | 102 ++++++++++++++++++++++++--------------------------- tinyxml2.h | 12 +++--- 2 files changed, 54 insertions(+), 60 deletions(-) diff --git a/tinyxml2.cpp b/tinyxml2.cpp index 51cf795..73a4143 100644 --- a/tinyxml2.cpp +++ b/tinyxml2.cpp @@ -358,7 +358,7 @@ char* XMLDocument::Identify( char* p, XMLNode** node ) p = XMLUtil::SkipWhiteSpace( p ); if( !p || !*p ) { - return 0; + return p; } // What is this thing? @@ -409,11 +409,6 @@ char* XMLDocument::Identify( char* p, XMLNode** node ) returnNode = new (elementPool.Alloc()) XMLElement( this ); returnNode->memPool = &elementPool; p += elementHeaderLen; - - p = XMLUtil::SkipWhiteSpace( p ); - if ( p && *p == '/' ) { - ((XMLElement*)returnNode)->closingType = XMLElement::CLOSING; - } } else { 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" // 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 // element, and the names must match. BUT the tricky bit is that the closing // 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 ) { XMLNode* node = 0; - char* mark = p; p = document->Identify( p, &node ); - if ( p == 0 ) { + if ( p == 0 || node == 0 ) { 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 ); - 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 ) { + // 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 ); p = 0; } - else if ( closingEle->ClosingType() != XMLElement::CLOSING ) { - document->SetError( ERROR_MISMATCHED_ELEMENT, node->Value(), 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; } // --------- XMLText ---------- // -char* XMLText::ParseDeep( char* p ) +char* XMLText::ParseDeep( char* p, StrPair* ) { const char* start = p; if ( this->CData() ) { @@ -721,7 +714,7 @@ XMLComment::~XMLComment() } -char* XMLComment::ParseDeep( char* p ) +char* XMLComment::ParseDeep( char* p, StrPair* ) { // Comment parses as text. 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. 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. const char* start = p; @@ -1056,7 +1049,7 @@ char* XMLElement::ParseAttributes( char* p ) // // foobar // -char* XMLElement::ParseDeep( char* p ) +char* XMLElement::ParseDeep( char* p, StrPair* strPair ) { // Read the element name. p = XMLUtil::SkipWhiteSpace( p ); @@ -1079,7 +1072,8 @@ char* XMLElement::ParseDeep( char* p ) if ( !p || !*p || closingType ) return p; - p = XMLNode::ParseDeep( p ); + p = XMLNode::ParseDeep( p, strPair ); + // FIXME: proces end tage here?? return p; } @@ -1207,7 +1201,7 @@ int XMLDocument::LoadFile( FILE* fp ) return errorID; } - ParseDeep( charBuffer + (p-charBuffer) ); + ParseDeep( charBuffer + (p-charBuffer), 0 ); return errorID; } @@ -1242,7 +1236,7 @@ int XMLDocument::Parse( const char* p ) memcpy( charBuffer, p, len+1 ); - ParseDeep( charBuffer ); + ParseDeep( charBuffer, 0 ); return errorID; } diff --git a/tinyxml2.h b/tinyxml2.h index 0e15231..9f63514 100644 --- a/tinyxml2.h +++ b/tinyxml2.h @@ -462,7 +462,7 @@ public: virtual bool Accept( XMLVisitor* visitor ) const = 0; - virtual char* ParseDeep( char* ); + virtual char* ParseDeep( char*, StrPair* ); protected: XMLNode( XMLDocument* ); @@ -499,7 +499,7 @@ public: void SetCData( bool value ) { isCData = true; } bool CData() const { return isCData; } - char* ParseDeep( char* ); + char* ParseDeep( char*, StrPair* endTag ); protected: XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {} @@ -521,7 +521,7 @@ public: virtual bool Accept( XMLVisitor* visitor ) const; - char* ParseDeep( char* ); + char* ParseDeep( char*, StrPair* endTag ); protected: XMLComment( XMLDocument* doc ); @@ -542,7 +542,7 @@ public: virtual bool Accept( XMLVisitor* visitor ) const; - char* ParseDeep( char* ); + char* ParseDeep( char*, StrPair* endTag ); protected: XMLDeclaration( XMLDocument* doc ); @@ -561,7 +561,7 @@ public: virtual bool Accept( XMLVisitor* visitor ) const; - char* ParseDeep( char* ); + char* ParseDeep( char*, StrPair* endTag ); protected: XMLUnknown( XMLDocument* doc ); @@ -686,7 +686,7 @@ public: CLOSING // }; int ClosingType() const { return closingType; } - char* ParseDeep( char* p ); + char* ParseDeep( char* p, StrPair* endTag ); private: XMLElement( XMLDocument* doc );