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;
}
return p;
return 0;
}
@ -198,17 +198,17 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
// What is this thing?
// - Elements start with a letter or underscore, but xml is reserved.
// - Comments: <!--
// - Decleration: <?xml
// - Decleration: <?
// - Everthing else is unknown to tinyxml.
//
static const char* xmlHeader = { "<?xml" };
static const char* xmlHeader = { "<?" };
static const char* commentHeader = { "<!--" };
static const char* dtdHeader = { "<!" };
static const char* cdataHeader = { "<![CDATA[" };
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 dtdHeaderLen = 2;
static const int cdataHeaderLen = 9;
@ -244,16 +244,11 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
returnNode->memPool = &elementPool;
p += elementHeaderLen;
}
else if ( (*p != '<') && XMLUtil::IsAlphaNum( *p ) ) {
else {
returnNode = new (textPool.Alloc()) XMLText( this );
returnNode->memPool = &textPool;
p = start; // Back it up, all the text counts.
}
else {
this->SetError( ERROR_IDENTIFYING_TAG, p, 0 );
p = 0;
returnNode = 0;
}
*node = returnNode;
return p;
@ -457,13 +452,19 @@ char* XMLNode::ParseDeep( char* p )
// --------- XMLText ---------- //
char* XMLText::ParseDeep( char* p )
{
const char* start = p;
if ( this->CData() ) {
p = value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
if ( !p ) {
document->SetError( XMLDocument::ERROR_PARSING_CDATA, start, 0 );
}
return p;
}
else {
p = value.ParseText( p, "<", StrPair::TEXT_ELEMENT );
// consumes the end tag.
if ( !p ) {
document->SetError( XMLDocument::ERROR_PARSING_TEXT, start, 0 );
}
if ( p && *p ) {
return p-1;
}
@ -494,7 +495,12 @@ XMLComment::~XMLComment()
char* XMLComment::ParseDeep( char* p )
{
// 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 )
{
// 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 )
{
// 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* 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 )
{
@ -928,9 +997,8 @@ int XMLDocument::Parse( const char* p )
size_t len = strlen( p );
charBuffer = new char[ len+1 ];
memcpy( charBuffer, p, len+1 );
XMLNode* node = 0;
char* q = ParseDeep( charBuffer );
ParseDeep( charBuffer );
return errorID;
}
@ -950,16 +1018,42 @@ void XMLDocument::Print( XMLStreamer* streamer )
void XMLDocument::SetError( int error, const char* str1, const char* str2 )
{
errorID = error;
printf( "ERROR: id=%d '%s' '%s'\n", error, str1, str2 ); // fixme: remove
errorStr1 = str1;
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 ) {
entityFlag[i] = false;
restrictedEntityFlag[i] = false;
}
for( int i=0; i<NUM_ENTITIES; ++i ) {
TIXMLASSERT( entities[i].value < ENTITY_RANGE );
@ -967,6 +1061,8 @@ XMLStreamer::XMLStreamer( FILE* file ) : fp( file ), depth( 0 ), elementJustOpen
entityFlag[ entities[i].value ] = true;
}
}
restrictedEntityFlag['&'] = true;
restrictedEntityFlag['<'] = true;
buffer.Push( 0 );
}
@ -984,10 +1080,12 @@ void XMLStreamer::Print( const char* format, ... )
// way on windows.
#ifdef _MSC_VER
int len = -1;
int expand = 1000;
while ( len < 0 ) {
len = vsnprintf_s( accumulator.Mem(), accumulator.Capacity(), accumulator.Capacity()-1, format, va );
if ( len < 0 ) {
accumulator.PushArr( 1000 );
accumulator.PushArr( expand );
expand *= 3/2;
}
}
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.
const char* q = p;
const bool* flag = restricted ? restrictedEntityFlag : entityFlag;
while ( *q ) {
if ( *q < ENTITY_RANGE ) {
// Check for entities. If one is found, flush
// the stream up until the entity, write the
// entity, and keep looking.
if ( entityFlag[*q] ) {
if ( flag[*q] ) {
while ( p < q ) {
Print( "%c", *p );
++p;
@ -1051,13 +1150,14 @@ void XMLStreamer::OpenElement( const char* name )
}
stack.Push( name );
if ( textDepth < 0 && depth > 0) {
if ( textDepth < 0 && !firstElement ) {
Print( "\n" );
PrintSpace( depth );
}
Print( "<%s", name );
elementJustOpened = true;
firstElement = false;
++depth;
}
@ -1066,7 +1166,7 @@ void XMLStreamer::PushAttribute( const char* name, const char* value )
{
TIXMLASSERT( elementJustOpened );
Print( " %s=\"", name );
PrintString( value );
PrintString( value, false );
Print( "\"" );
}
@ -1109,11 +1209,14 @@ void XMLStreamer::PushText( const char* text, bool cdata )
if ( elementJustOpened ) {
SealElement();
}
if ( cdata )
if ( cdata ) {
Print( "<![CDATA[" );
PrintString( text );
if ( cdata )
Print( "%s", text );
Print( "]]>" );
}
else {
PrintString( text, true );
}
}
@ -1122,14 +1225,43 @@ void XMLStreamer::PushComment( const char* comment )
if ( elementJustOpened ) {
SealElement();
}
if ( textDepth < 0 && depth > 0) {
if ( textDepth < 0 && !firstElement ) {
Print( "\n" );
PrintSpace( depth );
}
firstElement = false;
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 )
{
OpenElement( element.Name() );
@ -1160,3 +1292,18 @@ bool XMLStreamer::Visit( const XMLComment& comment )
PushComment( comment.Value() );
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 string buffer for sets. (Grr.)
- MS BOM
- print to memory buffer
X print to memory buffer
- tests from xml1
- xml1 tests especially UTF-8
- perf test: xml1
- perf test: xenowar
- test: load(char*)
- test: load(FILE*)
- rename declaration
- rename streamer
*/
#include <limits.h>
@ -689,9 +690,10 @@ public:
virtual XMLDocument* ToDocument() { return this; }
virtual const XMLDocument* ToDocument() const { return this; }
int Parse( const char* );
int Load( const char* );
int Parse( const char* xml );
int Load( const char* filename );
int Load( FILE* );
void Save( const char* filename );
void Print( XMLStreamer* streamer=0 );
virtual bool Accept( XMLVisitor* visitor ) const;
@ -716,10 +718,17 @@ public:
enum {
NO_ERROR = 0,
ERROR_FILE_NOT_FOUND,
ERROR_ELEMENT_MISMATCH,
ERROR_PARSING_ELEMENT,
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 );
@ -727,6 +736,7 @@ public:
int GetErrorID() const { return errorID; }
const char* GetErrorStr1() const { return errorStr1; }
const char* GetErrorStr2() const { return errorStr2; }
void PrintError() const;
char* Identify( char* p, XMLNode** node );
@ -759,6 +769,8 @@ public:
void PushText( const char* text, bool cdata=false );
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 VisitExit( const XMLDocument& /*doc*/ ) { return true; }
@ -768,24 +780,28 @@ public:
virtual bool Visit( const XMLText& text );
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(); }
private:
void SealElement();
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, ... );
bool elementJustOpened;
bool firstElement;
FILE* fp;
int depth;
bool elementJustOpened;
int textDepth;
enum {
ENTITY_RANGE = 64
};
bool entityFlag[ENTITY_RANGE];
bool restrictedEntityFlag[ENTITY_RANGE];
DynArray< const char*, 10 > stack;
DynArray< char, 20 > buffer, accumulator;

View File

@ -14,6 +14,36 @@ using namespace tinyxml2;
int gPass = 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 pass = !strcmp( expected, found );
@ -61,7 +91,7 @@ int main( int argc, const char* argv )
#if defined( WIN32 )
_CrtMemCheckpoint( &startMemState );
#endif
#ifndef DREAM_ONLY
#if 0
{
static const char* test = "<!--hello world\n"
@ -169,6 +199,40 @@ int main( int argc, const char* argv )
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 )
_CrtMemCheckpoint( &endMemState );
@ -177,6 +241,7 @@ int main( int argc, const char* argv )
_CrtMemState diffMemState;
_CrtMemDifference( &diffMemState, &startMemState, &endMemState );
_CrtMemDumpStatistics( &diffMemState );
//printf( "new total=%d\n", gNewTotal );
#endif
printf ("\nPass %d, Fail %d\n", gPass, gFail);