Dream test passing.
diff --git a/tinyxml2.cpp b/tinyxml2.cpp
index 3a9b2c9..740f1f5 100644
--- a/tinyxml2.cpp
+++ b/tinyxml2.cpp
@@ -82,7 +82,7 @@
 		}

 		++p;

 	}	

-	return p;

+	return 0;

 }

 

 

@@ -198,17 +198,17 @@
 	// 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 @@
 		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 @@
 // --------- 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 @@
 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 @@
 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 @@
 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 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 @@
 }

 

 

+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 @@
 	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::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 @@
 			entityFlag[ entities[i].value ] = true;

 		}

 	}

+	restrictedEntityFlag['&'] = true;

+	restrictedEntityFlag['<'] = true;

 	buffer.Push( 0 );

 }

 

@@ -984,10 +1080,12 @@
 		// 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::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 @@
 	}

 	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 @@
 {

 	TIXMLASSERT( elementJustOpened );

 	Print( " %s=\"", name );

-	PrintString( value );

+	PrintString( value, false );

 	Print( "\"" );

 }

 

@@ -1109,11 +1209,14 @@
 	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 @@
 	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 @@
 	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;

+}

+

+