#endif
#include <stdint.h>
-/*
- TODO: intern strings instead of allocation.
-*/
/*
gcc:
g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
# pragma warning(disable: 4251)
#endif
-#ifdef _WIN32
+#ifdef _MSC_VER
# ifdef TINYXML2_EXPORT
# define TINYXML2_LIB __declspec(dllexport)
# elif defined(TINYXML2_IMPORT)
#endif
+#if !defined(TIXMLASSERT)
#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(); }
+# define TIXMLASSERT( x ) do { if ( !((void)0,(x))) { __debugbreak(); } } while(false)
# elif defined (ANDROID_NDK)
# include <android/log.h>
-# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
+# define TIXMLASSERT( x ) do { if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } } while(false)
# else
# include <assert.h>
# define TIXMLASSERT assert
# endif
#else
-# define TIXMLASSERT( x ) {}
+# define TIXMLASSERT( x ) do {} while(false)
+#endif
#endif
-
/* Versioning, past 1.0.14:
http://semver.org/
*/
-static const int TIXML2_MAJOR_VERSION = 8;
+static const int TIXML2_MAJOR_VERSION = 11;
static const int TIXML2_MINOR_VERSION = 0;
static const int TIXML2_PATCH_VERSION = 0;
-#define TINYXML2_MAJOR_VERSION 8
+#define TINYXML2_MAJOR_VERSION 11
#define TINYXML2_MINOR_VERSION 0
#define TINYXML2_PATCH_VERSION 0
// 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;
+static const int TINYXML2_MAX_ELEMENT_DEPTH = 500;
namespace tinyxml2
{
class TINYXML2_LIB StrPair
{
public:
- enum {
+ enum Mode {
NEEDS_ENTITY_PROCESSING = 0x01,
NEEDS_NEWLINE_NORMALIZATION = 0x02,
NEEDS_WHITESPACE_COLLAPSING = 0x04,
Has a small initial memory pool, so that low or no usage will not
cause a call to new/delete
*/
-template <class T, int INITIAL_SIZE>
+template <class T, size_t INITIAL_SIZE>
class DynArray
{
public:
++_size;
}
- T* PushArr( int count ) {
- TIXMLASSERT( count >= 0 );
- TIXMLASSERT( _size <= INT_MAX - count );
+ T* PushArr( size_t count ) {
+ TIXMLASSERT( _size <= SIZE_MAX - count );
EnsureCapacity( _size+count );
T* ret = &_mem[_size];
_size += count;
return _mem[_size];
}
- void PopArr( int count ) {
+ void PopArr( size_t count ) {
TIXMLASSERT( _size >= count );
_size -= count;
}
return _size == 0;
}
- T& operator[](int i) {
- TIXMLASSERT( i>= 0 && i < _size );
+ T& operator[](size_t i) {
+ TIXMLASSERT( i < _size );
return _mem[i];
}
- const T& operator[](int i) const {
- TIXMLASSERT( i>= 0 && i < _size );
+ const T& operator[](size_t i) const {
+ TIXMLASSERT( i < _size );
return _mem[i];
}
return _mem[ _size - 1];
}
- int Size() const {
+ size_t Size() const {
TIXMLASSERT( _size >= 0 );
return _size;
}
- int Capacity() const {
+ size_t Capacity() const {
TIXMLASSERT( _allocated >= INITIAL_SIZE );
return _allocated;
}
- void SwapRemove(int i) {
- TIXMLASSERT(i >= 0 && i < _size);
+ void SwapRemove(size_t i) {
+ TIXMLASSERT(i < _size);
TIXMLASSERT(_size > 0);
_mem[i] = _mem[_size - 1];
--_size;
DynArray( const DynArray& ); // not supported
void operator=( const DynArray& ); // not supported
- void EnsureCapacity( int cap ) {
+ void EnsureCapacity( size_t cap ) {
TIXMLASSERT( cap > 0 );
if ( cap > _allocated ) {
- TIXMLASSERT( cap <= INT_MAX / 2 );
- const int newAllocated = cap * 2;
+ TIXMLASSERT( cap <= SIZE_MAX / 2 / sizeof(T));
+ const size_t 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
+ memcpy( newMem, _mem, sizeof(T) * _size ); // warning: not using constructors, only works for PODs
if ( _mem != _pool ) {
delete [] _mem;
}
T* _mem;
T _pool[INITIAL_SIZE];
- int _allocated; // objects allocated
- int _size; // number objects in use
+ size_t _allocated; // objects allocated
+ size_t _size; // number objects in use
};
MemPool() {}
virtual ~MemPool() {}
- virtual int ItemSize() const = 0;
+ virtual size_t ItemSize() const = 0;
virtual void* Alloc() = 0;
virtual void Free( void* ) = 0;
virtual void SetTracked() = 0;
/*
Template child class to create pools of the correct type.
*/
-template< int ITEM_SIZE >
+template< size_t ITEM_SIZE >
class MemPoolT : public MemPool
{
public:
_nUntracked = 0;
}
- virtual int ItemSize() const {
+ virtual size_t ItemSize() const override {
return ITEM_SIZE;
}
- int CurrentAllocs() const {
+ size_t CurrentAllocs() const {
return _currentAllocs;
}
- virtual void* Alloc() {
+ virtual void* Alloc() override{
if ( !_root ) {
// Need a new block.
- Block* block = new Block();
+ Block* block = new Block;
_blockPtrs.Push( block );
Item* blockItems = block->items;
- for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {
+ for( size_t i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {
blockItems[i].next = &(blockItems[i + 1]);
}
blockItems[ITEMS_PER_BLOCK - 1].next = 0;
return result;
}
- virtual void Free( void* mem ) {
+ virtual void Free( void* mem ) override {
if ( !mem ) {
return;
}
ITEM_SIZE, _nAllocs, _blockPtrs.Size() );
}
- void SetTracked() {
+ void SetTracked() override {
--_nUntracked;
}
- int Untracked() const {
+ size_t Untracked() const {
return _nUntracked;
}
union Item {
Item* next;
- char itemData[ITEM_SIZE];
+ char itemData[static_cast<size_t>(ITEM_SIZE)];
};
struct Block {
Item items[ITEMS_PER_BLOCK];
DynArray< Block*, 10 > _blockPtrs;
Item* _root;
- int _currentAllocs;
- int _nAllocs;
- int _maxAllocs;
- int _nUntracked;
+ size_t _currentAllocs;
+ size_t _nAllocs;
+ size_t _maxAllocs;
+ size_t _nUntracked;
};
TIXMLASSERT( p );
TIXMLASSERT( q );
TIXMLASSERT( nChar >= 0 );
- return strncmp( p, q, nChar ) == 0;
+ return strncmp( p, q, static_cast<size_t>(nChar) ) == 0;
}
inline static bool IsUTF8Continuation( const char p ) {
return 0;
}
+ // ChildElementCount was originally suggested by msteiger on the sourceforge page for TinyXML and modified by KB1SPH for TinyXML-2.
+
+ int ChildElementCount(const char *value) const;
+
+ int ChildElementCount() const;
+
/** The meaning of 'value' changes for the specific type.
@verbatim
Document: empty (NULL is returned, not an empty string)
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
+ is specified, the memory will be allocated in the
specified XMLDocument.
NOTE: This is probably not the correct tool to
{
friend class XMLDocument;
public:
- virtual bool Accept( XMLVisitor* visitor ) const;
+ virtual bool Accept( XMLVisitor* visitor ) const override;
- virtual XMLText* ToText() {
+ virtual XMLText* ToText() override {
return this;
}
- virtual const XMLText* ToText() const {
+ virtual const XMLText* ToText() const override {
return this;
}
return _isCData;
}
- virtual XMLNode* ShallowClone( XMLDocument* document ) const;
- virtual bool ShallowEqual( const XMLNode* compare ) const;
+ virtual XMLNode* ShallowClone( XMLDocument* document ) const override;
+ virtual bool ShallowEqual( const XMLNode* compare ) const override;
protected:
explicit XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
virtual ~XMLText() {}
- char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
+ char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) override;
private:
bool _isCData;
{
friend class XMLDocument;
public:
- virtual XMLComment* ToComment() {
+ virtual XMLComment* ToComment() override {
return this;
}
- virtual const XMLComment* ToComment() const {
+ virtual const XMLComment* ToComment() const override {
return this;
}
- virtual bool Accept( XMLVisitor* visitor ) const;
+ virtual bool Accept( XMLVisitor* visitor ) const override;
- virtual XMLNode* ShallowClone( XMLDocument* document ) const;
- virtual bool ShallowEqual( const XMLNode* compare ) const;
+ virtual XMLNode* ShallowClone( XMLDocument* document ) const override;
+ virtual bool ShallowEqual( const XMLNode* compare ) const override;
protected:
explicit XMLComment( XMLDocument* doc );
virtual ~XMLComment();
- char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);
+ char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr) override;
private:
XMLComment( const XMLComment& ); // not supported
{
friend class XMLDocument;
public:
- virtual XMLDeclaration* ToDeclaration() {
+ virtual XMLDeclaration* ToDeclaration() override {
return this;
}
- virtual const XMLDeclaration* ToDeclaration() const {
+ virtual const XMLDeclaration* ToDeclaration() const override {
return this;
}
- virtual bool Accept( XMLVisitor* visitor ) const;
+ virtual bool Accept( XMLVisitor* visitor ) const override;
- virtual XMLNode* ShallowClone( XMLDocument* document ) const;
- virtual bool ShallowEqual( const XMLNode* compare ) const;
+ virtual XMLNode* ShallowClone( XMLDocument* document ) const override;
+ virtual bool ShallowEqual( const XMLNode* compare ) const override;
protected:
explicit XMLDeclaration( XMLDocument* doc );
virtual ~XMLDeclaration();
- char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
+ char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) override;
private:
XMLDeclaration( const XMLDeclaration& ); // not supported
{
friend class XMLDocument;
public:
- virtual XMLUnknown* ToUnknown() {
+ virtual XMLUnknown* ToUnknown() override {
return this;
}
- virtual const XMLUnknown* ToUnknown() const {
+ virtual const XMLUnknown* ToUnknown() const override {
return this;
}
- virtual bool Accept( XMLVisitor* visitor ) const;
+ virtual bool Accept( XMLVisitor* visitor ) const override;
- virtual XMLNode* ShallowClone( XMLDocument* document ) const;
- virtual bool ShallowEqual( const XMLNode* compare ) const;
+ virtual XMLNode* ShallowClone( XMLDocument* document ) const override;
+ virtual bool ShallowEqual( const XMLNode* compare ) const override;
protected:
explicit XMLUnknown( XMLDocument* doc );
virtual ~XMLUnknown();
- char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
+ char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) override;
private:
XMLUnknown( const XMLUnknown& ); // not supported
SetValue( str, staticMem );
}
- virtual XMLElement* ToElement() {
+ virtual XMLElement* ToElement() override {
return this;
}
- virtual const XMLElement* ToElement() const {
+ virtual const XMLElement* ToElement() const override {
return this;
}
- virtual bool Accept( XMLVisitor* visitor ) const;
+ virtual bool Accept( XMLVisitor* visitor ) const override;
/** Given an attribute name, Attribute() returns the value
for the attribute of that name, or null if none
ElementClosingType ClosingType() const {
return _closingType;
}
- virtual XMLNode* ShallowClone( XMLDocument* document ) const;
- virtual bool ShallowEqual( const XMLNode* compare ) const;
+ virtual XMLNode* ShallowClone( XMLDocument* document ) const override;
+ virtual bool ShallowEqual( const XMLNode* compare ) const override;
protected:
- char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
+ char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) override;
private:
XMLElement( XMLDocument* doc );
enum Whitespace {
PRESERVE_WHITESPACE,
- COLLAPSE_WHITESPACE
+ COLLAPSE_WHITESPACE,
+ PEDANTIC_WHITESPACE
};
XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE );
~XMLDocument();
- virtual XMLDocument* ToDocument() {
+ virtual XMLDocument* ToDocument() override {
TIXMLASSERT( this == _document );
return this;
}
- virtual const XMLDocument* ToDocument() const {
+ virtual const XMLDocument* ToDocument() const override {
TIXMLASSERT( this == _document );
return this;
}
@endverbatim
*/
void Print( XMLPrinter* streamer=0 ) const;
- virtual bool Accept( XMLVisitor* visitor ) const;
+ virtual bool Accept( XMLVisitor* visitor ) const override;
/**
Create a new Element associated with
*/
void DeleteNode( XMLNode* node );
- void ClearError() {
- SetError(XML_SUCCESS, 0, 0);
- }
+ /// Clears the error flags.
+ void ClearError();
/// Return true if there was an error parsing the document.
bool Error() const {
void DeepCopy(XMLDocument* target) const;
// internal
- char* Identify( char* p, XMLNode** node );
+ char* Identify( char* p, XMLNode** node, bool first );
// internal
void MarkInUse(const XMLNode* const);
- virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
+ virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const override{
return 0;
}
- virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
+ virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const override{
return false;
}
void PushDepth();
void PopDepth();
- template<class NodeType, int PoolElementSize>
+ template<class NodeType, size_t PoolElementSize>
NodeType* CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool );
};
-template<class NodeType, int PoolElementSize>
+template<class NodeType, size_t PoolElementSize>
inline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool )
{
TIXMLASSERT( sizeof( NodeType ) == PoolElementSize );
void PushDeclaration( const char* value );
void PushUnknown( const char* value );
- virtual bool VisitEnter( const XMLDocument& /*doc*/ );
- virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
+ virtual bool VisitEnter( const XMLDocument& /*doc*/ ) override;
+ virtual bool VisitExit( const XMLDocument& /*doc*/ ) override {
return true;
}
- virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
- virtual bool VisitExit( const XMLElement& element );
+ virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute ) override;
+ virtual bool VisitExit( const XMLElement& element ) override;
- virtual bool Visit( const XMLText& text );
- virtual bool Visit( const XMLComment& comment );
- virtual bool Visit( const XMLDeclaration& declaration );
- virtual bool Visit( const XMLUnknown& unknown );
+ virtual bool Visit( const XMLText& text ) override;
+ virtual bool Visit( const XMLComment& comment ) override;
+ virtual bool Visit( const XMLDeclaration& declaration ) override;
+ virtual bool Visit( const XMLUnknown& unknown ) override;
/**
If in print to memory mode, return a pointer to
of the XML file in memory. (Note the size returned
includes the terminating null.)
*/
- int CStrSize() const {
+ size_t CStrSize() const {
return _buffer.Size();
}
/**
};
-} // tinyxml2
+} // namespace tinyxml2
#if defined(_MSC_VER)
# pragma warning(pop)
#include "tinyxml2.h"
#include <new> // yes, this one new style header, is in the Android SDK.
-#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)
+#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) || defined(__CC_ARM)
# include <stddef.h>
# include <stdarg.h>
#else
#if defined(_WIN64)
#define TIXML_FSEEK _fseeki64
#define TIXML_FTELL _ftelli64
-#elif defined(__APPLE__) || (__FreeBSD__)
+#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__CYGWIN__)
#define TIXML_FSEEK fseeko
#define TIXML_FTELL ftello
-#elif defined(__unix__) && defined(__x86_64__)
+#elif defined(__ANDROID__) && __ANDROID_API__ > 24
#define TIXML_FSEEK fseeko64
#define TIXML_FTELL ftello64
#else
if ( !p || !(*p) ) {
return 0;
}
- if ( !XMLUtil::IsNameStartChar( (unsigned char) *p ) ) {
+ if ( !XMLUtil::IsNameStartChar( static_cast<unsigned char>(*p) ) ) {
return 0;
}
char* const start = p;
++p;
- while ( *p && XMLUtil::IsNameChar( (unsigned char) *p ) ) {
+ while ( *p && XMLUtil::IsNameChar( static_cast<unsigned char>(*p) ) ) {
++p;
}
}
-const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )
+const char* XMLUtil::GetCharacterRef(const char* p, char* value, int* length)
{
- // Presume an entity, and pull it out.
+ // Assume an entity, and pull it out.
*length = 0;
- if ( *(p+1) == '#' && *(p+2) ) {
- unsigned long ucs = 0;
- TIXMLASSERT( sizeof( ucs ) >= 4 );
+ static const uint32_t MAX_CODE_POINT = 0x10FFFF;
+
+ if (*(p + 1) == '#' && *(p + 2)) {
+ uint32_t ucs = 0;
ptrdiff_t delta = 0;
- unsigned mult = 1;
+ uint32_t mult = 1;
static const char SEMICOLON = ';';
- if ( *(p+2) == 'x' ) {
+ bool hex = false;
+ uint32_t radix = 10;
+ const char* q = 0;
+ char terminator = '#';
+
+ if (*(p + 2) == 'x') {
// Hexadecimal.
- const char* q = p+3;
- if ( !(*q) ) {
- return 0;
- }
+ hex = true;
+ radix = 16;
+ terminator = 'x';
- q = strchr( q, SEMICOLON );
+ q = p + 3;
+ }
+ else {
+ // Decimal.
+ q = p + 2;
+ }
+ if (!(*q)) {
+ return 0;
+ }
- if ( !q ) {
- return 0;
- }
- TIXMLASSERT( *q == SEMICOLON );
+ q = strchr(q, SEMICOLON);
+ if (!q) {
+ return 0;
+ }
+ TIXMLASSERT(*q == SEMICOLON);
- delta = q-p;
- --q;
+ delta = q - p;
+ --q;
- while ( *q != 'x' ) {
- unsigned int digit = 0;
+ while (*q != terminator) {
+ uint32_t digit = 0;
- if ( *q >= '0' && *q <= '9' ) {
- digit = *q - '0';
- }
- else if ( *q >= 'a' && *q <= 'f' ) {
- digit = *q - 'a' + 10;
- }
- else if ( *q >= 'A' && *q <= 'F' ) {
- digit = *q - 'A' + 10;
- }
- else {
- return 0;
- }
- TIXMLASSERT( 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;
- --q;
+ if (*q >= '0' && *q <= '9') {
+ digit = *q - '0';
}
- }
- else {
- // Decimal.
- const char* q = p+2;
- if ( !(*q) ) {
- return 0;
+ else if (hex && (*q >= 'a' && *q <= 'f')) {
+ digit = *q - 'a' + 10;
}
-
- q = strchr( q, SEMICOLON );
-
- if ( !q ) {
+ else if (hex && (*q >= 'A' && *q <= 'F')) {
+ digit = *q - 'A' + 10;
+ }
+ else {
return 0;
}
- TIXMLASSERT( *q == SEMICOLON );
-
- delta = q-p;
- --q;
-
- while ( *q != '#' ) {
- if ( *q >= '0' && *q <= '9' ) {
- const unsigned int digit = *q - '0';
- TIXMLASSERT( digit < 10 );
- TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );
- const unsigned int digitScaled = mult * digit;
- TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );
- ucs += digitScaled;
- }
- else {
- return 0;
- }
- TIXMLASSERT( mult <= UINT_MAX / 10 );
- mult *= 10;
- --q;
+ TIXMLASSERT(digit < radix);
+
+ const unsigned int digitScaled = mult * digit;
+ ucs += digitScaled;
+ mult *= radix;
+
+ // Security check: could a value exist that is out of range?
+ // Easily; limit to the MAX_CODE_POINT, which also allows for a
+ // bunch of leading zeroes.
+ if (mult > MAX_CODE_POINT) {
+ mult = MAX_CODE_POINT;
}
+ --q;
+ }
+ // Out of range:
+ if (ucs > MAX_CODE_POINT) {
+ return 0;
}
// convert the UCS to UTF-8
- ConvertUTF32ToUTF8( ucs, value, length );
+ ConvertUTF32ToUTF8(ucs, value, length);
+ if (length == 0) {
+ // If length is 0, there was an error. (Security? Bad input?)
+ // Fail safely.
+ return 0;
+ }
return p + delta + 1;
}
- return p+1;
+ return p + 1;
}
-
void XMLUtil::ToStr( int v, char* buffer, int bufferSize )
{
TIXML_SNPRINTF( buffer, bufferSize, "%d", v );
void XMLUtil::ToStr( uint64_t v, char* buffer, int bufferSize )
{
// horrible syntax trick to make the compiler happy about %llu
- TIXML_SNPRINTF(buffer, bufferSize, "%llu", (long long)v);
+ TIXML_SNPRINTF(buffer, bufferSize, "%llu", static_cast<unsigned long long>(v));
}
bool XMLUtil::ToInt(const char* str, int* value)
{
- if (TIXML_SSCANF(str, IsPrefixHex(str) ? "%x" : "%d", value) == 1) {
- return true;
+ if (IsPrefixHex(str)) {
+ unsigned v;
+ if (TIXML_SSCANF(str, "%x", &v) == 1) {
+ *value = static_cast<int>(v);
+ return true;
+ }
+ }
+ else {
+ if (TIXML_SSCANF(str, "%d", value) == 1) {
+ return true;
+ }
}
return false;
}
bool XMLUtil::ToInt64(const char* str, int64_t* value)
{
- long long v = 0; // horrible syntax trick to make the compiler happy about %lld
- if (TIXML_SSCANF(str, IsPrefixHex(str) ? "%llx" : "%lld", &v) == 1) {
- *value = static_cast<int64_t>(v);
- return true;
- }
+ if (IsPrefixHex(str)) {
+ unsigned long long v = 0; // horrible syntax trick to make the compiler happy about %llx
+ if (TIXML_SSCANF(str, "%llx", &v) == 1) {
+ *value = static_cast<int64_t>(v);
+ return true;
+ }
+ }
+ else {
+ long long v = 0; // horrible syntax trick to make the compiler happy about %lld
+ if (TIXML_SSCANF(str, "%lld", &v) == 1) {
+ *value = static_cast<int64_t>(v);
+ return true;
+ }
+ }
return false;
}
bool XMLUtil::ToUnsigned64(const char* str, uint64_t* value) {
unsigned long long v = 0; // horrible syntax trick to make the compiler happy about %llu
if(TIXML_SSCANF(str, IsPrefixHex(str) ? "%llx" : "%llu", &v) == 1) {
- *value = (uint64_t)v;
+ *value = static_cast<uint64_t>(v);
return true;
}
return false;
}
-char* XMLDocument::Identify( char* p, XMLNode** node )
+char* XMLDocument::Identify( char* p, XMLNode** node, bool first )
{
TIXMLASSERT( node );
TIXMLASSERT( p );
p += dtdHeaderLen;
}
else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {
- returnNode = CreateUnlinkedNode<XMLElement>( _elementPool );
- returnNode->_parseLineNum = _parseCurLineNum;
- p += elementHeaderLen;
+
+ // Preserve whitespace pedantically before closing tag, when it's immediately after opening tag
+ if (WhitespaceMode() == PEDANTIC_WHITESPACE && first && p != start && *(p + elementHeaderLen) == '/') {
+ returnNode = CreateUnlinkedNode<XMLText>(_textPool);
+ returnNode->_parseLineNum = startLine;
+ p = start; // Back it up, all the text counts.
+ _parseCurLineNum = startLine;
+ }
+ else {
+ returnNode = CreateUnlinkedNode<XMLElement>(_elementPool);
+ returnNode->_parseLineNum = _parseCurLineNum;
+ p += elementHeaderLen;
+ }
}
else {
returnNode = CreateUnlinkedNode<XMLText>( _textPool );
}
}
+// ChildElementCount was originally suggested by msteiger on the sourceforge page for TinyXML and modified by KB1SPH for TinyXML-2.
+
+int XMLNode::ChildElementCount(const char *value) const {
+ int count = 0;
+
+ const XMLElement *e = FirstChildElement(value);
+
+ while (e) {
+ e = e->NextSiblingElement(value);
+ count++;
+ }
+
+ return count;
+}
+
+int XMLNode::ChildElementCount() const {
+ int count = 0;
+
+ const XMLElement *e = FirstChildElement();
+
+ while (e) {
+ e = e->NextSiblingElement();
+ count++;
+ }
+
+ return count;
+}
+
const char* XMLNode::Value() const
{
// Edge case: XMLDocuments don't have a Value. Return null.
if (_document->Error())
return 0;
+ bool first = true;
while( p && *p ) {
XMLNode* node = 0;
- p = _document->Identify( p, &node );
+ p = _document->Identify( p, &node, first );
TIXMLASSERT( p );
if ( node == 0 ) {
break;
}
+ first = false;
const int initialLineNum = node->_parseLineNum;
StrPair endTag;
p = node->ParseDeep( p, &endTag, curLineNumPtr );
if ( !p ) {
- DeleteNode( node );
+ _document->DeleteNode( node );
if ( !_document->Error() ) {
_document->SetError( XML_ERROR_PARSING, initialLineNum, 0);
}
}
if ( !wellLocated ) {
_document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, "XMLDeclaration value=%s", decl->Value());
- DeleteNode( node );
+ _document->DeleteNode( node );
break;
}
}
}
if ( mismatch ) {
_document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, "XMLElement name=%s", ele->Name());
- DeleteNode( node );
+ _document->DeleteNode( node );
break;
}
}
const char* XMLElement::GetText() const
{
- if ( FirstChild() && FirstChild()->ToText() ) {
- return FirstChild()->Value();
+ /* skip comment node */
+ const XMLNode* node = FirstChild();
+ while (node) {
+ if (node->ToComment()) {
+ node = node->NextSibling();
+ continue;
+ }
+ break;
+ }
+
+ if ( node && node->ToText() ) {
+ return node->Value();
}
return 0;
}
}
-XMLError XMLElement::QueryUnsigned64Text(uint64_t* ival) const
+XMLError XMLElement::QueryUnsigned64Text(uint64_t* uval) const
{
if(FirstChild() && FirstChild()->ToText()) {
const char* t = FirstChild()->Value();
- if(XMLUtil::ToUnsigned64(t, ival)) {
+ if(XMLUtil::ToUnsigned64(t, uval)) {
return XML_SUCCESS;
}
return XML_CAN_NOT_CONVERT_TEXT;
}
// attribute.
- if (XMLUtil::IsNameStartChar( (unsigned char) *p ) ) {
+ if (XMLUtil::IsNameStartChar( static_cast<unsigned char>(*p) ) ) {
XMLAttribute* attrib = CreateAttribute();
TIXMLASSERT( attrib );
attrib->_parseLineNum = _document->_parseCurLineNum;
TIXMLASSERT(node);
TIXMLASSERT(node->_parent == 0);
- for (int i = 0; i < _unlinked.Size(); ++i) {
+ for (size_t i = 0; i < _unlinked.Size(); ++i) {
if (node == _unlinked[i]) {
_unlinked.SwapRemove(i);
break;
}
-XMLError XMLDocument::Parse( const char* p, size_t len )
+XMLError XMLDocument::Parse( const char* xml, size_t nBytes )
{
Clear();
- if ( len == 0 || !p || !*p ) {
+ if ( nBytes == 0 || !xml || !*xml ) {
SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
return _errorID;
}
- if ( len == static_cast<size_t>(-1) ) {
- len = strlen( p );
+ if ( nBytes == static_cast<size_t>(-1) ) {
+ nBytes = strlen( xml );
}
TIXMLASSERT( _charBuffer == 0 );
- _charBuffer = new char[ len+1 ];
- memcpy( _charBuffer, p, len );
- _charBuffer[len] = 0;
+ _charBuffer = new char[ nBytes+1 ];
+ memcpy( _charBuffer, xml, nBytes );
+ _charBuffer[nBytes] = 0;
Parse();
if ( Error() ) {
}
+void XMLDocument::ClearError() {
+ _errorID = XML_SUCCESS;
+ _errorLineNum = 0;
+ _errorStr.Reset();
+}
+
+
void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... )
{
- TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT );
+ TIXMLASSERT(error >= 0 && error < XML_ERROR_COUNT);
_errorID = error;
_errorLineNum = lineNum;
_errorStr.Reset();
char* buffer = new char[BUFFER_SIZE];
TIXMLASSERT(sizeof(error) <= sizeof(int));
- TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d", ErrorIDToName(error), int(error), int(error), lineNum);
+ TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d",
+ ErrorIDToName(error), static_cast<int>(error), static_cast<unsigned int>(error), lineNum);
if (format) {
size_t len = strlen(buffer);