]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Upgrade tinyxml2 from v8.0 to v11.0
authorDimitris Panokostas <midwan@gmail.com>
Mon, 1 Sep 2025 14:12:14 +0000 (16:12 +0200)
committerDimitris Panokostas <midwan@gmail.com>
Mon, 1 Sep 2025 14:12:14 +0000 (16:12 +0200)
include/tinyxml2.h
tinyxml2.cpp

index 172413eca947d39370978b9bc5b684f6cbbe8ffc..9626be8a0f13b61069648989ac6d95468d27b86c 100644 (file)
@@ -42,9 +42,6 @@ distribution.
 #endif
 #include <stdint.h>
 
-/*
-   TODO: intern strings instead of allocation.
-*/
 /*
        gcc:
         g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
@@ -64,7 +61,7 @@ distribution.
 #   pragma warning(disable: 4251)
 #endif
 
-#ifdef _WIN32
+#ifdef _MSC_VER
 #   ifdef TINYXML2_EXPORT
 #       define TINYXML2_LIB __declspec(dllexport)
 #   elif defined(TINYXML2_IMPORT)
@@ -79,30 +76,31 @@ distribution.
 #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
 
@@ -111,7 +109,7 @@ static const int TIXML2_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
 {
@@ -135,7 +133,7 @@ class XMLPrinter;
 class TINYXML2_LIB StrPair
 {
 public:
-    enum {
+    enum Mode {
         NEEDS_ENTITY_PROCESSING                        = 0x01,
         NEEDS_NEWLINE_NORMALIZATION            = 0x02,
         NEEDS_WHITESPACE_COLLAPSING     = 0x04,
@@ -201,7 +199,7 @@ private:
        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:
@@ -229,9 +227,8 @@ 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;
@@ -244,7 +241,7 @@ public:
         return _mem[_size];
     }
 
-    void PopArr( int count ) {
+    void PopArr( size_t count ) {
         TIXMLASSERT( _size >= count );
         _size -= count;
     }
@@ -253,13 +250,13 @@ public:
         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];
     }
 
@@ -268,18 +265,18 @@ public:
         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;
@@ -299,14 +296,14 @@ private:
     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;
             }
@@ -317,8 +314,8 @@ private:
 
     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
 };
 
 
@@ -332,7 +329,7 @@ public:
     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;
@@ -342,7 +339,7 @@ public:
 /*
        Template child class to create pools of the correct type.
 */
-template< int ITEM_SIZE >
+template< size_t ITEM_SIZE >
 class MemPoolT : public MemPool
 {
 public:
@@ -364,21 +361,21 @@ 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;
@@ -397,7 +394,7 @@ public:
         return result;
     }
 
-    virtual void Free( void* mem ) {
+    virtual void Free( void* mem ) override {
         if ( !mem ) {
             return;
         }
@@ -415,11 +412,11 @@ public:
                 ITEM_SIZE, _nAllocs, _blockPtrs.Size() );
     }
 
