finally have the placement new working as desired.
diff --git a/tinyxml2.cpp b/tinyxml2.cpp
index 4711b83..65f2689 100644
--- a/tinyxml2.cpp
+++ b/tinyxml2.cpp
@@ -4,6 +4,9 @@
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
+#include <new.h>
+
+//#pragma warning ( disable : 4291 )
using namespace tinyxml2;
@@ -123,7 +126,7 @@
// --------- XMLBase ----------- //
-// fixme: should take in the entity/newline flags as param
+
char* XMLBase::ParseText( char* p, StrPair* pair, const char* endTag, int strFlags )
{
TIXMLASSERT( endTag && *endTag );
@@ -175,11 +178,11 @@
}
-char* XMLBase::Identify( XMLDocument* document, char* p, XMLNode** node )
+char* XMLDocument::Identify( char* p, XMLNode** node )
{
XMLNode* returnNode = 0;
char* start = p;
- p = XMLNode::SkipWhiteSpace( p );
+ p = XMLBase::SkipWhiteSpace( p );
if( !p || !*p )
{
return 0;
@@ -204,18 +207,20 @@
static const int cdataHeaderLen = 9;
static const int elementHeaderLen = 1;
- if ( StringEqual( p, commentHeader, commentHeaderLen ) ) {
- returnNode = new XMLComment( document );
+ if ( XMLBase::StringEqual( p, commentHeader, commentHeaderLen ) ) {
+ returnNode = new (commentPool.Alloc()) XMLComment( this );
+ returnNode->memPool = &commentPool;
p += commentHeaderLen;
}
- else if ( StringEqual( p, elementHeader, elementHeaderLen ) ) {
- returnNode = new XMLElement( document );
+ else if ( XMLBase::StringEqual( p, elementHeader, elementHeaderLen ) ) {
+ returnNode = new (elementPool.Alloc()) XMLElement( this );
+ returnNode->memPool = &elementPool;
p += elementHeaderLen;
}
// fixme: better text detection
- else if ( (*p != '<') && IsAlphaNum( *p ) ) {
- // fixme: this is filtering out empty text...should it?
- returnNode = new XMLText( document );
+ else if ( (*p != '<') && XMLBase::IsAlphaNum( *p ) ) {
+ returnNode = new (textPool.Alloc()) XMLText( this );
+ returnNode->memPool = &textPool;
p = start; // Back it up, all the text counts.
}
else {
@@ -254,7 +259,13 @@
while( firstChild ) {
XMLNode* node = firstChild;
Unlink( node );
- delete node;
+
+ //delete node;
+ // placement new!
+ MemPool* pool = node->memPool;
+ node->~XMLNode();
+ pool->Free( node );
+ // fixme: memory never free'd.
}
firstChild = lastChild = 0;
}
@@ -310,7 +321,7 @@
for( XMLNode* node=firstChild; node; node=node->next ) {
XMLElement* element = node->ToElement();
if ( element ) {
- if ( !value || StringEqual( element->Name(), value ) ) {
+ if ( !value || XMLBase::StringEqual( element->Name(), value ) ) {
return element;
}
}
@@ -331,12 +342,15 @@
{
while( p && *p ) {
XMLNode* node = 0;
- p = Identify( document, p, &node );
+ p = document->Identify( p, &node );
if ( p && node ) {
p = node->ParseDeep( p );
// FIXME: is it the correct closing element?
if ( node->IsClosingElement() ) {
- delete node;
+ //delete node;
+ MemPool* pool = node->memPool;
+ node->~XMLNode(); // fixme linked list memory not free
+ pool->Free( node );
return p;
}
this->InsertEndChild( node );
@@ -348,7 +362,7 @@
// --------- XMLText ---------- //
char* XMLText::ParseDeep( char* p )
{
- p = ParseText( p, &value, "<", StrPair::TEXT_ELEMENT );
+ p = XMLBase::ParseText( p, &value, "<", StrPair::TEXT_ELEMENT );
// consumes the end tag.
if ( p && *p ) {
return p-1;
@@ -388,19 +402,19 @@
char* XMLComment::ParseDeep( char* p )
{
// Comment parses as text.
- return ParseText( p, &value, "-->", StrPair::COMMENT );
+ return XMLBase::ParseText( p, &value, "-->", StrPair::COMMENT );
}
// --------- XMLAttribute ---------- //
char* XMLAttribute::ParseDeep( char* p )
{
- p = ParseText( p, &name, "=", StrPair::ATTRIBUTE_NAME );
+ p = XMLBase::ParseText( p, &name, "=", StrPair::ATTRIBUTE_NAME );
if ( !p || !*p ) return 0;
char endTag[2] = { *p, 0 };
++p;
- p = ParseText( p, &value, endTag, StrPair::ATTRIBUTE_VALUE );
+ p = XMLBase::ParseText( p, &value, endTag, StrPair::ATTRIBUTE_VALUE );
if ( value.Empty() ) return 0;
return p;
}
@@ -443,15 +457,16 @@
// Read the attributes.
while( p ) {
- p = SkipWhiteSpace( p );
+ p = XMLBase::SkipWhiteSpace( p );
if ( !p || !(*p) ) {
- document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, name.GetStr() );
+ document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, Name() );
return 0;
}
// attribute.
- if ( IsAlpha( *p ) ) {
+ if ( XMLBase::IsAlpha( *p ) ) {
XMLAttribute* attrib = new XMLAttribute( this );
+
p = attrib->ParseDeep( p );
if ( !p ) {
delete attrib;
@@ -497,7 +512,7 @@
char* XMLElement::ParseDeep( char* p )
{
// Read the element name.
- p = SkipWhiteSpace( p );
+ p = XMLBase::SkipWhiteSpace( p );
if ( !p ) return 0;
const char* start = p;
@@ -509,8 +524,8 @@
++p;
}
- p = ParseName( p, &name );
- if ( name.Empty() ) return 0;
+ p = XMLBase::ParseName( p, &value );
+ if ( value.Empty() ) return 0;
bool elementClosed=false;
p = ParseAttributes( p, &elementClosed );
@@ -554,7 +569,13 @@
XMLDocument::~XMLDocument()
{
+ ClearChildren();
delete [] charBuffer;
+
+ TIXMLASSERT( textPool.NAlloc() == 0 );
+ TIXMLASSERT( elementPool.NAlloc() == 0 );
+ TIXMLASSERT( commentPool.NAlloc() == 0 );
+ TIXMLASSERT( attributePool.NAlloc() == 0 );
}
@@ -572,7 +593,8 @@
XMLElement* XMLDocument::NewElement( const char* name )
{
- XMLElement* ele = new XMLElement( this );
+ XMLElement* ele = new (elementPool.Alloc()) XMLElement( this );
+ ele->memPool = &elementPool;
ele->SetName( name );
return ele;
}
diff --git a/tinyxml2.h b/tinyxml2.h
index afd01f4..1f4d719 100644
--- a/tinyxml2.h
+++ b/tinyxml2.h
@@ -12,6 +12,17 @@
- make constructors protected
- hide copy constructor
- hide = operator
+ - #define to remove mem-pooling, and make thread safe
+ - UTF8 support: isAlpha, etc.
+
+ (No reason to ever cast to base)
+ XMLBase -> Utility
+
+ XMLNode
+ Document
+ Pooled
+ Element
+ Text
*/
#include <limits.h>
@@ -150,6 +161,72 @@
int size; // number objects in use
};
+class MemPool
+{
+public:
+ MemPool() {}
+ virtual ~MemPool() {}
+
+ virtual int ItemSize() const = 0;
+ virtual void* Alloc() = 0;
+ virtual void Free( void* ) = 0;
+};
+
+template< int SIZE >
+class MemPoolT : public MemPool
+{
+public:
+ MemPoolT() : root( 0 ), nAlloc( 0 ) {}
+ ~MemPoolT() {
+ // Delete the blocks.
+ for( int i=0; i<blockPtrs.Size(); ++i ) {
+ delete blockPtrs[i];
+ }
+ }
+
+ virtual int ItemSize() const { return SIZE; }
+ int NAlloc() const { return nAlloc; }
+
+ virtual void* Alloc() {
+ if ( !root ) {
+ // Need a new block.
+ Block* block = new Block();
+ blockPtrs.Push( block );
+
+ for( int i=0; i<COUNT-1; ++i ) {
+ block->chunk[i].next = &block->chunk[i+1];
+ }
+ block->chunk[COUNT-1].next = 0;
+ root = block->chunk;
+ }
+ void* result = root;
+ root = root->next;
+ ++nAlloc;
+ return result;
+ }
+ virtual void Free( void* mem ) {
+ if ( !mem ) return;
+ --nAlloc;
+ Chunk* chunk = (Chunk*)mem;
+ memset( chunk, 0xfe, sizeof(Chunk) );
+ chunk->next = root;
+ root = chunk;
+ }
+
+private:
+ enum { COUNT = 1024/SIZE };
+ union Chunk {
+ Chunk* next;
+ char mem[SIZE];
+ };
+ struct Block {
+ Chunk chunk[COUNT];
+ };
+ DynArray< Block*, 10 > blockPtrs;
+ Chunk* root;
+ int nAlloc;
+};
+
/*
class StringStack
@@ -204,10 +281,11 @@
class XMLBase
{
public:
+
+public:
XMLBase() {}
virtual ~XMLBase() {}
-protected:
static const char* SkipWhiteSpace( const char* p ) { while( isspace( *p ) ) { ++p; } return p; }
static char* SkipWhiteSpace( char* p ) { while( isspace( *p ) ) { ++p; } return p; }
@@ -228,18 +306,20 @@
inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalnum( anyByte ) : 1; }
inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalpha( anyByte ) : 1; }
- char* ParseText( char* in, StrPair* pair, const char* endTag, int strFlags );
- char* ParseName( char* in, StrPair* pair );
- char* Identify( XMLDocument* document, char* p, XMLNode** node );
+ static char* ParseText( char* in, StrPair* pair, const char* endTag, int strFlags );
+ static char* ParseName( char* in, StrPair* pair );
+
+private:
};
-class XMLNode : public XMLBase
+class XMLNode
{
friend class XMLDocument;
friend class XMLElement;
public:
- virtual ~XMLNode();
+ //void* operator new( size_t size, MemPool* pool );
+ //void operator delete( void* mem, MemPool* pool );
XMLNode* InsertEndChild( XMLNode* addThis );
virtual void Print( XMLStreamer* streamer );
@@ -263,6 +343,8 @@
protected:
XMLNode( XMLDocument* );
+ virtual ~XMLNode();
+
void ClearChildren();
XMLDocument* document;
@@ -277,6 +359,7 @@
XMLNode* next;
private:
+ MemPool* memPool;
void Unlink( XMLNode* child );
};
@@ -286,7 +369,6 @@
friend class XMLBase;
friend class XMLDocument;
public:
- virtual ~XMLText() {}
virtual void Print( XMLStreamer* streamer );
const char* Value() { return value.GetStr(); }
void SetValue( const char* );
@@ -297,6 +379,7 @@
protected:
XMLText( XMLDocument* doc ) : XMLNode( doc ) {}
+ virtual ~XMLText() {}
private:
};
@@ -307,7 +390,6 @@
friend class XMLBase;
friend class XMLDocument;
public:
- virtual ~XMLComment();
virtual void Print( XMLStreamer* );
virtual XMLComment* ToComment() { return this; }
@@ -317,7 +399,7 @@
protected:
XMLComment( XMLDocument* doc );
-
+ virtual ~XMLComment();
private:
};
@@ -327,11 +409,11 @@
{
friend class XMLElement;
public:
- XMLAttribute( XMLElement* element ) : next( 0 ) {}
- virtual ~XMLAttribute() {}
virtual void Print( XMLStreamer* streamer );
private:
+ XMLAttribute( XMLElement* element ) : next( 0 ) {}
+ virtual ~XMLAttribute() {}
char* ParseDeep( char* p );
StrPair name;
@@ -345,8 +427,6 @@
friend class XMLBase;
friend class XMLDocument;
public:
- virtual ~XMLElement();
-
const char* Name() const { return Value(); }
void SetName( const char* str ) { SetValue( str ); }
@@ -360,11 +440,11 @@
protected:
XMLElement( XMLDocument* doc );
+ virtual ~XMLElement();
private:
char* ParseAttributes( char* p, bool *closedElement );
- mutable StrPair name;
bool closing;
XMLAttribute* rootAttribute;
XMLAttribute* lastAttribute;
@@ -373,6 +453,7 @@
class XMLDocument : public XMLNode
{
+ friend class XMLElement;
public:
XMLDocument();
~XMLDocument();
@@ -398,9 +479,10 @@
const char* GetErrorStr1() const { return errorStr1; }
const char* GetErrorStr2() const { return errorStr2; }
-// const char* Intern( const char* );
+ char* Identify( char* p, XMLNode** node );
private:
+
XMLDocument( const XMLDocument& ); // intentionally not implemented
void InitDocument();
@@ -409,6 +491,11 @@
const char* errorStr2;
char* charBuffer;
//StringStack stringPool;
+
+ MemPoolT< sizeof(XMLElement) > elementPool;
+ MemPoolT< sizeof(XMLAttribute) > attributePool;
+ MemPoolT< sizeof(XMLText) > textPool;
+ MemPoolT< sizeof(XMLComment) > commentPool;
};
diff --git a/xmltest.cpp b/xmltest.cpp
index 5df3feb..bef0216 100644
--- a/xmltest.cpp
+++ b/xmltest.cpp
@@ -61,5 +61,11 @@
root->InsertEndChild( newElement );
doc.Print();
}
+ {
+ XMLDocument* doc = new XMLDocument();
+ static const char* test = "<element><sub/></element>";
+ doc->Parse( test );
+ delete doc;
+ }
return 0;
}
\ No newline at end of file