Dream test passing.

This commit is contained in:
Lee Thomason (grinliz) 2012-02-20 20:14:33 -08:00
parent ae25a44d94
commit bd0a8ac60c
4 changed files with 4810 additions and 36 deletions

4546
dream.xml Executable file

File diff suppressed because it is too large Load Diff

View File

@ -82,7 +82,7 @@ char* StrPair::ParseText( char* p, const char* endTag, int strFlags )
} }
++p; ++p;
} }
return p; return 0;
} }
@ -198,17 +198,17 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
// What is this thing? // What is this thing?
// - Elements start with a letter or underscore, but xml is reserved. // - Elements start with a letter or underscore, but xml is reserved.
// - Comments: <!-- // - Comments: <!--
// - Decleration: <?xml // - Decleration: <?
// - Everthing else is unknown to tinyxml. // - Everthing else is unknown to tinyxml.
// //
static const char* xmlHeader = { "<?xml" }; static const char* xmlHeader = { "<?" };
static const char* commentHeader = { "<!--" }; static const char* commentHeader = { "<!--" };
static const char* dtdHeader = { "<!" }; static const char* dtdHeader = { "<!" };
static const char* cdataHeader = { "<![CDATA[" }; static const char* cdataHeader = { "<![CDATA[" };
static const char* elementHeader = { "<" }; // and a header for everything else; check last. static const char* elementHeader = { "<" }; // and a header for everything else; check last.
static const int xmlHeaderLen = 5; static const int xmlHeaderLen = 2;
static const int commentHeaderLen = 4; static const int commentHeaderLen = 4;
static const int dtdHeaderLen = 2; static const int dtdHeaderLen = 2;
static const int cdataHeaderLen = 9; static const int cdataHeaderLen = 9;
@ -244,16 +244,11 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
returnNode->memPool = &elementPool; returnNode->memPool = &elementPool;
p += elementHeaderLen; p += elementHeaderLen;
} }
else if ( (*p != '<') && XMLUtil::IsAlphaNum( *p ) ) { else {
returnNode = new (textPool.Alloc()) XMLText( this ); returnNode = new (textPool.Alloc()) XMLText( this );
returnNode->memPool = &textPool; returnNode->memPool = &textPool;
p = start; // Back it up, all the text counts. p = start; // Back it up, all the text counts.
} }
else {
this->SetError( ERROR_IDENTIFYING_TAG, p, 0 );
p = 0;
returnNode = 0;
}
*node = returnNode; *node = returnNode;
return p; return p;
@ -457,13 +452,19 @@ char* XMLNode::ParseDeep( char* p )
// --------- XMLText ---------- // // --------- XMLText ---------- //
char* XMLText::ParseDeep( char* p ) char* XMLText::ParseDeep( char* p )
{ {
const char* start = p;
if ( this->CData() ) { if ( this->CData() ) {
p = value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION ); p = value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
if ( !p ) {
document->SetError( XMLDocument::ERROR_PARSING_CDATA, start, 0 );
}
return p; return p;
} }
else { else {
p = value.ParseText( p, "<", StrPair::TEXT_ELEMENT ); p = value.ParseText( p, "<", StrPair::TEXT_ELEMENT );
// consumes the end tag. if ( !p ) {
document->SetError( XMLDocument::ERROR_PARSING_TEXT, start, 0 );
}
if ( p && *p ) { if ( p && *p ) {
return p-1; return p-1;
} }
@ -494,7 +495,12 @@ XMLComment::~XMLComment()
char* XMLComment::ParseDeep( char* p ) char* XMLComment::ParseDeep( char* p )
{ {
// Comment parses as text. // Comment parses as text.
return value.ParseText( p, "-->", StrPair::COMMENT ); const char* start = p;
p = value.ParseText( p, "-->", StrPair::COMMENT );
if ( p == 0 ) {
document->SetError( XMLDocument::ERROR_PARSING_COMMENT, start, 0 );
}
return p;
} }
@ -520,7 +526,12 @@ XMLDeclaration::~XMLDeclaration()
char* XMLDeclaration::ParseDeep( char* p ) char* XMLDeclaration::ParseDeep( char* p )
{ {
// Declaration parses as text. // Declaration parses as text.
return value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION ); const char* start = p;
p = value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
if ( p == 0 ) {
document->SetError( XMLDocument::ERROR_PARSING_DECLARATION, start, 0 );
}
return p;
} }
@ -544,7 +555,13 @@ XMLUnknown::~XMLUnknown()
char* XMLUnknown::ParseDeep( char* p ) char* XMLUnknown::ParseDeep( char* p )
{ {
// Unknown parses as text. // Unknown parses as text.
return value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION ); const char* start = p;
p = value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION );
if ( !p ) {
document->SetError( XMLDocument::ERROR_PARSING_UNKNOWN, start, 0 );
}
return p;
} }
@ -707,6 +724,16 @@ const XMLAttribute* XMLElement::FindAttribute( const char* name ) const
} }
const char* XMLElement::GetText() const
{
if ( FirstChild() && FirstChild()->ToText() ) {
return FirstChild()->ToText()->Value();
}
return 0;
}
XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name ) XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )
{ {
XMLAttribute* attrib = FindAttribute( name ); XMLAttribute* attrib = FindAttribute( name );
@ -916,6 +943,48 @@ XMLText* XMLDocument::NewText( const char* str )
} }
int XMLDocument::Load( const char* filename )
{
ClearChildren();
InitDocument();
FILE* fp = fopen( filename, "rb" );
if ( !fp ) {
SetError( ERROR_FILE_NOT_FOUND, filename, 0 );
return errorID;
}
Load( fp );
fclose( fp );
return errorID;
}
int XMLDocument::Load( FILE* fp )
{
ClearChildren();
InitDocument();
fseek( fp, 0, SEEK_END );
unsigned size = ftell( fp );
fseek( fp, 0, SEEK_SET );
charBuffer = new char[size+1];
fread( charBuffer, size, 1, fp );
charBuffer[size] = 0;
ParseDeep( charBuffer );
return errorID;
}
void XMLDocument::Save( const char* filename )
{
FILE* fp = fopen( filename, "w" );
XMLStreamer stream( fp );
Print( &stream );
fclose( fp );
}
int XMLDocument::Parse( const char* p ) int XMLDocument::Parse( const char* p )
{ {
@ -928,9 +997,8 @@ int XMLDocument::Parse( const char* p )
size_t len = strlen( p ); size_t len = strlen( p );
charBuffer = new char[ len+1 ]; charBuffer = new char[ len+1 ];
memcpy( charBuffer, p, len+1 ); memcpy( charBuffer, p, len+1 );
XMLNode* node = 0;
ParseDeep( charBuffer );
char* q = ParseDeep( charBuffer );
return errorID; return errorID;
} }
@ -950,16 +1018,42 @@ void XMLDocument::Print( XMLStreamer* streamer )
void XMLDocument::SetError( int error, const char* str1, const char* str2 ) void XMLDocument::SetError( int error, const char* str1, const char* str2 )
{ {
errorID = error; errorID = error;
printf( "ERROR: id=%d '%s' '%s'\n", error, str1, str2 ); // fixme: remove
errorStr1 = str1; errorStr1 = str1;
errorStr2 = str2; errorStr2 = str2;
} }
XMLStreamer::XMLStreamer( FILE* file ) : fp( file ), depth( 0 ), elementJustOpened( false ), textDepth( -1 ) void XMLDocument::PrintError() const
{
if ( errorID ) {
char buf1[20] = { 0 };
char buf2[20] = { 0 };
if ( errorStr1 ) {
strncpy( buf1, errorStr1, 20 );
buf1[19] = 0;
}
if ( errorStr2 ) {
strncpy( buf2, errorStr2, 20 );
buf2[19] = 0;
}
printf( "XMLDocument error id=%d str1=%s str2=%s\n",
errorID, buf1, buf2 );
}
}
XMLStreamer::XMLStreamer( FILE* file ) :
elementJustOpened( false ),
firstElement( true ),
fp( file ),
depth( 0 ),
textDepth( -1 )
{ {
for( int i=0; i<ENTITY_RANGE; ++i ) { for( int i=0; i<ENTITY_RANGE; ++i ) {
entityFlag[i] = false; entityFlag[i] = false;
restrictedEntityFlag[i] = false;
} }
for( int i=0; i<NUM_ENTITIES; ++i ) { for( int i=0; i<NUM_ENTITIES; ++i ) {
TIXMLASSERT( entities[i].value < ENTITY_RANGE ); TIXMLASSERT( entities[i].value < ENTITY_RANGE );
@ -967,6 +1061,8 @@ XMLStreamer::XMLStreamer( FILE* file ) : fp( file ), depth( 0 ), elementJustOpen
entityFlag[ entities[i].value ] = true; entityFlag[ entities[i].value ] = true;
} }
} }
restrictedEntityFlag['&'] = true;
restrictedEntityFlag['<'] = true;
buffer.Push( 0 ); buffer.Push( 0 );
} }
@ -984,10 +1080,12 @@ void XMLStreamer::Print( const char* format, ... )
// way on windows. // way on windows.
#ifdef _MSC_VER #ifdef _MSC_VER
int len = -1; int len = -1;
int expand = 1000;
while ( len < 0 ) { while ( len < 0 ) {
len = vsnprintf_s( accumulator.Mem(), accumulator.Capacity(), accumulator.Capacity()-1, format, va ); len = vsnprintf_s( accumulator.Mem(), accumulator.Capacity(), accumulator.Capacity()-1, format, va );
if ( len < 0 ) { if ( len < 0 ) {
accumulator.PushArr( 1000 ); accumulator.PushArr( expand );
expand *= 3/2;
} }
} }
char* p = buffer.PushArr( len ) - 1; char* p = buffer.PushArr( len ) - 1;
@ -1010,17 +1108,18 @@ void XMLStreamer::PrintSpace( int depth )
} }
void XMLStreamer::PrintString( const char* p ) void XMLStreamer::PrintString( const char* p, bool restricted )
{ {
// Look for runs of bytes between entities to print. // Look for runs of bytes between entities to print.
const char* q = p; const char* q = p;
const bool* flag = restricted ? restrictedEntityFlag : entityFlag;
while ( *q ) { while ( *q ) {
if ( *q < ENTITY_RANGE ) { if ( *q < ENTITY_RANGE ) {
// Check for entities. If one is found, flush // Check for entities. If one is found, flush
// the stream up until the entity, write the // the stream up until the entity, write the
// entity, and keep looking. // entity, and keep looking.
if ( entityFlag[*q] ) { if ( flag[*q] ) {
while ( p < q ) { while ( p < q ) {
Print( "%c", *p ); Print( "%c", *p );
++p; ++p;
@ -1051,13 +1150,14 @@ void XMLStreamer::OpenElement( const char* name )
} }
stack.Push( name ); stack.Push( name );
if ( textDepth < 0 && depth > 0) { if ( textDepth < 0 && !firstElement ) {
Print( "\n" ); Print( "\n" );
PrintSpace( depth ); PrintSpace( depth );
} }
Print( "<%s", name ); Print( "<%s", name );
elementJustOpened = true; elementJustOpened = true;
firstElement = false;
++depth; ++depth;
} }
@ -1066,7 +1166,7 @@ void XMLStreamer::PushAttribute( const char* name, const char* value )
{ {
TIXMLASSERT( elementJustOpened ); TIXMLASSERT( elementJustOpened );
Print( " %s=\"", name ); Print( " %s=\"", name );
PrintString( value ); PrintString( value, false );
Print( "\"" ); Print( "\"" );
} }
@ -1109,11 +1209,14 @@ void XMLStreamer::PushText( const char* text, bool cdata )
if ( elementJustOpened ) { if ( elementJustOpened ) {
SealElement(); SealElement();
} }
if ( cdata ) if ( cdata ) {
Print( "<![CDATA[" ); Print( "<![CDATA[" );
PrintString( text ); Print( "%s", text );
if ( cdata )
Print( "]]>" ); Print( "]]>" );
}
else {
PrintString( text, true );
}
} }
@ -1122,14 +1225,43 @@ void XMLStreamer::PushComment( const char* comment )
if ( elementJustOpened ) { if ( elementJustOpened ) {
SealElement(); SealElement();
} }
if ( textDepth < 0 && depth > 0) { if ( textDepth < 0 && !firstElement ) {
Print( "\n" ); Print( "\n" );
PrintSpace( depth ); PrintSpace( depth );
} }
firstElement = false;
Print( "<!--%s-->", comment ); Print( "<!--%s-->", comment );
} }
void XMLStreamer::PushDeclaration( const char* value )
{
if ( elementJustOpened ) {
SealElement();
}
if ( textDepth < 0 && !firstElement) {
Print( "\n" );
PrintSpace( depth );
}
firstElement = false;
Print( "<?%s?>", value );
}
void XMLStreamer::PushUnknown( const char* value )
{
if ( elementJustOpened ) {
SealElement();
}
if ( textDepth < 0 && !firstElement ) {
Print( "\n" );
PrintSpace( depth );
}
firstElement = false;
Print( "<!%s>", value );
}
bool XMLStreamer::VisitEnter( const XMLElement& element, const XMLAttribute* attribute ) bool XMLStreamer::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
{ {
OpenElement( element.Name() ); OpenElement( element.Name() );
@ -1160,3 +1292,18 @@ bool XMLStreamer::Visit( const XMLComment& comment )
PushComment( comment.Value() ); PushComment( comment.Value() );
return true; return true;
} }
bool XMLStreamer::Visit( const XMLDeclaration& declaration )
{
PushDeclaration( declaration.Value() );
return true;
}
bool XMLStreamer::Visit( const XMLUnknown& unknown )
{
PushUnknown( unknown.Value() );
return true;
}

View File

@ -15,14 +15,15 @@
X UTF8 support: isAlpha, etc. X UTF8 support: isAlpha, etc.
X string buffer for sets. (Grr.) X string buffer for sets. (Grr.)
- MS BOM - MS BOM
- print to memory buffer X print to memory buffer
- tests from xml1 - tests from xml1
- xml1 tests especially UTF-8 - xml1 tests especially UTF-8
- perf test: xml1 - perf test: xml1
- perf test: xenowar - perf test: xenowar
- test: load(char*) - test: load(char*)
- test: load(FILE*) - test: load(FILE*)
- rename declaration
- rename streamer
*/ */
#include <limits.h> #include <limits.h>
@ -689,9 +690,10 @@ public:
virtual XMLDocument* ToDocument() { return this; } virtual XMLDocument* ToDocument() { return this; }
virtual const XMLDocument* ToDocument() const { return this; } virtual const XMLDocument* ToDocument() const { return this; }
int Parse( const char* ); int Parse( const char* xml );
int Load( const char* ); int Load( const char* filename );
int Load( FILE* ); int Load( FILE* );
void Save( const char* filename );
void Print( XMLStreamer* streamer=0 ); void Print( XMLStreamer* streamer=0 );
virtual bool Accept( XMLVisitor* visitor ) const; virtual bool Accept( XMLVisitor* visitor ) const;
@ -716,10 +718,17 @@ public:
enum { enum {
NO_ERROR = 0, NO_ERROR = 0,
ERROR_FILE_NOT_FOUND,
ERROR_ELEMENT_MISMATCH, ERROR_ELEMENT_MISMATCH,
ERROR_PARSING_ELEMENT, ERROR_PARSING_ELEMENT,
ERROR_PARSING_ATTRIBUTE, ERROR_PARSING_ATTRIBUTE,
ERROR_IDENTIFYING_TAG ERROR_IDENTIFYING_TAG,
ERROR_PARSING_TEXT,
ERROR_PARSING_CDATA,
ERROR_PARSING_COMMENT,
ERROR_PARSING_DECLARATION,
ERROR_PARSING_UNKNOWN
}; };
void SetError( int error, const char* str1, const char* str2 ); void SetError( int error, const char* str1, const char* str2 );
@ -727,6 +736,7 @@ public:
int GetErrorID() const { return errorID; } int GetErrorID() const { return errorID; }
const char* GetErrorStr1() const { return errorStr1; } const char* GetErrorStr1() const { return errorStr1; }
const char* GetErrorStr2() const { return errorStr2; } const char* GetErrorStr2() const { return errorStr2; }
void PrintError() const;
char* Identify( char* p, XMLNode** node ); char* Identify( char* p, XMLNode** node );
@ -759,6 +769,8 @@ public:
void PushText( const char* text, bool cdata=false ); void PushText( const char* text, bool cdata=false );
void PushComment( const char* comment ); void PushComment( const char* comment );
void PushDeclaration( const char* value );
void PushUnknown( const char* value );
virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; } virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; } virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
@ -768,24 +780,28 @@ public:
virtual bool Visit( const XMLText& text ); virtual bool Visit( const XMLText& text );
virtual bool Visit( const XMLComment& comment ); virtual bool Visit( const XMLComment& comment );
virtual bool Visit( const XMLDeclaration& declaration );
virtual bool Visit( const XMLUnknown& unknown );
const char* CStr() const { return buffer.Mem(); } const char* CStr() const { return buffer.Mem(); }
private: private:
void SealElement(); void SealElement();
void PrintSpace( int depth ); void PrintSpace( int depth );
void PrintString( const char* ); // prints out, after detecting entities. void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
void Print( const char* format, ... ); void Print( const char* format, ... );
bool elementJustOpened;
bool firstElement;
FILE* fp; FILE* fp;
int depth; int depth;
bool elementJustOpened;
int textDepth; int textDepth;
enum { enum {
ENTITY_RANGE = 64 ENTITY_RANGE = 64
}; };
bool entityFlag[ENTITY_RANGE]; bool entityFlag[ENTITY_RANGE];
bool restrictedEntityFlag[ENTITY_RANGE];
DynArray< const char*, 10 > stack; DynArray< const char*, 10 > stack;
DynArray< char, 20 > buffer, accumulator; DynArray< char, 20 > buffer, accumulator;

