diff --git a/externals/tinyxml/tinyxml2.cpp b/externals/tinyxml/tinyxml2.cpp index 018f9a9ea..8a3f857fa 100644 --- a/externals/tinyxml/tinyxml2.cpp +++ b/externals/tinyxml/tinyxml2.cpp @@ -368,6 +368,19 @@ const char* StrPair::GetStr() // --------- XMLUtil ----------- // +const char* XMLUtil::writeBoolTrue = "true"; +const char* XMLUtil::writeBoolFalse = "false"; + +void XMLUtil::SetBoolSerialization(const char* writeTrue, const char* writeFalse) +{ + static const char* defTrue = "true"; + static const char* defFalse = "false"; + + writeBoolTrue = (writeTrue) ? writeTrue : defTrue; + writeBoolFalse = (writeFalse) ? writeFalse : defFalse; +} + + const char* XMLUtil::ReadBOM( const char* p, bool* bom ) { TIXMLASSERT( p ); @@ -411,20 +424,24 @@ void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length output += *length; - // Scary scary fall throughs. + // Scary scary fall throughs are annotated with carefully designed comments + // to suppress compiler warnings such as -Wimplicit-fallthrough in gcc switch (*length) { case 4: --output; *output = (char)((input | BYTE_MARK) & BYTE_MASK); input >>= 6; + //fall through case 3: --output; *output = (char)((input | BYTE_MARK) & BYTE_MASK); input >>= 6; + //fall through case 2: --output; *output = (char)((input | BYTE_MARK) & BYTE_MASK); input >>= 6; + //fall through case 1: --output; *output = (char)(input | FIRST_BYTE_MARK[*length]); @@ -545,7 +562,7 @@ void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize ) void XMLUtil::ToStr( bool v, char* buffer, int bufferSize ) { - TIXML_SNPRINTF( buffer, bufferSize, "%s", v ? "true" : "false" ); + TIXML_SNPRINTF( buffer, bufferSize, "%s", v ? writeBoolTrue : writeBoolFalse); } /* @@ -665,46 +682,34 @@ char* XMLDocument::Identify( char* p, XMLNode** node ) TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) ); // use same memory pool XMLNode* returnNode = 0; if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) { - TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() ); - returnNode = new (_commentPool.Alloc()) XMLDeclaration( this ); + returnNode = CreateUnlinkedNode( _commentPool ); returnNode->_parseLineNum = _parseCurLineNum; - returnNode->_memPool = &_commentPool; p += xmlHeaderLen; } else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) { - TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() ); - returnNode = new (_commentPool.Alloc()) XMLComment( this ); + returnNode = CreateUnlinkedNode( _commentPool ); returnNode->_parseLineNum = _parseCurLineNum; - returnNode->_memPool = &_commentPool; p += commentHeaderLen; } else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) { - TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); - XMLText* text = new (_textPool.Alloc()) XMLText( this ); + XMLText* text = CreateUnlinkedNode( _textPool ); returnNode = text; returnNode->_parseLineNum = _parseCurLineNum; - returnNode->_memPool = &_textPool; p += cdataHeaderLen; text->SetCData( true ); } else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) { - TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() ); - returnNode = new (_commentPool.Alloc()) XMLUnknown( this ); + returnNode = CreateUnlinkedNode( _commentPool ); returnNode->_parseLineNum = _parseCurLineNum; - returnNode->_memPool = &_commentPool; p += dtdHeaderLen; } else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) { - TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); - returnNode = new (_elementPool.Alloc()) XMLElement( this ); + returnNode = CreateUnlinkedNode( _elementPool ); returnNode->_parseLineNum = _parseCurLineNum; - returnNode->_memPool = &_elementPool; p += elementHeaderLen; } else { - TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); - returnNode = new (_textPool.Alloc()) XMLText( this ); - returnNode->_memPool = &_textPool; + returnNode = CreateUnlinkedNode( _textPool ); returnNode->_parseLineNum = _parseCurLineNum; // Report line of first non-whitespace character p = start; // Back it up, all the text counts. _parseCurLineNum = startLine; @@ -771,6 +776,18 @@ void XMLNode::SetValue( const char* str, bool staticMem ) } } +XMLNode* XMLNode::DeepClone(XMLDocument* target) const +{ + XMLNode* clone = this->ShallowClone(target); + if (!clone) return 0; + + for (const XMLNode* child = this->FirstChild(); child; child = child->NextSibling()) { + XMLNode* childClone = child->DeepClone(target); + TIXMLASSERT(childClone); + clone->InsertEndChild(childClone); + } + return clone; +} void XMLNode::DeleteChildren() { @@ -800,6 +817,8 @@ void XMLNode::Unlink( XMLNode* child ) if ( child->_next ) { child->_next->_prev = child->_prev; } + child->_next = 0; + child->_prev = 0; child->_parent = 0; } @@ -810,6 +829,9 @@ void XMLNode::DeleteChild( XMLNode* node ) TIXMLASSERT( node->_document == _document ); TIXMLASSERT( node->_parent == this ); Unlink( node ); + TIXMLASSERT(node->_prev == 0); + TIXMLASSERT(node->_next == 0); + TIXMLASSERT(node->_parent == 0); DeleteNode( node ); } @@ -954,7 +976,7 @@ const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const } -char* XMLNode::ParseDeep( char* p, StrPair* parentEnd, int* curLineNumPtr ) +char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) { // This is a recursive method, but thinking about it "at the current level" // it is a pretty simple flat list: @@ -1019,8 +1041,8 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEnd, int* curLineNumPtr ) if ( ele ) { // We read the end tag. Return it to the parent. if ( ele->ClosingType() == XMLElement::CLOSING ) { - if ( parentEnd ) { - ele->_value.TransferTo( parentEnd ); + if ( parentEndTag ) { + ele->_value.TransferTo( parentEndTag ); } node->_memPool->SetTracked(); // created and then immediately deleted. DeleteNode( node ); @@ -1054,11 +1076,16 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEnd, int* curLineNumPtr ) return 0; } -void XMLNode::DeleteNode( XMLNode* node ) +/*static*/ void XMLNode::DeleteNode( XMLNode* node ) { if ( node == 0 ) { return; } + TIXMLASSERT(node->_document); + if (!node->ToDocument()) { + node->_document->MarkInUse(node); + } + MemPool* pool = node->_memPool; node->~XMLNode(); pool->Free( node ); @@ -1069,10 +1096,13 @@ void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const TIXMLASSERT( insertThis ); TIXMLASSERT( insertThis->_document == _document ); - if ( insertThis->_parent ) + if (insertThis->_parent) { insertThis->_parent->Unlink( insertThis ); - else + } + else { + insertThis->_document->MarkInUse(insertThis); insertThis->_memPool->SetTracked(); + } } const XMLElement* XMLNode::ToElementWithName( const char* name ) const @@ -1132,6 +1162,7 @@ XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const bool XMLText::ShallowEqual( const XMLNode* compare ) const { + TIXMLASSERT( compare ); const XMLText* text = compare->ToText(); return ( text && XMLUtil::StringEqual( text->Value(), Value() ) ); } @@ -1447,7 +1478,7 @@ void XMLAttribute::SetAttribute( float v ) // --------- XMLElement ---------- // XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), - _closingType( 0 ), + _closingType( OPEN ), _rootAttribute( 0 ) { } @@ -1837,6 +1868,7 @@ XMLAttribute* XMLElement::CreateAttribute() { TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); + TIXMLASSERT( attrib ); attrib->_memPool = &_document->_attributePool; attrib->_memPool->SetTracked(); return attrib; @@ -1846,7 +1878,7 @@ XMLAttribute* XMLElement::CreateAttribute() // // foobar // -char* XMLElement::ParseDeep( char* p, StrPair* strPair, int* curLineNumPtr ) +char* XMLElement::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) { // Read the element name. p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); @@ -1865,11 +1897,11 @@ char* XMLElement::ParseDeep( char* p, StrPair* strPair, int* curLineNumPtr ) } p = ParseAttributes( p, curLineNumPtr ); - if ( !p || !*p || _closingType ) { + if ( !p || !*p || _closingType != OPEN ) { return p; } - p = XMLNode::ParseDeep( p, strPair, curLineNumPtr ); + p = XMLNode::ParseDeep( p, parentEndTag, curLineNumPtr ); return p; } @@ -1938,10 +1970,10 @@ const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = { "XML_ERROR_FILE_NOT_FOUND", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", "XML_ERROR_FILE_READ_ERROR", - "XML_ERROR_ELEMENT_MISMATCH", + "UNUSED_XML_ERROR_ELEMENT_MISMATCH", "XML_ERROR_PARSING_ELEMENT", "XML_ERROR_PARSING_ATTRIBUTE", - "XML_ERROR_IDENTIFYING_TAG", + "UNUSED_XML_ERROR_IDENTIFYING_TAG", "XML_ERROR_PARSING_TEXT", "XML_ERROR_PARSING_CDATA", "XML_ERROR_PARSING_COMMENT", @@ -1955,13 +1987,15 @@ const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = { }; -XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) : +XMLDocument::XMLDocument( bool processEntities, Whitespace whitespaceMode ) : XMLNode( 0 ), _writeBOM( false ), _processEntities( processEntities ), _errorID(XML_SUCCESS), - _whitespace( whitespace ), - _charBuffer( 0 ) + _whitespaceMode( whitespaceMode ), + _errorLineNum( 0 ), + _charBuffer( 0 ), + _parseCurLineNum( 0 ) { // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+) _document = this; @@ -1974,9 +2008,25 @@ XMLDocument::~XMLDocument() } +void XMLDocument::MarkInUse(XMLNode* node) +{ + TIXMLASSERT(node); + TIXMLASSERT(node->_parent == 0); + + for (int i = 0; i < _unlinked.Size(); ++i) { + if (node == _unlinked[i]) { + _unlinked.SwapRemove(i); + break; + } + } +} + void XMLDocument::Clear() { DeleteChildren(); + while( _unlinked.Size()) { + DeleteNode(_unlinked[0]); // Will remove from _unlinked as part of delete. + } #ifdef DEBUG const bool hadError = Error(); @@ -2004,11 +2054,22 @@ void XMLDocument::Clear() } +void XMLDocument::DeepCopy(XMLDocument* target) +{ + TIXMLASSERT(target); + if (target == this) { + return; // technically success - a no-op. + } + + target->Clear(); + for (const XMLNode* node = this->FirstChild(); node; node = node->NextSibling()) { + target->InsertEndChild(node->DeepClone(target)); + } +} + XMLElement* XMLDocument::NewElement( const char* name ) { - TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); - XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this ); - ele->_memPool = &_elementPool; + XMLElement* ele = CreateUnlinkedNode( _elementPool ); ele->SetName( name ); return ele; } @@ -2016,9 +2077,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; + XMLComment* comment = CreateUnlinkedNode( _commentPool ); comment->SetValue( str ); return comment; } @@ -2026,9 +2085,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; + XMLText* text = CreateUnlinkedNode( _textPool ); text->SetValue( str ); return text; } @@ -2036,9 +2093,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; + XMLDeclaration* dec = CreateUnlinkedNode( _commentPool ); dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" ); return dec; } @@ -2046,9 +2101,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; + XMLUnknown* unk = CreateUnlinkedNode( _commentPool ); unk->SetValue( str ); return unk; } @@ -2259,6 +2312,16 @@ void XMLDocument::SetError( XMLError error, const char* str1, const char* str2, return errorName; } +const char* XMLDocument::GetErrorStr1() const +{ + return _errorStr1.GetStr(); +} + +const char* XMLDocument::GetErrorStr2() const +{ + return _errorStr2.GetStr(); +} + const char* XMLDocument::ErrorName() const { return ErrorIDToName(_errorID); diff --git a/externals/tinyxml/tinyxml2.h b/externals/tinyxml/tinyxml2.h index de589bdeb..a372b413b 100644 --- a/externals/tinyxml/tinyxml2.h +++ b/externals/tinyxml/tinyxml2.h @@ -53,7 +53,7 @@ distribution. AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h */ -#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__) +#if defined( _DEBUG ) || defined (__DEBUG__) # ifndef DEBUG # define DEBUG # endif @@ -98,7 +98,7 @@ distribution. /* Versioning, past 1.0.14: http://semver.org/ */ -static const int TIXML2_MAJOR_VERSION = 4; +static const int TIXML2_MAJOR_VERSION = 5; static const int TIXML2_MINOR_VERSION = 0; static const int TIXML2_PATCH_VERSION = 1; @@ -264,6 +264,13 @@ public: return _allocated; } + void SwapRemove(int i) { + TIXMLASSERT(i >= 0 && i < _size); + TIXMLASSERT(_size > 0); + _mem[i] = _mem[_size - 1]; + --_size; + } + const T* Mem() const { TIXMLASSERT( _mem ); return _mem; @@ -284,6 +291,7 @@ private: TIXMLASSERT( cap <= INT_MAX / 2 ); int newAllocated = cap * 2; T* newMem = new T[newAllocated]; + TIXMLASSERT( newAllocated >= _size ); memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs if ( _mem != _pool ) { delete [] _mem; @@ -333,8 +341,8 @@ public: void Clear() { // Delete the blocks. while( !_blockPtrs.Empty()) { - Block* b = _blockPtrs.Pop(); - delete b; + Block* lastBlock = _blockPtrs.Pop(); + delete lastBlock; } _root = 0; _currentAllocs = 0; @@ -505,10 +513,10 @@ enum XMLError { XML_ERROR_FILE_NOT_FOUND, XML_ERROR_FILE_COULD_NOT_BE_OPENED, XML_ERROR_FILE_READ_ERROR, - XML_ERROR_ELEMENT_MISMATCH, + UNUSED_XML_ERROR_ELEMENT_MISMATCH, // remove at next major version XML_ERROR_PARSING_ELEMENT, XML_ERROR_PARSING_ATTRIBUTE, - XML_ERROR_IDENTIFYING_TAG, + UNUSED_XML_ERROR_IDENTIFYING_TAG, // remove at next major version XML_ERROR_PARSING_TEXT, XML_ERROR_PARSING_CDATA, XML_ERROR_PARSING_COMMENT, @@ -527,7 +535,7 @@ enum XMLError { /* Utility functionality. */ -class XMLUtil +class TINYXML2_LIB XMLUtil { public: static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr ) { @@ -605,6 +613,17 @@ public: static bool ToFloat( const char* str, float* value ); static bool ToDouble( const char* str, double* value ); static bool ToInt64(const char* str, int64_t* value); + + // Changes what is serialized for a boolean value. + // Default to "true" and "false". Shouldn't be changed + // unless you have a special testing or compatibility need. + // Be careful: static, global, & not thread safe. + // Be sure to set static const memory as parameters. + static void SetBoolSerialization(const char* writeTrue, const char* writeFalse); + +private: + static const char* writeBoolTrue; + static const char* writeBoolFalse; }; @@ -846,6 +865,21 @@ public: */ virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0; + /** + Make a copy of this node and all its children. + + If the 'target' is null, then the nodes will + be allocated in the current document. If 'target' + is specified, the memory will be allocated is the + specified XMLDocument. + + NOTE: This is probably not the correct tool to + copy a document, since XMLDocuments can have multiple + top level XMLNodes. You probably want to use + XMLDocument::DeepCopy() + */ + XMLNode* DeepClone( XMLDocument* target ) const; + /** Test if 2 nodes are the same, but don't test children. The 2 nodes do not need to be in the same Document. @@ -896,7 +930,7 @@ protected: XMLNode( XMLDocument* ); virtual ~XMLNode(); - virtual char* ParseDeep( char*, StrPair*, int* ); + virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); XMLDocument* _document; XMLNode* _parent; @@ -964,7 +998,7 @@ protected: XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} virtual ~XMLText() {} - char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr ); + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); private: bool _isCData; @@ -995,7 +1029,7 @@ protected: XMLComment( XMLDocument* doc ); virtual ~XMLComment(); - char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr); + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); private: XMLComment( const XMLComment& ); // not supported @@ -1034,7 +1068,7 @@ protected: XMLDeclaration( XMLDocument* doc ); virtual ~XMLDeclaration(); - char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr ); + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); private: XMLDeclaration( const XMLDeclaration& ); // not supported @@ -1069,7 +1103,7 @@ protected: XMLUnknown( XMLDocument* doc ); virtual ~XMLUnknown(); - char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr ); + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); private: XMLUnknown( const XMLUnknown& ); // not supported @@ -1177,7 +1211,7 @@ public: private: enum { BUF_SIZE = 200 }; - XMLAttribute() : _next( 0 ), _memPool( 0 ) {} + XMLAttribute() : _parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {} virtual ~XMLAttribute() {} XMLAttribute( const XMLAttribute& ); // not supported @@ -1548,19 +1582,19 @@ public: float FloatText(float defaultValue = 0) const; // internal: - enum { + enum ElementClosingType { OPEN, // CLOSED, // CLOSING // }; - int ClosingType() const { + ElementClosingType ClosingType() const { return _closingType; } virtual XMLNode* ShallowClone( XMLDocument* document ) const; virtual bool ShallowEqual( const XMLNode* compare ) const; protected: - char* ParseDeep( char* p, StrPair* endTag, int* curLineNumPtr ); + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); private: XMLElement( XMLDocument* doc ); @@ -1578,7 +1612,7 @@ private: XMLAttribute* CreateAttribute(); enum { BUF_SIZE = 200 }; - int _closingType; + ElementClosingType _closingType; // The attribute list is ordered; there is no 'lastAttribute' // because the list needs to be scanned for dupes before adding // a new attribute. @@ -1602,7 +1636,7 @@ class TINYXML2_LIB XMLDocument : public XMLNode friend class XMLElement; public: /// constructor - XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE ); + XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE ); ~XMLDocument(); virtual XMLDocument* ToDocument() { @@ -1666,7 +1700,7 @@ public: return _processEntities; } Whitespace WhitespaceMode() const { - return _whitespace; + return _whitespaceMode; } /** @@ -1769,13 +1803,11 @@ public: static const char* ErrorIDToName(XMLError errorID); /// Return a possibly helpful diagnostic location or string. - const char* GetErrorStr1() const { - return _errorStr1.GetStr(); - } + const char* GetErrorStr1() const; + /// Return a possibly helpful secondary diagnostic location or string. - const char* GetErrorStr2() const { - return _errorStr2.GetStr(); - } + const char* GetErrorStr2() const; + /// Return the line where the error occured, or zero if unknown. int GetErrorLineNum() const { @@ -1787,9 +1819,21 @@ public: /// Clear the document, resetting it to the initial state. void Clear(); - // internal + /** + Copies this document to a target document. + The target will be completely cleared before the copy. + If you want to copy a sub-tree, see XMLNode::DeepClone(). + + NOTE: that the 'target' must be non-null. + */ + void DeepCopy(XMLDocument* target); + + // internal char* Identify( char* p, XMLNode** node ); + // internal + void MarkInUse(XMLNode*); + virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { return 0; } @@ -1804,12 +1848,19 @@ private: bool _writeBOM; bool _processEntities; XMLError _errorID; - Whitespace _whitespace; + Whitespace _whitespaceMode; mutable StrPair _errorStr1; mutable StrPair _errorStr2; int _errorLineNum; char* _charBuffer; int _parseCurLineNum; + // Memory tracking does add some overhead. + // However, the code assumes that you don't + // have a bunch of unlinked nodes around. + // Therefore it takes less memory to track + // in the document vs. a linked list in the XMLNode, + // and the performance is the same. + DynArray _unlinked; MemPoolT< sizeof(XMLElement) > _elementPool; MemPoolT< sizeof(XMLAttribute) > _attributePool; @@ -1819,8 +1870,23 @@ private: static const char* _errorNames[XML_ERROR_COUNT]; void Parse(); + + template + NodeType* CreateUnlinkedNode( MemPoolT& pool ); }; +template +inline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT& pool ) +{ + TIXMLASSERT( sizeof( NodeType ) == PoolElementSize ); + TIXMLASSERT( sizeof( NodeType ) == pool.ItemSize() ); + NodeType* returnNode = new (pool.Alloc()) NodeType( this ); + TIXMLASSERT( returnNode ); + returnNode->_memPool = &pool; + + _unlinked.Push(returnNode); + return returnNode; +} /** A XMLHandle is a class that wraps a node pointer with null checks; this is @@ -2152,6 +2218,7 @@ public: void ClearBuffer() { _buffer.Clear(); _buffer.Push(0); + _firstElement = true; } protected: