Updated TinyXML

This commit is contained in:
Dmitry-Me 2017-08-11 17:56:41 +03:00
parent b28b7712c1
commit c9a63ca606
2 changed files with 207 additions and 77 deletions

View File

@ -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<XMLDeclaration>( _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<XMLComment>( _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<XMLText>( _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<XMLUnknown>( _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<XMLElement>( _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<XMLText>( _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()
// <ele></ele>
// <ele>foo<b>bar</b></ele>
//
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<XMLElement>( _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<XMLComment>( _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<XMLText>( _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<XMLDeclaration>( _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<XMLUnknown>( _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);

View File

@ -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, // <foo>
CLOSED, // <foo/>
CLOSING // </foo>
};
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<XMLNode*, 10> _unlinked;
MemPoolT< sizeof(XMLElement) > _elementPool;
MemPoolT< sizeof(XMLAttribute) > _attributePool;
@ -1819,8 +1870,23 @@ private:
static const char* _errorNames[XML_ERROR_COUNT];
void Parse();
template<class NodeType, int PoolElementSize>
NodeType* CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool );
};
template<class NodeType, int PoolElementSize>
inline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT<PoolElementSize>& 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: