From 1da9005861c9d504d48c379569958e11ba8fe899 Mon Sep 17 00:00:00 2001 From: PKEuS Date: Wed, 17 Dec 2014 19:57:01 +0100 Subject: [PATCH] Updated TinyXML https://github.com/leethomason/tinyxml2 --- externals/tinyxml/tinyxml2.cpp | 162 +++++++++++++++++++++++++-------- externals/tinyxml/tinyxml2.h | 57 ++++++++---- 2 files changed, 161 insertions(+), 58 deletions(-) diff --git a/externals/tinyxml/tinyxml2.cpp b/externals/tinyxml/tinyxml2.cpp index 2893a2798..2d3a1f7c1 100644 --- a/externals/tinyxml/tinyxml2.cpp +++ b/externals/tinyxml/tinyxml2.cpp @@ -24,7 +24,7 @@ distribution. #include "tinyxml2.h" #include // yes, this one new style header, is in the Android SDK. -# ifdef ANDROID_NDK +#if defined(ANDROID_NDK) || defined(__QNXNTO__) # include #else # include @@ -70,6 +70,29 @@ StrPair::~StrPair() } +void StrPair::TransferTo( StrPair* other ) +{ + if ( this == other ) { + return; + } + // This in effect implements the assignment operator by "moving" + // ownership (as in auto_ptr). + + TIXMLASSERT( other->_flags == 0 ); + TIXMLASSERT( other->_start == 0 ); + TIXMLASSERT( other->_end == 0 ); + + other->Reset(); + + other->_flags = _flags; + other->_start = _start; + other->_end = _end; + + _flags = 0; + _start = 0; + _end = 0; +} + void StrPair::Reset() { if ( _flags & NEEDS_DELETE ) { @@ -511,16 +534,19 @@ char* XMLDocument::Identify( char* p, XMLNode** node ) #endif XMLNode* returnNode = 0; if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() ); returnNode = new (_commentPool.Alloc()) XMLDeclaration( this ); returnNode->_memPool = &_commentPool; p += xmlHeaderLen; } else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() ); returnNode = new (_commentPool.Alloc()) XMLComment( this ); returnNode->_memPool = &_commentPool; p += commentHeaderLen; } else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); XMLText* text = new (_textPool.Alloc()) XMLText( this ); returnNode = text; returnNode->_memPool = &_textPool; @@ -528,16 +554,19 @@ char* XMLDocument::Identify( char* p, XMLNode** node ) text->SetCData( true ); } else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() ); returnNode = new (_commentPool.Alloc()) XMLUnknown( this ); returnNode->_memPool = &_commentPool; p += dtdHeaderLen; } else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); returnNode = new (_elementPool.Alloc()) XMLElement( this ); returnNode->_memPool = &_elementPool; p += elementHeaderLen; } else { + TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); returnNode = new (_textPool.Alloc()) XMLText( this ); returnNode->_memPool = &_textPool; p = start; // Back it up, all the text counts. @@ -600,6 +629,7 @@ void XMLNode::SetValue( const char* str, bool staticMem ) void XMLNode::DeleteChildren() { while( _firstChild ) { + TIXMLASSERT( _firstChild->_document == _document ); XMLNode* node = _firstChild; Unlink( node ); @@ -611,6 +641,7 @@ void XMLNode::DeleteChildren() void XMLNode::Unlink( XMLNode* child ) { + TIXMLASSERT( child->_document == _document ); if ( child == _firstChild ) { _firstChild = _firstChild->_next; } @@ -630,6 +661,7 @@ void XMLNode::Unlink( XMLNode* child ) void XMLNode::DeleteChild( XMLNode* node ) { + TIXMLASSERT( node->_document == _document ); TIXMLASSERT( node->_parent == this ); DeleteNode( node ); } @@ -637,8 +669,11 @@ void XMLNode::DeleteChild( XMLNode* node ) XMLNode* XMLNode::InsertEndChild( XMLNode* addThis ) { - if (addThis->_document != _document) - return 0; + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } if (addThis->_parent) addThis->_parent->Unlink( addThis ); @@ -668,8 +703,11 @@ XMLNode* XMLNode::InsertEndChild( XMLNode* addThis ) XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis ) { - if (addThis->_document != _document) - return 0; + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } if (addThis->_parent) addThis->_parent->Unlink( addThis ); @@ -700,12 +738,16 @@ XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis ) XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ) { - if (addThis->_document != _document) - return 0; + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } - TIXMLASSERT( afterThis->_parent == this ); + TIXMLASSERT( afterThis ); if ( afterThis->_parent != this ) { + TIXMLASSERT( false ); return 0; } @@ -824,7 +866,7 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEnd ) // We read the end tag. Return it to the parent. if ( ele && ele->ClosingType() == XMLElement::CLOSING ) { if ( parentEnd ) { - *parentEnd = ele->_value; + ele->_value.TransferTo( parentEnd ); } node->_memPool->SetTracked(); // created and then immediately deleted. DeleteNode( node ); @@ -921,6 +963,7 @@ bool XMLText::ShallowEqual( const XMLNode* compare ) const bool XMLText::Accept( XMLVisitor* visitor ) const { + TIXMLASSERT( visitor ); return visitor->Visit( *this ); } @@ -961,6 +1004,7 @@ XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const bool XMLComment::ShallowEqual( const XMLNode* compare ) const { + TIXMLASSERT( compare ); const XMLComment* comment = compare->ToComment(); return ( comment && XMLUtil::StringEqual( comment->Value(), Value() )); } @@ -968,6 +1012,7 @@ bool XMLComment::ShallowEqual( const XMLNode* compare ) const bool XMLComment::Accept( XMLVisitor* visitor ) const { + TIXMLASSERT( visitor ); return visitor->Visit( *this ); } @@ -1009,6 +1054,7 @@ XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const { + TIXMLASSERT( compare ); const XMLDeclaration* declaration = compare->ToDeclaration(); return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() )); } @@ -1017,6 +1063,7 @@ bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const bool XMLDeclaration::Accept( XMLVisitor* visitor ) const { + TIXMLASSERT( visitor ); return visitor->Visit( *this ); } @@ -1057,6 +1104,7 @@ XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const { + TIXMLASSERT( compare ); const XMLUnknown* unknown = compare->ToUnknown(); return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() )); } @@ -1064,6 +1112,7 @@ bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const bool XMLUnknown::Accept( XMLVisitor* visitor ) const { + TIXMLASSERT( visitor ); return visitor->Visit( *this ); } @@ -1220,17 +1269,6 @@ XMLElement::~XMLElement() } -XMLAttribute* XMLElement::FindAttribute( const char* name ) -{ - for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) { - if ( XMLUtil::StringEqual( a->Name(), name ) ) { - return a; - } - } - return 0; -} - - const XMLAttribute* XMLElement::FindAttribute( const char* name ) const { for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) { @@ -1393,6 +1431,7 @@ XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name ) } } if ( !attrib ) { + TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); attrib->_memPool = &_document->_attributePool; if ( last ) { @@ -1442,6 +1481,7 @@ char* XMLElement::ParseAttributes( char* p ) // attribute. if (XMLUtil::IsNameStartChar( *p ) ) { + TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); attrib->_memPool = &_document->_attributePool; attrib->_memPool->SetTracked(); @@ -1544,6 +1584,7 @@ XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const bool XMLElement::ShallowEqual( const XMLNode* compare ) const { + TIXMLASSERT( compare ); const XMLElement* other = compare->ToElement(); if ( other && XMLUtil::StringEqual( other->Value(), Value() )) { @@ -1569,6 +1610,7 @@ bool XMLElement::ShallowEqual( const XMLNode* compare ) const bool XMLElement::Accept( XMLVisitor* visitor ) const { + TIXMLASSERT( visitor ); if ( visitor->VisitEnter( *this, _rootAttribute ) ) { for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { if ( !node->Accept( visitor ) ) { @@ -1623,24 +1665,7 @@ XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) : XMLDocument::~XMLDocument() { - DeleteChildren(); - delete [] _charBuffer; - -#if 0 - _textPool.Trace( "text" ); - _elementPool.Trace( "element" ); - _commentPool.Trace( "comment" ); - _attributePool.Trace( "attribute" ); -#endif - -#ifdef DEBUG - if ( Error() == false ) { - TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() ); - TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() ); - TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() ); - TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() ); - } -#endif + Clear(); } @@ -1648,17 +1673,37 @@ void XMLDocument::Clear() { DeleteChildren(); +#ifdef DEBUG + const bool hadError = Error(); +#endif _errorID = XML_NO_ERROR; _errorStr1 = 0; _errorStr2 = 0; delete [] _charBuffer; _charBuffer = 0; + +#if 0 + _textPool.Trace( "text" ); + _elementPool.Trace( "element" ); + _commentPool.Trace( "comment" ); + _attributePool.Trace( "attribute" ); +#endif + +#ifdef DEBUG + if ( !hadError ) { + TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() ); + TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() ); + TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() ); + TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() ); + } +#endif } XMLElement* XMLDocument::NewElement( const char* name ) { + TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this ); ele->_memPool = &_elementPool; ele->SetName( name ); @@ -1668,6 +1713,7 @@ XMLElement* XMLDocument::NewElement( const char* name ) XMLComment* XMLDocument::NewComment( const char* str ) { + TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() ); XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this ); comment->_memPool = &_commentPool; comment->SetValue( str ); @@ -1677,6 +1723,7 @@ XMLComment* XMLDocument::NewComment( const char* str ) XMLText* XMLDocument::NewText( const char* str ) { + TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); XMLText* text = new (_textPool.Alloc()) XMLText( this ); text->_memPool = &_textPool; text->SetValue( str ); @@ -1686,6 +1733,7 @@ XMLText* XMLDocument::NewText( const char* str ) XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) { + TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() ); XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this ); dec->_memPool = &_commentPool; dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" ); @@ -1695,6 +1743,7 @@ XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) XMLUnknown* XMLDocument::NewUnknown( const char* str ) { + TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() ); XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this ); unk->_memPool = &_commentPool; unk->SetValue( str ); @@ -1703,6 +1752,8 @@ XMLUnknown* XMLDocument::NewUnknown( const char* str ) static FILE* callfopen( const char* filepath, const char* mode ) { + TIXMLASSERT( filepath ); + TIXMLASSERT( mode ); #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) FILE* fp = 0; errno_t err = fopen_s( &fp, filepath, mode ); @@ -1714,6 +1765,24 @@ static FILE* callfopen( const char* filepath, const char* mode ) #endif return fp; } + +void XMLDocument::DeleteNode( XMLNode* node ) { + TIXMLASSERT( node ); + TIXMLASSERT(node->_document == this ); + if (node->_parent) { + node->_parent->DeleteChild( node ); + } + else { + // Isn't in the tree. + // Use the parent delete. + // Also, we need to mark it tracked: we 'know' + // it was never used. + node->_memPool->SetTracked(); + // Call the static XMLNode version: + XMLNode::DeleteNode(node); + } +} + XMLError XMLDocument::LoadFile( const char* filename ) { @@ -1821,6 +1890,16 @@ XMLError XMLDocument::Parse( const char* p, size_t len ) ptrdiff_t delta = p - start; // skip initial whitespace, BOM, etc. ParseDeep( _charBuffer+delta, 0 ); + if ( Error() ) { + // clean up now essentially dangling memory. + // and the parse fail can put objects in the + // pools that are dead and inaccessible. + DeleteChildren(); + _elementPool.Clear(); + _attributePool.Clear(); + _textPool.Clear(); + _commentPool.Clear(); + } return _errorID; } @@ -1837,6 +1916,7 @@ void XMLDocument::Print( XMLPrinter* streamer ) const void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 ) { + TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT ); _errorID = error; _errorStr1 = str1; _errorStr2 = str2; @@ -1844,13 +1924,13 @@ void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 ) const char* XMLDocument::ErrorName() const { - TIXMLASSERT(_errorID >= 0 && _errorID < XML_ERROR_COUNT ); + TIXMLASSERT( _errorID >= 0 && _errorID < XML_ERROR_COUNT ); return _errorNames[_errorID]; } void XMLDocument::PrintError() const { - if ( _errorID ) { + if ( Error() ) { static const int LEN = 20; char buf1[LEN] = { 0 }; char buf2[LEN] = { 0 }; @@ -1887,6 +1967,8 @@ XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) : _entityFlag[ (int)entities[i].value ] = true; } } + // Clang doesn't like indexing arrays with 'char' + // so cast to int. (Looks strange.) _restrictedEntityFlag[(int)'&'] = true; _restrictedEntityFlag[(int)'<'] = true; _restrictedEntityFlag[(int)'>'] = true; // not required, but consistency is nice diff --git a/externals/tinyxml/tinyxml2.h b/externals/tinyxml/tinyxml2.h index 4dfb01505..dd1b2cd23 100644 --- a/externals/tinyxml/tinyxml2.h +++ b/externals/tinyxml/tinyxml2.h @@ -14,7 +14,6 @@ not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. @@ -25,7 +24,7 @@ distribution. #ifndef TINYXML2_INCLUDED #define TINYXML2_INCLUDED -#if defined(ANDROID_NDK) || defined(__BORLANDC__) +#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) # include # include # include @@ -122,9 +121,9 @@ inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) /* Versioning, past 1.0.14: http://semver.org/ */ -static const int TIXML2_MAJOR_VERSION = 2; -static const int TIXML2_MINOR_VERSION = 2; -static const int TIXML2_PATCH_VERSION = 0; +static const int TIXML2_MAJOR_VERSION = 2; +static const int TIXML2_MINOR_VERSION = 2; +static const int TIXML2_PATCH_VERSION = 0; namespace tinyxml2 { @@ -185,6 +184,8 @@ public: char* ParseText( char* in, const char* endTag, int strFlags ); char* ParseName( char* in ); + void TransferTo( StrPair* other ); + private: void Reset(); void CollapseWhitespace(); @@ -198,6 +199,9 @@ private: int _flags; char* _start; char* _end; + + StrPair( const StrPair& other ); // not supported + void operator=( StrPair& other ); // not supported, use TransferTo() }; @@ -261,7 +265,7 @@ public: return _mem[i]; } - const T& PeekTop() const { + const T& PeekTop() const { TIXMLASSERT( _size > 0 ); return _mem[ _size - 1]; } @@ -317,6 +321,7 @@ public: virtual void* Alloc() = 0; virtual void Free( void* ) = 0; virtual void SetTracked() = 0; + virtual void Clear() = 0; }; @@ -329,10 +334,20 @@ class MemPoolT : public MemPool public: MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {} ~MemPoolT() { + Clear(); + } + + void Clear() { // Delete the blocks. - for( int i=0; i<_blockPtrs.Size(); ++i ) { - delete _blockPtrs[i]; + while( !_blockPtrs.Empty()) { + Block* b = _blockPtrs.Pop(); + delete b; } + _root = 0; + _currentAllocs = 0; + _nAllocs = 0; + _maxAllocs = 0; + _nUntracked = 0; } virtual int ItemSize() const { @@ -365,6 +380,7 @@ public: _nUntracked++; return result; } + virtual void Free( void* mem ) { if ( !mem ) { return; @@ -480,7 +496,7 @@ public: } }; -// WARNING: must match XMLErrorNames[] +// WARNING: must match XMLDocument::_errorNames[] enum XMLError { XML_SUCCESS = 0, XML_NO_ERROR = 0, @@ -514,10 +530,8 @@ enum XMLError { class XMLUtil { public: - // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't - // correct, but simple, and usually works. static const char* SkipWhiteSpace( const char* p ) { - while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast(p) ) ) { + while( IsWhiteSpace(*p) ) { ++p; } return p; @@ -525,6 +539,9 @@ public: static char* SkipWhiteSpace( char* p ) { return const_cast( SkipWhiteSpace( const_cast(p) ) ); } + + // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't + // correct, but simple, and usually works. static bool IsWhiteSpace( char p ) { return !IsUTF8Continuation(p) && isspace( static_cast(p) ); } @@ -1474,7 +1491,9 @@ private: XMLElement( const XMLElement& ); // not supported void operator=( const XMLElement& ); // not supported - XMLAttribute* FindAttribute( const char* name ); + XMLAttribute* FindAttribute( const char* name ) { + return const_cast(const_cast(this)->FindAttribute( name )); + } XMLAttribute* FindOrCreateAttribute( const char* name ); //void LinkAttribute( XMLAttribute* attrib ); char* ParseAttributes( char* p ); @@ -1536,7 +1555,11 @@ public: /** Load an XML file from disk. You are responsible - for providing and closing the FILE*. + for providing and closing the FILE*. + + NOTE: The file should be opened as binary ("rb") + not text in order for TinyXML-2 to correctly + do newline normalization. Returns XML_NO_ERROR (0) on success, or an errorID. @@ -1646,9 +1669,7 @@ public: Delete a node associated with this document. It will be unlinked from the DOM. */ - void DeleteNode( XMLNode* node ) { - node->_parent->DeleteChild( node ); - } + void DeleteNode( XMLNode* node ); void SetError( XMLError error, const char* str1, const char* str2 ); @@ -1747,7 +1768,7 @@ private: @verbatim XMLHandle docHandle( &document ); - XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement(); + XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement(); if ( child2 ) { // do something useful