Lee Thomason (grinliz) пре 14 година
родитељ
комит
7ca5558bca
8 измењених фајлова са 238 додато и 69 уклоњено
  1. 1 1
      dox
  2. 18 34
      readme.txt
  3. 79 0
      setversion.py
  4. 34 28
      tinyxml2.cpp
  5. 17 4
      tinyxml2.h
  6. 3 0
      tinyxml2/tinyxml2.vcxproj
  7. 5 0
      tinyxml2/tinyxml2.vcxproj.filters
  8. 81 2
      xmltest.cpp

+ 1 - 1
dox

@@ -32,7 +32,7 @@ PROJECT_NAME           = "TinyXML-2"
 # This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         =
+PROJECT_NUMBER = 0.9.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer

+ 18 - 34
readme.txt

@@ -55,7 +55,7 @@ complete XML needs, TinyXML-2 is not the parser for you.
 Which should you use? TinyXML-2 uses a similar API to TinyXML-1 and the same
 rich test cases. But the implementation of the parser is completely re-written
 to make it more appropriate for use in a game. It uses less memory, is faster,
-and user far few memory allocations.
+and uses far few memory allocations.
 
 TinyXML-2 has no requirement for STL, but has also dropped all STL support. All
 strings are query and set as 'const char*'. This allows the use of internal 
@@ -71,7 +71,7 @@ Both parsers:
 Advantages of TinyXML-2
 <ol>
 	<li>The focus of all future dev.</li>	
-	<li>Many fewer memory allocation (about 1/100th), uses less memory (about 40% of TinyXML-1), and faster.</li>
+	<li>Many fewer memory allocation (1/10th to 1/100th), uses less memory (about 40% of TinyXML-1), and faster.</li>
 	<li>No STL requirement.</li>
 	<li>More modern C++, including a proper namespace.</li>
 	<li>Proper and useful handling of whitespace</li>
@@ -107,52 +107,41 @@ As a first step, all newlines / carriage-returns / line-feeds are normalized to
 line-feed character, as required by the XML spec.
 
 White space in text is preserved. For example:
-@verbatim
+
 	<element> Hello,  World</element>
-@endverbatim
 
 The leading space before the "Hello" and the double space after the comma are preserved.
 Line-feeds are preserved, as in this example:
 
-@verbatim
 	<element> Hello again,  
 	          World</element>
-@endverbatim
 
 However, white space between elements is *not* preserved. Although not strictly compliant,
 tracking and reporting inta-element space is awkward, and not normally valuable. TinyXML-2 
 sees these as the same XML:
 
-@verbatim
-<document>
-<data>1</data>
-<data>2</data>
-<data>3</data>
-</document>
-@endverbatim
+	<document>
+	<data>1</data>
+	<data>2</data>
+	<data>3</data>
+	</document>
 
-@verbatim
-<document><data>1</data><data>2</data><data>3</data></document>
-@endverbatim
+	<document><data>1</data><data>2</data><data>3</data></document>
 
 <h3> Entities </h3>
 TinyXML-2 recognizes the pre-defined "character entities", meaning special
 characters. Namely:
 
-@verbatim
 	&amp;	&
 	&lt;	<
 	&gt;	>
 	&quot;	"
 	&apos;	'
-@endverbatim
 
 These are recognized when the XML document is read, and translated to there
 UTF-8 equivalents. For instance, text with the XML of:
 
-@verbatim
 	Far &amp; Away
-@endverbatim
 
 will have the Value() of "Far & Away" when queried from the XMLText object,
 and will be written back to the XML stream/file as an ampersand. 
@@ -167,42 +156,37 @@ regular code point. The output is correct, but the entity syntax isn't preserved
 
 <h4> Print to file </h4>
 You can directly use the convenience function:
-@verbatim
+
 	XMLDocument doc;
 	...
 	doc.Save( "foo.xml" );
-@endverbatim
 
 Or the XMLPrinter class:
-@verbatim
+
 	XMLPrinter printer( fp );
 	doc.Print( &printer );
