From 5cae8977750b3738da08ae1f320a182792dc9c3b Mon Sep 17 00:00:00 2001 From: Lee Thomason Date: Tue, 24 Jan 2012 18:03:07 -0800 Subject: [PATCH] pulled out streamer class. --- tinyxml2.cpp | 186 +++++++++++++++++++++++++++++++++++++++++++++------ tinyxml2.h | 65 +++++++++++++++--- xmltest.cpp | 19 +++--- 3 files changed, 230 insertions(+), 40 deletions(-) diff --git a/tinyxml2.cpp b/tinyxml2.cpp index 9df038f..69a6289 100644 --- a/tinyxml2.cpp +++ b/tinyxml2.cpp @@ -250,10 +250,10 @@ XMLNode* XMLNode::InsertEndChild( XMLNode* addThis ) } -void XMLNode::Print( FILE* fp, int depth ) +void XMLNode::Print( XMLStreamer* streamer ) { for( XMLNode* node = firstChild; node; node=node->next ) { - node->Print( fp, depth ); + node->Print( streamer ); } } @@ -276,14 +276,14 @@ char* XMLNode::ParseDeep( char* p ) return 0; } - +/* void XMLNode::PrintSpace( FILE* fp, int depth ) { for( int i=0; iPushText( v ); } @@ -317,10 +317,11 @@ XMLComment::~XMLComment() } -void XMLComment::Print( FILE* fp, int depth ) +void XMLComment::Print( XMLStreamer* streamer ) { - XMLNode::Print( fp, depth ); - fprintf( fp, "\n", value.GetStr() ); +// XMLNode::Print( fp, depth ); +// fprintf( fp, "\n", value.GetStr() ); + streamer->PushComment( value.GetStr() ); } @@ -345,10 +346,11 @@ char* XMLAttribute::ParseDeep( char* p ) } -void XMLAttribute::Print( FILE* cfile ) +void XMLAttribute::Print( XMLStreamer* streamer ) { // fixme: sort out single vs. double quote - fprintf( cfile, "%s=\"%s\"", name.GetStr(), value.GetStr() ); + //fprintf( cfile, "%s=\"%s\"", name.GetStr(), value.GetStr() ); + streamer->PushAttribute( name.GetStr(), value.GetStr() ); } @@ -460,19 +462,26 @@ char* XMLElement::ParseDeep( char* p ) } -void XMLElement::Print( FILE* cfile, int depth ) +void XMLElement::Print( XMLStreamer* streamer ) { - if ( !parent || !parent->IsTextParent() ) { - PrintSpace( cfile, depth ); - } - fprintf( cfile, "<%s", Name() ); + //if ( !parent || !parent->IsTextParent() ) { + // PrintSpace( cfile, depth ); + //} + //fprintf( cfile, "<%s", Name() ); + streamer->OpenElement( Name(), IsTextParent() ); for( XMLAttribute* attrib=rootAttribute; attrib; attrib=attrib->next ) { - fprintf( cfile, " " ); - attrib->Print( cfile ); + //fprintf( cfile, " " ); + attrib->Print( streamer ); + } - if ( firstChild ) { + for( XMLNode* node=firstChild; node; node=node->next ) { + node->Print( streamer ); + } + streamer->CloseElement(); + +/* if ( firstChild ) { fprintf( cfile, ">", Name() ); if ( !IsTextParent() ) { fprintf( cfile, "\n" ); @@ -492,7 +501,7 @@ void XMLElement::Print( FILE* cfile, int depth ) if ( !IsTextParent() ) { fprintf( cfile, "\n" ); } - } + }*/ } @@ -520,10 +529,13 @@ bool XMLDocument::Parse( const char* p ) } -void XMLDocument::Print( FILE* fp, int depth ) +void XMLDocument::Print( XMLStreamer* streamer ) { + XMLStreamer stdStreamer( stdout ); + if ( !streamer ) + streamer = &stdStreamer; for( XMLNode* node = firstChild; node; node=node->next ) { - node->Print( fp, depth ); + node->Print( streamer ); } } @@ -533,3 +545,133 @@ void XMLDocument::SetError( int error, const char* str1, const char* str2 ) printf( "ERROR: id=%d '%s' '%s'\n", error, str1, str2 ); } + +StringStack::StringStack() +{ + mem = new char[INIT]; + *mem = 0; + inUse = 1; // always has a null + allocated = INIT; + nPositive = 0; +} + + +void StringStack::Push( const char* str ) { + int needed = strlen( str ) + 1; + if ( needed > 1 ) + nPositive++; + if ( inUse+needed > allocated ) { + // fixme: power of 2 + // less stupid allocation + int more = inUse+needed + 1000; + + char* newMem = new char[more]; + memcpy( newMem, mem, inUse ); + delete [] mem; + mem = newMem; + } + strcpy( mem+inUse, str ); + inUse += needed; +} + + +const char* StringStack::Pop() { + TIXMLASSERT( inUse > 1 ); + const char* p = mem+inUse-2; + if ( *p ) { + nPositive--; + } + while( *p ) { // stack starts with a null, don't need to check for 'mem' + TIXMLASSERT( p > mem ); + --p; + } + inUse = p-mem+1; + return p+1; +} + + +XMLStreamer::XMLStreamer( FILE* file ) : fp( file ), depth( 0 ), elementJustOpened( false ) +{ +} + + +void XMLStreamer::PrintSpace( int depth ) +{ + for( int i=0; i" ); + if ( text.NumPositive() == 0 ) { + fprintf( fp, "\n" ); + } + } + else { + PrintSpace( depth ); + fprintf( fp, "", name ); + if ( text.NumPositive() == 0 ) { + fprintf( fp, "\n" ); + } + } + elementJustOpened = false; +} + + +void XMLStreamer::SealElement() +{ + elementJustOpened = false; + fprintf( fp, ">" ); + if ( text.NumPositive() == 0 ) { + fprintf( fp, "\n" ); + } +} + + +void XMLStreamer::PushText( const char* text ) +{ + if ( elementJustOpened ) { + SealElement(); + } + fprintf( fp, "%s", text ); +} + + +void XMLStreamer::PushComment( const char* comment ) +{ + if ( elementJustOpened ) { + SealElement(); + } + PrintSpace( depth ); + fprintf( fp, "\n", comment ); +} diff --git a/tinyxml2.h b/tinyxml2.h index 4fbd33c..ddf285f 100644 --- a/tinyxml2.h +++ b/tinyxml2.h @@ -36,6 +36,8 @@ class XMLComment; class XMLNode; class XMLText; +class XMLStreamer; + // internal - move to separate namespace struct CharBuffer { @@ -106,6 +108,7 @@ protected: char* Identify( XMLDocument* document, char* p, XMLNode** node ); }; + class XMLNode : public XMLBase { friend class XMLDocument; @@ -114,7 +117,7 @@ public: virtual ~XMLNode(); XMLNode* InsertEndChild( XMLNode* addThis ); - virtual void Print( FILE* cfile, int depth ); + virtual void Print( XMLStreamer* streamer ); virtual XMLElement* ToElement() { return 0; } virtual XMLText* ToText() { return 0; } @@ -142,8 +145,6 @@ protected: XMLNode* next; private: - void PrintSpace( FILE* cfile, int depth ); // prints leading spaces. - }; @@ -153,7 +154,7 @@ public: XMLText( XMLDocument* doc ) : XMLNode( doc ) {} virtual ~XMLText() {} - virtual void Print( FILE* cfile, int depth ); + virtual void Print( XMLStreamer* streamer ); const char* Value() { return value.GetStr(); } virtual XMLText* ToText() { return this; } @@ -172,7 +173,7 @@ public: XMLComment( XMLDocument* doc ); virtual ~XMLComment(); - virtual void Print( FILE* cfile, int depth ); + virtual void Print( XMLStreamer* ); virtual XMLComment* ToComment() { return this; } const char* Value() { return value.GetStr(); } @@ -192,7 +193,7 @@ class XMLAttribute : public XMLBase public: XMLAttribute( XMLElement* element ) : next( 0 ) {} virtual ~XMLAttribute() {} - virtual void Print( FILE* cfile ); + virtual void Print( XMLStreamer* streamer ); private: char* ParseDeep( char* p ); @@ -210,7 +211,7 @@ public: virtual ~XMLElement(); const char* Name() { return name.GetStr(); } - virtual void Print( FILE* cfile, int depth ); + virtual void Print( XMLStreamer* ); virtual XMLElement* ToElement() { return this; } virtual bool IsClosingElement() const { return closing; } @@ -236,7 +237,7 @@ public: ~XMLDocument(); bool Parse( const char* ); - void Print( FILE* cfile=stdout, int depth=0 ); + void Print( XMLStreamer* streamer=0 ); /* XMLNode* Root() { return root; } @@ -255,6 +256,54 @@ private: }; +class StringStack +{ +public: + StringStack(); + ~StringStack() { delete[] mem; } + + void Push( const char* str ); + const char* Pop(); + + int NumPositive() const { return nPositive; } + +private: + enum { + INIT=10 // fixme, super small for testing + }; + char* mem; + int inUse; // includes null + int allocated; // bytes allocated + int nPositive; // number of strings with len > 0 +}; + + +class XMLStreamer +{ +public: + XMLStreamer( FILE* file ); + ~XMLStreamer() {} + + void OpenElement( const char* name, bool textParent ); + void PushAttribute( const char* name, const char* value ); + void CloseElement(); + + void PushText( const char* text ); + void PushComment( const char* comment ); + +private: + void SealElement(); + void PrintSpace( int depth ); + + FILE* fp; + int depth; + bool elementJustOpened; + + StringStack stack; + StringStack text; +}; + + }; // tinyxml2 diff --git a/xmltest.cpp b/xmltest.cpp index 6090a79..6376d91 100644 --- a/xmltest.cpp +++ b/xmltest.cpp @@ -28,25 +28,24 @@ int main( int argc, const char* argv ) } #endif { - static const char* test[] = { //"", - "", - "", - //"", - "", - "", + static const char* test[] = { //"", + //"", + //"", + //"", + "", "", - " \n \n ", + //" \n \n ", "", "", - "Text inside element.", - "", + //"Text inside element.", + //"", "Text inside and bolded in the element.", 0 }; for( int i=0; test[i]; ++i ) { XMLDocument doc; doc.Parse( test[i] ); - doc.Print( stdout ); + doc.Print(); printf( "----------------------------------------------\n" ); } }