From d198322032c6a5b5a95c64fd1850e26aaea4a0a5 Mon Sep 17 00:00:00 2001 From: Lee Thomason Date: Mon, 6 Feb 2012 08:41:24 -0800 Subject: [PATCH] finally have the placement new working as desired. --- tinyxml2.cpp | 72 ++++++++++++++++++++----------- tinyxml2.h | 117 ++++++++++++++++++++++++++++++++++++++++++++------- xmltest.cpp | 6 +++ 3 files changed, 155 insertions(+), 40 deletions(-) diff --git a/tinyxml2.cpp b/tinyxml2.cpp index 4711b83..65f2689 100644 --- a/tinyxml2.cpp +++ b/tinyxml2.cpp @@ -4,6 +4,9 @@ #include #include #include +#include + +//#pragma warning ( disable : 4291 ) using namespace tinyxml2; @@ -123,7 +126,7 @@ const char* StringPool::Intern( const char* str ) // --------- 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::ParseName( char* p, StrPair* pair ) } -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 @@ char* XMLBase::Identify( XMLDocument* document, char* p, XMLNode** node ) 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 @@ void XMLNode::ClearChildren() 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 @@ XMLElement* XMLNode::FirstChildElement( const char* value ) 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 @@ char* XMLNode::ParseDeep( char* p ) { 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 @@ char* XMLNode::ParseDeep( char* p ) // --------- 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 @@ void XMLComment::Print( XMLStreamer* streamer ) 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 @@ char* XMLElement::ParseAttributes( char* p, bool* closedElement ) // 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::ParseAttributes( char* p, bool* closedElement ) 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 @@ char* XMLElement::ParseDeep( char* p ) ++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() : 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 @@ void XMLDocument::InitDocument() 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 @@ -150,6 +161,72 @@ private: 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; ichunk[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 @@ -203,11 +280,12 @@ private: 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 @@ protected: 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 @@ public: protected: XMLNode( XMLDocument* ); + virtual ~XMLNode(); + void ClearChildren(); XMLDocument* document; @@ -277,6 +359,7 @@ protected: XMLNode* next; private: + MemPool* memPool; void Unlink( XMLNode* child ); }; @@ -286,7 +369,6 @@ class XMLText : public XMLNode 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 @@ public: protected: XMLText( XMLDocument* doc ) : XMLNode( doc ) {} + virtual ~XMLText() {} private: }; @@ -307,7 +390,6 @@ class XMLComment : public XMLNode friend class XMLBase; friend class XMLDocument; public: - virtual ~XMLComment(); virtual void Print( XMLStreamer* ); virtual XMLComment* ToComment() { return this; } @@ -317,7 +399,7 @@ public: protected: XMLComment( XMLDocument* doc ); - + virtual ~XMLComment(); private: }; @@ -327,11 +409,11 @@ class XMLAttribute : public XMLBase { 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 @@ class XMLElement : public XMLNode 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 @@ public: 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 @@ private: class XMLDocument : public XMLNode { + friend class XMLElement; public: XMLDocument(); ~XMLDocument(); @@ -398,9 +479,10 @@ public: 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 @@ private: 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 @@ int main( int argc, const char* argv ) root->InsertEndChild( newElement ); doc.Print(); } + { + XMLDocument* doc = new XMLDocument(); + static const char* test = ""; + doc->Parse( test ); + delete doc; + } return 0; } \ No newline at end of file