-    void SetTracked() {
+    void SetTracked() override {
         --_nUntracked;
     }
 
-    int Untracked() const {
+    size_t Untracked() const {
         return _nUntracked;
     }
 
@@ -442,7 +439,7 @@ private:
 
     union Item {
         Item*   next;
-        char    itemData[ITEM_SIZE];
+        char    itemData[static_cast<size_t>(ITEM_SIZE)];
     };
     struct Block {
         Item items[ITEMS_PER_BLOCK];
@@ -450,10 +447,10 @@ private:
     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;
 };
 
 
@@ -602,7 +599,7 @@ public:
         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 ) {
@@ -731,6 +728,12 @@ public:
         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)
@@ -888,7 +891,7 @@ public:
 
                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
@@ -991,12 +994,12 @@ class TINYXML2_LIB XMLText : public XMLNode
 {
     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;
     }
 
@@ -1009,14 +1012,14 @@ public:
         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;
@@ -1031,23 +1034,23 @@ class TINYXML2_LIB XMLComment : public XMLNode
 {
     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
@@ -1070,23 +1073,23 @@ class TINYXML2_LIB XMLDeclaration : public XMLNode
 {
     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
@@ -1105,23 +1108,23 @@ class TINYXML2_LIB XMLUnknown : public XMLNode
 {
     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
@@ -1273,13 +1276,13 @@ public:
         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
@@ -1675,11 +1678,11 @@ public:
     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 );
@@ -1703,7 +1706,8 @@ private:
 
 enum Whitespace {
     PRESERVE_WHITESPACE,
-    COLLAPSE_WHITESPACE
+    COLLAPSE_WHITESPACE,
+    PEDANTIC_WHITESPACE
 };
 
 
@@ -1727,11 +1731,11 @@ public:
     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;
     }
@@ -1828,7 +1832,7 @@ public:
        @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
@@ -1873,9 +1877,8 @@ public:
     */
     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 {
@@ -1915,15 +1918,15 @@ public:
        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;
     }
 
@@ -1977,11 +1980,11 @@ private:
        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 );
@@ -2286,18 +2289,18 @@ public:
     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
@@ -2311,7 +2314,7 @@ public:
        of the XML file in memory. (Note the size returned
        includes the terminating null.)
     */
-    int CStrSize() const {
+    size_t CStrSize() const {
         return _buffer.Size();
     }
     /**
@@ -2371,7 +2374,7 @@ private:
 };
 
 
-}      // tinyxml2
+} // namespace tinyxml2
 
 #if defined(_MSC_VER)
 #   pragma warning(pop)
index 3dcd3ef2e1695e71a361a5b3bee07ddd095a3ccb..8bb963582ec4886eefed92b01925e588348247f9 100644 (file)
@@ -24,7 +24,7 @@ distribution.
 #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
@@ -103,10 +103,10 @@ distribution.
 #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
@@ -234,13 +234,13 @@ char* StrPair::ParseName( char* p )
     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;
     }
 
@@ -467,102 +467,94 @@ void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length
 }
 
 
-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 );
@@ -605,13 +597,22 @@ void XMLUtil::ToStr( int64_t v, char* buffer, int bufferSize )
 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;
 }
@@ -670,11 +671,20 @@ bool XMLUtil::ToDouble( const char* str, double* value )
 
 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;
 }
 
@@ -682,14 +692,14 @@ bool XMLUtil::ToInt64(const char* str, int64_t* value)
 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 );
@@ -741,9 +751,19 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
         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 );
@@ -796,6 +816,34 @@ XMLNode::~XMLNode()
     }
 }
 
+// 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.
@@ -1044,21 +1092,23 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr )
        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);
             }
@@ -1091,7 +1141,7 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr )
             }
             if ( !wellLocated ) {
                 _document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, "XMLDeclaration value=%s", decl->Value());
-                DeleteNode( node );
+                _document->DeleteNode( node );
                 break;
             }
         }
@@ -1126,7 +1176,7 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr )
             }
             if ( mismatch ) {
                 _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, "XMLElement name=%s", ele->Name());
-                DeleteNode( node );
+                _document->DeleteNode( node );
                 break;
             }
         }
@@ -1637,8 +1687,18 @@ float XMLElement::FloatAttribute(const char* name, float defaultValue) const
 
 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;
 }
@@ -1748,11 +1808,11 @@ XMLError XMLElement::QueryInt64Text(int64_t* ival) const
 }
 
 
-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;
@@ -1909,7 +1969,7 @@ char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr )
         }
 
         // attribute.
-        if (XMLUtil::IsNameStartChar( (unsigned char) *p ) ) {
+        if (XMLUtil::IsNameStartChar( static_cast<unsigned char>(*p) ) ) {
             XMLAttribute* attrib = CreateAttribute();
             TIXMLASSERT( attrib );
             attrib->_parseLineNum = _document->_parseCurLineNum;
@@ -2153,7 +2213,7 @@ void XMLDocument::MarkInUse(const XMLNode* const node)
        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;
@@ -2384,21 +2444,21 @@ XMLError XMLDocument::SaveFile( FILE* fp, bool compact )
 }
 
 
-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() ) {
@@ -2427,9 +2487,16 @@ void XMLDocument::Print( XMLPrinter* streamer ) const
 }
 
 
+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();
@@ -2438,7 +2505,8 @@ void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ...
     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);