|
|
|
@ -47,15 +47,15 @@ distribution.
|
|
|
|
|
*/
|
|
|
|
|
/*
|
|
|
|
|
gcc:
|
|
|
|
|
g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
|
|
|
|
|
g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
|
|
|
|
|
|
|
|
|
|
Formatting, Artistic Style:
|
|
|
|
|
AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
|
|
|
|
|
# ifndef DEBUG
|
|
|
|
|
# define DEBUG
|
|
|
|
|
#if defined( _DEBUG ) || defined (__DEBUG__)
|
|
|
|
|
# ifndef TINYXML2_DEBUG
|
|
|
|
|
# define TINYXML2_DEBUG
|
|
|
|
|
# endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
@ -79,7 +79,7 @@ distribution.
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(DEBUG)
|
|
|
|
|
#if defined(TINYXML2_DEBUG)
|
|
|
|
|
# if defined(_MSC_VER)
|
|
|
|
|
# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
|
|
|
|
|
# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); }
|
|
|
|
@ -98,9 +98,20 @@ distribution.
|
|
|
|
|
/* Versioning, past 1.0.14:
|
|
|
|
|
http://semver.org/
|
|
|
|
|
*/
|
|
|
|
|
static const int TIXML2_MAJOR_VERSION = 4;
|
|
|
|
|
static const int TIXML2_MINOR_VERSION = 0;
|
|
|
|
|
static const int TIXML2_PATCH_VERSION = 1;
|
|
|
|
|
static const int TIXML2_MAJOR_VERSION = 7;
|
|
|
|
|
static const int TIXML2_MINOR_VERSION = 1;
|
|
|
|
|
static const int TIXML2_PATCH_VERSION = 0;
|
|
|
|
|
|
|
|
|
|
#define TINYXML2_MAJOR_VERSION 7
|
|
|
|
|
#define TINYXML2_MINOR_VERSION 1
|
|
|
|
|
#define TINYXML2_PATCH_VERSION 0
|
|
|
|
|
|
|
|
|
|
// A fixed element depth limit is problematic. There needs to be a
|
|
|
|
|
// limit to avoid a stack overflow. However, that limit varies per
|
|
|
|
|
// system, and the capacity of the stack. On the other hand, it's a trivial
|
|
|
|
|
// attack that can result from ill, malicious, or even correctly formed XML,
|
|
|
|
|
// so there needs to be a limit in place.
|
|
|
|
|
static const int TINYXML2_MAX_ELEMENT_DEPTH = 100;
|
|
|
|
|
|
|
|
|
|
namespace tinyxml2
|
|
|
|
|
{
|
|
|
|
@ -118,8 +129,10 @@ class XMLPrinter;
|
|
|
|
|
pointers into the XML file itself, and will apply normalization
|
|
|
|
|
and entity translation if actually read. Can also store (and memory
|
|
|
|
|
manage) a traditional char[]
|
|
|
|
|
|
|
|
|
|
Isn't clear why TINYXML2_LIB is needed; but seems to fix #719
|
|
|
|
|
*/
|
|
|
|
|
class StrPair
|
|
|
|
|
class TINYXML2_LIB StrPair
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
enum {
|
|
|
|
@ -179,7 +192,7 @@ private:
|
|
|
|
|
char* _end;
|
|
|
|
|
|
|
|
|
|
StrPair( const StrPair& other ); // not supported
|
|
|
|
|
void operator=( StrPair& other ); // not supported, use TransferTo()
|
|
|
|
|
void operator=( const StrPair& other ); // not supported, use TransferTo()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -192,10 +205,11 @@ template <class T, int INITIAL_SIZE>
|
|
|
|
|
class DynArray
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
DynArray() {
|
|
|
|
|
_mem = _pool;
|
|
|
|
|
_allocated = INITIAL_SIZE;
|
|
|
|
|
_size = 0;
|
|
|
|
|
DynArray() :
|
|
|
|
|
_mem( _pool ),
|
|
|
|
|
_allocated( INITIAL_SIZE ),
|
|
|
|
|
_size( 0 )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~DynArray() {
|
|
|
|
@ -264,12 +278,19 @@ public:
|
|
|
|
|
return _allocated;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SwapRemove(int i) {
|
|
|
|
|
TIXMLASSERT(i >= 0 && i < _size);
|
|
|
|
|
TIXMLASSERT(_size > 0);
|
|
|
|
|
_mem[i] = _mem[_size - 1];
|
|
|
|
|
--_size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const T* Mem() const {
|
|
|
|
|
TIXMLASSERT( _mem );
|
|
|
|
|
return _mem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
T* Mem() {
|
|
|
|
|
T* Mem() {
|
|
|
|
|
TIXMLASSERT( _mem );
|
|
|
|
|
return _mem;
|
|
|
|
|
}
|
|
|
|
@ -282,8 +303,9 @@ private:
|
|
|
|
|
TIXMLASSERT( cap > 0 );
|
|
|
|
|
if ( cap > _allocated ) {
|
|
|
|
|
TIXMLASSERT( cap <= INT_MAX / 2 );
|
|
|
|
|
int newAllocated = cap * 2;
|
|
|
|
|
const int newAllocated = cap * 2;
|
|
|
|
|
T* newMem = new T[newAllocated];
|
|
|
|
|
TIXMLASSERT( newAllocated >= _size );
|
|
|
|
|
memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
|
|
|
|
|
if ( _mem != _pool ) {
|
|
|
|
|
delete [] _mem;
|
|
|
|
@ -314,7 +336,6 @@ public:
|
|
|
|
|
virtual void* Alloc() = 0;
|
|
|
|
|
virtual void Free( void* ) = 0;
|
|
|
|
|
virtual void SetTracked() = 0;
|
|
|
|
|
virtual void Clear() = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -325,16 +346,16 @@ template< int ITEM_SIZE >
|
|
|
|
|
class MemPoolT : public MemPool
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
|
|
|
|
|
MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
|
|
|
|
|
~MemPoolT() {
|
|
|
|
|
Clear();
|
|
|
|
|
MemPoolT< ITEM_SIZE >::Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Clear() {
|
|
|
|
|
// Delete the blocks.
|
|
|
|
|
while( !_blockPtrs.Empty()) {
|
|
|
|
|
Block* b = _blockPtrs.Pop();
|
|
|
|
|
delete b;
|
|
|
|
|
Block* lastBlock = _blockPtrs.Pop();
|
|
|
|
|
delete lastBlock;
|
|
|
|
|
}
|
|
|
|
|
_root = 0;
|
|
|
|
|
_currentAllocs = 0;
|
|
|
|
@ -375,14 +396,14 @@ public:
|
|
|
|
|
++_nUntracked;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Free( void* mem ) {
|
|
|
|
|
if ( !mem ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
--_currentAllocs;
|
|
|
|
|
Item* item = static_cast<Item*>( mem );
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
#ifdef TINYXML2_DEBUG
|
|
|
|
|
memset( item, 0xfe, sizeof( *item ) );
|
|
|
|
|
#endif
|
|
|
|
|
item->next = _root;
|
|
|
|
@ -505,10 +526,8 @@ enum XMLError {
|
|
|
|
|
XML_ERROR_FILE_NOT_FOUND,
|
|
|
|
|
XML_ERROR_FILE_COULD_NOT_BE_OPENED,
|
|
|
|
|
XML_ERROR_FILE_READ_ERROR,
|
|
|
|
|
XML_ERROR_ELEMENT_MISMATCH,
|
|
|
|
|
XML_ERROR_PARSING_ELEMENT,
|
|
|
|
|
XML_ERROR_PARSING_ATTRIBUTE,
|
|
|
|
|
XML_ERROR_IDENTIFYING_TAG,
|
|
|
|
|
XML_ERROR_PARSING_TEXT,
|
|
|
|
|
XML_ERROR_PARSING_CDATA,
|
|
|
|
|
XML_ERROR_PARSING_COMMENT,
|
|
|
|
@ -519,6 +538,7 @@ enum XMLError {
|
|
|
|
|
XML_ERROR_PARSING,
|
|
|
|
|
XML_CAN_NOT_CONVERT_TEXT,
|
|
|
|
|
XML_NO_TEXT_NODE,
|
|
|
|
|
XML_ELEMENT_DEPTH_EXCEEDED,
|
|
|
|
|
|
|
|
|
|
XML_ERROR_COUNT
|
|
|
|
|
};
|
|
|
|
@ -551,7 +571,7 @@ public:
|
|
|
|
|
static bool IsWhiteSpace( char p ) {
|
|
|
|
|
return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline static bool IsNameStartChar( unsigned char ch ) {
|
|
|
|
|
if ( ch >= 128 ) {
|
|
|
|
|
// This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
|
|
|
|
@ -562,7 +582,7 @@ public:
|
|
|
|
|
}
|
|
|
|
|
return ch == ':' || ch == '_';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline static bool IsNameChar( unsigned char ch ) {
|
|
|
|
|
return IsNameStartChar( ch )
|
|
|
|
|
|| isdigit( ch )
|
|
|
|
@ -579,7 +599,7 @@ public:
|
|
|
|
|
TIXMLASSERT( nChar >= 0 );
|
|
|
|
|
return strncmp( p, q, nChar ) == 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline static bool IsUTF8Continuation( char p ) {
|
|
|
|
|
return ( p & 0x80 ) != 0;
|
|
|
|
|
}
|
|
|
|
@ -597,6 +617,7 @@ public:
|
|
|
|
|
static void ToStr( float v, char* buffer, int bufferSize );
|
|
|
|
|
static void ToStr( double v, char* buffer, int bufferSize );
|
|
|
|
|
static void ToStr(int64_t v, char* buffer, int bufferSize);
|
|
|
|
|
static void ToStr(uint64_t v, char* buffer, int bufferSize);
|
|
|
|
|
|
|
|
|
|
// converts strings to primitive types
|
|
|
|
|
static bool ToInt( const char* str, int* value );
|
|
|
|
@ -605,7 +626,7 @@ public:
|
|
|
|
|
static bool ToFloat( const char* str, float* value );
|
|
|
|
|
static bool ToDouble( const char* str, double* value );
|
|
|
|
|
static bool ToInt64(const char* str, int64_t* value);
|
|
|
|
|
|
|
|
|
|
static bool ToUnsigned64(const char* str, uint64_t* value);
|
|
|
|
|
// Changes what is serialized for a boolean value.
|
|
|
|
|
// Default to "true" and "false". Shouldn't be changed
|
|
|
|
|
// unless you have a special testing or compatibility need.
|
|
|
|
@ -857,6 +878,21 @@ public:
|
|
|
|
|
*/
|
|
|
|
|
virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Make a copy of this node and all its children.
|
|
|
|
|
|
|
|
|
|
If the 'target' is null, then the nodes will
|
|
|
|
|
be allocated in the current document. If 'target'
|
|
|
|
|
is specified, the memory will be allocated is the
|
|
|
|
|
specified XMLDocument.
|
|
|
|
|
|
|
|
|
|
NOTE: This is probably not the correct tool to
|
|
|
|
|
copy a document, since XMLDocuments can have multiple
|
|
|
|
|
top level XMLNodes. You probably want to use
|
|
|
|
|
XMLDocument::DeepCopy()
|
|
|
|
|
*/
|
|
|
|
|
XMLNode* DeepClone( XMLDocument* target ) const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Test if 2 nodes are the same, but don't test children.
|
|
|
|
|
The 2 nodes do not need to be in the same Document.
|
|
|
|
@ -889,8 +925,8 @@ public:
|
|
|
|
|
*/
|
|
|
|
|
virtual bool Accept( XMLVisitor* visitor ) const = 0;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Set user data into the XMLNode. TinyXML-2 in
|
|
|
|
|
/**
|
|
|
|
|
Set user data into the XMLNode. TinyXML-2 in
|
|
|
|
|
no way processes or interprets user data.
|
|
|
|
|
It is initially 0.
|
|
|
|
|
*/
|
|
|
|
@ -904,10 +940,10 @@ public:
|
|
|
|
|
void* GetUserData() const { return _userData; }
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
XMLNode( XMLDocument* );
|
|
|
|
|
explicit XMLNode( XMLDocument* );
|
|
|
|
|
virtual ~XMLNode();
|
|
|
|
|
|
|
|
|
|
virtual char* ParseDeep( char*, StrPair*, int* );
|
|
|
|
|
virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);
|
|
|
|
|
|
|
|
|
|
XMLDocument* _document;
|
|
|
|
|
XMLNode* _parent;
|
|
|
|
@ -972,10 +1008,10 @@ public:
|
|
|
|
|
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
|
|
|
|
|
explicit XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
|
|
|
|
|
virtual ~XMLText() {}
|
|
|
|
|
|
|
|
|
|
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr );
|
|
|
|
|
char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
bool _isCData;
|
|
|
|
@ -1003,10 +1039,10 @@ public:
|
|
|
|
|
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
XMLComment( XMLDocument* doc );
|
|
|
|
|
explicit XMLComment( XMLDocument* doc );
|
|
|
|
|
virtual ~XMLComment();
|
|
|
|
|
|
|
|
|
|
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr);
|
|
|
|
|
char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
XMLComment( const XMLComment& ); // not supported
|
|
|
|
@ -1042,10 +1078,10 @@ public:
|
|
|
|
|
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
XMLDeclaration( XMLDocument* doc );
|
|
|
|
|
explicit XMLDeclaration( XMLDocument* doc );
|
|
|
|
|
virtual ~XMLDeclaration();
|
|
|
|
|
|
|
|
|
|
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr );
|
|
|
|
|
char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
XMLDeclaration( const XMLDeclaration& ); // not supported
|
|
|
|
@ -1077,10 +1113,10 @@ public:
|
|
|
|
|
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
XMLUnknown( XMLDocument* doc );
|
|
|
|
|
explicit XMLUnknown( XMLDocument* doc );
|
|
|
|
|
virtual ~XMLUnknown();
|
|
|
|
|
|
|
|
|
|
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr );
|
|
|
|
|
char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
XMLUnknown( const XMLUnknown& ); // not supported
|
|
|
|
@ -1129,6 +1165,12 @@ public:
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t Unsigned64Value() const {
|
|
|
|
|
uint64_t i = 0;
|
|
|
|
|
QueryUnsigned64Value(&i);
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Query as an unsigned integer. See IntValue()
|
|
|
|
|
unsigned UnsignedValue() const {
|
|
|
|
|
unsigned i=0;
|
|
|
|
@ -1163,6 +1205,8 @@ public:
|
|
|
|
|
XMLError QueryUnsignedValue( unsigned int* value ) const;
|
|
|
|
|
/// See QueryIntValue
|
|
|
|
|
XMLError QueryInt64Value(int64_t* value) const;
|
|
|
|
|
/// See QueryIntValue
|
|
|
|
|
XMLError QueryUnsigned64Value(uint64_t* value) const;
|
|
|
|
|
/// See QueryIntValue
|
|
|
|
|
XMLError QueryBoolValue( bool* value ) const;
|
|
|
|
|
/// See QueryIntValue
|
|
|
|
@ -1178,7 +1222,9 @@ public:
|
|
|
|
|
void SetAttribute( unsigned value );
|
|
|
|
|
/// Set the attribute to value.
|
|
|
|
|
void SetAttribute(int64_t value);
|
|
|
|
|
/// Set the attribute to value.
|
|
|
|
|
/// Set the attribute to value.
|
|
|
|
|
void SetAttribute(uint64_t value);
|
|
|
|
|
/// Set the attribute to value.
|
|
|
|
|
void SetAttribute( bool value );
|
|
|
|
|
/// Set the attribute to value.
|
|
|
|
|
void SetAttribute( double value );
|
|
|
|
@ -1188,7 +1234,7 @@ public:
|
|
|
|
|
private:
|
|
|
|
|
enum { BUF_SIZE = 200 };
|
|
|
|
|
|
|
|
|
|
XMLAttribute() : _parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {}
|
|
|
|
|
XMLAttribute() : _name(), _value(),_parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {}
|
|
|
|
|
virtual ~XMLAttribute() {}
|
|
|
|
|
|
|
|
|
|
XMLAttribute( const XMLAttribute& ); // not supported
|
|
|
|
@ -1266,6 +1312,8 @@ public:
|
|
|
|
|
unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const;
|
|
|
|
|
/// See IntAttribute()
|
|
|
|
|
int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const;
|
|
|
|
|
/// See IntAttribute()
|
|
|
|
|
uint64_t Unsigned64Attribute(const char* name, uint64_t defaultValue = 0) const;
|
|
|
|
|
/// See IntAttribute()
|
|
|
|
|
bool BoolAttribute(const char* name, bool defaultValue = false) const;
|
|
|
|
|
/// See IntAttribute()
|
|
|
|
@ -1312,6 +1360,15 @@ public:
|
|
|
|
|
return a->QueryInt64Value(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// See QueryIntAttribute()
|
|
|
|
|
XMLError QueryUnsigned64Attribute(const char* name, uint64_t* value) const {
|
|
|
|
|
const XMLAttribute* a = FindAttribute(name);
|
|
|
|
|
if(!a) {
|
|
|
|
|
return XML_NO_ATTRIBUTE;
|
|
|
|
|
}
|
|
|
|
|
return a->QueryUnsigned64Value(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// See QueryIntAttribute()
|
|
|
|
|
XMLError QueryBoolAttribute( const char* name, bool* value ) const {
|
|
|
|
|
const XMLAttribute* a = FindAttribute( name );
|
|
|
|
@ -1337,14 +1394,25 @@ public:
|
|
|
|
|
return a->QueryFloatValue( value );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// See QueryIntAttribute()
|
|
|
|
|
XMLError QueryStringAttribute(const char* name, const char** value) const {
|
|
|
|
|
const XMLAttribute* a = FindAttribute(name);
|
|
|
|
|
if (!a) {
|
|
|
|
|
return XML_NO_ATTRIBUTE;
|
|
|
|
|
}
|
|
|
|
|
*value = a->Value();
|
|
|
|
|
return XML_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Given an attribute name, QueryAttribute() returns
|
|
|
|
|
XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion
|
|
|
|
|
can't be performed, or XML_NO_ATTRIBUTE if the attribute
|
|
|
|
|
doesn't exist. It is overloaded for the primitive types,
|
|
|
|
|
and is a generally more convenient replacement of
|
|
|
|
|
QueryIntAttribute() and related functions.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
If successful, the result of the conversion
|
|
|
|
|
will be written to 'value'. If not successful, nothing will
|
|
|
|
|
be written to 'value'. This allows you to provide default
|
|
|
|
@ -1355,27 +1423,31 @@ public:
|
|
|
|
|
QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
|
|
|
|
|
@endverbatim
|
|
|
|
|
*/
|
|
|
|
|
int QueryAttribute( const char* name, int* value ) const {
|
|
|
|
|
XMLError QueryAttribute( const char* name, int* value ) const {
|
|
|
|
|
return QueryIntAttribute( name, value );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int QueryAttribute( const char* name, unsigned int* value ) const {
|
|
|
|
|
XMLError QueryAttribute( const char* name, unsigned int* value ) const {
|
|
|
|
|
return QueryUnsignedAttribute( name, value );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int QueryAttribute(const char* name, int64_t* value) const {
|
|
|
|
|
XMLError QueryAttribute(const char* name, int64_t* value) const {
|
|
|
|
|
return QueryInt64Attribute(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int QueryAttribute( const char* name, bool* value ) const {
|
|
|
|
|
XMLError QueryAttribute(const char* name, uint64_t* value) const {
|
|
|
|
|
return QueryUnsigned64Attribute(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
XMLError QueryAttribute( const char* name, bool* value ) const {
|
|
|
|
|
return QueryBoolAttribute( name, value );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int QueryAttribute( const char* name, double* value ) const {
|
|
|
|
|
XMLError QueryAttribute( const char* name, double* value ) const {
|
|
|
|
|
return QueryDoubleAttribute( name, value );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int QueryAttribute( const char* name, float* value ) const {
|
|
|
|
|
XMLError QueryAttribute( const char* name, float* value ) const {
|
|
|
|
|
return QueryFloatAttribute( name, value );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1401,7 +1473,13 @@ public:
|
|
|
|
|
a->SetAttribute(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Sets the named attribute to value.
|
|
|
|
|
/// Sets the named attribute to value.
|
|
|
|
|
void SetAttribute(const char* name, uint64_t value) {
|
|
|
|
|
XMLAttribute* a = FindOrCreateAttribute(name);
|
|
|
|
|
a->SetAttribute(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Sets the named attribute to value.
|
|
|
|
|
void SetAttribute( const char* name, bool value ) {
|
|
|
|
|
XMLAttribute* a = FindOrCreateAttribute( name );
|
|
|
|
|
a->SetAttribute( value );
|
|
|
|
@ -1483,7 +1561,7 @@ public:
|
|
|
|
|
@verbatim
|
|
|
|
|
<foo>Hullaballoo!<b>This is text</b></foo>
|
|
|
|
|
@endverbatim
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
For this XML:
|
|
|
|
|
@verbatim
|
|
|
|
|
<foo />
|
|
|
|
@ -1497,15 +1575,17 @@ public:
|
|
|
|
|
/// Convenience method for setting text inside an element. See SetText() for important limitations.
|
|
|
|
|
void SetText( int value );
|
|
|
|
|
/// Convenience method for setting text inside an element. See SetText() for important limitations.
|
|
|
|
|
void SetText( unsigned value );
|
|
|
|
|
void SetText( unsigned value );
|
|
|
|
|
/// Convenience method for setting text inside an element. See SetText() for important limitations.
|
|
|
|
|
void SetText(int64_t value);
|
|
|
|
|
/// Convenience method for setting text inside an element. See SetText() for important limitations.
|
|
|
|
|
void SetText(uint64_t value);
|
|
|
|
|
/// Convenience method for setting text inside an element. See SetText() for important limitations.
|
|
|
|
|
void SetText( bool value );
|
|
|
|
|
void SetText( bool value );
|
|
|
|
|
/// Convenience method for setting text inside an element. See SetText() for important limitations.
|
|
|
|
|
void SetText( double value );
|
|
|
|
|
void SetText( double value );
|
|
|
|
|
/// Convenience method for setting text inside an element. See SetText() for important limitations.
|
|
|
|
|
void SetText( float value );
|
|
|
|
|
void SetText( float value );
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Convenience method to query the value of a child text node. This is probably best
|
|
|
|
@ -1539,6 +1619,8 @@ public:
|
|
|
|
|
/// See QueryIntText()
|
|
|
|
|
XMLError QueryInt64Text(int64_t* uval) const;
|
|
|
|
|
/// See QueryIntText()
|
|
|
|
|
XMLError QueryUnsigned64Text(uint64_t* uval) const;
|
|
|
|
|
/// See QueryIntText()
|
|
|
|
|
XMLError QueryBoolText( bool* bval ) const;
|
|
|
|
|
/// See QueryIntText()
|
|
|
|
|
XMLError QueryDoubleText( double* dval ) const;
|
|
|
|
@ -1551,6 +1633,8 @@ public:
|
|
|
|
|
unsigned UnsignedText(unsigned defaultValue = 0) const;
|
|
|
|
|
/// See QueryIntText()
|
|
|
|
|
int64_t Int64Text(int64_t defaultValue = 0) const;
|
|
|
|
|
/// See QueryIntText()
|
|
|
|
|
uint64_t Unsigned64Text(uint64_t defaultValue = 0) const;
|
|
|
|
|
/// See QueryIntText()
|
|
|
|
|
bool BoolText(bool defaultValue = false) const;
|
|
|
|
|
/// See QueryIntText()
|
|
|
|
@ -1559,19 +1643,19 @@ public:
|
|
|
|
|
float FloatText(float defaultValue = 0) const;
|
|
|
|
|
|
|
|
|
|
// internal:
|
|
|
|
|
enum {
|
|
|
|
|
enum ElementClosingType {
|
|
|
|
|
OPEN, // <foo>
|
|
|
|
|
CLOSED, // <foo/>
|
|
|
|
|
CLOSING // </foo>
|
|
|
|
|
};
|
|
|
|
|
int ClosingType() const {
|
|
|
|
|
ElementClosingType ClosingType() const {
|
|
|
|
|
return _closingType;
|
|
|
|
|
}
|
|
|
|
|
virtual XMLNode* ShallowClone( XMLDocument* document ) const;
|
|
|
|
|
virtual bool ShallowEqual( const XMLNode* compare ) const;
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
char* ParseDeep( char* p, StrPair* endTag, int* curLineNumPtr );
|
|
|
|
|
char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
XMLElement( XMLDocument* doc );
|
|
|
|
@ -1579,17 +1663,13 @@ private:
|
|
|
|
|
XMLElement( const XMLElement& ); // not supported
|
|
|
|
|
void operator=( const XMLElement& ); // not supported
|
|
|
|
|
|
|
|
|
|
XMLAttribute* FindAttribute( const char* name ) {
|
|
|
|
|
return const_cast<XMLAttribute*>(const_cast<const XMLElement*>(this)->FindAttribute( name ));
|
|
|
|
|
}
|
|
|
|
|
XMLAttribute* FindOrCreateAttribute( const char* name );
|
|
|
|
|
//void LinkAttribute( XMLAttribute* attrib );
|
|
|
|
|
char* ParseAttributes( char* p, int* curLineNumPtr );
|
|
|
|
|
static void DeleteAttribute( XMLAttribute* attribute );
|
|
|
|
|
XMLAttribute* CreateAttribute();
|
|
|
|
|
|
|
|
|
|
enum { BUF_SIZE = 200 };
|
|
|
|
|
int _closingType;
|
|
|
|
|
ElementClosingType _closingType;
|
|
|
|
|
// The attribute list is ordered; there is no 'lastAttribute'
|
|
|
|
|
// because the list needs to be scanned for dupes before adding
|
|
|
|
|
// a new attribute.
|
|
|
|
@ -1611,6 +1691,13 @@ enum Whitespace {
|
|
|
|
|
class TINYXML2_LIB XMLDocument : public XMLNode
|
|
|
|
|
{
|
|
|
|
|
friend class XMLElement;
|
|
|
|
|
// Gives access to SetError and Push/PopDepth, but over-access for everything else.
|
|
|
|
|
// Wishing C++ had "internal" scope.
|
|
|
|
|
friend class XMLNode;
|
|
|
|
|
friend class XMLText;
|
|
|
|
|
friend class XMLComment;
|
|
|
|
|
friend class XMLDeclaration;
|
|
|
|
|
friend class XMLUnknown;
|
|
|
|
|
public:
|
|
|
|
|
/// constructor
|
|
|
|
|
XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE );
|
|
|
|
@ -1635,7 +1722,7 @@ public:
|
|
|
|
|
specified, TinyXML-2 will assume 'xml' points to a
|
|
|
|
|
null terminated string.
|
|
|
|
|
*/
|
|
|
|
|
XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
|
|
|
|
|
XMLError Parse( const char* xml, size_t nBytes=static_cast<size_t>(-1) );
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Load an XML file from disk.
|
|
|
|
@ -1646,8 +1733,8 @@ public:
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Load an XML file from disk. You are responsible
|
|
|
|
|
for providing and closing the FILE*.
|
|
|
|
|
|
|
|
|
|
for providing and closing the FILE*.
|
|
|
|
|
|
|
|
|
|
NOTE: The file should be opened as binary ("rb")
|
|
|
|
|
not text in order for TinyXML-2 to correctly
|
|
|
|
|
do newline normalization.
|
|
|
|
@ -1762,10 +1849,8 @@ public:
|
|
|
|
|
*/
|
|
|
|
|
void DeleteNode( XMLNode* node );
|
|
|
|
|
|
|
|
|
|
void SetError( XMLError error, const char* str1, const char* str2, int lineNum );
|
|
|
|
|
|
|
|
|
|
void ClearError() {
|
|
|
|
|
SetError(XML_SUCCESS, 0, 0, 0);
|
|
|
|
|
SetError(XML_SUCCESS, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Return true if there was an error parsing the document.
|
|
|
|
@ -1779,28 +1864,38 @@ public:
|
|
|
|
|
const char* ErrorName() const;
|
|
|
|
|
static const char* ErrorIDToName(XMLError errorID);
|
|
|
|
|
|
|
|
|
|
/// Return a possibly helpful diagnostic location or string.
|
|
|
|
|
const char* GetErrorStr1() const {
|
|
|
|
|
return _errorStr1.GetStr();
|
|
|
|
|
}
|
|
|
|
|
/// Return a possibly helpful secondary diagnostic location or string.
|
|
|
|
|
const char* GetErrorStr2() const {
|
|
|
|
|
return _errorStr2.GetStr();
|
|
|
|
|
}
|
|
|
|
|
/// Return the line where the error occured, or zero if unknown.
|
|
|
|
|
int GetErrorLineNum() const
|
|
|
|
|
/** Returns a "long form" error description. A hopefully helpful
|
|
|
|
|
diagnostic with location, line number, and/or additional info.
|
|
|
|
|
*/
|
|
|
|
|
const char* ErrorStr() const;
|
|
|
|
|
|
|
|
|
|
/// A (trivial) utility function that prints the ErrorStr() to stdout.
|
|
|
|
|
void PrintError() const;
|
|
|
|
|
|
|
|
|
|
/// Return the line where the error occurred, or zero if unknown.
|
|
|
|
|
int ErrorLineNum() const
|
|
|
|
|
{
|
|
|
|
|
return _errorLineNum;
|
|
|
|
|
}
|
|
|
|
|
/// If there is an error, print it to stdout.
|
|
|
|
|
void PrintError() const;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Clear the document, resetting it to the initial state.
|
|
|
|
|
void Clear();
|
|
|
|
|
|
|
|
|
|
// internal
|
|
|
|
|
/**
|
|
|
|
|
Copies this document to a target document.
|
|
|
|
|
The target will be completely cleared before the copy.
|
|
|
|
|
If you want to copy a sub-tree, see XMLNode::DeepClone().
|
|
|
|
|
|
|
|
|
|
NOTE: that the 'target' must be non-null.
|
|
|
|
|
*/
|
|
|
|
|
void DeepCopy(XMLDocument* target) const;
|
|
|
|
|
|
|
|
|
|
// internal
|
|
|
|
|
char* Identify( char* p, XMLNode** node );
|
|
|
|
|
|
|
|
|
|
// internal
|
|
|
|
|
void MarkInUse(XMLNode*);
|
|
|
|
|
|
|
|
|
|
virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@ -1816,11 +1911,18 @@ private:
|
|
|
|
|
bool _processEntities;
|
|
|
|
|
XMLError _errorID;
|
|
|
|
|
Whitespace _whitespaceMode;
|
|
|
|
|
mutable StrPair _errorStr1;
|
|
|
|
|
mutable StrPair _errorStr2;
|
|
|
|
|
mutable StrPair _errorStr;
|
|
|
|
|
int _errorLineNum;
|
|
|
|
|
char* _charBuffer;
|
|
|
|
|
int _parseCurLineNum;
|
|
|
|
|
int _parsingDepth;
|
|
|
|
|
// Memory tracking does add some overhead.
|
|
|
|
|
// However, the code assumes that you don't
|
|
|
|
|
// have a bunch of unlinked nodes around.
|
|
|
|
|
// Therefore it takes less memory to track
|
|
|
|
|
// in the document vs. a linked list in the XMLNode,
|
|
|
|
|
// and the performance is the same.
|
|
|
|
|
DynArray<XMLNode*, 10> _unlinked;
|
|
|
|
|
|
|
|
|
|
MemPoolT< sizeof(XMLElement) > _elementPool;
|
|
|
|
|
MemPoolT< sizeof(XMLAttribute) > _attributePool;
|
|
|
|
@ -1831,6 +1933,26 @@ private:
|
|
|
|
|
|
|
|
|
|
void Parse();
|
|
|
|
|
|
|
|
|
|
void SetError( XMLError error, int lineNum, const char* format, ... );
|
|
|
|
|
|
|
|
|
|
// Something of an obvious security hole, once it was discovered.
|
|
|
|
|
// Either an ill-formed XML or an excessively deep one can overflow
|
|
|
|
|
// the stack. Track stack depth, and error out if needed.
|
|
|
|
|
class DepthTracker {
|
|
|
|
|
public:
|
|
|
|
|
explicit DepthTracker(XMLDocument * document) {
|
|
|
|
|
this->_document = document;
|
|
|
|
|
document->PushDepth();
|
|
|
|
|
}
|
|
|
|
|
~DepthTracker() {
|
|
|
|
|
_document->PopDepth();
|
|
|
|
|
}
|
|
|
|
|
private:
|
|
|
|
|
XMLDocument * _document;
|
|
|
|
|
};
|
|
|
|
|
void PushDepth();
|
|
|
|
|
void PopDepth();
|
|
|
|
|
|
|
|
|
|
template<class NodeType, int PoolElementSize>
|
|
|
|
|
NodeType* CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool );
|
|
|
|
|
};
|
|
|
|
@ -1843,6 +1965,8 @@ inline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT<PoolElementSize>& poo
|
|
|
|
|
NodeType* returnNode = new (pool.Alloc()) NodeType( this );
|
|
|
|
|
TIXMLASSERT( returnNode );
|
|
|
|
|
returnNode->_memPool = &pool;
|
|
|
|
|
|
|
|
|
|
_unlinked.Push(returnNode);
|
|
|
|
|
return returnNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1905,16 +2029,13 @@ class TINYXML2_LIB XMLHandle
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
/// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
|
|
|
|
|
XMLHandle( XMLNode* node ) {
|
|
|
|
|
_node = node;
|
|
|
|
|
explicit XMLHandle( XMLNode* node ) : _node( node ) {
|
|
|
|
|
}
|
|
|
|
|
/// Create a handle from a node.
|
|
|
|
|
XMLHandle( XMLNode& node ) {
|
|
|
|
|
_node = &node;
|
|
|
|
|
explicit XMLHandle( XMLNode& node ) : _node( &node ) {
|
|
|
|
|
}
|
|
|
|
|
/// Copy constructor
|
|
|
|
|
XMLHandle( const XMLHandle& ref ) {
|
|
|
|
|
_node = ref._node;
|
|
|
|
|
XMLHandle( const XMLHandle& ref ) : _node( ref._node ) {
|
|
|
|
|
}
|
|
|
|
|
/// Assignment
|
|
|
|
|
XMLHandle& operator=( const XMLHandle& ref ) {
|
|
|
|
@ -1988,14 +2109,11 @@ private:
|
|
|
|
|
class TINYXML2_LIB XMLConstHandle
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
XMLConstHandle( const XMLNode* node ) {
|
|
|
|
|
_node = node;
|
|
|
|
|
explicit XMLConstHandle( const XMLNode* node ) : _node( node ) {
|
|
|
|
|
}
|
|
|
|
|
XMLConstHandle( const XMLNode& node ) {
|
|
|
|
|
_node = &node;
|
|
|
|
|
explicit XMLConstHandle( const XMLNode& node ) : _node( &node ) {
|
|
|
|
|
}
|
|
|
|
|
XMLConstHandle( const XMLConstHandle& ref ) {
|
|
|
|
|
_node = ref._node;
|
|
|
|
|
XMLConstHandle( const XMLConstHandle& ref ) : _node( ref._node ) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
XMLConstHandle& operator=( const XMLConstHandle& ref ) {
|
|
|
|
@ -2114,7 +2232,8 @@ public:
|
|
|
|
|
void PushAttribute( const char* name, const char* value );
|
|
|
|
|
void PushAttribute( const char* name, int value );
|
|
|
|
|
void PushAttribute( const char* name, unsigned value );
|
|
|
|
|
void PushAttribute(const char* name, int64_t value);
|
|
|
|
|
void PushAttribute( const char* name, int64_t value );
|
|
|
|
|
void PushAttribute( const char* name, uint64_t value );
|
|
|
|
|
void PushAttribute( const char* name, bool value );
|
|
|
|
|
void PushAttribute( const char* name, double value );
|
|
|
|
|
/// If streaming, close the Element.
|
|
|
|
@ -2126,8 +2245,10 @@ public:
|
|
|
|
|
void PushText( int value );
|
|
|
|
|
/// Add a text node from an unsigned.
|
|
|
|
|
void PushText( unsigned value );
|
|
|
|
|
/// Add a text node from an unsigned.
|
|
|
|
|
void PushText(int64_t value);
|
|
|
|
|
/// Add a text node from a signed 64bit integer.
|
|
|
|
|
void PushText( int64_t value );
|
|
|
|
|
/// Add a text node from an unsigned 64bit integer.
|
|
|
|
|
void PushText( uint64_t value );
|
|
|
|
|
/// Add a text node from a bool.
|
|
|
|
|
void PushText( bool value );
|
|
|
|
|
/// Add a text node from a float.
|
|
|
|
@ -2173,9 +2294,10 @@ public:
|
|
|
|
|
If in print to memory mode, reset the buffer to the
|
|
|
|
|
beginning.
|
|
|
|
|
*/
|
|
|
|
|
void ClearBuffer() {
|
|
|
|
|
void ClearBuffer( bool resetToFirstElement = true ) {
|
|
|
|
|
_buffer.Clear();
|
|
|
|
|
_buffer.Push(0);
|
|
|
|
|
_firstElement = resetToFirstElement;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
@ -2186,6 +2308,9 @@ protected:
|
|
|
|
|
*/
|
|
|
|
|
virtual void PrintSpace( int depth );
|
|
|
|
|
void Print( const char* format, ... );
|
|
|
|
|
void Write( const char* data, size_t size );
|
|
|
|
|
inline void Write( const char* data ) { Write( data, strlen( data ) ); }
|
|
|
|
|
void Putc( char ch );
|
|
|
|
|
|
|
|
|
|
void SealElementIfJustOpened();
|
|
|
|
|
bool _elementJustOpened;
|
|
|
|
@ -2209,6 +2334,10 @@ private:
|
|
|
|
|
bool _restrictedEntityFlag[ENTITY_RANGE];
|
|
|
|
|
|
|
|
|
|
DynArray< char, 20 > _buffer;
|
|
|
|
|
|
|
|
|
|
// Prohibit cloning, intentionally not implemented
|
|
|
|
|
XMLPrinter( const XMLPrinter& );
|
|
|
|
|
XMLPrinter& operator=( const XMLPrinter& );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|