-@endverbatim
 
 <h4> Print to memory </h4>
 Printing to memory is supported by the XMLPrinter.
-@verbatim
+
 	XMLPrinter printer;
 	doc->Print( &printer );
 	// printer.CStr() has a const char* to the XML
-@endverbatim
 
 <h4> Print without an XMLDocument </h4>
 
-	When loading, an XML parser is very useful. However, sometimes
-	when saving, it just gets in the way. The code is often set up
-	for streaming, and constructing the DOM is just overhead.
+When loading, an XML parser is very useful. However, sometimes
+when saving, it just gets in the way. The code is often set up
+for streaming, and constructing the DOM is just overhead.
 
-	The Printer supports the streaming case. The following code
-	prints out a trivially simple XML file without ever creating
-	an XML document.
+The Printer supports the streaming case. The following code
+prints out a trivially simple XML file without ever creating
+an XML document.
 
-@verbatim
 	XMLPrinter printer( fp );
 	printer.OpenElement( "foo" );
 	printer.PushAttribute( "foo", "bar" );
 	printer.CloseElement();
-@endverbatim
 
 <h2> Using and Installing </h2>
 

+ 79 - 0
setversion.py

@@ -0,0 +1,79 @@
+# Python program to set the version.
+##############################################
+
+import re
+import sys
+
+def fileProcess( name, lineFunction ):
+	filestream = open( name, 'r' )
+	if filestream.closed:
+		print( "file " + name + " not open." )
+		return
+
+	output = ""
+	print( "--- Processing " + name + " ---------" )
+	while 1:
+		line = filestream.readline()
+		if not line: break
+		output += lineFunction( line )
+	filestream.close()
+	
+	if not output: return			# basic error checking
+	
+	print( "Writing file " + name )
+	filestream = open( name, "w" );
+	filestream.write( output );
+	filestream.close()
+	
+	
+def echoInput( line ):
+	return line
+
+major = input( "Major: " )
+minor = input( "Minor: " )
+build = input( "Build: " )
+
+print "Setting dox,tinyxml2.h"
+print "Version: " + `major` + "." + `minor` + "." + `build`
+
+#### Write the tinyxml.h ####
+
+def engineRule( line ):
+
+	matchMajor = "static const int TIXML2_MAJOR_VERSION"
+	matchMinor = "static const int TIXML2_MINOR_VERSION"
+	matchBuild = "static const int TIXML2_PATCH_VERSION"
+
+	if line[0:len(matchMajor)] == matchMajor:
+		print "1)tinyxml2.h Major found"
+		return matchMajor + " = " + `major` + ";\n"
+
+	elif line[0:len(matchMinor)] == matchMinor:
+		print "2)tinyxml2.h Minor found"
+		return matchMinor + " = " + `minor` + ";\n"
+
+	elif line[0:len(matchBuild)] == matchBuild:
+		print "3)tinyxml2.h Build found"
+		return matchBuild + " = " + `build` + ";\n"
+
+	else:
+		return line;
+
+fileProcess( "tinyxml2.h", engineRule )
+
+
+#### Write the dox ####
+
+def doxRule( line ):
+
+	match = "PROJECT_NUMBER"
+
+	if line[0:len( match )] == match:
+		print "dox project found"
+		return "PROJECT_NUMBER = " + `major` + "." + `minor` + "." + `build` + "\n"
+
+	else:
+		return line;
+
+fileProcess( "dox", doxRule )
+

+ 34 - 28
tinyxml2.cpp

@@ -312,7 +312,7 @@ const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )
 	if ( *(p+1) == '#' && *(p+2) )
 	{
 		unsigned long ucs = 0;
-		ptrdiff_t delta = 0;
+		int delta = 0;
 		unsigned mult = 1;
 
 		if ( *(p+2) == 'x' )
@@ -325,7 +325,7 @@ const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )
 
 			if ( !q || !*q ) return 0;
 
-			delta = q-p;
+			delta = (q-p);
 			--q;
 
 			while ( *q != 'x' )
