From 2c85a711f109501bf0862e94420012c949c21376 Mon Sep 17 00:00:00 2001 From: Lee Thomason Date: Tue, 31 Jan 2012 08:24:24 -0800 Subject: [PATCH] more refactoring. cleaning out container classes. --- tinyxml2.cpp | 64 ++++++++++-- tinyxml2.h | 272 ++++++++++++++++++++++++++++++++------------------- xmltest.cpp | 9 ++ 3 files changed, 236 insertions(+), 109 deletions(-) diff --git a/tinyxml2.cpp b/tinyxml2.cpp index 148c9ad..4711b83 100644 --- a/tinyxml2.cpp +++ b/tinyxml2.cpp @@ -95,6 +95,32 @@ const char* StrPair::GetStr() return start; } +/* +const char* StringPool::Intern( const char* str ) +{ + // Treat the array as a linear, inplace hash table. + // Nothing can get deleted, so that's handy. + if ( size > pool.Size()*3/4 ) { + DynArray< const char*, 20 > store; + for( int i=0; inext ) { + XMLElement* element = node->ToElement(); + if ( element ) { + if ( !value || StringEqual( element->Name(), value ) ) { + return element; + } + } + } + return 0; +} + + void XMLNode::Print( XMLStreamer* streamer ) { for( XMLNode* node = firstChild; node; node=node->next ) { @@ -530,6 +570,14 @@ void XMLDocument::InitDocument() } +XMLElement* XMLDocument::NewElement( const char* name ) +{ + XMLElement* ele = new XMLElement( this ); + ele->SetName( name ); + return ele; +} + + int XMLDocument::Parse( const char* p ) { ClearChildren(); @@ -568,6 +616,7 @@ void XMLDocument::SetError( int error, const char* str1, const char* str2 ) } +/* StringStack::StringStack() { nPositive = 0; @@ -602,6 +651,7 @@ const char* StringStack::Pop() { mem.PopArr( strlen(p)+1 ); return p+1; } +*/ XMLStreamer::XMLStreamer( FILE* file ) : fp( file ), depth( 0 ), elementJustOpened( false ) @@ -664,11 +714,11 @@ void XMLStreamer::OpenElement( const char* name, bool textParent ) if ( elementJustOpened ) { SealElement(); } - if ( text.NumPositive() == 0 ) { + if ( !TextOnStack() ) { PrintSpace( depth ); } stack.Push( name ); - text.Push( textParent ? "T" : "" ); + text.Push( textParent ? 'T' : 'e' ); // fixme: can names have entities? fprintf( fp, "<%s", name ); @@ -690,22 +740,22 @@ void XMLStreamer::CloseElement() { --depth; const char* name = stack.Pop(); - int wasPositive = text.NumPositive(); + bool wasText = TextOnStack(); text.Pop(); if ( elementJustOpened ) { fprintf( fp, "/>" ); - if ( text.NumPositive() == 0 ) { + if ( !wasText ) { fprintf( fp, "\n" ); } } else { - if ( wasPositive == 0 ) { + if ( !wasText ) { PrintSpace( depth ); } // fixme can names have entities? fprintf( fp, "", name ); - if ( text.NumPositive() == 0 ) { + if ( !TextOnStack() ) { fprintf( fp, "\n" ); } } @@ -717,7 +767,7 @@ void XMLStreamer::SealElement() { elementJustOpened = false; fprintf( fp, ">" ); - if ( text.NumPositive() == 0 ) { + if ( !TextOnStack() ) { fprintf( fp, "\n" ); } } diff --git a/tinyxml2.h b/tinyxml2.h index 4d2d70e..afd01f4 100644 --- a/tinyxml2.h +++ b/tinyxml2.h @@ -1,9 +1,23 @@ #ifndef TINYXML2_INCLUDED #define TINYXML2_INCLUDED +/* + TODO + - const and non-const versions of API + - memory pool the class construction + - attribute accessors + - node navigation + - handles + - visit pattern - change streamer? + - make constructors protected + - hide copy constructor + - hide = operator +*/ + #include #include #include +#include #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__) #ifndef DEBUG @@ -38,18 +52,6 @@ class XMLText; class XMLStreamer; -/* -// internal - move to separate namespace -struct CharBuffer -{ - size_t length; - char mem[1]; - - static CharBuffer* Construct( const char* in ); - static void Free( CharBuffer* ); -}; -*/ - class StrPair { public: @@ -70,6 +72,8 @@ public: const char* GetStr(); bool Empty() const { return start == end; } + void SetInternedStr( const char* str ) { this->start = (char*) str; this->end = 0; this->flags = 0; } + private: enum { NEEDS_FLUSH = 0x100 @@ -82,6 +86,121 @@ private: }; +template +class DynArray +{ +public: + DynArray< T, INIT >() + { + mem = pool; + allocated = INIT; + size = 0; + } + ~DynArray() + { + if ( mem != pool ) { + delete mem; + } + } + void Push( T t ) + { + EnsureCapacity( size+1 ); + mem[size++] = t; + } + + T* PushArr( int count ) + { + EnsureCapacity( size+count ); + T* ret = &mem[size]; + size += count; + return ret; + } + T Pop() { + return mem[--size]; + } + void PopArr( int count ) + { + TIXMLASSERT( size >= count ); + size -= count; + } + + bool Empty() const { return size == 0; } + T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; } + const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; } + int Size() const { return size; } + const T* Mem() const { return mem; } + T* Mem() { return mem; } + + +private: + void EnsureCapacity( int cap ) { + if ( cap > allocated ) { + int newAllocated = cap * 2; + T* newMem = new T[newAllocated]; + memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs + if ( mem != pool ) delete [] mem; + mem = newMem; + allocated = newAllocated; + } + } + + T* mem; + T pool[INIT]; + int allocated; // objects allocated + int size; // number objects in use +}; + + +/* +class StringStack +{ +public: + StringStack(); + virtual ~StringStack(); + + void Push( const char* str ); + const char* Pop(); + + int NumPositive() const { return nPositive; } + +private: + DynArray< char, 50 > mem; + int nPositive; // number of strings with len > 0 +}; +*/ + +/* +class StringPool +{ +public: + enum { INIT_SIZE=20 }; + + StringPool() : size( 0 ) { + const char** mem = pool.PushArr( INIT_SIZE ); + memset( (void*)mem, 0, sizeof(char)*INIT_SIZE ); + } + ~StringPool() {} + + const char* Intern( const char* str ); + +private: + // FNV hash + int Hash( const char* s ) { + #define FNV_32_PRIME ((int)0x01000193) + int hval = 0; + while (*s) { + hval *= FNV_32_PRIME; + hval ^= (int)*s++; + } + return hval; + } + + int size; + DynArray< const char*, INIT_SIZE > pool; // the hash table + StringStack store; // memory for the interned strings +}; +*/ + class XMLBase { public: @@ -125,10 +244,16 @@ public: XMLNode* InsertEndChild( XMLNode* addThis ); virtual void Print( XMLStreamer* streamer ); + const char* Value() const { return value.GetStr(); } + void SetValue( const char* val ) { value.SetInternedStr( val ); } + virtual XMLElement* ToElement() { return 0; } virtual XMLText* ToText() { return 0; } virtual XMLComment* ToComment() { return 0; } + XMLNode* FirstChild() { return firstChild; } + XMLElement* FirstChildElement( const char* value=0 ); + // fixme: guarentee null terminator to avoid internal checks virtual char* ParseDeep( char* ); @@ -143,6 +268,7 @@ protected: XMLDocument* document; XMLNode* parent; bool isTextParent; + mutable StrPair value; XMLNode* firstChild; XMLNode* lastChild; @@ -157,29 +283,31 @@ private: class XMLText : public XMLNode { + friend class XMLBase; + friend class XMLDocument; public: - XMLText( XMLDocument* doc ) : XMLNode( doc ) {} virtual ~XMLText() {} - virtual void Print( XMLStreamer* streamer ); const char* Value() { return value.GetStr(); } + void SetValue( const char* ); + virtual XMLText* ToText() { return this; } char* ParseDeep( char* ); protected: + XMLText( XMLDocument* doc ) : XMLNode( doc ) {} private: - StrPair value; }; class XMLComment : public XMLNode { + friend class XMLBase; + friend class XMLDocument; public: - XMLComment( XMLDocument* doc ); virtual ~XMLComment(); - virtual void Print( XMLStreamer* ); virtual XMLComment* ToComment() { return this; } @@ -188,9 +316,10 @@ public: char* ParseDeep( char* ); protected: + XMLComment( XMLDocument* doc ); + private: - StrPair value; }; @@ -213,24 +342,29 @@ private: class XMLElement : public XMLNode { + friend class XMLBase; + friend class XMLDocument; public: - XMLElement( XMLDocument* doc ); virtual ~XMLElement(); - const char* Name() { return name.GetStr(); } + const char* Name() const { return Value(); } + void SetName( const char* str ) { SetValue( str ); } + virtual void Print( XMLStreamer* ); virtual XMLElement* ToElement() { return this; } - virtual bool IsClosingElement() const { return closing; } + // internal: + virtual bool IsClosingElement() const { return closing; } char* ParseDeep( char* p ); protected: + XMLElement( XMLDocument* doc ); private: char* ParseAttributes( char* p, bool *closedElement ); - StrPair name; + mutable StrPair name; bool closing; XMLAttribute* rootAttribute; XMLAttribute* lastAttribute; @@ -249,6 +383,8 @@ public: void Print( XMLStreamer* streamer=0 ); + XMLElement* NewElement( const char* name ); + enum { NO_ERROR = 0, ERROR_ELEMENT_MISMATCH, @@ -262,6 +398,8 @@ public: const char* GetErrorStr1() const { return errorStr1; } const char* GetErrorStr2() const { return errorStr2; } +// const char* Intern( const char* ); + private: XMLDocument( const XMLDocument& ); // intentionally not implemented void InitDocument(); @@ -270,84 +408,7 @@ private: const char* errorStr1; const char* errorStr2; char* charBuffer; -}; - - -template -class DynArray -{ -public: - DynArray< T, INIT >() - { - mem = pool; - allocated = INIT; - size = 0; - } - ~DynArray() - { - if ( mem != pool ) { - delete mem; - } - } - void Push( T t ) - { - EnsureCapacity( size+1 ); - mem[size++] = t; - } - - T* PushArr( int count ) - { - EnsureCapacity( size+count ); - T* ret = &mem[size]; - size += count; - return ret; - } - T Pop() { - return mem[--size]; - } - void PopArr( int count ) - { - TIXMLASSERT( size >= count ); - size -= count; - } - int Size() const { return size; } - const T* Mem() const { return mem; } - T* Mem() { return mem; } - - -private: - void EnsureCapacity( int cap ) { - if ( cap > allocated ) { - int newAllocated = cap * 2; - T* newMem = new T[newAllocated]; - memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs - if ( mem != pool ) delete [] mem; - mem = newMem; - allocated = newAllocated; - } - } - - T* mem; - T pool[INIT]; - int allocated; // objects allocated - int size; // number objects in use -}; - - -class StringStack -{ -public: - StringStack(); - virtual ~StringStack(); - - void Push( const char* str ); - const char* Pop(); - - int NumPositive() const { return nPositive; } - -private: - DynArray< char, 50 > mem; - int nPositive; // number of strings with len > 0 + //StringStack stringPool; }; @@ -368,6 +429,13 @@ private: void SealElement(); void PrintSpace( int depth ); void PrintString( const char* ); // prints out, after detecting entities. + bool TextOnStack() const { + for( int i=0; i stack; - StringStack text; + DynArray< const char*, 10 > stack; + DynArray< char, 10 > text; }; diff --git a/xmltest.cpp b/xmltest.cpp index 8d09bc6..5df3feb 100644 --- a/xmltest.cpp +++ b/xmltest.cpp @@ -52,5 +52,14 @@ int main( int argc, const char* argv ) printf( "----------------------------------------------\n" ); } } + { + static const char* test = "Text before."; + XMLDocument doc; + doc.Parse( test ); + XMLElement* root = doc.FirstChildElement(); + XMLElement* newElement = doc.NewElement( "Subelement" ); + root->InsertEndChild( newElement ); + doc.Print(); + } return 0; } \ No newline at end of file