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
# 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

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
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
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) )
{
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 );
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;
}
for( int i=0; i<NUM_ENTITIES; ++i ) {
if ( entities[i].value == *q ) {
Print( "&%s;", entities[i].pattern );
break;
}
}
++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;
}

View File

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

View File

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

View File

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

View File

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