@@ -740,7 +740,7 @@ char* XMLText::ParseDeep( char* p, StrPair* )
 		return p;
 	}
 	else {
-		p = value.ParseText( p, "<", StrPair::TEXT_ELEMENT );
+		p = value.ParseText( p, "<", document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES );
 		if ( !p ) {
 			document->SetError( ERROR_PARSING_TEXT, start, 0 );
 		}
@@ -916,14 +916,14 @@ bool XMLUnknown::Accept( XMLVisitor* visitor ) const
 }
 
 // --------- XMLAttribute ---------- //
-char* XMLAttribute::ParseDeep( char* p )
+char* XMLAttribute::ParseDeep( char* p, bool processEntities )
 {
 	p = name.ParseText( p, "=", StrPair::ATTRIBUTE_NAME );
 	if ( !p || !*p ) return 0;
 
 	char endTag[2] = { *p, 0 };
 	++p;
-	p = value.ParseText( p, endTag, StrPair::ATTRIBUTE_VALUE );
+	p = value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES );
 	//if ( value.Empty() ) return 0;
 	return p;
 }
@@ -1141,7 +1141,7 @@ char* XMLElement::ParseAttributes( char* p )
 			XMLAttribute* attrib = new (document->attributePool.Alloc() ) XMLAttribute();
 			attrib->memPool = &document->attributePool;
 