View File

@ -14,6 +14,36 @@ using namespace tinyxml2;
int gPass = 0; int gPass = 0;
int gFail = 0; int gFail = 0;
//#define DREAM_ONLY
/*
int gNew = 0;
int gNewTotal = 0;
void* operator new( size_t size )
{
++gNew;
return malloc( size );
}
void* operator new[]( size_t size )
{
++gNew;
return malloc( size );
}
void operator delete[]( void* mem )
{
free( mem );
}
void operator delete( void* mem )
{
free( mem );
}
*/
bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true ) bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true )
{ {
bool pass = !strcmp( expected, found ); bool pass = !strcmp( expected, found );
@ -61,7 +91,7 @@ int main( int argc, const char* argv )
#if defined( WIN32 ) #if defined( WIN32 )
_CrtMemCheckpoint( &startMemState ); _CrtMemCheckpoint( &startMemState );
#endif #endif
#ifndef DREAM_ONLY
#if 0 #if 0
{ {
static const char* test = "<!--hello world\n" static const char* test = "<!--hello world\n"
@ -169,6 +199,40 @@ int main( int argc, const char* argv )
delete doc; delete doc;
} }
#endif
{
// Test: Dream
// XML1 : 1,187,569 bytes in 31,209 allocations
// XML2 : 469,073 bytes in 323 allocations
//int newStart = gNew;
XMLDocument doc;
doc.Load( "dream.xml" );
doc.Save( "dreamout.xml" );
doc.PrintError();
XMLTest( "Dream", "xml version=\"1.0\"",
doc.FirstChild()->ToDeclaration()->Value() );
XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
XMLTest( "Dream", "And Robin shall restore amends.",
doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
XMLTest( "Dream", "And Robin shall restore amends.",
doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
XMLDocument doc2;
doc2.Load( "dreamout.xml" );
XMLTest( "Dream-out", "xml version=\"1.0\"",
doc2.FirstChild()->ToDeclaration()->Value() );
XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
XMLTest( "Dream-out", "And Robin shall restore amends.",
doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
//gNewTotal = gNew - newStart;
}
#if defined( WIN32 ) #if defined( WIN32 )
_CrtMemCheckpoint( &endMemState ); _CrtMemCheckpoint( &endMemState );
@ -177,6 +241,7 @@ int main( int argc, const char* argv )
_CrtMemState diffMemState; _CrtMemState diffMemState;
_CrtMemDifference( &diffMemState, &startMemState, &endMemState ); _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
_CrtMemDumpStatistics( &diffMemState ); _CrtMemDumpStatistics( &diffMemState );
//printf( "new total=%d\n", gNewTotal );
#endif #endif
printf ("\nPass %d, Fail %d\n", gPass, gFail); printf ("\nPass %d, Fail %d\n", gPass, gFail);