parent
e71ab70356
commit
fc19c6ca11
|
@ -26,10 +26,81 @@ distribution.
|
||||||
#include <new> // yes, this one new style header, is in the Android SDK.
|
#include <new> // yes, this one new style header, is in the Android SDK.
|
||||||
#if defined(ANDROID_NDK) || defined(__QNXNTO__)
|
#if defined(ANDROID_NDK) || defined(__QNXNTO__)
|
||||||
# include <stddef.h>
|
# include <stddef.h>
|
||||||
|
# include <stdarg.h>
|
||||||
#else
|
#else
|
||||||
# include <cstddef>
|
# include <cstddef>
|
||||||
|
# include <cstdarg>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE)
|
||||||
|
// Microsoft Visual Studio, version 2005 and higher. Not WinCE.
|
||||||
|
/*int _snprintf_s(
|
||||||
|
char *buffer,
|
||||||
|
size_t sizeOfBuffer,
|
||||||
|
size_t count,
|
||||||
|
const char *format [,
|
||||||
|
argument] ...
|
||||||
|
);*/
|
||||||
|
inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
va_start( va, format );
|
||||||
|
int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
|
||||||
|
va_end( va );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int TIXML_VSNPRINTF( char* buffer, size_t size, const char* format, va_list va )
|
||||||
|
{
|
||||||
|
int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TIXML_VSCPRINTF _vscprintf
|
||||||
|
#define TIXML_SSCANF sscanf_s
|
||||||
|
#elif defined _MSC_VER
|
||||||
|
// Microsoft Visual Studio 2003 and earlier or WinCE
|
||||||
|
#define TIXML_SNPRINTF _snprintf
|
||||||
|
#define TIXML_VSNPRINTF _vsnprintf
|
||||||
|
#define TIXML_SSCANF sscanf
|
||||||
|
#if (_MSC_VER < 1400 ) && (!defined WINCE)
|
||||||
|
// Microsoft Visual Studio 2003 and not WinCE.
|
||||||
|
#define TIXML_VSCPRINTF _vscprintf // VS2003's C runtime has this, but VC6 C runtime or WinCE SDK doesn't have.
|
||||||
|
#else
|
||||||
|
// Microsoft Visual Studio 2003 and earlier or WinCE.
|
||||||
|
inline int TIXML_VSCPRINTF( const char* format, va_list va )
|
||||||
|
{
|
||||||
|
int len = 512;
|
||||||
|
for (;;) {
|
||||||
|
len = len*2;
|
||||||
|
char* str = new char[len]();
|
||||||
|
const int required = _vsnprintf(str, len, format, va);
|
||||||
|
delete[] str;
|
||||||
|
if ( required != -1 ) {
|
||||||
|
TIXMLASSERT( required >= 0 );
|
||||||
|
len = required;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TIXMLASSERT( len >= 0 );
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
// GCC version 3 and higher
|
||||||
|
//#warning( "Using sn* functions." )
|
||||||
|
#define TIXML_SNPRINTF snprintf
|
||||||
|
#define TIXML_VSNPRINTF vsnprintf
|
||||||
|
inline int TIXML_VSCPRINTF( const char* format, va_list va )
|
||||||
|
{
|
||||||
|
int len = vsnprintf( 0, 0, format, va );
|
||||||
|
TIXMLASSERT( len >= 0 );
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
#define TIXML_SSCANF sscanf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static const char LINE_FEED = (char)0x0a; // all line endings are normalized to LF
|
static const char LINE_FEED = (char)0x0a; // all line endings are normalized to LF
|
||||||
static const char LF = LINE_FEED;
|
static const char LF = LINE_FEED;
|
||||||
static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out
|
static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out
|
||||||
|
@ -140,19 +211,19 @@ char* StrPair::ParseName( char* p )
|
||||||
if ( !p || !(*p) ) {
|
if ( !p || !(*p) ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if ( !XMLUtil::IsNameStartChar( *p ) ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
char* const start = p;
|
char* const start = p;
|
||||||
|
++p;
|
||||||
while( *p && ( p == start ? XMLUtil::IsNameStartChar( *p ) : XMLUtil::IsNameChar( *p ) )) {
|
while ( *p && XMLUtil::IsNameChar( *p ) ) {
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( p > start ) {
|
|
||||||
Set( start, p, 0 );
|
Set( start, p, 0 );
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void StrPair::CollapseWhitespace()
|
void StrPair::CollapseWhitespace()
|
||||||
|
@ -162,7 +233,7 @@ void StrPair::CollapseWhitespace()
|
||||||
// Trim leading space.
|
// Trim leading space.
|
||||||
_start = XMLUtil::SkipWhiteSpace( _start );
|
_start = XMLUtil::SkipWhiteSpace( _start );
|
||||||
|
|
||||||
if ( _start && *_start ) {
|
if ( *_start ) {
|
||||||
char* p = _start; // the read pointer
|
char* p = _start; // the read pointer
|
||||||
char* q = _start; // the write pointer
|
char* q = _start; // the write pointer
|
||||||
|
|
||||||
|
@ -186,6 +257,8 @@ void StrPair::CollapseWhitespace()
|
||||||
|
|
||||||
const char* StrPair::GetStr()
|
const char* StrPair::GetStr()
|
||||||
{
|
{
|
||||||
|
TIXMLASSERT( _start );
|
||||||
|
TIXMLASSERT( _end );
|
||||||
if ( _flags & NEEDS_FLUSH ) {
|
if ( _flags & NEEDS_FLUSH ) {
|
||||||
*_end = 0;
|
*_end = 0;
|
||||||
_flags ^= NEEDS_FLUSH;
|
_flags ^= NEEDS_FLUSH;
|
||||||
|
@ -226,15 +299,23 @@ const char* StrPair::GetStr()
|
||||||
const int buflen = 10;
|
const int buflen = 10;
|
||||||
char buf[buflen] = { 0 };
|
char buf[buflen] = { 0 };
|
||||||
int len = 0;
|
int len = 0;
|
||||||
p = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );
|
char* adjusted = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );
|
||||||
|
if ( adjusted == 0 ) {
|
||||||
|
*q = *p;
|
||||||
|
++p;
|
||||||
|
++q;
|
||||||
|
}
|
||||||
|
else {
|
||||||
TIXMLASSERT( 0 <= len && len <= buflen );
|
TIXMLASSERT( 0 <= len && len <= buflen );
|
||||||
TIXMLASSERT( q + len <= p );
|
TIXMLASSERT( q + len <= adjusted );
|
||||||
|
p = adjusted;
|
||||||
memcpy( q, buf, len );
|
memcpy( q, buf, len );
|
||||||
q += len;
|
q += len;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
int i=0;
|
bool entityFound = false;
|
||||||
for(; i<NUM_ENTITIES; ++i ) {
|
for( int i = 0; i < NUM_ENTITIES; ++i ) {
|
||||||
const Entity& entity = entities[i];
|
const Entity& entity = entities[i];
|
||||||
if ( strncmp( p + 1, entity.pattern, entity.length ) == 0
|
if ( strncmp( p + 1, entity.pattern, entity.length ) == 0
|
||||||
&& *( p + entity.length + 1 ) == ';' ) {
|
&& *( p + entity.length + 1 ) == ';' ) {
|
||||||
|
@ -242,10 +323,11 @@ const char* StrPair::GetStr()
|
||||||
*q = entity.value;
|
*q = entity.value;
|
||||||
++q;
|
++q;
|
||||||
p += entity.length + 2;
|
p += entity.length + 2;
|
||||||
|
entityFound = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( i == NUM_ENTITIES ) {
|
if ( !entityFound ) {
|
||||||
// fixme: treat as error?
|
// fixme: treat as error?
|
||||||
++p;
|
++p;
|
||||||
++q;
|
++q;
|
||||||
|
@ -262,11 +344,12 @@ const char* StrPair::GetStr()
|
||||||
}
|
}
|
||||||
// The loop below has plenty going on, and this
|
// The loop below has plenty going on, and this
|
||||||
// is a less useful mode. Break it out.
|
// is a less useful mode. Break it out.
|
||||||
if ( _flags & COLLAPSE_WHITESPACE ) {
|
if ( _flags & NEEDS_WHITESPACE_COLLAPSING ) {
|
||||||
CollapseWhitespace();
|
CollapseWhitespace();
|
||||||
}
|
}
|
||||||
_flags = (_flags & NEEDS_DELETE);
|
_flags = (_flags & NEEDS_DELETE);
|
||||||
}
|
}
|
||||||
|
TIXMLASSERT( _start );
|
||||||
return _start;
|
return _start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,6 +360,8 @@ const char* StrPair::GetStr()
|
||||||
|
|
||||||
const char* XMLUtil::ReadBOM( const char* p, bool* bom )
|
const char* XMLUtil::ReadBOM( const char* p, bool* bom )
|
||||||
{
|
{
|
||||||
|
TIXMLASSERT( p );
|
||||||
|
TIXMLASSERT( bom );
|
||||||
*bom = false;
|
*bom = false;
|
||||||
const unsigned char* pu = reinterpret_cast<const unsigned char*>(p);
|
const unsigned char* pu = reinterpret_cast<const unsigned char*>(p);
|
||||||
// Check for BOM:
|
// Check for BOM:
|
||||||
|
@ -286,6 +371,7 @@ const char* XMLUtil::ReadBOM( const char* p, bool* bom )
|
||||||
*bom = true;
|
*bom = true;
|
||||||
p += 3;
|
p += 3;
|
||||||
}
|
}
|
||||||
|
TIXMLASSERT( p );
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +395,7 @@ void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length
|
||||||
*length = 4;
|
*length = 4;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*length = 0; // This code won't covert this correctly anyway.
|
*length = 0; // This code won't convert this correctly anyway.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,8 +418,9 @@ void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length
|
||||||
case 1:
|
case 1:
|
||||||
--output;
|
--output;
|
||||||
*output = (char)(input | FIRST_BYTE_MARK[*length]);
|
*output = (char)(input | FIRST_BYTE_MARK[*length]);
|
||||||
default:
|
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
TIXMLASSERT( false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,65 +432,83 @@ 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;
|
||||||
|
TIXMLASSERT( sizeof( ucs ) >= 4 );
|
||||||
ptrdiff_t delta = 0;
|
ptrdiff_t delta = 0;
|
||||||
unsigned mult = 1;
|
unsigned mult = 1;
|
||||||
|
static const char SEMICOLON = ';';
|
||||||
|
|
||||||
if ( *(p+2) == 'x' ) {
|
if ( *(p+2) == 'x' ) {
|
||||||
// Hexadecimal.
|
// Hexadecimal.
|
||||||
if ( !*(p+3) ) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* q = p+3;
|
const char* q = p+3;
|
||||||
q = strchr( q, ';' );
|
if ( !(*q) ) {
|
||||||
|
|
||||||
if ( !q || !*q ) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
q = strchr( q, SEMICOLON );
|
||||||
|
|
||||||
|
if ( !q ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
TIXMLASSERT( *q == SEMICOLON );
|
||||||
|
|
||||||
delta = q-p;
|
delta = q-p;
|
||||||
--q;
|
--q;
|
||||||
|
|
||||||
while ( *q != 'x' ) {
|
while ( *q != 'x' ) {
|
||||||
|
unsigned int digit = 0;
|
||||||
|
|
||||||
if ( *q >= '0' && *q <= '9' ) {
|
if ( *q >= '0' && *q <= '9' ) {
|
||||||
ucs += mult * (*q - '0');
|
digit = *q - '0';
|
||||||
}
|
}
|
||||||
else if ( *q >= 'a' && *q <= 'f' ) {
|
else if ( *q >= 'a' && *q <= 'f' ) {
|
||||||
ucs += mult * (*q - 'a' + 10);
|
digit = *q - 'a' + 10;
|
||||||
}
|
}
|
||||||
else if ( *q >= 'A' && *q <= 'F' ) {
|
else if ( *q >= 'A' && *q <= 'F' ) {
|
||||||
ucs += mult * (*q - 'A' + 10 );
|
digit = *q - 'A' + 10;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
TIXMLASSERT( digit >= 0 && digit < 16);
|
||||||
|
TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );
|
||||||
|
const unsigned int digitScaled = mult * digit;
|
||||||
|
TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );
|
||||||
|
ucs += digitScaled;
|
||||||
|
TIXMLASSERT( mult <= UINT_MAX / 16 );
|
||||||
mult *= 16;
|
mult *= 16;
|
||||||
--q;
|
--q;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Decimal.
|
// Decimal.
|
||||||
if ( !*(p+2) ) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* q = p+2;
|
const char* q = p+2;
|
||||||
q = strchr( q, ';' );
|
if ( !(*q) ) {
|
||||||
|
|
||||||
if ( !q || !*q ) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
q = strchr( q, SEMICOLON );
|
||||||
|
|
||||||
|
if ( !q ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
TIXMLASSERT( *q == SEMICOLON );
|
||||||
|
|
||||||
delta = q-p;
|
delta = q-p;
|
||||||
--q;
|
--q;
|
||||||
|
|
||||||
while ( *q != '#' ) {
|
while ( *q != '#' ) {
|
||||||
if ( *q >= '0' && *q <= '9' ) {
|
if ( *q >= '0' && *q <= '9' ) {
|
||||||
ucs += mult * (*q - '0');
|
const unsigned int digit = *q - '0';
|
||||||
|
TIXMLASSERT( digit >= 0 && digit < 10);
|
||||||
|
TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );
|
||||||
|
const unsigned int digitScaled = mult * digit;
|
||||||
|
TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );
|
||||||
|
ucs += digitScaled;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
TIXMLASSERT( mult <= UINT_MAX / 10 );
|
||||||
mult *= 10;
|
mult *= 10;
|
||||||
--q;
|
--q;
|
||||||
}
|
}
|
||||||
|
@ -503,35 +608,31 @@ bool XMLUtil::ToDouble( const char* str, double* value )
|
||||||
|
|
||||||
char* XMLDocument::Identify( char* p, XMLNode** node )
|
char* XMLDocument::Identify( char* p, XMLNode** node )
|
||||||
{
|
{
|
||||||
|
TIXMLASSERT( node );
|
||||||
|
TIXMLASSERT( p );
|
||||||
char* const start = p;
|
char* const start = p;
|
||||||
p = XMLUtil::SkipWhiteSpace( p );
|
p = XMLUtil::SkipWhiteSpace( p );
|
||||||
if( !p || !*p ) {
|
if( !*p ) {
|
||||||
|
*node = 0;
|
||||||
|
TIXMLASSERT( p );
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
// What is this thing?
|
// These strings define the matching patterns:
|
||||||
// These strings define the matching patters:
|
|
||||||
static const char* xmlHeader = { "<?" };
|
static const char* xmlHeader = { "<?" };
|
||||||
static const char* commentHeader = { "<!--" };
|
static const char* commentHeader = { "<!--" };
|
||||||
static const char* dtdHeader = { "<!" };
|
|
||||||
static const char* cdataHeader = { "<![CDATA[" };
|
static const char* cdataHeader = { "<![CDATA[" };
|
||||||
|
static const char* dtdHeader = { "<!" };
|
||||||
static const char* elementHeader = { "<" }; // and a header for everything else; check last.
|
static const char* elementHeader = { "<" }; // and a header for everything else; check last.
|
||||||
|
|
||||||
static const int xmlHeaderLen = 2;
|
static const int xmlHeaderLen = 2;
|
||||||
static const int commentHeaderLen = 4;
|
static const int commentHeaderLen = 4;
|
||||||
static const int dtdHeaderLen = 2;
|
|
||||||
static const int cdataHeaderLen = 9;
|
static const int cdataHeaderLen = 9;
|
||||||
|
static const int dtdHeaderLen = 2;
|
||||||
static const int elementHeaderLen = 1;
|
static const int elementHeaderLen = 1;
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#pragma warning ( push )
|
|
||||||
#pragma warning ( disable : 4127 )
|
|
||||||
#endif
|
|
||||||
TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) ); // use same memory pool
|
TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) ); // use same memory pool
|
||||||
TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) ); // use same memory pool
|
TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) ); // use same memory pool
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#pragma warning (pop)
|
|
||||||
#endif
|
|
||||||
XMLNode* returnNode = 0;
|
XMLNode* returnNode = 0;
|
||||||
if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
|
if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
|
||||||
TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() );
|
TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() );
|
||||||
|
@ -572,6 +673,8 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
|
||||||
p = start; // Back it up, all the text counts.
|
p = start; // Back it up, all the text counts.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TIXMLASSERT( returnNode );
|
||||||
|
TIXMLASSERT( p );
|
||||||
*node = returnNode;
|
*node = returnNode;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -579,6 +682,7 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
|
||||||
|
|
||||||
bool XMLDocument::Accept( XMLVisitor* visitor ) const
|
bool XMLDocument::Accept( XMLVisitor* visitor ) const
|
||||||
{
|
{
|
||||||
|
TIXMLASSERT( visitor );
|
||||||
if ( visitor->VisitEnter( *this ) ) {
|
if ( visitor->VisitEnter( *this ) ) {
|
||||||
for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
|
for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
|
||||||
if ( !node->Accept( visitor ) ) {
|
if ( !node->Accept( visitor ) ) {
|
||||||
|
@ -612,6 +716,9 @@ XMLNode::~XMLNode()
|
||||||
|
|
||||||
const char* XMLNode::Value() const
|
const char* XMLNode::Value() const
|
||||||
{
|
{
|
||||||
|
// Catch an edge case: XMLDocuments don't have a a Value. Carefully return nullptr.
|
||||||
|
if ( this->ToDocument() )
|
||||||
|
return 0;
|
||||||
return _value.GetStr();
|
return _value.GetStr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,6 +736,7 @@ void XMLNode::SetValue( const char* str, bool staticMem )
|
||||||
void XMLNode::DeleteChildren()
|
void XMLNode::DeleteChildren()
|
||||||
{
|
{
|
||||||
while( _firstChild ) {
|
while( _firstChild ) {
|
||||||
|
TIXMLASSERT( _lastChild );
|
||||||
TIXMLASSERT( _firstChild->_document == _document );
|
TIXMLASSERT( _firstChild->_document == _document );
|
||||||
XMLNode* node = _firstChild;
|
XMLNode* node = _firstChild;
|
||||||
Unlink( node );
|
Unlink( node );
|
||||||
|
@ -641,7 +749,9 @@ void XMLNode::DeleteChildren()
|
||||||
|
|
||||||
void XMLNode::Unlink( XMLNode* child )
|
void XMLNode::Unlink( XMLNode* child )
|
||||||
{
|
{
|
||||||
|
TIXMLASSERT( child );
|
||||||
TIXMLASSERT( child->_document == _document );
|
TIXMLASSERT( child->_document == _document );
|
||||||
|
TIXMLASSERT( child->_parent == this );
|
||||||
if ( child == _firstChild ) {
|
if ( child == _firstChild ) {
|
||||||
_firstChild = _firstChild->_next;
|
_firstChild = _firstChild->_next;
|
||||||
}
|
}
|
||||||
|
@ -661,6 +771,7 @@ void XMLNode::Unlink( XMLNode* child )
|
||||||
|
|
||||||
void XMLNode::DeleteChild( XMLNode* node )
|
void XMLNode::DeleteChild( XMLNode* node )
|
||||||
{
|
{
|
||||||
|
TIXMLASSERT( node );
|
||||||
TIXMLASSERT( node->_document == _document );
|
TIXMLASSERT( node->_document == _document );
|
||||||
TIXMLASSERT( node->_parent == this );
|
TIXMLASSERT( node->_parent == this );
|
||||||
DeleteNode( node );
|
DeleteNode( node );
|
||||||
|
@ -674,11 +785,7 @@ XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )
|
||||||
TIXMLASSERT( false );
|
TIXMLASSERT( false );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
InsertChildPreamble( addThis );
|
||||||
if (addThis->_parent)
|
|
||||||
addThis->_parent->Unlink( addThis );
|
|
||||||
else
|
|
||||||
addThis->_memPool->SetTracked();
|
|
||||||
|
|
||||||
if ( _lastChild ) {
|
if ( _lastChild ) {
|
||||||
TIXMLASSERT( _firstChild );
|
TIXMLASSERT( _firstChild );
|
||||||
|
@ -708,11 +815,7 @@ XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis )
|
||||||
TIXMLASSERT( false );
|
TIXMLASSERT( false );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
InsertChildPreamble( addThis );
|
||||||
if (addThis->_parent)
|
|
||||||
addThis->_parent->Unlink( addThis );
|
|
||||||
else
|
|
||||||
addThis->_memPool->SetTracked();
|
|
||||||
|
|
||||||
if ( _firstChild ) {
|
if ( _firstChild ) {
|
||||||
TIXMLASSERT( _lastChild );
|
TIXMLASSERT( _lastChild );
|
||||||
|
@ -755,10 +858,7 @@ XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )
|
||||||
// The last node or the only node.
|
// The last node or the only node.
|
||||||
return InsertEndChild( addThis );
|
return InsertEndChild( addThis );
|
||||||
}
|
}
|
||||||
if (addThis->_parent)
|
InsertChildPreamble( addThis );
|
||||||
addThis->_parent->Unlink( addThis );
|
|
||||||
else
|
|
||||||
addThis->_memPool->SetTracked();
|
|
||||||
addThis->_prev = afterThis;
|
addThis->_prev = afterThis;
|
||||||
addThis->_next = afterThis->_next;
|
addThis->_next = afterThis->_next;
|
||||||
afterThis->_next->_prev = addThis;
|
afterThis->_next->_prev = addThis;
|
||||||
|
@ -770,12 +870,12 @@ XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const XMLElement* XMLNode::FirstChildElement( const char* value ) const
|
const XMLElement* XMLNode::FirstChildElement( const char* name ) const
|
||||||
{
|
{
|
||||||
for( XMLNode* node=_firstChild; node; node=node->_next ) {
|
for( const XMLNode* node = _firstChild; node; node = node->_next ) {
|
||||||
XMLElement* element = node->ToElement();
|
const XMLElement* element = node->ToElement();
|
||||||
if ( element ) {
|
if ( element ) {
|
||||||
if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
|
if ( !name || XMLUtil::StringEqual( element->Name(), name ) ) {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -784,12 +884,12 @@ const XMLElement* XMLNode::FirstChildElement( const char* value ) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const XMLElement* XMLNode::LastChildElement( const char* value ) const
|
const XMLElement* XMLNode::LastChildElement( const char* name ) const
|
||||||
{
|
{
|
||||||
for( XMLNode* node=_lastChild; node; node=node->_prev ) {
|
for( const XMLNode* node = _lastChild; node; node = node->_prev ) {
|
||||||
XMLElement* element = node->ToElement();
|
const XMLElement* element = node->ToElement();
|
||||||
if ( element ) {
|
if ( element ) {
|
||||||
if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
|
if ( !name || XMLUtil::StringEqual( element->Name(), name ) ) {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -798,12 +898,12 @@ const XMLElement* XMLNode::LastChildElement( const char* value ) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const XMLElement* XMLNode::NextSiblingElement( const char* value ) const
|
const XMLElement* XMLNode::NextSiblingElement( const char* name ) const
|
||||||
{
|
{
|
||||||
for( XMLNode* node=this->_next; node; node = node->_next ) {
|
for( const XMLNode* node = _next; node; node = node->_next ) {
|
||||||
const XMLElement* element = node->ToElement();
|
const XMLElement* element = node->ToElement();
|
||||||
if ( element
|
if ( element
|
||||||
&& (!value || XMLUtil::StringEqual( value, node->Value() ))) {
|
&& (!name || XMLUtil::StringEqual( name, element->Name() ))) {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -811,12 +911,12 @@ const XMLElement* XMLNode::NextSiblingElement( const char* value ) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const XMLElement* XMLNode::PreviousSiblingElement( const char* value ) const
|
const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const
|
||||||
{
|
{
|
||||||
for( XMLNode* node=_prev; node; node = node->_prev ) {
|
for( const XMLNode* node = _prev; node; node = node->_prev ) {
|
||||||
const XMLElement* element = node->ToElement();
|
const XMLElement* element = node->ToElement();
|
||||||
if ( element
|
if ( element
|
||||||
&& (!value || XMLUtil::StringEqual( value, node->Value() ))) {
|
&& (!name || XMLUtil::StringEqual( name, element->Name() ))) {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -847,7 +947,7 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
|
||||||
XMLNode* node = 0;
|
XMLNode* node = 0;
|
||||||
|
|
||||||
p = _document->Identify( p, &node );
|
p = _document->Identify( p, &node );
|
||||||
if ( p == 0 || node == 0 ) {
|
if ( node == 0 ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -855,16 +955,27 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
|
||||||
p = node->ParseDeep( p, &endTag );
|
p = node->ParseDeep( p, &endTag );
|
||||||
if ( !p ) {
|
if ( !p ) {
|
||||||
DeleteNode( node );
|
DeleteNode( node );
|
||||||
node = 0;
|
|
||||||
if ( !_document->Error() ) {
|
if ( !_document->Error() ) {
|
||||||
_document->SetError( XML_ERROR_PARSING, 0, 0 );
|
_document->SetError( XML_ERROR_PARSING, 0, 0 );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XMLDeclaration* decl = node->ToDeclaration();
|
||||||
|
if ( decl ) {
|
||||||
|
// A declaration can only be the first child of a document.
|
||||||
|
// Set error, if document already has children.
|
||||||
|
if ( !_document->NoChildren() ) {
|
||||||
|
_document->SetError( XML_ERROR_PARSING_DECLARATION, decl->Value(), 0);
|
||||||
|
DeleteNode( decl );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
XMLElement* ele = node->ToElement();
|
XMLElement* ele = node->ToElement();
|
||||||
|
if ( ele ) {
|
||||||
// We read the end tag. Return it to the parent.
|
// We read the end tag. Return it to the parent.
|
||||||
if ( ele && ele->ClosingType() == XMLElement::CLOSING ) {
|
if ( ele->ClosingType() == XMLElement::CLOSING ) {
|
||||||
if ( parentEnd ) {
|
if ( parentEnd ) {
|
||||||
ele->_value.TransferTo( parentEnd );
|
ele->_value.TransferTo( parentEnd );
|
||||||
}
|
}
|
||||||
|
@ -875,31 +986,27 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
|
||||||
|
|
||||||
// Handle an end tag returned to this level.
|
// Handle an end tag returned to this level.
|
||||||
// And handle a bunch of annoying errors.
|
// And handle a bunch of annoying errors.
|
||||||
if ( ele ) {
|
|
||||||
bool mismatch = false;
|
bool mismatch = false;
|
||||||
if ( endTag.Empty() && ele->ClosingType() == XMLElement::OPEN ) {
|
if ( endTag.Empty() ) {
|
||||||
|
if ( ele->ClosingType() == XMLElement::OPEN ) {
|
||||||
mismatch = true;
|
mismatch = true;
|
||||||
}
|
}
|
||||||
else if ( !endTag.Empty() && ele->ClosingType() != XMLElement::OPEN ) {
|
}
|
||||||
|
else {
|
||||||
|
if ( ele->ClosingType() != XMLElement::OPEN ) {
|
||||||
mismatch = true;
|
mismatch = true;
|
||||||
}
|
}
|
||||||
else if ( !endTag.Empty() ) {
|
else if ( !XMLUtil::StringEqual( endTag.GetStr(), ele->Name() ) ) {
|
||||||
if ( !XMLUtil::StringEqual( endTag.GetStr(), node->Value() )) {
|
|
||||||
mismatch = true;
|
mismatch = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( mismatch ) {
|
if ( mismatch ) {
|
||||||
_document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
|
_document->SetError( XML_ERROR_MISMATCHED_ELEMENT, ele->Name(), 0 );
|
||||||
p = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( p == 0 ) {
|
|
||||||
DeleteNode( node );
|
DeleteNode( node );
|
||||||
node = 0;
|
break;
|
||||||
}
|
}
|
||||||
if ( node ) {
|
|
||||||
this->InsertEndChild( node );
|
|
||||||
}
|
}
|
||||||
|
InsertEndChild( node );
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -914,6 +1021,17 @@ void XMLNode::DeleteNode( XMLNode* node )
|
||||||
pool->Free( node );
|
pool->Free( node );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const
|
||||||
|
{
|
||||||
|
TIXMLASSERT( insertThis );
|
||||||
|
TIXMLASSERT( insertThis->_document == _document );
|
||||||
|
|
||||||
|
if ( insertThis->_parent )
|
||||||
|
insertThis->_parent->Unlink( insertThis );
|
||||||
|
else
|
||||||
|
insertThis->_memPool->SetTracked();
|
||||||
|
}
|
||||||
|
|
||||||
// --------- XMLText ---------- //
|
// --------- XMLText ---------- //
|
||||||
char* XMLText::ParseDeep( char* p, StrPair* )
|
char* XMLText::ParseDeep( char* p, StrPair* )
|
||||||
{
|
{
|
||||||
|
@ -928,16 +1046,16 @@ char* XMLText::ParseDeep( char* p, StrPair* )
|
||||||
else {
|
else {
|
||||||
int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES;
|
int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES;
|
||||||
if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) {
|
if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) {
|
||||||
flags |= StrPair::COLLAPSE_WHITESPACE;
|
flags |= StrPair::NEEDS_WHITESPACE_COLLAPSING;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = _value.ParseText( p, "<", flags );
|
p = _value.ParseText( p, "<", flags );
|
||||||
if ( !p ) {
|
|
||||||
_document->SetError( XML_ERROR_PARSING_TEXT, start, 0 );
|
|
||||||
}
|
|
||||||
if ( p && *p ) {
|
if ( p && *p ) {
|
||||||
return p-1;
|
return p-1;
|
||||||
}
|
}
|
||||||
|
if ( !p ) {
|
||||||
|
_document->SetError( XML_ERROR_PARSING_TEXT, start, 0 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1138,7 +1256,7 @@ char* XMLAttribute::ParseDeep( char* p, bool processEntities )
|
||||||
|
|
||||||
// Skip white space before =
|
// Skip white space before =
|
||||||
p = XMLUtil::SkipWhiteSpace( p );
|
p = XMLUtil::SkipWhiteSpace( p );
|
||||||
if ( !p || *p != '=' ) {
|
if ( *p != '=' ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1474,7 +1592,7 @@ char* XMLElement::ParseAttributes( char* p )
|
||||||
// Read the attributes.
|
// Read the attributes.
|
||||||
while( p ) {
|
while( p ) {
|
||||||
p = XMLUtil::SkipWhiteSpace( p );
|
p = XMLUtil::SkipWhiteSpace( p );
|
||||||
if ( !p || !(*p) ) {
|
if ( !(*p) ) {
|
||||||
_document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() );
|
_document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1506,15 +1624,15 @@ char* XMLElement::ParseAttributes( char* p )
|
||||||
prevAttribute = attrib;
|
prevAttribute = attrib;
|
||||||
}
|
}
|
||||||
// end of the tag
|
// end of the tag
|
||||||
else if ( *p == '/' && *(p+1) == '>' ) {
|
|
||||||
_closingType = CLOSED;
|
|
||||||
return p+2; // done; sealed element.
|
|
||||||
}
|
|
||||||
// end of the tag
|
|
||||||
else if ( *p == '>' ) {
|
else if ( *p == '>' ) {
|
||||||
++p;
|
++p;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// end of the tag
|
||||||
|
else if ( *p == '/' && *(p+1) == '>' ) {
|
||||||
|
_closingType = CLOSED;
|
||||||
|
return p+2; // done; sealed element.
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
_document->SetError( XML_ERROR_PARSING_ELEMENT, start, p );
|
_document->SetError( XML_ERROR_PARSING_ELEMENT, start, p );
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1541,9 +1659,6 @@ char* XMLElement::ParseDeep( char* p, StrPair* strPair )
|
||||||
{
|
{
|
||||||
// Read the element name.
|
// Read the element name.
|
||||||
p = XMLUtil::SkipWhiteSpace( p );
|
p = XMLUtil::SkipWhiteSpace( p );
|
||||||
if ( !p ) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The closing element is the </element> form. It is
|
// The closing element is the </element> form. It is
|
||||||
// parsed just like a regular element then deleted from
|
// parsed just like a regular element then deleted from
|
||||||
|
@ -1586,7 +1701,7 @@ bool XMLElement::ShallowEqual( const XMLNode* compare ) const
|
||||||
{
|
{
|
||||||
TIXMLASSERT( compare );
|
TIXMLASSERT( compare );
|
||||||
const XMLElement* other = compare->ToElement();
|
const XMLElement* other = compare->ToElement();
|
||||||
if ( other && XMLUtil::StringEqual( other->Value(), Value() )) {
|
if ( other && XMLUtil::StringEqual( other->Name(), Name() )) {
|
||||||
|
|
||||||
const XMLAttribute* a=FirstAttribute();
|
const XMLAttribute* a=FirstAttribute();
|
||||||
const XMLAttribute* b=other->FirstAttribute();
|
const XMLAttribute* b=other->FirstAttribute();
|
||||||
|
@ -1659,7 +1774,8 @@ XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) :
|
||||||
_errorStr2( 0 ),
|
_errorStr2( 0 ),
|
||||||
_charBuffer( 0 )
|
_charBuffer( 0 )
|
||||||
{
|
{
|
||||||
_document = this; // avoid warning about 'this' in initializer list
|
// avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+)
|
||||||
|
_document = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1816,12 +1932,18 @@ XMLError XMLDocument::LoadFile( FILE* fp )
|
||||||
return _errorID;
|
return _errorID;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t size = filelength;
|
if ( (unsigned long)filelength >= (size_t)-1 ) {
|
||||||
if ( size == 0 ) {
|
// Cannot handle files which won't fit in buffer together with null terminator
|
||||||
|
SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
|
||||||
|
return _errorID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( filelength == 0 ) {
|
||||||
SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
|
SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
|
||||||
return _errorID;
|
return _errorID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const size_t size = filelength;
|
||||||
_charBuffer = new char[size+1];
|
_charBuffer = new char[size+1];
|
||||||
size_t read = fread( _charBuffer, 1, size, fp );
|
size_t read = fread( _charBuffer, 1, size, fp );
|
||||||
if ( read != size ) {
|
if ( read != size ) {
|
||||||
|
@ -1831,15 +1953,7 @@ XMLError XMLDocument::LoadFile( FILE* fp )
|
||||||
|
|
||||||
_charBuffer[size] = 0;
|
_charBuffer[size] = 0;
|
||||||
|
|
||||||
const char* p = _charBuffer;
|
Parse();
|
||||||
p = XMLUtil::SkipWhiteSpace( p );
|
|
||||||
p = XMLUtil::ReadBOM( p, &_writeBOM );
|
|
||||||
if ( !p || !*p ) {
|
|
||||||
SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
|
|
||||||
return _errorID;
|
|
||||||
}
|
|
||||||
|
|
||||||
ParseDeep( _charBuffer + (p-_charBuffer), 0 );
|
|
||||||
return _errorID;
|
return _errorID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1859,6 +1973,9 @@ XMLError XMLDocument::SaveFile( const char* filename, bool compact )
|
||||||
|
|
||||||
XMLError XMLDocument::SaveFile( FILE* fp, bool compact )
|
XMLError XMLDocument::SaveFile( FILE* fp, bool compact )
|
||||||
{
|
{
|
||||||
|
// Clear any error from the last save, otherwise it will get reported
|
||||||
|
// for *this* call.
|
||||||
|
SetError( XML_NO_ERROR, 0, 0 );
|
||||||
XMLPrinter stream( fp, compact );
|
XMLPrinter stream( fp, compact );
|
||||||
Print( &stream );
|
Print( &stream );
|
||||||
return _errorID;
|
return _errorID;
|
||||||
|
@ -1867,7 +1984,6 @@ XMLError XMLDocument::SaveFile( FILE* fp, bool compact )
|
||||||
|
|
||||||
XMLError XMLDocument::Parse( const char* p, size_t len )
|
XMLError XMLDocument::Parse( const char* p, size_t len )
|
||||||
{
|
{
|
||||||
const char* start = p;
|
|
||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
if ( len == 0 || !p || !*p ) {
|
if ( len == 0 || !p || !*p ) {
|
||||||
|
@ -1881,15 +1997,7 @@ XMLError XMLDocument::Parse( const char* p, size_t len )
|
||||||
memcpy( _charBuffer, p, len );
|
memcpy( _charBuffer, p, len );
|
||||||
_charBuffer[len] = 0;
|
_charBuffer[len] = 0;
|
||||||
|
|
||||||
p = XMLUtil::SkipWhiteSpace( p );
|
Parse();
|
||||||
p = XMLUtil::ReadBOM( p, &_writeBOM );
|
|
||||||
if ( !p || !*p ) {
|
|
||||||
SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
|
|
||||||
return _errorID;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptrdiff_t delta = p - start; // skip initial whitespace, BOM, etc.
|
|
||||||
ParseDeep( _charBuffer+delta, 0 );
|
|
||||||
if ( Error() ) {
|
if ( Error() ) {
|
||||||
// clean up now essentially dangling memory.
|
// clean up now essentially dangling memory.
|
||||||
// and the parse fail can put objects in the
|
// and the parse fail can put objects in the
|
||||||
|
@ -1906,12 +2014,14 @@ XMLError XMLDocument::Parse( const char* p, size_t len )
|
||||||
|
|
||||||
void XMLDocument::Print( XMLPrinter* streamer ) const
|
void XMLDocument::Print( XMLPrinter* streamer ) const
|
||||||
{
|
{
|
||||||
XMLPrinter stdStreamer( stdout );
|
if ( streamer ) {
|
||||||
if ( !streamer ) {
|
|
||||||
streamer = &stdStreamer;
|
|
||||||
}
|
|
||||||
Accept( streamer );
|
Accept( streamer );
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
XMLPrinter stdoutStreamer( stdout );
|
||||||
|
Accept( &stdoutStreamer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 )
|
void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 )
|
||||||
|
@ -1925,7 +2035,9 @@ void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 )
|
||||||
const char* XMLDocument::ErrorName() const
|
const char* XMLDocument::ErrorName() const
|
||||||
{
|
{
|
||||||
TIXMLASSERT( _errorID >= 0 && _errorID < XML_ERROR_COUNT );
|
TIXMLASSERT( _errorID >= 0 && _errorID < XML_ERROR_COUNT );
|
||||||
return _errorNames[_errorID];
|
const char* errorName = _errorNames[_errorID];
|
||||||
|
TIXMLASSERT( errorName && errorName[0] );
|
||||||
|
return errorName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XMLDocument::PrintError() const
|
void XMLDocument::PrintError() const
|
||||||
|
@ -1942,11 +2054,27 @@ void XMLDocument::PrintError() const
|
||||||
TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 );
|
TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Should check INT_MIN <= _errorID && _errorId <= INT_MAX, but that
|
||||||
|
// causes a clang "always true" -Wtautological-constant-out-of-range-compare warning
|
||||||
|
TIXMLASSERT( 0 <= _errorID && XML_ERROR_COUNT - 1 <= INT_MAX );
|
||||||
printf( "XMLDocument error id=%d '%s' str1=%s str2=%s\n",
|
printf( "XMLDocument error id=%d '%s' str1=%s str2=%s\n",
|
||||||
_errorID, ErrorName(), buf1, buf2 );
|
static_cast<int>( _errorID ), ErrorName(), buf1, buf2 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XMLDocument::Parse()
|
||||||
|
{
|
||||||
|
TIXMLASSERT( NoChildren() ); // Clear() must have been called previously
|
||||||
|
TIXMLASSERT( _charBuffer );
|
||||||
|
char* p = _charBuffer;
|
||||||
|
p = XMLUtil::SkipWhiteSpace( p );
|
||||||
|
p = const_cast<char*>( XMLUtil::ReadBOM( p, &_writeBOM ) );
|
||||||
|
if ( !*p ) {
|
||||||
|
SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ParseDeep(p, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :
|
XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :
|
||||||
_elementJustOpened( false ),
|
_elementJustOpened( false ),
|
||||||
|
@ -1962,16 +2090,13 @@ XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :
|
||||||
_restrictedEntityFlag[i] = false;
|
_restrictedEntityFlag[i] = false;
|
||||||
}
|
}
|
||||||
for( int i=0; i<NUM_ENTITIES; ++i ) {
|
for( int i=0; i<NUM_ENTITIES; ++i ) {
|
||||||
TIXMLASSERT( entities[i].value < ENTITY_RANGE );
|
const char entityValue = entities[i].value;
|
||||||
if ( entities[i].value < ENTITY_RANGE ) {
|
TIXMLASSERT( 0 <= entityValue && entityValue < ENTITY_RANGE );
|
||||||
_entityFlag[ (int)entities[i].value ] = true;
|
_entityFlag[ (unsigned char)entityValue ] = true;
|
||||||
}
|
}
|
||||||
}
|
_restrictedEntityFlag[(unsigned char)'&'] = true;
|
||||||
// Clang doesn't like indexing arrays with 'char'
|
_restrictedEntityFlag[(unsigned char)'<'] = true;
|
||||||
// so cast to int. (Looks strange.)
|
_restrictedEntityFlag[(unsigned char)'>'] = true; // not required, but consistency is nice
|
||||||
_restrictedEntityFlag[(int)'&'] = true;
|
|
||||||
_restrictedEntityFlag[(int)'<'] = true;
|
|
||||||
_restrictedEntityFlag[(int)'>'] = true; // not required, but consistency is nice
|
|
||||||
_buffer.Push( 0 );
|
_buffer.Push( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1985,34 +2110,14 @@ void XMLPrinter::Print( const char* format, ... )
|
||||||
vfprintf( _fp, format, va );
|
vfprintf( _fp, format, va );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
|
const int len = TIXML_VSCPRINTF( format, va );
|
||||||
#if defined(WINCE)
|
|
||||||
int len = 512;
|
|
||||||
do {
|
|
||||||
len = len*2;
|
|
||||||
char* str = new char[len]();
|
|
||||||
len = _vsnprintf(str, len, format, va);
|
|
||||||
delete[] str;
|
|
||||||
}while (len < 0);
|
|
||||||
#else
|
|
||||||
int len = _vscprintf( format, va );
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
int len = vsnprintf( 0, 0, format, va );
|
|
||||||
#endif
|
|
||||||
// Close out and re-start the va-args
|
// Close out and re-start the va-args
|
||||||
va_end( va );
|
va_end( va );
|
||||||
|
TIXMLASSERT( len >= 0 );
|
||||||
va_start( va, format );
|
va_start( va, format );
|
||||||
|
TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 );
|
||||||
char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator.
|
char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator.
|
||||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
|
TIXML_VSNPRINTF( p, len+1, format, va );
|
||||||
#if defined(WINCE)
|
|
||||||
_vsnprintf( p, len+1, format, va );
|
|
||||||
#else
|
|
||||||
vsnprintf_s( p, len+1, _TRUNCATE, format, va );
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
vsnprintf( p, len+1, format, va );
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
va_end( va );
|
va_end( va );
|
||||||
}
|
}
|
||||||
|
@ -2030,35 +2135,47 @@ void XMLPrinter::PrintString( const char* p, bool restricted )
|
||||||
{
|
{
|
||||||
// Look for runs of bytes between entities to print.
|
// Look for runs of bytes between entities to print.
|
||||||
const char* q = p;
|
const char* q = p;
|
||||||
const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag;
|
|
||||||
|
|
||||||
if ( _processEntities ) {
|
if ( _processEntities ) {
|
||||||
|
const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag;
|
||||||
while ( *q ) {
|
while ( *q ) {
|
||||||
|
TIXMLASSERT( p <= 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 ) {
|
||||||
// Check for entities. If one is found, flush
|
// Check for entities. If one is found, flush
|
||||||
// the stream up until the entity, write the
|
// the stream up until the entity, write the
|
||||||
// entity, and keep looking.
|
// entity, and keep looking.
|
||||||
if ( flag[(unsigned)(*q)] ) {
|
if ( flag[(unsigned char)(*q)] ) {
|
||||||
while ( p < q ) {
|
while ( p < q ) {
|
||||||
Print( "%c", *p );
|
const size_t delta = q - p;
|
||||||
++p;
|
// %.*s accepts type int as "precision"
|
||||||
|
const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta;
|
||||||
|
Print( "%.*s", toPrint, p );
|
||||||
|
p += toPrint;
|
||||||
}
|
}
|
||||||
|
bool entityPatternPrinted = false;
|
||||||
for( int i=0; i<NUM_ENTITIES; ++i ) {
|
for( int i=0; i<NUM_ENTITIES; ++i ) {
|
||||||
if ( entities[i].value == *q ) {
|
if ( entities[i].value == *q ) {
|
||||||
Print( "&%s;", entities[i].pattern );
|
Print( "&%s;", entities[i].pattern );
|
||||||
|
entityPatternPrinted = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ( !entityPatternPrinted ) {
|
||||||
|
// TIXMLASSERT( entityPatternPrinted ) causes gcc -Wunused-but-set-variable in release
|
||||||
|
TIXMLASSERT( false );
|
||||||
|
}
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++q;
|
++q;
|
||||||
|
TIXMLASSERT( p <= 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 ( !_processEntities || (q-p > 0) ) {
|
TIXMLASSERT( p <= q );
|
||||||
|
if ( !_processEntities || ( p < q ) ) {
|
||||||
Print( "%s", p );
|
Print( "%s", p );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2078,9 +2195,7 @@ void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
|
||||||
|
|
||||||
void XMLPrinter::OpenElement( const char* name, bool compactMode )
|
void XMLPrinter::OpenElement( const char* name, bool compactMode )
|
||||||
{
|
{
|
||||||
if ( _elementJustOpened ) {
|
SealElementIfJustOpened();
|
||||||
SealElement();
|
|
||||||
}
|
|
||||||
_stack.Push( name );
|
_stack.Push( name );
|
||||||
|
|
||||||
if ( _textDepth < 0 && !_firstElement && !compactMode ) {
|
if ( _textDepth < 0 && !_firstElement && !compactMode ) {
|
||||||
|
@ -2164,8 +2279,11 @@ void XMLPrinter::CloseElement( bool compactMode )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLPrinter::SealElement()
|
void XMLPrinter::SealElementIfJustOpened()
|
||||||
{
|
{
|
||||||
|
if ( !_elementJustOpened ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
_elementJustOpened = false;
|
_elementJustOpened = false;
|
||||||
Print( ">" );
|
Print( ">" );
|
||||||
}
|
}
|
||||||
|
@ -2175,13 +2293,9 @@ void XMLPrinter::PushText( const char* text, bool cdata )
|
||||||
{
|
{
|
||||||
_textDepth = _depth-1;
|
_textDepth = _depth-1;
|
||||||
|
|
||||||
if ( _elementJustOpened ) {
|
SealElementIfJustOpened();
|
||||||
SealElement();
|
|
||||||
}
|
|
||||||
if ( cdata ) {
|
if ( cdata ) {
|
||||||
Print( "<![CDATA[" );
|
Print( "<![CDATA[%s]]>", text );
|
||||||
Print( "%s", text );
|
|
||||||
Print( "]]>" );
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PrintString( text, true );
|
PrintString( text, true );
|
||||||
|
@ -2230,9 +2344,7 @@ void XMLPrinter::PushText( double value )
|
||||||
|
|
||||||
void XMLPrinter::PushComment( const char* comment )
|
void XMLPrinter::PushComment( const char* comment )
|
||||||
{
|
{
|
||||||
if ( _elementJustOpened ) {
|
SealElementIfJustOpened();
|
||||||
SealElement();
|
|
||||||
}
|
|
||||||
if ( _textDepth < 0 && !_firstElement && !_compactMode) {
|
if ( _textDepth < 0 && !_firstElement && !_compactMode) {
|
||||||
Print( "\n" );
|
Print( "\n" );
|
||||||
PrintSpace( _depth );
|
PrintSpace( _depth );
|
||||||
|
@ -2244,9 +2356,7 @@ void XMLPrinter::PushComment( const char* comment )
|
||||||
|
|
||||||
void XMLPrinter::PushDeclaration( const char* value )
|
void XMLPrinter::PushDeclaration( const char* value )
|
||||||
{
|
{
|
||||||
if ( _elementJustOpened ) {
|
SealElementIfJustOpened();
|
||||||
SealElement();
|
|
||||||
}
|
|
||||||
if ( _textDepth < 0 && !_firstElement && !_compactMode) {
|
if ( _textDepth < 0 && !_firstElement && !_compactMode) {
|
||||||
Print( "\n" );
|
Print( "\n" );
|
||||||
PrintSpace( _depth );
|
PrintSpace( _depth );
|
||||||
|
@ -2258,9 +2368,7 @@ void XMLPrinter::PushDeclaration( const char* value )
|
||||||
|
|
||||||
void XMLPrinter::PushUnknown( const char* value )
|
void XMLPrinter::PushUnknown( const char* value )
|
||||||
{
|
{
|
||||||
if ( _elementJustOpened ) {
|
SealElementIfJustOpened();
|
||||||
SealElement();
|
|
||||||
}
|
|
||||||
if ( _textDepth < 0 && !_firstElement && !_compactMode) {
|
if ( _textDepth < 0 && !_firstElement && !_compactMode) {
|
||||||
Print( "\n" );
|
Print( "\n" );
|
||||||
PrintSpace( _depth );
|
PrintSpace( _depth );
|
||||||
|
@ -2282,8 +2390,11 @@ bool XMLPrinter::VisitEnter( const XMLDocument& doc )
|
||||||
|
|
||||||
bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
|
bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
|
||||||
{
|
{
|
||||||
const XMLElement* parentElem = element.Parent()->ToElement();
|
const XMLElement* parentElem = 0;
|
||||||
bool compactMode = parentElem ? CompactMode(*parentElem) : _compactMode;
|
if ( element.Parent() ) {
|
||||||
|
parentElem = element.Parent()->ToElement();
|
||||||
|
}
|
||||||
|
const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode;
|
||||||
OpenElement( element.Name(), compactMode );
|
OpenElement( element.Name(), compactMode );
|
||||||
while ( attribute ) {
|
while ( attribute ) {
|
||||||
PushAttribute( attribute->Name(), attribute->Value() );
|
PushAttribute( attribute->Name(), attribute->Value() );
|
||||||
|
|
|
@ -30,14 +30,12 @@ distribution.
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
# include <stdarg.h>
|
|
||||||
#else
|
#else
|
||||||
# include <cctype>
|
# include <cctype>
|
||||||
# include <climits>
|
# include <climits>
|
||||||
# include <cstdio>
|
# include <cstdio>
|
||||||
# include <cstdlib>
|
# include <cstdlib>
|
||||||
# include <cstring>
|
# include <cstring>
|
||||||
# include <cstdarg>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -77,7 +75,8 @@ distribution.
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
# if defined(_MSC_VER)
|
# if defined(_MSC_VER)
|
||||||
# define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
|
# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
|
||||||
|
# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
|
||||||
# elif defined (ANDROID_NDK)
|
# elif defined (ANDROID_NDK)
|
||||||
# include <android/log.h>
|
# include <android/log.h>
|
||||||
# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
|
# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
|
||||||
|
@ -90,39 +89,11 @@ distribution.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE)
|
|
||||||
// Microsoft visual studio, version 2005 and higher.
|
|
||||||
/*int _snprintf_s(
|
|
||||||
char *buffer,
|
|
||||||
size_t sizeOfBuffer,
|
|
||||||
size_t count,
|
|
||||||
const char *format [,
|
|
||||||
argument] ...
|
|
||||||
);*/
|
|
||||||
inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
|
|
||||||
{
|
|
||||||
va_list va;
|
|
||||||
va_start( va, format );
|
|
||||||
int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
|
|
||||||
va_end( va );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#define TIXML_SSCANF sscanf_s
|
|
||||||
#elif defined WINCE
|
|
||||||
#define TIXML_SNPRINTF _snprintf
|
|
||||||
#define TIXML_SSCANF sscanf
|
|
||||||
#else
|
|
||||||
// GCC version 3 and higher
|
|
||||||
//#warning( "Using sn* functions." )
|
|
||||||
#define TIXML_SNPRINTF snprintf
|
|
||||||
#define TIXML_SSCANF sscanf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Versioning, past 1.0.14:
|
/* Versioning, past 1.0.14:
|
||||||
http://semver.org/
|
http://semver.org/
|
||||||
*/
|
*/
|
||||||
static const int TIXML2_MAJOR_VERSION = 2;
|
static const int TIXML2_MAJOR_VERSION = 3;
|
||||||
static const int TIXML2_MINOR_VERSION = 2;
|
static const int TIXML2_MINOR_VERSION = 0;
|
||||||
static const int TIXML2_PATCH_VERSION = 0;
|
static const int TIXML2_PATCH_VERSION = 0;
|
||||||
|
|
||||||
namespace tinyxml2
|
namespace tinyxml2
|
||||||
|
@ -148,7 +119,7 @@ public:
|
||||||
enum {
|
enum {
|
||||||
NEEDS_ENTITY_PROCESSING = 0x01,
|
NEEDS_ENTITY_PROCESSING = 0x01,
|
||||||
NEEDS_NEWLINE_NORMALIZATION = 0x02,
|
NEEDS_NEWLINE_NORMALIZATION = 0x02,
|
||||||
COLLAPSE_WHITESPACE = 0x04,
|
NEEDS_WHITESPACE_COLLAPSING = 0x04,
|
||||||
|
|
||||||
TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
|
TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
|
||||||
TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
|
TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
|
||||||
|
@ -210,13 +181,13 @@ private:
|
||||||
Has a small initial memory pool, so that low or no usage will not
|
Has a small initial memory pool, so that low or no usage will not
|
||||||
cause a call to new/delete
|
cause a call to new/delete
|
||||||
*/
|
*/
|
||||||
template <class T, int INIT>
|
template <class T, int INITIAL_SIZE>
|
||||||
class DynArray
|
class DynArray
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DynArray< T, INIT >() {
|
DynArray() {
|
||||||
_mem = _pool;
|
_mem = _pool;
|
||||||
_allocated = INIT;
|
_allocated = INITIAL_SIZE;
|
||||||
_size = 0;
|
_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,11 +202,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void Push( T t ) {
|
void Push( T t ) {
|
||||||
|
TIXMLASSERT( _size < INT_MAX );
|
||||||
EnsureCapacity( _size+1 );
|
EnsureCapacity( _size+1 );
|
||||||
_mem[_size++] = t;
|
_mem[_size++] = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
T* PushArr( int count ) {
|
T* PushArr( int count ) {
|
||||||
|
TIXMLASSERT( count >= 0 );
|
||||||
|
TIXMLASSERT( _size <= INT_MAX - count );
|
||||||
EnsureCapacity( _size+count );
|
EnsureCapacity( _size+count );
|
||||||
T* ret = &_mem[_size];
|
T* ret = &_mem[_size];
|
||||||
_size += count;
|
_size += count;
|
||||||
|
@ -243,6 +217,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
T Pop() {
|
T Pop() {
|
||||||
|
TIXMLASSERT( _size > 0 );
|
||||||
return _mem[--_size];
|
return _mem[--_size];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,24 +246,33 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
int Size() const {
|
int Size() const {
|
||||||
|
TIXMLASSERT( _size >= 0 );
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Capacity() const {
|
int Capacity() const {
|
||||||
|
TIXMLASSERT( _allocated >= INITIAL_SIZE );
|
||||||
return _allocated;
|
return _allocated;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T* Mem() const {
|
const T* Mem() const {
|
||||||
|
TIXMLASSERT( _mem );
|
||||||
return _mem;
|
return _mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
T* Mem() {
|
T* Mem() {
|
||||||
|
TIXMLASSERT( _mem );
|
||||||
return _mem;
|
return _mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
DynArray( const DynArray& ); // not supported
|
||||||
|
void operator=( const DynArray& ); // not supported
|
||||||
|
|
||||||
void EnsureCapacity( int cap ) {
|
void EnsureCapacity( int cap ) {
|
||||||
|
TIXMLASSERT( cap > 0 );
|
||||||
if ( cap > _allocated ) {
|
if ( cap > _allocated ) {
|
||||||
|
TIXMLASSERT( cap <= INT_MAX / 2 );
|
||||||
int newAllocated = cap * 2;
|
int newAllocated = cap * 2;
|
||||||
T* newMem = new T[newAllocated];
|
T* newMem = new T[newAllocated];
|
||||||
memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
|
memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
|
||||||
|
@ -301,7 +285,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
T* _mem;
|
T* _mem;
|
||||||
T _pool[INIT];
|
T _pool[INITIAL_SIZE];
|
||||||
int _allocated; // objects allocated
|
int _allocated; // objects allocated
|
||||||
int _size; // number objects in use
|
int _size; // number objects in use
|
||||||
};
|
};
|
||||||
|
@ -418,6 +402,9 @@ public:
|
||||||
enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
|
enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
MemPoolT( const MemPoolT& ); // not supported
|
||||||
|
void operator=( const MemPoolT& ); // not supported
|
||||||
|
|
||||||
union Chunk {
|
union Chunk {
|
||||||
Chunk* next;
|
Chunk* next;
|
||||||
char mem[SIZE];
|
char mem[SIZE];
|
||||||
|
@ -531,9 +518,11 @@ class XMLUtil
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static const char* SkipWhiteSpace( const char* p ) {
|
static const char* SkipWhiteSpace( const char* p ) {
|
||||||
|
TIXMLASSERT( p );
|
||||||
while( IsWhiteSpace(*p) ) {
|
while( IsWhiteSpace(*p) ) {
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
TIXMLASSERT( p );
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
static char* SkipWhiteSpace( char* p ) {
|
static char* SkipWhiteSpace( char* p ) {
|
||||||
|
@ -547,9 +536,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static bool IsNameStartChar( unsigned char ch ) {
|
inline static bool IsNameStartChar( unsigned char ch ) {
|
||||||
return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
|
if ( ch >= 128 ) {
|
||||||
|| ch == ':'
|
// This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
|
||||||
|| ch == '_';
|
return true;
|
||||||
|
}
|
||||||
|
if ( isalpha( ch ) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return ch == ':' || ch == '_';
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static bool IsNameChar( unsigned char ch ) {
|
inline static bool IsNameChar( unsigned char ch ) {
|
||||||
|
@ -560,10 +554,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
|
inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
|
||||||
int n = 0;
|
|
||||||
if ( p == q ) {
|
if ( p == q ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
int n = 0;
|
||||||
while( *p && *q && *p == *q && n<nChar ) {
|
while( *p && *q && *p == *q && n<nChar ) {
|
||||||
++p;
|
++p;
|
||||||
++q;
|
++q;
|
||||||
|
@ -575,7 +569,7 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static bool IsUTF8Continuation( const char p ) {
|
inline static bool IsUTF8Continuation( char p ) {
|
||||||
return ( p & 0x80 ) != 0;
|
return ( p & 0x80 ) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,10 +628,12 @@ public:
|
||||||
|
|
||||||
/// Get the XMLDocument that owns this XMLNode.
|
/// Get the XMLDocument that owns this XMLNode.
|
||||||
const XMLDocument* GetDocument() const {
|
const XMLDocument* GetDocument() const {
|
||||||
|
TIXMLASSERT( _document );
|
||||||
return _document;
|
return _document;
|
||||||
}
|
}
|
||||||
/// Get the XMLDocument that owns this XMLNode.
|
/// Get the XMLDocument that owns this XMLNode.
|
||||||
XMLDocument* GetDocument() {
|
XMLDocument* GetDocument() {
|
||||||
|
TIXMLASSERT( _document );
|
||||||
return _document;
|
return _document;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -687,7 +683,7 @@ public:
|
||||||
|
|
||||||
/** The meaning of 'value' changes for the specific type.
|
/** The meaning of 'value' changes for the specific type.
|
||||||
@verbatim
|
@verbatim
|
||||||
Document: empty
|
Document: empty (NULL is returned, not an empty string)
|
||||||
Element: name of the element
|
Element: name of the element
|
||||||
Comment: the comment text
|
Comment: the comment text
|
||||||
Unknown: the tag contents
|
Unknown: the tag contents
|
||||||
|
@ -727,10 +723,10 @@ public:
|
||||||
/** Get the first child element, or optionally the first child
|
/** Get the first child element, or optionally the first child
|
||||||
element with the specified name.
|
element with the specified name.
|
||||||
*/
|
*/
|
||||||
const XMLElement* FirstChildElement( const char* value=0 ) const;
|
const XMLElement* FirstChildElement( const char* name = 0 ) const;
|
||||||
|
|
||||||
XMLElement* FirstChildElement( const char* value=0 ) {
|
XMLElement* FirstChildElement( const char* name = 0 ) {
|
||||||
return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
|
return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the last child node, or null if none exists.
|
/// Get the last child node, or null if none exists.
|
||||||
|
@ -739,16 +735,16 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
XMLNode* LastChild() {
|
XMLNode* LastChild() {
|
||||||
return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
|
return _lastChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the last child element or optionally the last child
|
/** Get the last child element or optionally the last child
|
||||||
element with the specified name.
|
element with the specified name.
|
||||||
*/
|
*/
|
||||||
const XMLElement* LastChildElement( const char* value=0 ) const;
|
const XMLElement* LastChildElement( const char* name = 0 ) const;
|
||||||
|
|
||||||
XMLElement* LastChildElement( const char* value=0 ) {
|
XMLElement* LastChildElement( const char* name = 0 ) {
|
||||||
return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
|
return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the previous (left) sibling node of this node.
|
/// Get the previous (left) sibling node of this node.
|
||||||
|
@ -761,10 +757,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the previous (left) sibling element of this node, with an optionally supplied name.
|
/// Get the previous (left) sibling element of this node, with an optionally supplied name.
|
||||||
const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
|
const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ;
|
||||||
|
|
||||||
XMLElement* PreviousSiblingElement( const char* value=0 ) {
|
XMLElement* PreviousSiblingElement( const char* name = 0 ) {
|
||||||
return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
|
return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the next (right) sibling node of this node.
|
/// Get the next (right) sibling node of this node.
|
||||||
|
@ -777,10 +773,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the next (right) sibling element of this node, with an optionally supplied name.
|
/// Get the next (right) sibling element of this node, with an optionally supplied name.
|
||||||
const XMLElement* NextSiblingElement( const char* value=0 ) const;
|
const XMLElement* NextSiblingElement( const char* name = 0 ) const;
|
||||||
|
|
||||||
XMLElement* NextSiblingElement( const char* value=0 ) {
|
XMLElement* NextSiblingElement( const char* name = 0 ) {
|
||||||
return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
|
return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -866,14 +862,11 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool Accept( XMLVisitor* visitor ) const = 0;
|
virtual bool Accept( XMLVisitor* visitor ) const = 0;
|
||||||
|
|
||||||
// internal
|
|
||||||
virtual char* ParseDeep( char*, StrPair* );
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
XMLNode( XMLDocument* );
|
XMLNode( XMLDocument* );
|
||||||
virtual ~XMLNode();
|
virtual ~XMLNode();
|
||||||
XMLNode( const XMLNode& ); // not supported
|
|
||||||
XMLNode& operator=( const XMLNode& ); // not supported
|
virtual char* ParseDeep( char*, StrPair* );
|
||||||
|
|
||||||
XMLDocument* _document;
|
XMLDocument* _document;
|
||||||
XMLNode* _parent;
|
XMLNode* _parent;
|
||||||
|
@ -889,6 +882,10 @@ private:
|
||||||
MemPool* _memPool;
|
MemPool* _memPool;
|
||||||
void Unlink( XMLNode* child );
|
void Unlink( XMLNode* child );
|
||||||
static void DeleteNode( XMLNode* node );
|
static void DeleteNode( XMLNode* node );
|
||||||
|
void InsertChildPreamble( XMLNode* insertThis ) const;
|
||||||
|
|
||||||
|
XMLNode( const XMLNode& ); // not supported
|
||||||
|
XMLNode& operator=( const XMLNode& ); // not supported
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -927,18 +924,20 @@ public:
|
||||||
return _isCData;
|
return _isCData;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* ParseDeep( char*, StrPair* endTag );
|
|
||||||
virtual XMLNode* ShallowClone( XMLDocument* document ) const;
|
virtual XMLNode* ShallowClone( XMLDocument* document ) const;
|
||||||
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
|
XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
|
||||||
virtual ~XMLText() {}
|
virtual ~XMLText() {}
|
||||||
XMLText( const XMLText& ); // not supported
|
|
||||||
XMLText& operator=( const XMLText& ); // not supported
|
char* ParseDeep( char*, StrPair* endTag );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _isCData;
|
bool _isCData;
|
||||||
|
|
||||||
|
XMLText( const XMLText& ); // not supported
|
||||||
|
XMLText& operator=( const XMLText& ); // not supported
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -956,17 +955,18 @@ public:
|
||||||
|
|
||||||
virtual bool Accept( XMLVisitor* visitor ) const;
|
virtual bool Accept( XMLVisitor* visitor ) const;
|
||||||
|
|
||||||
char* ParseDeep( char*, StrPair* endTag );
|
|
||||||
virtual XMLNode* ShallowClone( XMLDocument* document ) const;
|
virtual XMLNode* ShallowClone( XMLDocument* document ) const;
|
||||||
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
XMLComment( XMLDocument* doc );
|
XMLComment( XMLDocument* doc );
|
||||||
virtual ~XMLComment();
|
virtual ~XMLComment();
|
||||||
XMLComment( const XMLComment& ); // not supported
|
|
||||||
XMLComment& operator=( const XMLComment& ); // not supported
|
char* ParseDeep( char*, StrPair* endTag );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
XMLComment( const XMLComment& ); // not supported
|
||||||
|
XMLComment& operator=( const XMLComment& ); // not supported
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -994,13 +994,16 @@ public:
|
||||||
|
|
||||||
virtual bool Accept( XMLVisitor* visitor ) const;
|
virtual bool Accept( XMLVisitor* visitor ) const;
|
||||||
|
|
||||||
char* ParseDeep( char*, StrPair* endTag );
|
|
||||||
virtual XMLNode* ShallowClone( XMLDocument* document ) const;
|
virtual XMLNode* ShallowClone( XMLDocument* document ) const;
|
||||||
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
XMLDeclaration( XMLDocument* doc );
|
XMLDeclaration( XMLDocument* doc );
|
||||||
virtual ~XMLDeclaration();
|
virtual ~XMLDeclaration();
|
||||||
|
|
||||||
|
char* ParseDeep( char*, StrPair* endTag );
|
||||||
|
|
||||||
|
private:
|
||||||
XMLDeclaration( const XMLDeclaration& ); // not supported
|
XMLDeclaration( const XMLDeclaration& ); // not supported
|
||||||
XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
|
XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
|
||||||
};
|
};
|
||||||
|
@ -1026,13 +1029,16 @@ public:
|
||||||
|
|
||||||
virtual bool Accept( XMLVisitor* visitor ) const;
|
virtual bool Accept( XMLVisitor* visitor ) const;
|
||||||
|
|
||||||
char* ParseDeep( char*, StrPair* endTag );
|
|
||||||
virtual XMLNode* ShallowClone( XMLDocument* document ) const;
|
virtual XMLNode* ShallowClone( XMLDocument* document ) const;
|
||||||
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
XMLUnknown( XMLDocument* doc );
|
XMLUnknown( XMLDocument* doc );
|
||||||
virtual ~XMLUnknown();
|
virtual ~XMLUnknown();
|
||||||
|
|
||||||
|
char* ParseDeep( char*, StrPair* endTag );
|
||||||
|
|
||||||
|
private:
|
||||||
XMLUnknown( const XMLUnknown& ); // not supported
|
XMLUnknown( const XMLUnknown& ); // not supported
|
||||||
XMLUnknown& operator=( const XMLUnknown& ); // not supported
|
XMLUnknown& operator=( const XMLUnknown& ); // not supported
|
||||||
};
|
};
|
||||||
|
@ -1481,10 +1487,12 @@ public:
|
||||||
int ClosingType() const {
|
int ClosingType() const {
|
||||||
return _closingType;
|
return _closingType;
|
||||||
}
|
}
|
||||||
char* ParseDeep( char* p, StrPair* endTag );
|
|
||||||
virtual XMLNode* ShallowClone( XMLDocument* document ) const;
|
virtual XMLNode* ShallowClone( XMLDocument* document ) const;
|
||||||
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
char* ParseDeep( char* p, StrPair* endTag );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
XMLElement( XMLDocument* doc );
|
XMLElement( XMLDocument* doc );
|
||||||
virtual ~XMLElement();
|
virtual ~XMLElement();
|
||||||
|
@ -1528,9 +1536,11 @@ public:
|
||||||
~XMLDocument();
|
~XMLDocument();
|
||||||
|
|
||||||
virtual XMLDocument* ToDocument() {
|
virtual XMLDocument* ToDocument() {
|
||||||
|
TIXMLASSERT( this == _document );
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
virtual const XMLDocument* ToDocument() const {
|
virtual const XMLDocument* ToDocument() const {
|
||||||
|
TIXMLASSERT( this == _document );
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1725,6 +1735,8 @@ private:
|
||||||
MemPoolT< sizeof(XMLComment) > _commentPool;
|
MemPoolT< sizeof(XMLComment) > _commentPool;
|
||||||
|
|
||||||
static const char* _errorNames[XML_ERROR_COUNT];
|
static const char* _errorNames[XML_ERROR_COUNT];
|
||||||
|
|
||||||
|
void Parse();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1809,32 +1821,32 @@ public:
|
||||||
return XMLHandle( _node ? _node->FirstChild() : 0 );
|
return XMLHandle( _node ? _node->FirstChild() : 0 );
|
||||||
}
|
}
|
||||||
/// Get the first child element of this handle.
|
/// Get the first child element of this handle.
|
||||||
XMLHandle FirstChildElement( const char* value=0 ) {
|
XMLHandle FirstChildElement( const char* name = 0 ) {
|
||||||
return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
|
return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
|
||||||
}
|
}
|
||||||
/// Get the last child of this handle.
|
/// Get the last child of this handle.
|
||||||
XMLHandle LastChild() {
|
XMLHandle LastChild() {
|
||||||
return XMLHandle( _node ? _node->LastChild() : 0 );
|
return XMLHandle( _node ? _node->LastChild() : 0 );
|
||||||
}
|
}
|
||||||
/// Get the last child element of this handle.
|
/// Get the last child element of this handle.
|
||||||
XMLHandle LastChildElement( const char* _value=0 ) {
|
XMLHandle LastChildElement( const char* name = 0 ) {
|
||||||
return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
|
return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
|
||||||
}
|
}
|
||||||
/// Get the previous sibling of this handle.
|
/// Get the previous sibling of this handle.
|
||||||
XMLHandle PreviousSibling() {
|
XMLHandle PreviousSibling() {
|
||||||
return XMLHandle( _node ? _node->PreviousSibling() : 0 );
|
return XMLHandle( _node ? _node->PreviousSibling() : 0 );
|
||||||
}
|
}
|
||||||
/// Get the previous sibling element of this handle.
|
/// Get the previous sibling element of this handle.
|
||||||
XMLHandle PreviousSiblingElement( const char* _value=0 ) {
|
XMLHandle PreviousSiblingElement( const char* name = 0 ) {
|
||||||
return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
|
return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
|
||||||
}
|
}
|
||||||
/// Get the next sibling of this handle.
|
/// Get the next sibling of this handle.
|
||||||
XMLHandle NextSibling() {
|
XMLHandle NextSibling() {
|
||||||
return XMLHandle( _node ? _node->NextSibling() : 0 );
|
return XMLHandle( _node ? _node->NextSibling() : 0 );
|
||||||
}
|
}
|
||||||
/// Get the next sibling element of this handle.
|
/// Get the next sibling element of this handle.
|
||||||
XMLHandle NextSiblingElement( const char* _value=0 ) {
|
XMLHandle NextSiblingElement( const char* name = 0 ) {
|
||||||
return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
|
return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Safe cast to XMLNode. This can return null.
|
/// Safe cast to XMLNode. This can return null.
|
||||||
|
@ -1888,26 +1900,26 @@ public:
|
||||||
const XMLConstHandle FirstChild() const {
|
const XMLConstHandle FirstChild() const {
|
||||||
return XMLConstHandle( _node ? _node->FirstChild() : 0 );
|
return XMLConstHandle( _node ? _node->FirstChild() : 0 );
|
||||||
}
|
}
|
||||||
const XMLConstHandle FirstChildElement( const char* value=0 ) const {
|
const XMLConstHandle FirstChildElement( const char* name = 0 ) const {
|
||||||
return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
|
return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
|
||||||
}
|
}
|
||||||
const XMLConstHandle LastChild() const {
|
const XMLConstHandle LastChild() const {
|
||||||
return XMLConstHandle( _node ? _node->LastChild() : 0 );
|
return XMLConstHandle( _node ? _node->LastChild() : 0 );
|
||||||
}
|
}
|
||||||
const XMLConstHandle LastChildElement( const char* _value=0 ) const {
|
const XMLConstHandle LastChildElement( const char* name = 0 ) const {
|
||||||
return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
|
return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
|
||||||
}
|
}
|
||||||
const XMLConstHandle PreviousSibling() const {
|
const XMLConstHandle PreviousSibling() const {
|
||||||
return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
|
return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
|
||||||
}
|
}
|
||||||
const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
|
const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const {
|
||||||
return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
|
return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
|
||||||
}
|
}
|
||||||
const XMLConstHandle NextSibling() const {
|
const XMLConstHandle NextSibling() const {
|
||||||
return XMLConstHandle( _node ? _node->NextSibling() : 0 );
|
return XMLConstHandle( _node ? _node->NextSibling() : 0 );
|
||||||
}
|
}
|
||||||
const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
|
const XMLConstHandle NextSiblingElement( const char* name = 0 ) const {
|
||||||
return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
|
return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2066,7 +2078,7 @@ protected:
|
||||||
virtual void PrintSpace( int depth );
|
virtual void PrintSpace( int depth );
|
||||||
void Print( const char* format, ... );
|
void Print( const char* format, ... );
|
||||||
|
|
||||||
void SealElement();
|
void SealElementIfJustOpened();
|
||||||
bool _elementJustOpened;
|
bool _elementJustOpened;
|
||||||
DynArray< const char*, 10 > _stack;
|
DynArray< const char*, 10 > _stack;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue