removed the pointer-diff

This commit is contained in:
Lee Thomason (grinliz) 2012-03-07 21:54:57 -08:00
commit 7ca5558bca
8 changed files with 238 additions and 69 deletions

2
dox
View File

@ -32,7 +32,7 @@ PROJECT_NAME = "TinyXML-2"
# This could be handy for archiving the generated documentation or # This could be handy for archiving the generated documentation or
# if some version control system is used. # 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 # 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 # for a project that appears at the top of each page and should give viewer

View File

@ -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 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 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, 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 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 strings are query and set as 'const char*'. This allows the use of internal
@ -71,7 +71,7 @@ Both parsers:
Advantages of TinyXML-2 Advantages of TinyXML-2
<ol> <ol>
<li>The focus of all future dev.</li> <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>No STL requirement.</li>
<li>More modern C++, including a proper namespace.</li> <li>More modern C++, including a proper namespace.</li>
<li>Proper and useful handling of whitespace</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. line-feed character, as required by the XML spec.
White space in text is preserved. For example: White space in text is preserved. For example:
@verbatim
<element> Hello, World</element> <element> Hello, World</element>
@endverbatim
The leading space before the "Hello" and the double space after the comma are preserved. The leading space before the "Hello" and the double space after the comma are preserved.
Line-feeds are preserved, as in this example: Line-feeds are preserved, as in this example:
@verbatim
<element> Hello again, <element> Hello again,
World</element> World</element>
@endverbatim
However, white space between elements is *not* preserved. Although not strictly compliant, 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 tracking and reporting inta-element space is awkward, and not normally valuable. TinyXML-2
sees these as the same XML: sees these as the same XML:
@verbatim <document>
<document> <data>1</data>
<data>1</data> <data>2</data>
<data>2</data> <data>3</data>
<data>3</data> </document>
</document>
@endverbatim
@verbatim <document><data>1</data><data>2</data><data>3</data></document>
<document><data>1</data><data>2</data><data>3</data></document>
@endverbatim
<h3> Entities </h3> <h3> Entities </h3>
TinyXML-2 recognizes the pre-defined "character entities", meaning special TinyXML-2 recognizes the pre-defined "character entities", meaning special
characters. Namely: characters. Namely:
@verbatim
&amp; & &amp; &
&lt; < &lt; <
&gt; > &gt; >
&quot; " &quot; "
&apos; ' &apos; '
@endverbatim
These are recognized when the XML document is read, and translated to there These are recognized when the XML document is read, and translated to there
UTF-8 equivalents. For instance, text with the XML of: UTF-8 equivalents. For instance, text with the XML of:
@verbatim
Far &amp; Away Far &amp; Away
@endverbatim
will have the Value() of "Far & Away" when queried from the XMLText object, 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. 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> <h4> Print to file </h4>
You can directly use the convenience function: You can directly use the convenience function:
@verbatim
XMLDocument doc; XMLDocument doc;
... ...
doc.Save( "foo.xml" ); doc.Save( "foo.xml" );
@endverbatim
Or the XMLPrinter class: Or the XMLPrinter class:
@verbatim
XMLPrinter printer( fp ); XMLPrinter printer( fp );
doc.Print( &printer ); doc.Print( &printer );
@endverbatim
<h4> Print to memory </h4> <h4> Print to memory </h4>
Printing to memory is supported by the XMLPrinter. Printing to memory is supported by the XMLPrinter.
@verbatim
XMLPrinter printer; XMLPrinter printer;
doc->Print( &printer ); doc->Print( &printer );
// printer.CStr() has a const char* to the XML // printer.CStr() has a const char* to the XML
@endverbatim
<h4> Print without an XMLDocument </h4> <h4> Print without an XMLDocument </h4>
When loading, an XML parser is very useful. However, sometimes When loading, an XML parser is very useful. However, sometimes
when saving, it just gets in the way. The code is often set up when saving, it just gets in the way. The code is often set up
for streaming, and constructing the DOM is just overhead. for streaming, and constructing the DOM is just overhead.
The Printer supports the streaming case. The following code The Printer supports the streaming case. The following code
prints out a trivially simple XML file without ever creating prints out a trivially simple XML file without ever creating
an XML document. an XML document.
@verbatim
XMLPrinter printer( fp ); XMLPrinter printer( fp );
printer.OpenElement( "foo" ); printer.OpenElement( "foo" );
printer.PushAttribute( "foo", "bar" ); printer.PushAttribute( "foo", "bar" );
printer.CloseElement(); printer.CloseElement();
@endverbatim
<h2> Using and Installing </h2> <h2> Using and Installing </h2>

79
setversion.py Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,9 +3,12 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h>
#if defined( _MSC_VER ) && defined( DEBUG ) #if defined( _MSC_VER )
#include <crtdbg.h> #include <crtdbg.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
_CrtMemState startMemState; _CrtMemState startMemState;
_CrtMemState endMemState; _CrtMemState endMemState;
#endif #endif
@ -211,6 +214,8 @@ int main( int /*argc*/, const char* /*argv*/ )
//gNewTotal = gNew - newStart; //gNewTotal = gNew - newStart;
} }
{ {
const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n" const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
"<passages count=\"006\" formatversion=\"20020620\">\n" "<passages count=\"006\" formatversion=\"20020620\">\n"
@ -458,6 +463,24 @@ int main( int /*argc*/, const char* /*argv*/ )
fclose( textfile ); 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'/>"; const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
@ -654,6 +677,62 @@ int main( int /*argc*/, const char* /*argv*/ )
XMLTest( "Clone and Equal", 4, count ); XMLTest( "Clone and Equal", 4, count );
} }
// ----------- 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 ) #if defined( _MSC_VER ) && defined( DEBUG )
_CrtMemCheckpoint( &endMemState ); _CrtMemCheckpoint( &endMemState );
//_CrtMemDumpStatistics( &endMemState ); //_CrtMemDumpStatistics( &endMemState );