-			p = attrib->ParseDeep( p );
+			p = attrib->ParseDeep( p, document->ProcessEntities() );
 			if ( !p || Attribute( attrib->Name() ) ) {
 				DELETE_ATTRIBUTE( attrib );
 				document->SetError( ERROR_PARSING_ATTRIBUTE, start, p );
@@ -1250,9 +1250,13 @@ bool XMLElement::Accept( XMLVisitor* visitor ) const
 
 
 // --------- XMLDocument ----------- //
-XMLDocument::XMLDocument() :
+XMLDocument::XMLDocument( bool _processEntities ) :
 	XMLNode( 0 ),
 	writeBOM( false ),
+	processEntities( _processEntities ),
+	errorID( 0 ),
+	errorStr1( 0 ),
+	errorStr2( 0 ),
 	charBuffer( 0 )
 {
 	document = this;	// avoid warning about 'this' in initializer list
@@ -1474,7 +1478,8 @@ XMLPrinter::XMLPrinter( FILE* file ) :
 	firstElement( true ),
 	fp( file ), 
 	depth( 0 ), 
-	textDepth( -1 )
+	textDepth( -1 ),
+	processEntities( true )
 {
 	for( int i=0; i<ENTITY_RANGE; ++i ) {
 		entityFlag[i] = false;
@@ -1540,31 +1545,33 @@ void XMLPrinter::PrintString( const char* p, bool restricted )
 	const char* q = p;
 	const bool* flag = restricted ? restrictedEntityFlag : entityFlag;
 
-	while ( *q ) {
-		// Remember, char is sometimes signed. (How many times has that bitten me?)
-		if ( *q > 0 && *q < ENTITY_RANGE ) {
-			// Check for entities. If one is found, flush
-			// the stream up until the entity, write the 
-			// entity, and keep looking.
-			if ( flag[*q] ) {
-				while ( p < q ) {
-					Print( "%c", *p );
-					++p;
-				}
-				for( int i=0; i<NUM_ENTITIES; ++i ) {
-					if ( entities[i].value == *q ) {
-						Print( "&%s;", entities[i].pattern );
-						break;
+	if ( processEntities ) {
+		while ( *q ) {
+			// Remember, char is sometimes signed. (How many times has that bitten me?)
+			if ( *q > 0 && *q < ENTITY_RANGE ) {
+				// Check for entities. If one is found, flush
+				// the stream up until the entity, write the 
+				// entity, and keep looking.
+				if ( flag[*q] ) {
+					while ( p < q ) {
+						Print( "%c", *p );
+						++p;
 					}
+					for( int i=0; i<NUM_ENTITIES; ++i ) {
+						if ( entities[i].value == *q ) {
+							Print( "&%s;", entities[i].pattern );
+							break;
+						}
+					}
+					++p;
 				}
-				++p;
 			}
+			++q;
 		}
-		++q;
 	}
 	// Flush the remaining string. This will be the entire
 	// string if an entity wasn't found.
-	if ( q-p > 0 ) {
+	if ( !processEntities || (q-p > 0) ) {
 		Print( "%s", p );
 	}
 }
@@ -1735,6 +1742,7 @@ void XMLPrinter::PushUnknown( const char* value )
 
 bool XMLPrinter::VisitEnter( const XMLDocument& doc )
 {
+	processEntities = doc.ProcessEntities();
 	if ( doc.HasBOM() ) {
 		PushHeader( true, false );
 	}
@@ -1785,5 +1793,3 @@ bool XMLPrinter::Visit( const XMLUnknown& unknown )
 	PushUnknown( unknown.Value() );
 	return true;
 }
-
-

+ 17 - 4
tinyxml2.h

@@ -36,6 +36,7 @@ distribution.
 */
 /*
 	gcc: g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
+
 */
 
 #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
@@ -84,6 +85,9 @@ distribution.
 	#define TIXML_SSCANF   sscanf
 #endif
 
+static const int TIXML2_MAJOR_VERSION = 0;
+static const int TIXML2_MINOR_VERSION = 9;
+static const int TIXML2_PATCH_VERSION = 0;
 
 namespace tinyxml2
 {
@@ -112,8 +116,10 @@ public:
 		NEEDS_NEWLINE_NORMALIZATION		= 0x02,
 
 		TEXT_ELEMENT		= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
+		TEXT_ELEMENT_LEAVE_ENTITIES		= NEEDS_NEWLINE_NORMALIZATION,
 		ATTRIBUTE_NAME		= 0,
 		ATTRIBUTE_VALUE		= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
+		ATTRIBUTE_VALUE_LEAVE_ENTITIES		= NEEDS_NEWLINE_NORMALIZATION,
 		COMMENT				= NEEDS_NEWLINE_NORMALIZATION,
 	};
 
@@ -801,7 +807,7 @@ private:
 	void operator=( const XMLAttribute& );	// not supported
 	void SetName( const char* name );
 
-	char* ParseDeep( char* p );
+	char* ParseDeep( char* p, bool processEntities );
 
 	mutable StrPair name;
 	mutable StrPair value;
@@ -959,7 +965,7 @@ class XMLDocument : public XMLNode
 	friend class XMLElement;
 public:
 	/// constructor
-	XMLDocument(); 
+	XMLDocument( bool processEntities = true ); 
 	~XMLDocument();
 
 	virtual XMLDocument* ToDocument()				{ return this; }
@@ -990,6 +996,11 @@ public:
 	*/
 	void SaveFile( const char* filename );
 
+	bool ProcessEntities() const						{ return processEntities; }
+
+	/**
+		Returns true if this document has a leading Byte Order Mark of UTF8.
+	*/
 	bool HasBOM() const { return writeBOM; }
 
 	/** Return the root element of DOM. Equivalent to FirstChildElement().
@@ -1068,8 +1079,8 @@ public:
 	// internal
 	char* Identify( char* p, XMLNode** node );
 
-	virtual XMLNode* ShallowClone( XMLDocument* ) const	{ return 0; }
-	virtual bool ShallowEqual( const XMLNode* ) const	{ return false; }
+	virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const	{ return 0; }
+	virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const	{ return false; }
 
 private:
 	XMLDocument( const XMLDocument& );	// not supported
@@ -1077,6 +1088,7 @@ private:
 	void InitDocument();
 
 	bool writeBOM;
+	bool processEntities;
 	int errorID;
 	const char* errorStr1;
 	const char* errorStr2;
@@ -1193,6 +1205,7 @@ private:
 	FILE* fp;
 	int depth;
 	int textDepth;
+	bool processEntities;
 
 	enum {
 		ENTITY_RANGE = 64,

+ 3 - 0
tinyxml2/tinyxml2.vcxproj

@@ -80,6 +80,9 @@
   <ItemGroup>
     <ClInclude Include="..\tinyxml2.h" />
   </ItemGroup>
+  <ItemGroup>
+    <None Include="..\readme.txt" />
+  </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>

+ 5 - 0
tinyxml2/tinyxml2.vcxproj.filters

@@ -19,4 +19,9 @@
       <Filter>Source Files</Filter>
     </ClInclude>
   </ItemGroup>
+  <ItemGroup>
+    <None Include="..\readme.txt">
+      <Filter>Source Files</Filter>
+    </None>
+  </ItemGroup>
 </Project>

+ 81 - 2
xmltest.cpp

@@ -3,9 +3,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 
-#if defined( _MSC_VER ) && defined( DEBUG )
+#if defined( _MSC_VER )
 	#include <crtdbg.h>
+	#define WIN32_LEAN_AND_MEAN
+	#include <windows.h>
 	_CrtMemState startMemState;
 	_CrtMemState endMemState;
 #endif
@@ -211,6 +214,8 @@ int main( int /*argc*/, const char* /*argv*/ )
 
 		//gNewTotal = gNew - newStart;
 	}
+
+
 	{
 		const char* error =	"<?xml version=\"1.0\" standalone=\"no\" ?>\n"
 							"<passages count=\"006\" formatversion=\"20020620\">\n"
@@ -458,6 +463,24 @@ int main( int /*argc*/, const char* /*argv*/ )
 		fclose( textfile );
 	}
 
+	{
+		// Suppress entities.
+		const char* passages =
+			"<?xml version=\"1.0\" standalone=\"no\" ?>"
+			"<passages count=\"006\" formatversion=\"20020620\">"
+				"<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
+			"</passages>";
+		
+		XMLDocument doc( false );
+		doc.Parse( passages );
+
+		XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ), 
+				 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
+		XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
+				 "Crazy &ttk;" );
+		doc.Print();
+	}
+
 	{
         const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
 
@@ -654,7 +677,63 @@ int main( int /*argc*/, const char* /*argv*/ )
 		XMLTest( "Clone and Equal", 4, count );
 	}
 
-	#if defined( _MSC_VER ) && defined( DEBUG )
+	// ----------- Performance tracking --------------
+	{
+#if defined( _MSC_VER )
+		__int64 start, end, freq;
+		QueryPerformanceFrequency( (LARGE_INTEGER*) &freq );
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning ( push )
+#pragma warning ( disable : 4996 )		// Fail to see a compelling reason why this should be deprecated.
+#endif
+		FILE* fp  = fopen( "dream.xml", "r" );
+#if defined(_MSC_VER)
+#pragma warning ( pop )
+#endif
+		fseek( fp, 0, SEEK_END );
+		long size = ftell( fp );
+		fseek( fp, 0, SEEK_SET );
+
+		char* mem = new char[size+1];
+		fread( mem, size, 1, fp );
+		fclose( fp );
+		mem[size] = 0;
+
+#if defined( _MSC_VER )
+		QueryPerformanceCounter( (LARGE_INTEGER*) &start );
+#else
+		clock_t cstart = clock();
+#endif
+		static const int COUNT = 10;
+		for( int i=0; i<COUNT; ++i ) {
+			XMLDocument doc;
+			doc.Parse( mem );
+		}
+#if defined( _MSC_VER )
+		QueryPerformanceCounter( (LARGE_INTEGER*) &end );
+#else
+		clock_t cend = clock();
+#endif
+
+		delete [] mem;
+
+		static const char* note = 
+#ifdef DEBUG
+			"DEBUG";
+#else
+			"Release";
+#endif
+
+#if defined( _MSC_VER )
+		printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end-start) / ( (double)freq * (double)COUNT) );
+#else
+		printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart)/(double)COUNT );
+#endif
+	}
+
+	#if defined( _MSC_VER ) &&  defined( DEBUG )
 		_CrtMemCheckpoint( &endMemState );  
 		//_CrtMemDumpStatistics( &endMemState );