From 338103324096b78ae4718f97ac2150c4bb98c2d1 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Fri, 21 Jun 2019 20:15:15 +0200 Subject: [PATCH] XMLConverter: replace tinyxml by pugixml the former is unmaintained and has an arcane API --- Tools/XMLConverter/CMakeLists.txt | 26 +- .../include/OgreXMLMeshSerializer.h | 64 +- .../include/OgreXMLPrerequisites.h | 2 +- .../include/OgreXMLSkeletonSerializer.h | 29 +- Tools/XMLConverter/include/tinystr.h | 305 --- Tools/XMLConverter/include/tinyxml.h | 1805 ---------------- .../src/OgreXMLMeshSerializer.cpp | 1012 ++++----- .../src/OgreXMLSkeletonSerializer.cpp | 316 ++- Tools/XMLConverter/src/main.cpp | 19 +- Tools/XMLConverter/src/tinystr.cpp | 111 - Tools/XMLConverter/src/tinyxml.cpp | 1886 ----------------- Tools/XMLConverter/src/tinyxmlerror.cpp | 52 - Tools/XMLConverter/src/tinyxmlparser.cpp | 1638 -------------- 13 files changed, 645 insertions(+), 6620 deletions(-) delete mode 100644 Tools/XMLConverter/include/tinystr.h delete mode 100644 Tools/XMLConverter/include/tinyxml.h delete mode 100644 Tools/XMLConverter/src/tinystr.cpp delete mode 100644 Tools/XMLConverter/src/tinyxml.cpp delete mode 100644 Tools/XMLConverter/src/tinyxmlerror.cpp delete mode 100644 Tools/XMLConverter/src/tinyxmlparser.cpp diff --git a/Tools/XMLConverter/CMakeLists.txt b/Tools/XMLConverter/CMakeLists.txt index 7e697895cd4..0ea3c5df864 100644 --- a/Tools/XMLConverter/CMakeLists.txt +++ b/Tools/XMLConverter/CMakeLists.txt @@ -21,31 +21,13 @@ set(SOURCE_FILES src/OgreXMLSkeletonSerializer.cpp ) -# If TinyXML is not found on the system use the embedded version. -if(NOT TINYXML_FOUND) - list(APPEND SOURCE_FILES - src/tinystr.cpp - src/tinyxml.cpp - src/tinyxmlerror.cpp - src/tinyxmlparser.cpp) +# allow override by cmake +find_package(pugixml) - list(APPEND HEADER_FILES - include/tinystr.h - include/tinyxml.h) - - set(TINYXML_INCLUDE_DIR "") - set(TINYXML_LIBRARIES "") -endif(NOT TINYXML_FOUND) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include ${TINYXML_INCLUDE_DIR}) -add_definitions(-DTIXML_USE_STL) - -if(UNIX) - add_definitions(-Wno-shadow -Wno-implicit-fallthrough) # inside tinyxml sources -endif() +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) add_executable(OgreXMLConverter ${HEADER_FILES} ${SOURCE_FILES}) -target_link_libraries(OgreXMLConverter ${OGRE_LIBRARIES} ${TINYXML_LIBRARIES} ${OGRE_MeshLodGenerator_LIBRARIES}) +target_link_libraries(OgreXMLConverter ${OGRE_LIBRARIES} pugixml ${OGRE_MeshLodGenerator_LIBRARIES}) if (APPLE) set_target_properties(OgreXMLConverter PROPERTIES diff --git a/Tools/XMLConverter/include/OgreXMLMeshSerializer.h b/Tools/XMLConverter/include/OgreXMLMeshSerializer.h index e32687bb9a9..3526724169c 100644 --- a/Tools/XMLConverter/include/OgreXMLMeshSerializer.h +++ b/Tools/XMLConverter/include/OgreXMLMeshSerializer.h @@ -63,48 +63,46 @@ namespace Ogre { void exportMesh(const Mesh* pMesh, const String& filename); protected: - // State for export - TiXmlDocument* mXMLDoc; // State for import Mesh* mMesh; VertexElementType mColourElementType; // Internal methods - void writeMesh(const Mesh* pMesh); - void writeSubMesh(TiXmlElement* mSubmeshesNode, const SubMesh* s); - void writeGeometry(TiXmlElement* mParentNode, const VertexData* pData); - void writeSkeletonLink(TiXmlElement* mMeshNode, const String& skelName); - void writeBoneAssignment(TiXmlElement* mBoneAssignNode, const VertexBoneAssignment* assign); - void writeTextureAliases(TiXmlElement* mSubmeshesNode, const SubMesh* s); - void writeLodInfo(TiXmlElement* mMeshNode, const Mesh* pMesh); - void writeLodUsageManual(TiXmlElement* usageNode, unsigned short levelNum, + void writeMesh(const Mesh* pMesh, pugi::xml_node& rootNode); + void writeSubMesh(pugi::xml_node& mSubmeshesNode, const SubMesh* s); + void writeGeometry(pugi::xml_node& mParentNode, const VertexData* pData); + void writeSkeletonLink(pugi::xml_node& mMeshNode, const String& skelName); + void writeBoneAssignment(pugi::xml_node& mBoneAssignNode, const VertexBoneAssignment* assign); + void writeTextureAliases(pugi::xml_node& mSubmeshesNode, const SubMesh* s); + void writeLodInfo(pugi::xml_node& mMeshNode, const Mesh* pMesh); + void writeLodUsageManual(pugi::xml_node& usageNode, unsigned short levelNum, const MeshLodUsage& usage); - void writeLodUsageGenerated(TiXmlElement* usageNode, unsigned short levelNum, + void writeLodUsageGenerated(pugi::xml_node& usageNode, unsigned short levelNum, const MeshLodUsage& usage, const Mesh* pMesh); - void writeSubMeshNames(TiXmlElement* mMeshNode, const Mesh* m); - void writePoses(TiXmlElement* meshNode, const Mesh* m); - void writeAnimations(TiXmlElement* meshNode, const Mesh* m); - void writeMorphKeyFrames(TiXmlElement* trackNode, const VertexAnimationTrack* track); - void writePoseKeyFrames(TiXmlElement* trackNode, const VertexAnimationTrack* track); - void writeExtremes(TiXmlElement* mMeshNode, const Mesh* m); + void writeSubMeshNames(pugi::xml_node& mMeshNode, const Mesh* m); + void writePoses(pugi::xml_node& meshNode, const Mesh* m); + void writeAnimations(pugi::xml_node& meshNode, const Mesh* m); + void writeMorphKeyFrames(pugi::xml_node& trackNode, const VertexAnimationTrack* track); + void writePoseKeyFrames(pugi::xml_node& trackNode, const VertexAnimationTrack* track); + void writeExtremes(pugi::xml_node& mMeshNode, const Mesh* m); - void readSubMeshes(TiXmlElement* mSubmeshesNode); - void readGeometry(TiXmlElement* mGeometryNode, VertexData* pData); - void readSkeletonLink(TiXmlElement* mSkelNode); - void readBoneAssignments(TiXmlElement* mBoneAssignmentsNode); - void readBoneAssignments(TiXmlElement* mBoneAssignmentsNode, SubMesh* sm); - void readTextureAliases(TiXmlElement* mTextureAliasesNode, SubMesh* sm); - void readLodInfo(TiXmlElement* lodNode); - void readLodUsageManual(TiXmlElement* manualNode, unsigned short index); - void readLodUsageGenerated(TiXmlElement* genNode, unsigned short index); - void readSubMeshNames(TiXmlElement* mMeshNamesNode, Mesh* sm); - void readPoses(TiXmlElement* posesNode, Mesh *m); - void readAnimations(TiXmlElement* mAnimationsNode, Mesh *m); - void readTracks(TiXmlElement* tracksNode, Mesh *m, Animation* anim); - void readMorphKeyFrames(TiXmlElement* keyframesNode, VertexAnimationTrack* track, + void readSubMeshes(pugi::xml_node& mSubmeshesNode); + void readGeometry(pugi::xml_node& mGeometryNode, VertexData* pData); + void readSkeletonLink(pugi::xml_node& mSkelNode); + void readBoneAssignments(pugi::xml_node& mBoneAssignmentsNode); + void readBoneAssignments(pugi::xml_node& mBoneAssignmentsNode, SubMesh* sm); + void readTextureAliases(pugi::xml_node& mTextureAliasesNode, SubMesh* sm); + void readLodInfo(pugi::xml_node& lodNode); + void readLodUsageManual(pugi::xml_node& manualNode, unsigned short index); + void readLodUsageGenerated(pugi::xml_node& genNode, unsigned short index); + void readSubMeshNames(pugi::xml_node& mMeshNamesNode, Mesh* sm); + void readPoses(pugi::xml_node& posesNode, Mesh *m); + void readAnimations(pugi::xml_node& mAnimationsNode, Mesh *m); + void readTracks(pugi::xml_node& tracksNode, Mesh *m, Animation* anim); + void readMorphKeyFrames(pugi::xml_node& keyframesNode, VertexAnimationTrack* track, size_t vertexCount); - void readPoseKeyFrames(TiXmlElement* keyframesNode, VertexAnimationTrack* track); - void readExtremes(TiXmlElement* extremesNode, Mesh *m); + void readPoseKeyFrames(pugi::xml_node& keyframesNode, VertexAnimationTrack* track); + void readExtremes(pugi::xml_node& extremesNode, Mesh *m); }; } diff --git a/Tools/XMLConverter/include/OgreXMLPrerequisites.h b/Tools/XMLConverter/include/OgreXMLPrerequisites.h index 5577ea22259..c4287595468 100644 --- a/Tools/XMLConverter/include/OgreXMLPrerequisites.h +++ b/Tools/XMLConverter/include/OgreXMLPrerequisites.h @@ -32,7 +32,7 @@ THE SOFTWARE. #include "OgrePrerequisites.h" // Include tinyxml headers -#include "tinyxml.h" +#include #endif diff --git a/Tools/XMLConverter/include/OgreXMLSkeletonSerializer.h b/Tools/XMLConverter/include/OgreXMLSkeletonSerializer.h index 910f45cfcad..02e4105cb83 100644 --- a/Tools/XMLConverter/include/OgreXMLSkeletonSerializer.h +++ b/Tools/XMLConverter/include/OgreXMLSkeletonSerializer.h @@ -63,25 +63,22 @@ namespace Ogre { void exportSkeleton(const Skeleton* pSkeleton, const String& filename); private: - // State for export - TiXmlDocument* mXMLDoc; - - void writeSkeleton(const Skeleton* pSkel); - void writeBone(TiXmlElement* bonesElement, const Bone* pBone); - void writeBoneParent(TiXmlElement* boneHierarchyNode, String boneName , String parentName); - void writeAnimation(TiXmlElement* animsNode, const Animation* anim); - void writeAnimationTrack(TiXmlElement* tracksNode, + void writeSkeleton(const Skeleton* pSkel, pugi::xml_node& root); + void writeBone(pugi::xml_node& bonesElement, const Bone* pBone); + void writeBoneParent(pugi::xml_node& boneHierarchyNode, String boneName , String parentName); + void writeAnimation(pugi::xml_node& animsNode, const Animation* anim); + void writeAnimationTrack(pugi::xml_node& tracksNode, const NodeAnimationTrack* track); - void writeKeyFrame(TiXmlElement* keysNode, const TransformKeyFrame* key); - void writeSkeletonAnimationLink(TiXmlElement* linksNode, + void writeKeyFrame(pugi::xml_node& keysNode, const TransformKeyFrame* key); + void writeSkeletonAnimationLink(pugi::xml_node& linksNode, const LinkedSkeletonAnimationSource& link); - void readBones(Skeleton* skel, TiXmlElement* mBonesNode); - void readBones2(Skeleton* skel, TiXmlElement* mBonesNode); - void createHierarchy(Skeleton* skel, TiXmlElement* mHierNode); - void readKeyFrames(NodeAnimationTrack* track, TiXmlElement* mKeyfNode); - void readAnimations(Skeleton* skel, TiXmlElement* mAnimNode) ; - void readSkeletonAnimationLinks(Skeleton* skel, TiXmlElement* linksNode); + void readBones(Skeleton* skel, pugi::xml_node& mBonesNode); + void readBones2(Skeleton* skel, pugi::xml_node& mBonesNode); + void createHierarchy(Skeleton* skel, pugi::xml_node& mHierNode); + void readKeyFrames(NodeAnimationTrack* track, const pugi::xml_node& mKeyfNode); + void readAnimations(Skeleton* skel, pugi::xml_node& mAnimNode) ; + void readSkeletonAnimationLinks(Skeleton* skel, pugi::xml_node& linksNode); }; diff --git a/Tools/XMLConverter/include/tinystr.h b/Tools/XMLConverter/include/tinystr.h deleted file mode 100644 index 89cca334156..00000000000 --- a/Tools/XMLConverter/include/tinystr.h +++ /dev/null @@ -1,305 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - - -#ifndef TIXML_USE_STL - -#ifndef TIXML_STRING_INCLUDED -#define TIXML_STRING_INCLUDED - -#include -#include - -/* The support for explicit isn't that universal, and it isn't really - required - it is used to check that the TiXmlString class isn't incorrectly - used. Be nice to old compilers and macro it here: -*/ -#if defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - #define TIXML_EXPLICIT explicit -#elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - #define TIXML_EXPLICIT explicit -#else - #define TIXML_EXPLICIT -#endif - - -/* - TiXmlString is an emulation of a subset of the std::string template. - Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. - Only the member functions relevant to the TinyXML project have been implemented. - The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase - a string and there's no more room, we allocate a buffer twice as big as we need. -*/ -class TiXmlString -{ - public : - // The size type used - typedef size_t size_type; - - // Error value for find primitive - static const size_type npos; // = -1; - - - // TiXmlString empty constructor - TiXmlString () : rep_(&nullrep_) - { - } - - // TiXmlString copy constructor - TiXmlString ( const TiXmlString & copy) : rep_(0) - { - init(copy.length()); - memcpy(start(), copy.data(), length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) - { - init( static_cast( strlen(copy) )); - memcpy(start(), copy, length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) - { - init(len); - memcpy(start(), str, len); - } - - // TiXmlString destructor - ~TiXmlString () - { - quit(); - } - - TiXmlString& operator = (const char * copy) - { - return assign( copy, (size_type)strlen(copy)); - } - - TiXmlString& operator = (const TiXmlString & copy) - { - return assign(copy.start(), copy.length()); - } - - - // += operator. Maps to append - TiXmlString& operator += (const char * suffix) - { - return append(suffix, static_cast( strlen(suffix) )); - } - - // += operator. Maps to append - TiXmlString& operator += (char single) - { - return append(&single, 1); - } - - // += operator. Maps to append - TiXmlString& operator += (const TiXmlString & suffix) - { - return append(suffix.data(), suffix.length()); - } - - - // Convert a TiXmlString into a null-terminated char * - const char * c_str () const { return rep_->str; } - - // Convert a TiXmlString into a char * (need not be null terminated). - const char * data () const { return rep_->str; } - - // Return the length of a TiXmlString - size_type length () const { return rep_->size; } - - // Alias for length() - size_type size () const { return rep_->size; } - - // Checks if a TiXmlString is empty - bool empty () const { return rep_->size == 0; } - - // Return capacity of string - size_type capacity () const { return rep_->capacity; } - - - // single char extraction - const char& at (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // [] operator - char& operator [] (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // find a char in a string. Return TiXmlString::npos if not found - size_type find (char lookup) const - { - return find(lookup, 0); - } - - // find a char in a string from an offset. Return TiXmlString::npos if not found - size_type find (char tofind, size_type offset) const - { - if (offset >= length()) return npos; - - for (const char* p = c_str() + offset; *p != '\0'; ++p) - { - if (*p == tofind) return static_cast< size_type >( p - c_str() ); - } - return npos; - } - - void clear () - { - //Lee: - //The original was just too strange, though correct: - // TiXmlString().swap(*this); - //Instead use the quit & re-init: - quit(); - init(0,0); - } - - /* Function to reserve a big amount of data when we know we'll need it. Be aware that this - function DOES NOT clear the content of the TiXmlString if any exists. - */ - void reserve (size_type cap); - - TiXmlString& assign (const char* str, size_type len); - - TiXmlString& append (const char* str, size_type len); - - void swap (TiXmlString& other) - { - Rep* r = rep_; - rep_ = other.rep_; - other.rep_ = r; - } - - private: - - void init(size_type sz) { init(sz, sz); } - void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } - char* start() const { return rep_->str; } - char* finish() const { return rep_->str + rep_->size; } - - struct Rep - { - size_type size, capacity; - char str[1]; - }; - - void init(size_type sz, size_type cap) - { - if (cap) - { - // Lee: the original form: - // rep_ = static_cast(operator new(sizeof(Rep) + cap)); - // doesn't work in some cases of new being overloaded. Switching - // to the normal allocation, although use an 'int' for systems - // that are overly picky about structure alignment. - const size_type bytesNeeded = sizeof(Rep) + cap; - const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); - rep_ = reinterpret_cast( new int[ intsNeeded ] ); - - rep_->str[ rep_->size = sz ] = '\0'; - rep_->capacity = cap; - } - else - { - rep_ = &nullrep_; - } - } - - void quit() - { - if (rep_ != &nullrep_) - { - // The rep_ is really an array of ints. (see the allocator, above). - // Cast it back before delete, so the compiler won't incorrectly call destructors. - delete [] ( reinterpret_cast( rep_ ) ); - } - } - - Rep * rep_; - static Rep nullrep_; - -} ; - - -inline bool operator == (const TiXmlString & a, const TiXmlString & b) -{ - return ( a.length() == b.length() ) // optimization on some platforms - && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare -} -inline bool operator < (const TiXmlString & a, const TiXmlString & b) -{ - return strcmp(a.c_str(), b.c_str()) < 0; -} - -inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } -inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } -inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } -inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } - -inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } -inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } -inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } -inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); -TiXmlString operator + (const TiXmlString & a, const char* b); -TiXmlString operator + (const char* a, const TiXmlString & b); - - -/* - TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. - Only the operators that we need for TinyXML have been developped. -*/ -class TiXmlOutStream : public TiXmlString -{ -public : - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const TiXmlString & in) - { - *this += in; - return *this; - } - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const char * in) - { - *this += in; - return *this; - } - -} ; - -#endif // TIXML_STRING_INCLUDED -#endif // TIXML_USE_STL diff --git a/Tools/XMLConverter/include/tinyxml.h b/Tools/XMLConverter/include/tinyxml.h deleted file mode 100644 index a3589e5b269..00000000000 --- a/Tools/XMLConverter/include/tinyxml.h +++ /dev/null @@ -1,1805 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code by Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - - -#ifndef TINYXML_INCLUDED -#define TINYXML_INCLUDED - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4530 ) -#pragma warning( disable : 4786 ) -#endif - -#include -#include -#include -#include -#include - -// Help out windows: -#if defined( _DEBUG ) && !defined( DEBUG ) -#define DEBUG -#endif - -#ifdef TIXML_USE_STL - #include - #include - #include - #define TIXML_STRING std::string -#else - #include "tinystr.h" - #define TIXML_STRING TiXmlString -#endif - -// Deprecated library function hell. Compilers want to use the -// new safe versions. This probably doesn't fully address the problem, -// but it gets closer. There are too many compilers for me to fully -// test. If you get compilation troubles, undefine TIXML_SAFE -#define TIXML_SAFE - -#ifdef TIXML_SAFE - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - // Microsoft visual studio, version 2005 and higher. - #define TIXML_SNPRINTF _snprintf_s - #define TIXML_SSCANF sscanf_s - #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - //#pragma message( "Using _sn* functions." ) - #define TIXML_SNPRINTF _snprintf - #define TIXML_SSCANF sscanf - #elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - //#warning( "Using sn* functions." ) - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf - #else - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf - #endif -#endif - -class TiXmlDocument; -class TiXmlElement; -class TiXmlComment; -class TiXmlUnknown; -class TiXmlAttribute; -class TiXmlText; -class TiXmlDeclaration; -class TiXmlParsingData; - -const int TIXML_MAJOR_VERSION = 2; -const int TIXML_MINOR_VERSION = 6; -const int TIXML_PATCH_VERSION = 2; - -/* Internal structure for tracking location of items - in the XML file. -*/ -struct TiXmlCursor -{ - TiXmlCursor() { Clear(); } - void Clear() { row = col = -1; } - - int row; // 0 based. - int col; // 0 based. -}; - - -/** - Implements the interface to the "Visitor pattern" (see the Accept() method.) - If you call the Accept() method, it requires being passed a TiXmlVisitor - class to handle callbacks. For nodes that contain other nodes (Document, Element) - you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves - are simply called with Visit(). - - If you return 'true' from a Visit method, recursive parsing will continue. If you return - false, no children of this node or its sibilings will be Visited. - - All flavors of Visit methods have a default implementation that returns 'true' (continue - visiting). You need to only override methods that are interesting to you. - - Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. - - You should never change the document from a callback. - - @sa TiXmlNode::Accept() -*/ -class TiXmlVisitor -{ -public: - virtual ~TiXmlVisitor() {} - - /// Visit a document. - virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } - /// Visit a document. - virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } - - /// Visit an element. - virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } - /// Visit an element. - virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } - - /// Visit a declaration - virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } - /// Visit a text node - virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } - /// Visit a comment node - virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } - /// Visit an unknown node - virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } -}; - -// Only used by Attribute::Query functions -enum -{ - TIXML_SUCCESS, - TIXML_NO_ATTRIBUTE, - TIXML_WRONG_TYPE -}; - - -// Used by the parsing routines. -enum TiXmlEncoding -{ - TIXML_ENCODING_UNKNOWN, - TIXML_ENCODING_UTF8, - TIXML_ENCODING_LEGACY -}; - -const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; - -/** TiXmlBase is a base class for every class in TinyXml. - It does little except to establish that TinyXml classes - can be printed and provide some utility functions. - - In XML, the document and elements can contain - other elements and other types of nodes. - - @verbatim - A Document can contain: Element (container or leaf) - Comment (leaf) - Unknown (leaf) - Declaration( leaf ) - - An Element can contain: Element (container or leaf) - Text (leaf) - Attributes (not on tree) - Comment (leaf) - Unknown (leaf) - - A Decleration contains: Attributes (not on tree) - @endverbatim -*/ -class TiXmlBase -{ - friend class TiXmlNode; - friend class TiXmlElement; - friend class TiXmlDocument; - -public: - TiXmlBase() : userData(0) {} - virtual ~TiXmlBase() {} - - /** All TinyXml classes can print themselves to a filestream - or the string class (TiXmlString in non-STL mode, std::string - in STL mode.) Either or both cfile and str can be null. - - This is a formatted print, and will insert - tabs and newlines. - - (For an unformatted stream, use the << operator.) - */ - virtual void Print( FILE* cfile, int depth ) const = 0; - - /** The world does not agree on whether white space should be kept or - not. In order to make everyone happy, these global, static functions - are provided to set whether or not TinyXml will condense all white space - into a single space or not. The default is to condense. Note changing this - value is not thread safe. - */ - static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } - - /// Return the current white space setting. - static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } - - /** Return the position, in the original source file, of this node or attribute. - The row and column are 1-based. (That is the first row and first column is - 1,1). If the returns values are 0 or less, then the parser does not have - a row and column value. - - Generally, the row and column value will be set when the TiXmlDocument::Load(), - TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set - when the DOM was created from operator>>. - - The values reflect the initial load. Once the DOM is modified programmatically - (by adding or changing nodes and attributes) the new values will NOT update to - reflect changes in the document. - - There is a minor performance cost to computing the row and column. Computation - can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. - - @sa TiXmlDocument::SetTabSize() - */ - int Row() const { return location.row + 1; } - int Column() const { return location.col + 1; } ///< See Row() - - void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. - void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. - const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. - - // Table that returs, for a given lead byte, the total number of bytes - // in the UTF-8 sequence. - static const int utf8ByteTable[256]; - - virtual const char* Parse( const char* p, - TiXmlParsingData* data, - TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; - - /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, - or they will be transformed into entities! - */ - static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); - - enum - { - TIXML_NO_ERROR = 0, - TIXML_ERROR, - TIXML_ERROR_OPENING_FILE, - TIXML_ERROR_PARSING_ELEMENT, - TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, - TIXML_ERROR_READING_ELEMENT_VALUE, - TIXML_ERROR_READING_ATTRIBUTES, - TIXML_ERROR_PARSING_EMPTY, - TIXML_ERROR_READING_END_TAG, - TIXML_ERROR_PARSING_UNKNOWN, - TIXML_ERROR_PARSING_COMMENT, - TIXML_ERROR_PARSING_DECLARATION, - TIXML_ERROR_DOCUMENT_EMPTY, - TIXML_ERROR_EMBEDDED_NULL, - TIXML_ERROR_PARSING_CDATA, - TIXML_ERROR_DOCUMENT_TOP_ONLY, - - TIXML_ERROR_STRING_COUNT - }; - -protected: - - static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); - - inline static bool IsWhiteSpace( char c ) - { - return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); - } - inline static bool IsWhiteSpace( int c ) - { - if ( c < 256 ) - return IsWhiteSpace( (char) c ); - return false; // Again, only truly correct for English/Latin...but usually works. - } - - #ifdef TIXML_USE_STL - static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); - static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); - #endif - - /* Reads an XML name into the string provided. Returns - a pointer just past the last character of the name, - or 0 if the function has an error. - */ - static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); - - /* Reads text. Returns a pointer past the given end tag. - Wickedly complex options, but it keeps the (sensitive) code in one place. - */ - static const char* ReadText( const char* in, // where to start - TIXML_STRING* text, // the string read - bool ignoreWhiteSpace, // whether to keep the white space - const char* endTag, // what ends this text - bool ignoreCase, // whether to ignore case in the end tag - TiXmlEncoding encoding ); // the current encoding - - // If an entity has been found, transform it into a character. - static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); - - // Get a character, while interpreting entities. - // The length can be from 0 to 4 bytes. - inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) - { - assert( p ); - if ( encoding == TIXML_ENCODING_UTF8 ) - { - *length = utf8ByteTable[ *((const unsigned char*)p) ]; - assert( *length >= 0 && *length < 5 ); - } - else - { - *length = 1; - } - - if ( *length == 1 ) - { - if ( *p == '&' ) - return GetEntity( p, _value, length, encoding ); - *_value = *p; - return p+1; - } - else if ( *length ) - { - //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), - // and the null terminator isn't needed - for( int i=0; p[i] && i<*length; ++i ) { - _value[i] = p[i]; - } - return p + (*length); - } - else - { - // Not valid text. - return 0; - } - } - - // Return true if the next characters in the stream are any of the endTag sequences. - // Ignore case only works for english, and should only be relied on when comparing - // to English words: StringEqual( p, "version", true ) is fine. - static bool StringEqual( const char* p, - const char* endTag, - bool ignoreCase, - TiXmlEncoding encoding ); - - static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; - - TiXmlCursor location; - - /// Field containing a generic user pointer - void* userData; - - // None of these methods are reliable for any language except English. - // Good for approximation, not great for accuracy. - static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); - static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); - inline static int ToLower( int v, TiXmlEncoding encoding ) - { - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( v < 128 ) return tolower( v ); - return v; - } - else - { - return tolower( v ); - } - } - static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); - -private: - TiXmlBase( const TiXmlBase& ); // not implemented. - void operator=( const TiXmlBase& base ); // not allowed. - - struct Entity - { - const char* str; - unsigned int strLength; - char chr; - }; - enum - { - NUM_ENTITY = 5, - MAX_ENTITY_LENGTH = 6 - - }; - static Entity entity[ NUM_ENTITY ]; - static bool condenseWhiteSpace; -}; - - -/** The parent class for everything in the Document Object Model. - (Except for attributes). - Nodes have siblings, a parent, and children. A node can be - in a document, or stand on its own. The type of a TiXmlNode - can be queried, and it can be cast to its more defined type. -*/ -class TiXmlNode : public TiXmlBase -{ - friend class TiXmlDocument; - friend class TiXmlElement; - -public: - #ifdef TIXML_USE_STL - - /** An input stream operator, for every class. Tolerant of newlines and - formatting, but doesn't expect them. - */ - friend std::istream& operator >> (std::istream& in, TiXmlNode& base); - - /** An output stream operator, for every class. Note that this outputs - without any newlines or formatting, as opposed to Print(), which - includes tabs and new lines. - - The operator<< and operator>> are not completely symmetric. Writing - a node to a stream is very well defined. You'll get a nice stream - of output, without any extra whitespace or newlines. - - But reading is not as well defined. (As it always is.) If you create - a TiXmlElement (for example) and read that from an input stream, - the text needs to define an element or junk will result. This is - true of all input streams, but it's worth keeping in mind. - - A TiXmlDocument will read nodes until it reads a root element, and - all the children of that root element. - */ - friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); - - /// Appends the XML node or attribute to a std::string. - friend std::string& operator<< (std::string& out, const TiXmlNode& base ); - - #endif - - /** The types of XML nodes supported by TinyXml. (All the - unsupported types are picked up by UNKNOWN.) - */ - enum NodeType - { - TINYXML_DOCUMENT, - TINYXML_ELEMENT, - TINYXML_COMMENT, - TINYXML_UNKNOWN, - TINYXML_TEXT, - TINYXML_DECLARATION, - TINYXML_TYPECOUNT - }; - - virtual ~TiXmlNode(); - - /** The meaning of 'value' changes for the specific type of - TiXmlNode. - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - - The subclasses will wrap this function. - */ - const char *Value() const { return value.c_str (); } - - #ifdef TIXML_USE_STL - /** Return Value() as a std::string. If you only use STL, - this is more efficient than calling Value(). - Only available in STL mode. - */ - const std::string& ValueStr() const { return value; } - #endif - - const TIXML_STRING& ValueTStr() const { return value; } - - /** Changes the value of the node. Defined as: - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - */ - void SetValue(const char * _value) { value = _value;} - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Delete all the children of this node. Does not affect 'this'. - void Clear(); - - /// One step up the DOM. - TiXmlNode* Parent() { return parent; } - const TiXmlNode* Parent() const { return parent; } - - const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. - TiXmlNode* FirstChild() { return firstChild; } - const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. - /// The first child of this node with the matching 'value'. Will be null if none found. - TiXmlNode* FirstChild( const char * _value ) { - // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) - // call the method, cast the return back to non-const. - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); - } - const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. - TiXmlNode* LastChild() { return lastChild; } - - const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. - TiXmlNode* LastChild( const char * _value ) { - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. - #endif - - /** An alternate way to walk the children of a node. - One way to iterate over nodes is: - @verbatim - for( child = parent->FirstChild(); child; child = child->NextSibling() ) - @endverbatim - - IterateChildren does the same thing with the syntax: - @verbatim - child = 0; - while( child = parent->IterateChildren( child ) ) - @endverbatim - - IterateChildren takes the previous child as input and finds - the next one. If the previous child is null, it returns the - first. IterateChildren will return null when done. - */ - const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); - } - - /// This flavor of IterateChildren searches for children with a particular 'value' - const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - #endif - - /** Add a new node related to this. Adds a child past the LastChild. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); - - - /** Add a new node related to this. Adds a child past the LastChild. - - NOTE: the node to be added is passed by pointer, and will be - henceforth owned (and deleted) by tinyXml. This method is efficient - and avoids an extra copy, but should be used with care as it - uses a different memory model than the other insert functions. - - @sa InsertEndChild - */ - TiXmlNode* LinkEndChild( TiXmlNode* addThis ); - - /** Add a new node related to this. Adds a child before the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); - - /** Add a new node related to this. Adds a child after the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); - - /** Replace a child of this node. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); - - /// Delete a child of this node. - bool RemoveChild( TiXmlNode* removeThis ); - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling() const { return prev; } - TiXmlNode* PreviousSibling() { return prev; } - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling( const char * ) const; - TiXmlNode* PreviousSibling( const char *_prev ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Navigate to a sibling node. - const TiXmlNode* NextSibling() const { return next; } - TiXmlNode* NextSibling() { return next; } - - /// Navigate to a sibling node with the given 'value'. - const TiXmlNode* NextSibling( const char * ) const; - TiXmlNode* NextSibling( const char* _next ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement() const; - TiXmlElement* NextSiblingElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement( const char * ) const; - TiXmlElement* NextSiblingElement( const char *_next ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement() const; - TiXmlElement* FirstChildElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); - } - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement( const char * _value ) const; - TiXmlElement* FirstChildElement( const char * _value ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /** Query the type (as an enumerated value, above) of this node. - The possible types are: TINYXML_DOCUMENT, TINYXML_ELEMENT, TINYXML_COMMENT, - TINYXML_UNKNOWN, TINYXML_TEXT, and TINYXML_DECLARATION. - */ - int Type() const { return type; } - - /** Return a pointer to the Document this node lives in. - Returns null if not in a document. - */ - const TiXmlDocument* GetDocument() const; - TiXmlDocument* GetDocument() { - return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); - } - - /// Returns true if this node has no children. - bool NoChildren() const { return !firstChild; } - - virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - /** Create an exact duplicate of this node and return it. The memory must be deleted - by the caller. - */ - virtual TiXmlNode* Clone() const = 0; - - /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the - XML tree will be conditionally visited and the host will be called back - via the TiXmlVisitor interface. - - This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse - the XML for the callbacks, so the performance of TinyXML is unchanged by using this - interface versus any other.) - - The interface has been based on ideas from: - - - http://www.saxproject.org/ - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern - - Which are both good references for "visiting". - - An example of using Accept(): - @verbatim - TiXmlPrinter printer; - tinyxmlDoc.Accept( &printer ); - const char* xmlcstr = printer.CStr(); - @endverbatim - */ - virtual bool Accept( TiXmlVisitor* visitor ) const = 0; - -protected: - TiXmlNode( NodeType _type ); - - // Copy to the allocated object. Shared functionality between Clone, Copy constructor, - // and the assignment operator. - void CopyTo( TiXmlNode* target ) const; - - #ifdef TIXML_USE_STL - // The real work of the input operator. - virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; - #endif - - // Figure out what is at *p, and parse it. Returns null if it is not an xml node. - TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); - - TiXmlNode* parent; - NodeType type; - - TiXmlNode* firstChild; - TiXmlNode* lastChild; - - TIXML_STRING value; - - TiXmlNode* prev; - TiXmlNode* next; - -private: - TiXmlNode( const TiXmlNode& ); // not implemented. - void operator=( const TiXmlNode& base ); // not allowed. -}; - - -/** An attribute is a name-value pair. Elements have an arbitrary - number of attributes, each with a unique name. - - @note The attributes are not TiXmlNodes, since they are not - part of the tinyXML document object model. There are other - suggested ways to look at this problem. -*/ -class TiXmlAttribute : public TiXmlBase -{ - friend class TiXmlAttributeSet; - -public: - /// Construct an empty attribute. - TiXmlAttribute() : TiXmlBase() - { - document = 0; - prev = next = 0; - } - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlAttribute( const std::string& _name, const std::string& _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - #endif - - /// Construct an attribute with a name and value. - TiXmlAttribute( const char * _name, const char * _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - - const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. - const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. - #ifdef TIXML_USE_STL - const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. - #endif - int IntValue() const; ///< Return the value of this attribute, converted to an integer. - double DoubleValue() const; ///< Return the value of this attribute, converted to a double. - - // Get the tinyxml string representation - const TIXML_STRING& NameTStr() const { return name; } - - /** QueryIntValue examines the value string. It is an alternative to the - IntValue() method with richer error checking. - If the value is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. - - A specialized but useful call. Note that for success it returns 0, - which is the opposite of almost all other TinyXml calls. - */ - int QueryIntValue( int* _value ) const; - /// QueryDoubleValue examines the value string. See QueryIntValue(). - int QueryDoubleValue( double* _value ) const; - - void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. - void SetValue( const char* _value ) { value = _value; } ///< Set the value. - - void SetIntValue( int _value ); ///< Set the value from an integer. - void SetDoubleValue( double _value ); ///< Set the value from a double. - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetName( const std::string& _name ) { name = _name; } - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Get the next sibling attribute in the DOM. Returns null at end. - const TiXmlAttribute* Next() const; - TiXmlAttribute* Next() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); - } - - /// Get the previous sibling attribute in the DOM. Returns null at beginning. - const TiXmlAttribute* Previous() const; - TiXmlAttribute* Previous() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); - } - - bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } - bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } - bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } - - /* Attribute parsing starts: first letter of the name - returns: the next char after the value end quote - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - // Prints this Attribute to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - - // [internal use] - // Set the document pointer so the attribute can report errors. - void SetDocument( TiXmlDocument* doc ) { document = doc; } - -private: - TiXmlAttribute( const TiXmlAttribute& ); // not implemented. - void operator=( const TiXmlAttribute& base ); // not allowed. - - TiXmlDocument* document; // A pointer back to a document, for error reporting. - TIXML_STRING name; - TIXML_STRING value; - TiXmlAttribute* prev; - TiXmlAttribute* next; -}; - - -/* A class used to manage a group of attributes. - It is only used internally, both by the ELEMENT and the DECLARATION. - - The set can be changed transparent to the Element and Declaration - classes that use it, but NOT transparent to the Attribute - which has to implement a next() and previous() method. Which makes - it a bit problematic and prevents the use of STL. - - This version is implemented with circular lists because: - - I like circular lists - - it demonstrates some independence from the (typical) doubly linked list. -*/ -class TiXmlAttributeSet -{ -public: - TiXmlAttributeSet(); - ~TiXmlAttributeSet(); - - void Add( TiXmlAttribute* attribute ); - void Remove( TiXmlAttribute* attribute ); - - const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - - TiXmlAttribute* Find( const char* _name ) const; - TiXmlAttribute* FindOrCreate( const char* _name ); - -# ifdef TIXML_USE_STL - TiXmlAttribute* Find( const std::string& _name ) const; - TiXmlAttribute* FindOrCreate( const std::string& _name ); -# endif - - -private: - //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), - //*ME: this class must be also use a hidden/disabled copy-constructor !!! - TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed - void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) - - TiXmlAttribute sentinel; -}; - - -/** The element is a container class. It has a value, the element name, - and can contain other elements, text, comments, and unknowns. - Elements also contain an arbitrary number of attributes. -*/ -class TiXmlElement : public TiXmlNode -{ -public: - /// Construct an element. - TiXmlElement (const char * in_value); - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlElement( const std::string& _value ); - #endif - - TiXmlElement( const TiXmlElement& ); - - TiXmlElement& operator=( const TiXmlElement& base ); - - virtual ~TiXmlElement(); - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - */ - const char* Attribute( const char* name ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an integer, - the integer value will be put in the return 'i', if 'i' - is non-null. - */ - const char* Attribute( const char* name, int* i ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an double, - the double value will be put in the return 'd', if 'd' - is non-null. - */ - const char* Attribute( const char* name, double* d ) const; - - /** QueryIntAttribute examines the attribute - it is an alternative to the - Attribute() method with richer error checking. - If the attribute is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. If the attribute - does not exist, then TIXML_NO_ATTRIBUTE is returned. - */ - int QueryIntAttribute( const char* name, int* _value ) const; - /// QueryUnsignedAttribute examines the attribute - see QueryIntAttribute(). - int QueryUnsignedAttribute( const char* name, unsigned* _value ) const; - /** QueryBoolAttribute examines the attribute - see QueryIntAttribute(). - Note that '1', 'true', or 'yes' are considered true, while '0', 'false' - and 'no' are considered false. - */ - int QueryBoolAttribute( const char* name, bool* _value ) const; - /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). - int QueryDoubleAttribute( const char* name, double* _value ) const; - /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). - int QueryFloatAttribute( const char* name, float* _value ) const { - double d; - int result = QueryDoubleAttribute( name, &d ); - if ( result == TIXML_SUCCESS ) { - *_value = (float)d; - } - return result; - } - - #ifdef TIXML_USE_STL - /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). - int QueryStringAttribute( const char* name, std::string* _value ) const { - const char* cstr = Attribute( name ); - if ( cstr ) { - *_value = std::string( cstr ); - return TIXML_SUCCESS; - } - return TIXML_NO_ATTRIBUTE; - } - - /** Template form of the attribute query which will try to read the - attribute into the specified type. Very easy, very powerful, but - be careful to make sure to call this with the correct type. - - NOTE: This method doesn't work correctly for 'string' types that contain spaces. - - @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE - */ - template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - std::stringstream sstream( node->ValueStr() ); - sstream >> *outValue; - if ( !sstream.fail() ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; - } - - int QueryValueAttribute( const std::string& name, std::string* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - *outValue = node->ValueStr(); - return TIXML_SUCCESS; - } - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char* name, const char * _value ); - - #ifdef TIXML_USE_STL - const std::string* Attribute( const std::string& name ) const; - const std::string* Attribute( const std::string& name, int* i ) const; - const std::string* Attribute( const std::string& name, double* d ) const; - int QueryIntAttribute( const std::string& name, int* _value ) const; - int QueryDoubleAttribute( const std::string& name, double* _value ) const; - - /// STL std::string form. - void SetAttribute( const std::string& name, const std::string& _value ); - ///< STL std::string form. - void SetAttribute( const std::string& name, int _value ); - ///< STL std::string form. - void SetDoubleAttribute( const std::string& name, double value ); - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char * name, int value ); - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetDoubleAttribute( const char * name, double value ); - - /** Deletes an attribute with the given name. - */ - void RemoveAttribute( const char * name ); - #ifdef TIXML_USE_STL - void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. - #endif - - const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. - TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } - const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. - TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, GetText() is limited compared to getting the TiXmlText child - and accessing it directly. - - If the first child of 'this' is a TiXmlText, the GetText() - returns the character string of the Text node, else null is returned. - - This is a convenient method for getting the text of simple contained text: - @verbatim - This is text - const char* str = fooElement->GetText(); - @endverbatim - - 'str' will be a pointer to "This is text". - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - This is text - @endverbatim - - then the value of str would be null. The first child node isn't a text node, it is - another element. From this XML: - @verbatim - This is text - @endverbatim - GetText() will return "This is ". - - WARNING: GetText() accesses a child node - don't become confused with the - similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are - safe type casts on the referenced node. - */ - const char* GetText() const; - - /// Creates a new Element and returns it - the returned element is a copy. - virtual TiXmlNode* Clone() const; - // Print the Element to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: next char past '<' - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - - void CopyTo( TiXmlElement* target ) const; - void ClearThis(); // like clear, but initializes 'this' object as well - - // Used to be public [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - /* [internal use] - Reads the "value" of the element -- another element, or text. - This should terminate with the current end tag. - */ - const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - -private: - TiXmlAttributeSet attributeSet; -}; - - -/** An XML comment. -*/ -class TiXmlComment : public TiXmlNode -{ -public: - /// Constructs an empty comment. - TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} - /// Construct a comment from text. - TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { - SetValue( _value ); - } - TiXmlComment( const TiXmlComment& ); - TiXmlComment& operator=( const TiXmlComment& base ); - - virtual ~TiXmlComment() {} - - /// Returns a copy of this Comment. - virtual TiXmlNode* Clone() const; - // Write this Comment to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: at the ! of the !-- - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlComment* target ) const; - - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif -// virtual void StreamOut( TIXML_OSTREAM * out ) const; - -private: - -}; - - -/** XML text. A text node can have 2 ways to output the next. "normal" output - and CDATA. It will default to the mode it was parsed from the XML file and - you generally want to leave it alone, but you can change the output mode with - SetCDATA() and query it with CDATA(). -*/ -class TiXmlText : public TiXmlNode -{ - friend class TiXmlElement; -public: - /** Constructor for text element. By default, it is treated as - normal, encoded text. If you want it be output as a CDATA text - element, set the parameter _cdata to 'true' - */ - TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) - { - SetValue( initValue ); - cdata = false; - } - virtual ~TiXmlText() {} - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) - { - SetValue( initValue ); - cdata = false; - } - #endif - - TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } - TiXmlText& operator=( const TiXmlText& base ) { base.CopyTo( this ); return *this; } - - // Write this text object to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /// Queries whether this represents text using a CDATA section. - bool CDATA() const { return cdata; } - /// Turns on or off a CDATA representation of text. - void SetCDATA( bool _cdata ) { cdata = _cdata; } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - /// [internal use] Creates a new Element and returns it. - virtual TiXmlNode* Clone() const; - void CopyTo( TiXmlText* target ) const; - - bool Blank() const; // returns true if all white space and new lines - // [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - bool cdata; // true if this should be input and output as a CDATA style text element -}; - - -/** In correct XML the declaration is the first entry in the file. - @verbatim - - @endverbatim - - TinyXml will happily read or write files without a declaration, - however. There are 3 possible attributes to the declaration: - version, encoding, and standalone. - - Note: In this version of the code, the attributes are - handled as special cases, not generic attributes, simply - because there can only be at most 3 and they are always the same. -*/ -class TiXmlDeclaration : public TiXmlNode -{ -public: - /// Construct an empty declaration. - TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} - -#ifdef TIXML_USE_STL - /// Constructor. - TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ); -#endif - - /// Construct. - TiXmlDeclaration( const char* _version, - const char* _encoding, - const char* _standalone ); - - TiXmlDeclaration( const TiXmlDeclaration& copy ); - TiXmlDeclaration& operator=( const TiXmlDeclaration& copy ); - - virtual ~TiXmlDeclaration() {} - - /// Version. Will return an empty string if none was found. - const char *Version() const { return version.c_str (); } - /// Encoding. Will return an empty string if none was found. - const char *Encoding() const { return encoding.c_str (); } - /// Is this a standalone document? - const char *Standalone() const { return standalone.c_str (); } - - /// Creates a copy of this Declaration and returns it. - virtual TiXmlNode* Clone() const; - // Print this declaration to a FILE stream. - virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlDeclaration* target ) const; - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - - TIXML_STRING version; - TIXML_STRING encoding; - TIXML_STRING standalone; -}; - - -/** Any tag that tinyXml doesn't recognize is saved as an - unknown. It is a tag of text, but should not be modified. - It will be written back to the XML, unchanged, when the file - is saved. - - DTD tags get thrown into TiXmlUnknowns. -*/ -class TiXmlUnknown : public TiXmlNode -{ -public: - TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} - virtual ~TiXmlUnknown() {} - - TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } - TiXmlUnknown& operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); return *this; } - - /// Creates a copy of this Unknown and returns it. - virtual TiXmlNode* Clone() const; - // Print this Unknown to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected: - void CopyTo( TiXmlUnknown* target ) const; - - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - -}; - - -/** Always the top level node. A document binds together all the - XML pieces. It can be saved, loaded, and printed to the screen. - The 'value' of a document node is the xml file name. -*/ -class TiXmlDocument : public TiXmlNode -{ -public: - /// Create an empty document, that has no name. - TiXmlDocument(); - /// Create a document with a name. The name of the document is also the filename of the xml. - TiXmlDocument( const char * documentName ); - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlDocument( const std::string& documentName ); - #endif - - TiXmlDocument( const TiXmlDocument& copy ); - TiXmlDocument& operator=( const TiXmlDocument& copy ); - - virtual ~TiXmlDocument() {} - - /** Load a file using the current document value. - Returns true if successful. Will delete any existing - document data before loading. - */ - bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the current document value. Returns true if successful. - bool SaveFile() const; - /// Load a file using the given filename. Returns true if successful. - bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given filename. Returns true if successful. - bool SaveFile( const char * filename ) const; - /** Load a file using the given FILE*. Returns true if successful. Note that this method - doesn't stream - the entire object pointed at by the FILE* - will be interpreted as an XML file. TinyXML doesn't stream in XML from the current - file location. Streaming may be added in the future. - */ - bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given FILE*. Returns true if successful. - bool SaveFile( FILE* ) const; - - #ifdef TIXML_USE_STL - bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. - { - return LoadFile( filename.c_str(), encoding ); - } - bool SaveFile( const std::string& filename ) const ///< STL std::string version. - { - return SaveFile( filename.c_str() ); - } - #endif - - /** Parse the given null terminated block of xml data. Passing in an encoding to this - method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml - to use that encoding, regardless of what TinyXml might otherwise try to detect. - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - - /** Get the root element -- the only top level element -- of the document. - In well formed XML, there should only be one. TinyXml is tolerant of - multiple elements at the document level. - */ - const TiXmlElement* RootElement() const { return FirstChildElement(); } - TiXmlElement* RootElement() { return FirstChildElement(); } - - /** If an error occurs, Error will be set to true. Also, - - The ErrorId() will contain the integer identifier of the error (not generally useful) - - The ErrorDesc() method will return the name of the error. (very useful) - - The ErrorRow() and ErrorCol() will return the location of the error (if known) - */ - bool Error() const { return error; } - - /// Contains a textual (english) description of the error if one occurs. - const char * ErrorDesc() const { return errorDesc.c_str (); } - - /** Generally, you probably want the error string ( ErrorDesc() ). But if you - prefer the ErrorId, this function will fetch it. - */ - int ErrorId() const { return errorId; } - - /** Returns the location (if known) of the error. The first column is column 1, - and the first row is row 1. A value of 0 means the row and column wasn't applicable - (memory errors, for example, have no row/column) or the parser lost the error. (An - error in the error reporting, in that case.) - - @sa SetTabSize, Row, Column - */ - int ErrorRow() const { return errorLocation.row+1; } - int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() - - /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) - to report the correct values for row and column. It does not change the output - or input in any way. - - By calling this method, with a tab size - greater than 0, the row and column of each node and attribute is stored - when the file is loaded. Very useful for tracking the DOM back in to - the source file. - - The tab size is required for calculating the location of nodes. If not - set, the default of 4 is used. The tabsize is set per document. Setting - the tabsize to 0 disables row/column tracking. - - Note that row and column tracking is not supported when using operator>>. - - The tab size needs to be enabled before the parse or load. Correct usage: - @verbatim - TiXmlDocument doc; - doc.SetTabSize( 8 ); - doc.Load( "myfile.xml" ); - @endverbatim - - @sa Row, Column - */ - void SetTabSize( int _tabsize ) { tabsize = _tabsize; } - - int TabSize() const { return tabsize; } - - /** If you have handled the error, it can be reset with this call. The error - state is automatically cleared if you Parse a new XML block. - */ - void ClearError() { error = false; - errorId = 0; - errorDesc = ""; - errorLocation.row = errorLocation.col = 0; - //errorLocation.last = 0; - } - - /** Write the document to standard out using formatted printing ("pretty print"). */ - void Print() const { Print( stdout, 0 ); } - - /* Write the document to a string using formatted printing ("pretty print"). This - will allocate a character array (new char[]) and return it as a pointer. The - calling code pust call delete[] on the return char* to avoid a memory leak. - */ - //char* PrintToMemory() const; - - /// Print this Document to a FILE stream. - virtual void Print( FILE* cfile, int depth = 0 ) const; - // [internal use] - void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - - virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - // [internal use] - virtual TiXmlNode* Clone() const; - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - void CopyTo( TiXmlDocument* target ) const; - - bool error; - int errorId; - TIXML_STRING errorDesc; - int tabsize; - TiXmlCursor errorLocation; - bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. -}; - - -/** - A TiXmlHandle is a class that wraps a node pointer with null checks; this is - an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml - DOM structure. It is a separate utility class. - - Take an example: - @verbatim - - - - - - - @endverbatim - - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very - easy to write a *lot* of code that looks like: - - @verbatim - TiXmlElement* root = document.FirstChildElement( "Document" ); - if ( root ) - { - TiXmlElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - TiXmlElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - TiXmlElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. - @endverbatim - - And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity - of such code. A TiXmlHandle checks for null pointers so it is perfectly safe - and correct to use: - - @verbatim - TiXmlHandle docHandle( &document ); - TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); - if ( child2 ) - { - // do something useful - @endverbatim - - Which is MUCH more concise and useful. - - It is also safe to copy handles - internally they are nothing more than node pointers. - @verbatim - TiXmlHandle handleCopy = handle; - @endverbatim - - What they should not be used for is iteration: - - @verbatim - int i=0; - while ( true ) - { - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); - if ( !child ) - break; - // do something - ++i; - } - @endverbatim - - It seems reasonable, but it is in fact two embedded while loops. The Child method is - a linear walk to find the element, so this code would iterate much more than it needs - to. Instead, prefer: - - @verbatim - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); - - for( child; child; child=child->NextSiblingElement() ) - { - // do something - } - @endverbatim -*/ -class TiXmlHandle -{ -public: - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } - /// Copy constructor - TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } - TiXmlHandle operator=( const TiXmlHandle& ref ) { if ( &ref != this ) this->node = ref.node; return *this; } - - /// Return a handle to the first child node. - TiXmlHandle FirstChild() const; - /// Return a handle to the first child node with the given name. - TiXmlHandle FirstChild( const char * value ) const; - /// Return a handle to the first child element. - TiXmlHandle FirstChildElement() const; - /// Return a handle to the first child element with the given name. - TiXmlHandle FirstChildElement( const char * value ) const; - - /** Return a handle to the "index" child with the given name. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( const char* value, int index ) const; - /** Return a handle to the "index" child. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( int index ) const; - /** Return a handle to the "index" child element with the given name. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( const char* value, int index ) const; - /** Return a handle to the "index" child element. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( int index ) const; - - #ifdef TIXML_USE_STL - TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } - TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } - - TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } - TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } - #endif - - /** Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* ToNode() const { return node; } - /** Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } - /** Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } - /** Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } - - /** @deprecated use ToNode. - Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* Node() const { return ToNode(); } - /** @deprecated use ToElement. - Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* Element() const { return ToElement(); } - /** @deprecated use ToText() - Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* Text() const { return ToText(); } - /** @deprecated use ToUnknown() - Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* Unknown() const { return ToUnknown(); } - -private: - TiXmlNode* node; -}; - - -/** Print to memory functionality. The TiXmlPrinter is useful when you need to: - - -# Print to memory (especially in non-STL mode) - -# Control formatting (line endings, etc.) - - When constructed, the TiXmlPrinter is in its default "pretty printing" mode. - Before calling Accept() you can call methods to control the printing - of the XML document. After TiXmlNode::Accept() is called, the printed document can - be accessed via the CStr(), Str(), and Size() methods. - - TiXmlPrinter uses the Visitor API. - @verbatim - TiXmlPrinter printer; - printer.SetIndent( "\t" ); - - doc.Accept( &printer ); - fprintf( stdout, "%s", printer.CStr() ); - @endverbatim -*/ -class TiXmlPrinter : public TiXmlVisitor -{ -public: - TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), - buffer(), indent( " " ), lineBreak( "\n" ) {} - - virtual bool VisitEnter( const TiXmlDocument& doc ); - virtual bool VisitExit( const TiXmlDocument& doc ); - - virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); - virtual bool VisitExit( const TiXmlElement& element ); - - virtual bool Visit( const TiXmlDeclaration& declaration ); - virtual bool Visit( const TiXmlText& text ); - virtual bool Visit( const TiXmlComment& comment ); - virtual bool Visit( const TiXmlUnknown& unknown ); - - /** Set the indent characters for printing. By default 4 spaces - but tab (\t) is also useful, or null/empty string for no indentation. - */ - void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } - /// Query the indention string. - const char* Indent() { return indent.c_str(); } - /** Set the line breaking string. By default set to newline (\n). - Some operating systems prefer other characters, or can be - set to the null/empty string for no indenation. - */ - void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } - /// Query the current line breaking string. - const char* LineBreak() { return lineBreak.c_str(); } - - /** Switch over to "stream printing" which is the most dense formatting without - linebreaks. Common when the XML is needed for network transmission. - */ - void SetStreamPrinting() { indent = ""; - lineBreak = ""; - } - /// Return the result. - const char* CStr() { return buffer.c_str(); } - /// Return the length of the result string. - size_t Size() { return buffer.size(); } - - #ifdef TIXML_USE_STL - /// Return the result. - const std::string& Str() { return buffer; } - #endif - -private: - void DoIndent() { - for( int i=0; iLoadFile(); + pugi::xml_document mXMLDoc; + mXMLDoc.load_file(filename.c_str()); - TiXmlElement* elem; + pugi::xml_node elem; - TiXmlElement* rootElem = mXMLDoc->RootElement(); + pugi::xml_node rootElem = mXMLDoc.document_element(); // shared geometry - elem = rootElem->FirstChildElement("sharedgeometry"); + elem = rootElem.child("sharedgeometry"); if (elem) { - const char *claimedVertexCount_ = elem->Attribute("vertexcount"); + const char *claimedVertexCount_ = elem.attribute("vertexcount").as_string(NULL); if(!claimedVertexCount_ || StringConverter::parseInt(claimedVertexCount_) > 0) { mMesh->sharedVertexData = new VertexData(); @@ -79,47 +79,45 @@ namespace Ogre { } // submeshes - elem = rootElem->FirstChildElement("submeshes"); + elem = rootElem.child("submeshes"); if (elem) readSubMeshes(elem); // skeleton link - elem = rootElem->FirstChildElement("skeletonlink"); + elem = rootElem.child("skeletonlink"); if (elem) readSkeletonLink(elem); // bone assignments - elem = rootElem->FirstChildElement("boneassignments"); + elem = rootElem.child("boneassignments"); if (elem) readBoneAssignments(elem); //Lod - elem = rootElem->FirstChildElement("levelofdetail"); + elem = rootElem.child("levelofdetail"); if (elem) readLodInfo(elem); // submesh names - elem = rootElem->FirstChildElement("submeshnames"); + elem = rootElem.child("submeshnames"); if (elem) readSubMeshNames(elem, mMesh); // submesh extremes - elem = rootElem->FirstChildElement("extremes"); + elem = rootElem.child("extremes"); if (elem) readExtremes(elem, mMesh); // poses - elem = rootElem->FirstChildElement("poses"); + elem = rootElem.child("poses"); if (elem) readPoses(elem, mMesh); // animations - elem = rootElem->FirstChildElement("animations"); + elem = rootElem.child("animations"); if (elem) readAnimations(elem, mMesh); - delete mXMLDoc; - LogManager::getSingleton().logMessage("XMLMeshSerializer import successful."); } @@ -130,19 +128,19 @@ namespace Ogre { mMesh = const_cast(pMesh); - mXMLDoc = new TiXmlDocument(); - mXMLDoc->InsertEndChild(TiXmlElement("mesh")); + pugi::xml_document mXMLDoc; + pugi::xml_node rootNode = mXMLDoc.append_child("mesh"); LogManager::getSingleton().logMessage("Populating DOM..."); // Write to DOM - writeMesh(pMesh); + writeMesh(pMesh, rootNode); LogManager::getSingleton().logMessage("DOM populated, writing XML file.."); // Write out to a file - if(! mXMLDoc->SaveFile(filename) ) + if(! mXMLDoc.save_file(filename.c_str()) ) { LogManager::getSingleton().logMessage("XMLMeshSerializer failed writing the XML file.", LML_CRITICAL); } @@ -150,27 +148,19 @@ namespace Ogre { { LogManager::getSingleton().logMessage("XMLMeshSerializer export successful."); } - - - delete mXMLDoc; - - } //--------------------------------------------------------------------- - void XMLMeshSerializer::writeMesh(const Mesh* pMesh) + void XMLMeshSerializer::writeMesh(const Mesh* pMesh, pugi::xml_node& rootNode) { - TiXmlElement* rootNode = mXMLDoc->RootElement(); // Write geometry if (pMesh->sharedVertexData) { - TiXmlElement* geomNode = - rootNode->InsertEndChild(TiXmlElement("sharedgeometry"))->ToElement(); + pugi::xml_node geomNode = rootNode.append_child("sharedgeometry"); writeGeometry(geomNode, pMesh->sharedVertexData); } // Write Submeshes - TiXmlElement* subMeshesNode = - rootNode->InsertEndChild(TiXmlElement("submeshes"))->ToElement(); + pugi::xml_node subMeshesNode = rootNode.append_child("submeshes"); for (size_t i = 0; i < pMesh->getNumSubMeshes(); ++i) { LogManager::getSingleton().logMessage("Writing submesh..."); @@ -191,8 +181,7 @@ namespace Ogre { if (bi.hasMoreElements()) { LogManager::getSingleton().logMessage("Exporting shared geometry bone assignments..."); - TiXmlElement* boneAssignNode = - rootNode->InsertEndChild(TiXmlElement("boneassignments"))->ToElement(); + pugi::xml_node boneAssignNode = rootNode.append_child("boneassignments"); while (bi.hasMoreElements()) { @@ -219,56 +208,55 @@ namespace Ogre { writeExtremes(rootNode, pMesh); } //--------------------------------------------------------------------- - void XMLMeshSerializer::writeSubMesh(TiXmlElement* mSubMeshesNode, const SubMesh* s) + void XMLMeshSerializer::writeSubMesh(pugi::xml_node& mSubMeshesNode, const SubMesh* s) { - TiXmlElement* subMeshNode = - mSubMeshesNode->InsertEndChild(TiXmlElement("submesh"))->ToElement(); + pugi::xml_node subMeshNode = mSubMeshesNode.append_child("submesh"); size_t numFaces; // Material name - subMeshNode->SetAttribute("material", s->getMaterialName()); + subMeshNode.append_attribute("material") = s->getMaterialName().c_str(); // bool useSharedVertices - subMeshNode->SetAttribute("usesharedvertices", - StringConverter::toString(s->useSharedVertices) ); + subMeshNode.append_attribute("usesharedvertices") = + StringConverter::toString(s->useSharedVertices).c_str(); // bool use32BitIndexes bool use32BitIndexes = (s->indexData->indexBuffer && s->indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT); - subMeshNode->SetAttribute("use32bitindexes", - StringConverter::toString( use32BitIndexes )); + subMeshNode.append_attribute("use32bitindexes") = + StringConverter::toString( use32BitIndexes ).c_str(); // Operation type switch(s->operationType) { case RenderOperation::OT_LINE_LIST: - subMeshNode->SetAttribute("operationtype", "line_list"); + subMeshNode.append_attribute("operationtype") = "line_list"; break; case RenderOperation::OT_LINE_STRIP: - subMeshNode->SetAttribute("operationtype", "line_strip"); + subMeshNode.append_attribute("operationtype") = "line_strip"; break; case RenderOperation::OT_POINT_LIST: - subMeshNode->SetAttribute("operationtype", "point_list"); + subMeshNode.append_attribute("operationtype") = "point_list"; break; case RenderOperation::OT_TRIANGLE_FAN: - subMeshNode->SetAttribute("operationtype", "triangle_fan"); + subMeshNode.append_attribute("operationtype") = "triangle_fan"; break; case RenderOperation::OT_TRIANGLE_LIST: - subMeshNode->SetAttribute("operationtype", "triangle_list"); + subMeshNode.append_attribute("operationtype") = "triangle_list"; break; case RenderOperation::OT_TRIANGLE_STRIP: - subMeshNode->SetAttribute("operationtype", "triangle_strip"); + subMeshNode.append_attribute("operationtype") = "triangle_strip"; break; case RenderOperation::OT_TRIANGLE_LIST_ADJ: - subMeshNode->SetAttribute("operationtype", "triangle_list_adj"); + subMeshNode.append_attribute("operationtype") = "triangle_list_adj"; break; case RenderOperation::OT_TRIANGLE_STRIP_ADJ: - subMeshNode->SetAttribute("operationtype", "triangle_strip_adj"); + subMeshNode.append_attribute("operationtype") = "triangle_strip_adj"; break; case RenderOperation::OT_LINE_LIST_ADJ: - subMeshNode->SetAttribute("operationtype", "line_list_adj"); + subMeshNode.append_attribute("operationtype") = "line_list_adj"; break; case RenderOperation::OT_LINE_STRIP_ADJ: - subMeshNode->SetAttribute("operationtype", "line_strip_adj"); + subMeshNode.append_attribute("operationtype") = "line_strip_adj"; break; default: OgreAssert(false, "Patch control point operations not supported"); @@ -278,8 +266,8 @@ namespace Ogre { if (s->indexData->indexCount > 0) { // Faces - TiXmlElement* facesNode = - subMeshNode->InsertEndChild(TiXmlElement("faces"))->ToElement(); + pugi::xml_node facesNode = + subMeshNode.append_child("faces"); switch(s->operationType) { case RenderOperation::OT_TRIANGLE_LIST: @@ -300,8 +288,7 @@ namespace Ogre { default: OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Unsupported render operation type"); } - facesNode->SetAttribute("count", - StringConverter::toString(numFaces)); + facesNode.append_attribute("count") = StringConverter::toString(numFaces).c_str(); // Write each face in turn size_t i; unsigned int* pInt = 0; @@ -319,34 +306,33 @@ namespace Ogre { } for (i = 0; i < numFaces; ++i) { - TiXmlElement* faceNode = - facesNode->InsertEndChild(TiXmlElement("face"))->ToElement(); + pugi::xml_node faceNode = facesNode.append_child("face"); if (use32BitIndexes) { - faceNode->SetAttribute("v1", StringConverter::toString(*pInt++)); + faceNode.append_attribute("v1") = StringConverter::toString(*pInt++).c_str(); if(s->operationType == RenderOperation::OT_LINE_LIST) { - faceNode->SetAttribute("v2", StringConverter::toString(*pInt++)); + faceNode.append_attribute("v2") = StringConverter::toString(*pInt++).c_str(); } /// Only need all 3 vertex indices if trilist or first face else if (s->operationType == RenderOperation::OT_TRIANGLE_LIST || i == 0) { - faceNode->SetAttribute("v2", StringConverter::toString(*pInt++)); - faceNode->SetAttribute("v3", StringConverter::toString(*pInt++)); + faceNode.append_attribute("v2") = StringConverter::toString(*pInt++).c_str(); + faceNode.append_attribute("v3") = StringConverter::toString(*pInt++).c_str(); } } else { - faceNode->SetAttribute("v1", StringConverter::toString(*pShort++)); + faceNode.append_attribute("v1") = StringConverter::toString(*pShort++).c_str(); if(s->operationType == RenderOperation::OT_LINE_LIST) { - faceNode->SetAttribute("v2", StringConverter::toString(*pShort++)); + faceNode.append_attribute("v2") = StringConverter::toString(*pShort++).c_str(); } /// Only need all 3 vertex indices if trilist or first face else if (s->operationType == RenderOperation::OT_TRIANGLE_LIST || i == 0) { - faceNode->SetAttribute("v2", StringConverter::toString(*pShort++)); - faceNode->SetAttribute("v3", StringConverter::toString(*pShort++)); + faceNode.append_attribute("v2") = StringConverter::toString(*pShort++).c_str(); + faceNode.append_attribute("v3") = StringConverter::toString(*pShort++).c_str(); } } } @@ -356,8 +342,7 @@ namespace Ogre { // M_GEOMETRY chunk (Optional: present only if useSharedVertices = false) if (!s->useSharedVertices) { - TiXmlElement* geomNode = - subMeshNode->InsertEndChild(TiXmlElement("geometry"))->ToElement(); + pugi::xml_node geomNode = subMeshNode.append_child("geometry"); writeGeometry(geomNode, s->vertexData); } @@ -370,8 +355,7 @@ namespace Ogre { SubMesh::BoneAssignmentIterator bi = const_cast(s)->getBoneAssignmentIterator(); LogManager::getSingleton().logMessage("Exporting dedicated geometry bone assignments..."); - TiXmlElement* boneAssignNode = - subMeshNode->InsertEndChild(TiXmlElement("boneassignments"))->ToElement(); + pugi::xml_node boneAssignNode = subMeshNode.append_child("boneassignments"); while (bi.hasMoreElements()) { const VertexBoneAssignment& assign = bi.getNext(); @@ -382,14 +366,14 @@ namespace Ogre { } //--------------------------------------------------------------------- - void XMLMeshSerializer::writeGeometry(TiXmlElement* mParentNode, const VertexData* vertexData) + void XMLMeshSerializer::writeGeometry(pugi::xml_node& mParentNode, const VertexData* vertexData) { // Write a vertex buffer per element - TiXmlElement *vbNode, *vertexNode, *dataNode; + pugi::xml_node vbNode, vertexNode, dataNode; // Set num verts on parent - mParentNode->SetAttribute("vertexcount", StringConverter::toString(vertexData->vertexCount)); + mParentNode.append_attribute("vertexcount") = StringConverter::toString(vertexData->vertexCount).c_str(); VertexDeclaration* decl = vertexData->vertexDeclaration; VertexBufferBinding* bind = vertexData->vertexBufferBinding; @@ -399,7 +383,7 @@ namespace Ogre { // Iterate over buffers for(b = bind->getBindings().begin(); b != bend; ++b) { - vbNode = mParentNode->InsertEndChild(TiXmlElement("vertexbuffer"))->ToElement(); + vbNode = mParentNode.append_child("vertexbuffer"); const HardwareVertexBufferSharedPtr vbuf = b->second; unsigned short bufferIdx = b->first; // Get all the elements that relate to this buffer @@ -425,26 +409,26 @@ namespace Ogre { switch(elem.getSemantic()) { case VES_POSITION: - vbNode->SetAttribute("positions","true"); + vbNode.append_attribute("positions") = "true"; break; case VES_NORMAL: - vbNode->SetAttribute("normals","true"); + vbNode.append_attribute("normals") = "true"; break; case VES_TANGENT: - vbNode->SetAttribute("tangents","true"); + vbNode.append_attribute("tangents") = "true"; if (elem.getType() == VET_FLOAT4) { - vbNode->SetAttribute("tangent_dimensions", "4"); + vbNode.append_attribute("tangent_dimensions") = "4"; } break; case VES_BINORMAL: - vbNode->SetAttribute("binormals","true"); + vbNode.append_attribute("binormals") = "true"; break; case VES_DIFFUSE: - vbNode->SetAttribute("colours_diffuse","true"); + vbNode.append_attribute("colours_diffuse") = "true"; break; case VES_SPECULAR: - vbNode->SetAttribute("colours_specular","true"); + vbNode.append_attribute("colours_specular") = "true"; break; case VES_TEXTURE_COORDINATES: { @@ -487,8 +471,8 @@ namespace Ogre { OgreAssert(false, "Unsupported VET"); break; } - vbNode->SetAttribute( - "texture_coord_dimensions_" + StringConverter::toString(numTextureCoords), type); + vbNode.append_attribute( + ("texture_coord_dimensions_" + StringConverter::toString(numTextureCoords)).c_str()) = type; ++numTextureCoords; } break; @@ -499,15 +483,14 @@ namespace Ogre { } if (numTextureCoords > 0) { - vbNode->SetAttribute("texture_coords", - StringConverter::toString(numTextureCoords)); + vbNode.append_attribute("texture_coords") = + StringConverter::toString(numTextureCoords).c_str(); } // For each vertex for (size_t v = 0; v < vertexData->vertexCount; ++v) { - vertexNode = - vbNode->InsertEndChild(TiXmlElement("vertex"))->ToElement(); + vertexNode = vbNode.append_child("vertex"); // Iterate over the elements for (i = elems.begin(); i != iend; ++i) { @@ -516,44 +499,39 @@ namespace Ogre { { case VES_POSITION: elem.baseVertexPointerToElement(pVert, &pFloat); - dataNode = - vertexNode->InsertEndChild(TiXmlElement("position"))->ToElement(); - dataNode->SetAttribute("x", StringConverter::toString(pFloat[0])); - dataNode->SetAttribute("y", StringConverter::toString(pFloat[1])); - dataNode->SetAttribute("z", StringConverter::toString(pFloat[2])); + dataNode = vertexNode.append_child("position"); + dataNode.append_attribute("x") = StringConverter::toString(pFloat[0]).c_str(); + dataNode.append_attribute("y") = StringConverter::toString(pFloat[1]).c_str(); + dataNode.append_attribute("z") = StringConverter::toString(pFloat[2]).c_str(); break; case VES_NORMAL: elem.baseVertexPointerToElement(pVert, &pFloat); - dataNode = - vertexNode->InsertEndChild(TiXmlElement("normal"))->ToElement(); - dataNode->SetAttribute("x", StringConverter::toString(pFloat[0])); - dataNode->SetAttribute("y", StringConverter::toString(pFloat[1])); - dataNode->SetAttribute("z", StringConverter::toString(pFloat[2])); + dataNode = vertexNode.append_child("normal"); + dataNode.append_attribute("x") = StringConverter::toString(pFloat[0]).c_str(); + dataNode.append_attribute("y") = StringConverter::toString(pFloat[1]).c_str(); + dataNode.append_attribute("z") = StringConverter::toString(pFloat[2]).c_str(); break; case VES_TANGENT: elem.baseVertexPointerToElement(pVert, &pFloat); - dataNode = - vertexNode->InsertEndChild(TiXmlElement("tangent"))->ToElement(); - dataNode->SetAttribute("x", StringConverter::toString(pFloat[0])); - dataNode->SetAttribute("y", StringConverter::toString(pFloat[1])); - dataNode->SetAttribute("z", StringConverter::toString(pFloat[2])); + dataNode = vertexNode.append_child("tangent"); + dataNode.append_attribute("x") = StringConverter::toString(pFloat[0]).c_str(); + dataNode.append_attribute("y") = StringConverter::toString(pFloat[1]).c_str(); + dataNode.append_attribute("z") = StringConverter::toString(pFloat[2]).c_str(); if (elem.getType() == VET_FLOAT4) { - dataNode->SetAttribute("w", StringConverter::toString(pFloat[3])); + dataNode.append_attribute("w") = StringConverter::toString(pFloat[3]).c_str(); } break; case VES_BINORMAL: elem.baseVertexPointerToElement(pVert, &pFloat); - dataNode = - vertexNode->InsertEndChild(TiXmlElement("binormal"))->ToElement(); - dataNode->SetAttribute("x", StringConverter::toString(pFloat[0])); - dataNode->SetAttribute("y", StringConverter::toString(pFloat[1])); - dataNode->SetAttribute("z", StringConverter::toString(pFloat[2])); + dataNode = vertexNode.append_child("binormal"); + dataNode.append_attribute("x") = StringConverter::toString(pFloat[0]).c_str(); + dataNode.append_attribute("y") = StringConverter::toString(pFloat[1]).c_str(); + dataNode.append_attribute("z") = StringConverter::toString(pFloat[2]).c_str(); break; case VES_DIFFUSE: elem.baseVertexPointerToElement(pVert, &pColour); - dataNode = - vertexNode->InsertEndChild(TiXmlElement("colour_diffuse"))->ToElement(); + dataNode = vertexNode.append_child("colour_diffuse"); { ARGB rc = *pColour++; ColourValue cv; @@ -561,13 +539,12 @@ namespace Ogre { cv.g = (rc & 0xFF) / 255.0f; rc >>= 8; cv.r = (rc & 0xFF) / 255.0f; rc >>= 8; cv.a = (rc & 0xFF) / 255.0f; - dataNode->SetAttribute("value", StringConverter::toString(cv)); + dataNode.append_attribute("value") = StringConverter::toString(cv).c_str(); } break; case VES_SPECULAR: elem.baseVertexPointerToElement(pVert, &pColour); - dataNode = - vertexNode->InsertEndChild(TiXmlElement("colour_specular"))->ToElement(); + dataNode = vertexNode.append_child("colour_specular"); { ARGB rc = *pColour++; ColourValue cv; @@ -575,58 +552,57 @@ namespace Ogre { cv.g = (rc & 0xFF) / 255.0f; rc >>= 8; cv.r = (rc & 0xFF) / 255.0f; rc >>= 8; cv.a = (rc & 0xFF) / 255.0f; - dataNode->SetAttribute("value", StringConverter::toString(cv)); + dataNode.append_attribute("value") = StringConverter::toString(cv).c_str(); } break; case VES_TEXTURE_COORDINATES: - dataNode = - vertexNode->InsertEndChild(TiXmlElement("texcoord"))->ToElement(); + dataNode = vertexNode.append_child("texcoord"); switch(elem.getType()) { case VET_FLOAT1: elem.baseVertexPointerToElement(pVert, &pFloat); - dataNode->SetAttribute("u", StringConverter::toString(*pFloat++)); + dataNode.append_attribute("u") = StringConverter::toString(*pFloat++).c_str(); break; case VET_FLOAT2: elem.baseVertexPointerToElement(pVert, &pFloat); - dataNode->SetAttribute("u", StringConverter::toString(*pFloat++)); - dataNode->SetAttribute("v", StringConverter::toString(*pFloat++)); + dataNode.append_attribute("u") = StringConverter::toString(*pFloat++).c_str(); + dataNode.append_attribute("v") = StringConverter::toString(*pFloat++).c_str(); break; case VET_FLOAT3: elem.baseVertexPointerToElement(pVert, &pFloat); - dataNode->SetAttribute("u", StringConverter::toString(*pFloat++)); - dataNode->SetAttribute("v", StringConverter::toString(*pFloat++)); - dataNode->SetAttribute("w", StringConverter::toString(*pFloat++)); + dataNode.append_attribute("u") = StringConverter::toString(*pFloat++).c_str(); + dataNode.append_attribute("v") = StringConverter::toString(*pFloat++).c_str(); + dataNode.append_attribute("w") = StringConverter::toString(*pFloat++).c_str(); break; case VET_FLOAT4: elem.baseVertexPointerToElement(pVert, &pFloat); - dataNode->SetAttribute("u", StringConverter::toString(*pFloat++)); - dataNode->SetAttribute("v", StringConverter::toString(*pFloat++)); - dataNode->SetAttribute("w", StringConverter::toString(*pFloat++)); - dataNode->SetAttribute("x", StringConverter::toString(*pFloat++)); + dataNode.append_attribute("u") = StringConverter::toString(*pFloat++).c_str(); + dataNode.append_attribute("v") = StringConverter::toString(*pFloat++).c_str(); + dataNode.append_attribute("w") = StringConverter::toString(*pFloat++).c_str(); + dataNode.append_attribute("x") = StringConverter::toString(*pFloat++).c_str(); break; case VET_SHORT1: elem.baseVertexPointerToElement(pVert, &pShort); - dataNode->SetAttribute("u", StringConverter::toString(*pShort++ / 65535.0f)); + dataNode.append_attribute("u") = StringConverter::toString(*pShort++ / 65535.0f).c_str(); break; case VET_SHORT2: elem.baseVertexPointerToElement(pVert, &pShort); - dataNode->SetAttribute("u", StringConverter::toString(*pShort++ / 65535.0f)); - dataNode->SetAttribute("v", StringConverter::toString(*pShort++ / 65535.0f)); + dataNode.append_attribute("u") = StringConverter::toString(*pShort++ / 65535.0f).c_str(); + dataNode.append_attribute("v") = StringConverter::toString(*pShort++ / 65535.0f).c_str(); break; case VET_SHORT3: elem.baseVertexPointerToElement(pVert, &pShort); - dataNode->SetAttribute("u", StringConverter::toString(*pShort++ / 65535.0f)); - dataNode->SetAttribute("v", StringConverter::toString(*pShort++ / 65535.0f)); - dataNode->SetAttribute("w", StringConverter::toString(*pShort++ / 65535.0f)); + dataNode.append_attribute("u") = StringConverter::toString(*pShort++ / 65535.0f).c_str(); + dataNode.append_attribute("v") = StringConverter::toString(*pShort++ / 65535.0f).c_str(); + dataNode.append_attribute("w") = StringConverter::toString(*pShort++ / 65535.0f).c_str(); break; case VET_SHORT4: elem.baseVertexPointerToElement(pVert, &pShort); - dataNode->SetAttribute("u", StringConverter::toString(*pShort++ / 65535.0f)); - dataNode->SetAttribute("v", StringConverter::toString(*pShort++ / 65535.0f)); - dataNode->SetAttribute("w", StringConverter::toString(*pShort++ / 65535.0f)); - dataNode->SetAttribute("x", StringConverter::toString(*pShort++ / 65535.0f)); + dataNode.append_attribute("u") = StringConverter::toString(*pShort++ / 65535.0f).c_str(); + dataNode.append_attribute("v") = StringConverter::toString(*pShort++ / 65535.0f).c_str(); + dataNode.append_attribute("w") = StringConverter::toString(*pShort++ / 65535.0f).c_str(); + dataNode.append_attribute("x") = StringConverter::toString(*pShort++ / 65535.0f).c_str(); break; case VET_COLOUR: case VET_COLOUR_ARGB: case VET_COLOUR_ABGR: elem.baseVertexPointerToElement(pVert, &pColour); @@ -637,15 +613,15 @@ namespace Ogre { cv.g = (rc & 0xFF) / 255.0f; rc >>= 8; cv.r = (rc & 0xFF) / 255.0f; rc >>= 8; cv.a = (rc & 0xFF) / 255.0f; - dataNode->SetAttribute("u", StringConverter::toString(cv)); + dataNode.append_attribute("u") = StringConverter::toString(cv).c_str(); } break; case VET_UBYTE4: elem.baseVertexPointerToElement(pVert, &pChar); - dataNode->SetAttribute("u", StringConverter::toString(*pChar++ / 255.0f)); - dataNode->SetAttribute("v", StringConverter::toString(*pChar++ / 255.0f)); - dataNode->SetAttribute("w", StringConverter::toString(*pChar++ / 255.0f)); - dataNode->SetAttribute("x", StringConverter::toString(*pChar++ / 255.0f)); + dataNode.append_attribute("u") = StringConverter::toString(*pChar++ / 255.0f).c_str(); + dataNode.append_attribute("v") = StringConverter::toString(*pChar++ / 255.0f).c_str(); + dataNode.append_attribute("w") = StringConverter::toString(*pChar++ / 255.0f).c_str(); + dataNode.append_attribute("x") = StringConverter::toString(*pChar++ / 255.0f).c_str(); break; default: OgreAssert(false, "Unsupported VET"); @@ -664,64 +640,58 @@ namespace Ogre { } //--------------------------------------------------------------------- - void XMLMeshSerializer::writeSkeletonLink(TiXmlElement* mMeshNode, const String& skelName) + void XMLMeshSerializer::writeSkeletonLink(pugi::xml_node& mMeshNode, const String& skelName) { - TiXmlElement* skelNode = - mMeshNode->InsertEndChild(TiXmlElement("skeletonlink"))->ToElement(); - skelNode->SetAttribute("name", skelName); + pugi::xml_node skelNode = mMeshNode.append_child("skeletonlink"); + skelNode.append_attribute("name") = skelName.c_str(); } //--------------------------------------------------------------------- - void XMLMeshSerializer::writeBoneAssignment(TiXmlElement* mBoneAssignNode, const VertexBoneAssignment* assign) + void XMLMeshSerializer::writeBoneAssignment(pugi::xml_node& mBoneAssignNode, const VertexBoneAssignment* assign) { - TiXmlElement* assignNode = - mBoneAssignNode->InsertEndChild( - TiXmlElement("vertexboneassignment"))->ToElement(); + pugi::xml_node assignNode = mBoneAssignNode.append_child("vertexboneassignment"); - assignNode->SetAttribute("vertexindex", - StringConverter::toString(assign->vertexIndex)); - assignNode->SetAttribute("boneindex", - StringConverter::toString(assign->boneIndex)); - assignNode->SetAttribute("weight", - StringConverter::toString(assign->weight)); + assignNode.append_attribute("vertexindex") = + StringConverter::toString(assign->vertexIndex).c_str(); + assignNode.append_attribute("boneindex") = + StringConverter::toString(assign->boneIndex).c_str(); + assignNode.append_attribute("weight" ) = + StringConverter::toString(assign->weight).c_str(); } //--------------------------------------------------------------------- - void XMLMeshSerializer::writeTextureAliases(TiXmlElement* mSubmeshesNode, const SubMesh* subMesh) + void XMLMeshSerializer::writeTextureAliases(pugi::xml_node& mSubmeshesNode, const SubMesh* subMesh) { if (!subMesh->hasTextureAliases()) return; // do nothing - TiXmlElement* textureAliasesNode = - mSubmeshesNode->InsertEndChild(TiXmlElement("textures"))->ToElement(); + pugi::xml_node textureAliasesNode = mSubmeshesNode.append_child("textures"); // use ogre map iterator SubMesh::AliasTextureIterator aliasIterator = subMesh->getAliasTextureIterator(); while (aliasIterator.hasMoreElements()) { - TiXmlElement* aliasTextureNode = - textureAliasesNode->InsertEndChild(TiXmlElement("texture"))->ToElement(); + pugi::xml_node aliasTextureNode = textureAliasesNode.append_child("texture"); // iterator key is alias and value is texture name - aliasTextureNode->SetAttribute("alias", aliasIterator.peekNextKey()); - aliasTextureNode->SetAttribute("name", aliasIterator.peekNextValue()); + aliasTextureNode.append_attribute("alias") = aliasIterator.peekNextKey().c_str(); + aliasTextureNode.append_attribute("name") = aliasIterator.peekNextValue().c_str(); aliasIterator.moveNext(); } } //--------------------------------------------------------------------- - void XMLMeshSerializer::readSubMeshes(TiXmlElement* mSubmeshesNode) + void XMLMeshSerializer::readSubMeshes(pugi::xml_node& mSubmeshesNode) { LogManager::getSingleton().logMessage("Reading submeshes..."); assert(mMesh->getNumSubMeshes() == 0); - for (TiXmlElement* smElem = mSubmeshesNode->FirstChildElement(); - smElem != 0; smElem = smElem->NextSiblingElement()) + for (pugi::xml_node& smElem : mSubmeshesNode.children()) { // All children should be submeshes SubMesh* sm = mMesh->createSubMesh(); - const char* mat = smElem->Attribute("material"); + const char* mat = smElem.attribute("material").as_string(NULL); if (mat && mat[0] != '\0') { // we do not load any materials - so create a dummy here to just store the name @@ -730,7 +700,7 @@ namespace Ogre { // Read operation type bool readFaces = true; - const char* optype = smElem->Attribute("operationtype"); + const char* optype = smElem.attribute("operationtype").as_string(NULL); if (optype) { if (!strcmp(optype, "triangle_list")) @@ -780,10 +750,10 @@ namespace Ogre { } } - const char* tmp = smElem->Attribute("usesharedvertices"); + const char* tmp = smElem.attribute("usesharedvertices").as_string(NULL); if (tmp) sm->useSharedVertices = StringConverter::parseBool(tmp); - tmp = smElem->Attribute("use32bitindexes"); + tmp = smElem.attribute("use32bitindexes").as_string(NULL); bool use32BitIndexes = false; if (tmp) use32BitIndexes = StringConverter::parseBool(tmp); @@ -791,13 +761,13 @@ namespace Ogre { // Faces if (readFaces) { - TiXmlElement* faces = smElem->FirstChildElement("faces"); + pugi::xml_node faces = smElem.child("faces"); int actualCount = 0; - for (TiXmlElement *faceElem = faces->FirstChildElement(); faceElem != 0; faceElem = faceElem->NextSiblingElement()) + for (pugi::xml_node faceElem : faces.children()) { actualCount++; } - const char *claimedCount_ = faces->Attribute("count"); + const char *claimedCount_ = faces.attribute("count").as_string(NULL); if (claimedCount_ && StringConverter::parseInt(claimedCount_)!=actualCount) { LogManager::getSingleton().stream(LML_WARNING) @@ -851,37 +821,36 @@ namespace Ogre { pShort = static_cast( ibuf->lock(HardwareBuffer::HBL_DISCARD)); } - TiXmlElement* faceElem; + bool firstTri = true; - for (faceElem = faces->FirstChildElement(); - faceElem != 0; faceElem = faceElem->NextSiblingElement()) + for (auto faceElem : faces.children()) { if (use32BitIndexes) { - *pInt++ = StringConverter::parseInt(faceElem->Attribute("v1")); + *pInt++ = StringConverter::parseInt(faceElem.attribute("v1").value()); if(sm->operationType == RenderOperation::OT_LINE_LIST) { - *pInt++ = StringConverter::parseInt(faceElem->Attribute("v2")); + *pInt++ = StringConverter::parseInt(faceElem.attribute("v2").value()); } // only need all 3 vertices if it's a trilist or first tri else if (sm->operationType == RenderOperation::OT_TRIANGLE_LIST || firstTri) { - *pInt++ = StringConverter::parseInt(faceElem->Attribute("v2")); - *pInt++ = StringConverter::parseInt(faceElem->Attribute("v3")); + *pInt++ = StringConverter::parseInt(faceElem.attribute("v2").value()); + *pInt++ = StringConverter::parseInt(faceElem.attribute("v3").value()); } } else { - *pShort++ = StringConverter::parseInt(faceElem->Attribute("v1")); + *pShort++ = StringConverter::parseInt(faceElem.attribute("v1").value()); if(sm->operationType == RenderOperation::OT_LINE_LIST) { - *pShort++ = StringConverter::parseInt(faceElem->Attribute("v2")); + *pShort++ = StringConverter::parseInt(faceElem.attribute("v2").value()); } // only need all 3 vertices if it's a trilist or first tri else if (sm->operationType == RenderOperation::OT_TRIANGLE_LIST || firstTri) { - *pShort++ = StringConverter::parseInt(faceElem->Attribute("v2")); - *pShort++ = StringConverter::parseInt(faceElem->Attribute("v3")); + *pShort++ = StringConverter::parseInt(faceElem.attribute("v2").value()); + *pShort++ = StringConverter::parseInt(faceElem.attribute("v3").value()); } } firstTri = false; @@ -893,7 +862,7 @@ namespace Ogre { // Geometry if (!sm->useSharedVertices) { - TiXmlElement* geomNode = smElem->FirstChildElement("geometry"); + pugi::xml_node geomNode = smElem.child("geometry"); if (geomNode) { sm->vertexData = new VertexData(); @@ -902,12 +871,12 @@ namespace Ogre { } // texture aliases - TiXmlElement* textureAliasesNode = smElem->FirstChildElement("textures"); + pugi::xml_node textureAliasesNode = smElem.child("textures"); if(textureAliasesNode) readTextureAliases(textureAliasesNode, sm); // Bone assignments - TiXmlElement* boneAssigns = smElem->FirstChildElement("boneassignments"); + pugi::xml_node boneAssigns = smElem.child("boneassignments"); if(boneAssigns) readBoneAssignments(boneAssigns, sm); @@ -915,7 +884,7 @@ namespace Ogre { LogManager::getSingleton().logMessage("Submeshes done."); } //--------------------------------------------------------------------- - void XMLMeshSerializer::readGeometry(TiXmlElement* mGeometryNode, VertexData* vertexData) + void XMLMeshSerializer::readGeometry(pugi::xml_node& mGeometryNode, VertexData* vertexData) { LogManager::getSingleton().logMessage("Reading geometry..."); unsigned char *pVert; @@ -924,7 +893,7 @@ namespace Ogre { uint8 *pChar; ARGB *pCol; - const char *claimedVertexCount_ = mGeometryNode->Attribute("vertexcount"); + const char *claimedVertexCount_ = mGeometryNode.attribute("vertexcount").as_string(NULL); ptrdiff_t claimedVertexCount = 0; if (claimedVertexCount_) { @@ -946,32 +915,31 @@ namespace Ogre { bool first = true; // Iterate over all children (vertexbuffer entries) - for (TiXmlElement* vbElem = mGeometryNode->FirstChildElement(); - vbElem != 0; vbElem = vbElem->NextSiblingElement()) + for (pugi::xml_node& vbElem : mGeometryNode.children()) { size_t offset = 0; // Skip non-vertexbuffer elems - if (stricmp(vbElem->Value(), "vertexbuffer")) continue; + if (stricmp(vbElem.name(), "vertexbuffer")) continue; - const char* attrib = vbElem->Attribute("positions"); + const char* attrib = vbElem.attribute("positions").as_string(NULL); if (attrib && StringConverter::parseBool(attrib)) { // Add element decl->addElement(bufCount, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); } - attrib = vbElem->Attribute("normals"); + attrib = vbElem.attribute("normals").as_string(NULL); if (attrib && StringConverter::parseBool(attrib)) { // Add element decl->addElement(bufCount, offset, VET_FLOAT3, VES_NORMAL); offset += VertexElement::getTypeSize(VET_FLOAT3); } - attrib = vbElem->Attribute("tangents"); + attrib = vbElem.attribute("tangents").as_string(NULL); if (attrib && StringConverter::parseBool(attrib)) { VertexElementType tangentType = VET_FLOAT3; - attrib = vbElem->Attribute("tangent_dimensions"); + attrib = vbElem.attribute("tangent_dimensions").value(); if (attrib) { unsigned int dims = StringConverter::parseUnsignedInt(attrib); @@ -983,38 +951,38 @@ namespace Ogre { decl->addElement(bufCount, offset, tangentType, VES_TANGENT); offset += VertexElement::getTypeSize(tangentType); } - attrib = vbElem->Attribute("binormals"); + attrib = vbElem.attribute("binormals").as_string(NULL); if (attrib && StringConverter::parseBool(attrib)) { // Add element decl->addElement(bufCount, offset, VET_FLOAT3, VES_BINORMAL); offset += VertexElement::getTypeSize(VET_FLOAT3); } - attrib = vbElem->Attribute("colours_diffuse"); + attrib = vbElem.attribute("colours_diffuse").as_string(NULL); if (attrib && StringConverter::parseBool(attrib)) { // Add element decl->addElement(bufCount, offset, mColourElementType, VES_DIFFUSE); offset += VertexElement::getTypeSize(mColourElementType); } - attrib = vbElem->Attribute("colours_specular"); + attrib = vbElem.attribute("colours_specular").as_string(NULL); if (attrib && StringConverter::parseBool(attrib)) { // Add element decl->addElement(bufCount, offset, mColourElementType, VES_SPECULAR); offset += VertexElement::getTypeSize(mColourElementType); } - attrib = vbElem->Attribute("texture_coords"); + attrib = vbElem.attribute("texture_coords").as_string(NULL); if (attrib && StringConverter::parseInt(attrib)) { - unsigned short numTexCoords = StringConverter::parseInt(vbElem->Attribute("texture_coords")); + unsigned short numTexCoords = StringConverter::parseInt(vbElem.attribute("texture_coords").value()); for (unsigned short tx = 0; tx < numTexCoords; ++tx) { // NB set is local to this buffer, but will be translated into a // global set number across all vertex buffers StringStream str; str << "texture_coord_dimensions_" << tx; - attrib = vbElem->Attribute(str.str().c_str()); + attrib = vbElem.attribute(str.str().c_str()).as_string(NULL); VertexElementType vtype = VET_FLOAT2; // Default if (attrib) { @@ -1052,8 +1020,9 @@ namespace Ogre { vtype = VET_COLOUR_ABGR; else { - std::cerr << "ERROR: Did not recognise texture_coord_dimensions value of \""<FirstChildElement(); vertexElem != 0; vertexElem = vertexElem->NextSiblingElement()) + for (pugi::xml_node& vertexElem : vbElem.children()) { actualVertexCount++; } @@ -1090,13 +1059,12 @@ namespace Ogre { // Get the element list for this buffer alone VertexDeclaration::VertexElementList elems = decl->findElementsBySource(bufCount); // Now the buffer is set up, parse all the vertices - for (TiXmlElement* vertexElem = vbElem->FirstChildElement(); - vertexElem != 0; vertexElem = vertexElem->NextSiblingElement()) + for (pugi::xml_node& vertexElem : vbElem.children()) { // Now parse the elements, ensure they are all matched VertexDeclaration::VertexElementList::const_iterator ielem, ielemend; - TiXmlElement* xmlElem; - TiXmlElement* texCoordElem = 0; + pugi::xml_node xmlElem; + pugi::xml_node texCoordElem; ielemend = elems.end(); for (ielem = elems.begin(); ielem != ielemend; ++ielem) { @@ -1105,7 +1073,7 @@ namespace Ogre { switch(elem.getSemantic()) { case VES_POSITION: - xmlElem = vertexElem->FirstChildElement("position"); + xmlElem = vertexElem.child("position"); if (!xmlElem) { OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing element.", @@ -1113,19 +1081,13 @@ namespace Ogre { } elem.baseVertexPointerToElement(pVert, &pFloat); - *pFloat++ = StringConverter::parseReal( - xmlElem->Attribute("x")); - *pFloat++ = StringConverter::parseReal( - xmlElem->Attribute("y")); - *pFloat++ = StringConverter::parseReal( - xmlElem->Attribute("z")); - - pos.x = StringConverter::parseReal( - xmlElem->Attribute("x")); - pos.y = StringConverter::parseReal( - xmlElem->Attribute("y")); - pos.z = StringConverter::parseReal( - xmlElem->Attribute("z")); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("x").value()); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("y").value()); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("z").value()); + + pos.x = StringConverter::parseReal(xmlElem.attribute("x").value()); + pos.y = StringConverter::parseReal(xmlElem.attribute("y").value()); + pos.z = StringConverter::parseReal(xmlElem.attribute("z").value()); if (first) { @@ -1141,7 +1103,7 @@ namespace Ogre { } break; case VES_NORMAL: - xmlElem = vertexElem->FirstChildElement("normal"); + xmlElem = vertexElem.child("normal"); if (!xmlElem) { OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing element.", @@ -1149,15 +1111,12 @@ namespace Ogre { } elem.baseVertexPointerToElement(pVert, &pFloat); - *pFloat++ = StringConverter::parseReal( - xmlElem->Attribute("x")); - *pFloat++ = StringConverter::parseReal( - xmlElem->Attribute("y")); - *pFloat++ = StringConverter::parseReal( - xmlElem->Attribute("z")); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("x").value()); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("y").value()); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("z").value()); break; case VES_TANGENT: - xmlElem = vertexElem->FirstChildElement("tangent"); + xmlElem = vertexElem.child("tangent"); if (!xmlElem) { OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing element.", @@ -1165,20 +1124,16 @@ namespace Ogre { } elem.baseVertexPointerToElement(pVert, &pFloat); - *pFloat++ = StringConverter::parseReal( - xmlElem->Attribute("x")); - *pFloat++ = StringConverter::parseReal( - xmlElem->Attribute("y")); - *pFloat++ = StringConverter::parseReal( - xmlElem->Attribute("z")); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("x").value()); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("y").value()); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("z").value()); if (elem.getType() == VET_FLOAT4) { - *pFloat++ = StringConverter::parseReal( - xmlElem->Attribute("w")); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("w").value()); } break; case VES_BINORMAL: - xmlElem = vertexElem->FirstChildElement("binormal"); + xmlElem = vertexElem.child("binormal"); if (!xmlElem) { OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing element.", @@ -1186,15 +1141,12 @@ namespace Ogre { } elem.baseVertexPointerToElement(pVert, &pFloat); - *pFloat++ = StringConverter::parseReal( - xmlElem->Attribute("x")); - *pFloat++ = StringConverter::parseReal( - xmlElem->Attribute("y")); - *pFloat++ = StringConverter::parseReal( - xmlElem->Attribute("z")); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("x").value()); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("y").value()); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("z").value()); break; case VES_DIFFUSE: - xmlElem = vertexElem->FirstChildElement("colour_diffuse"); + xmlElem = vertexElem.child("colour_diffuse"); if (!xmlElem) { OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing element.", @@ -1203,13 +1155,12 @@ namespace Ogre { elem.baseVertexPointerToElement(pVert, &pCol); { ColourValue cv; - cv = StringConverter::parseColourValue( - xmlElem->Attribute("value")); + cv = StringConverter::parseColourValue(xmlElem.attribute("value").value()); *pCol++ = VertexElement::convertColourValue(cv, mColourElementType); } break; case VES_SPECULAR: - xmlElem = vertexElem->FirstChildElement("colour_specular"); + xmlElem = vertexElem.child("colour_specular"); if (!xmlElem) { OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Missing element.", @@ -1218,8 +1169,7 @@ namespace Ogre { elem.baseVertexPointerToElement(pVert, &pCol); { ColourValue cv; - cv = StringConverter::parseColourValue( - xmlElem->Attribute("value")); + cv = StringConverter::parseColourValue(xmlElem.attribute("value").value()); *pCol++ = VertexElement::convertColourValue(cv, mColourElementType); } break; @@ -1227,12 +1177,12 @@ namespace Ogre { if (!texCoordElem) { // Get first texcoord - xmlElem = vertexElem->FirstChildElement("texcoord"); + xmlElem = vertexElem.child("texcoord"); } else { // Get next texcoord - xmlElem = texCoordElem->NextSiblingElement("texcoord"); + xmlElem = texCoordElem.next_sibling("texcoord"); } if (!xmlElem) { @@ -1242,7 +1192,7 @@ namespace Ogre { // Record the latest texture coord entry texCoordElem = xmlElem; - if (!xmlElem->Attribute("u")) + if (!xmlElem.attribute("u")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'u' attribute not found.", "XMLMeshSerializer::readGeometry"); // depending on type, pack appropriately, can process colour channels separately which is a bonus @@ -1250,99 +1200,99 @@ namespace Ogre { { case VET_FLOAT1: elem.baseVertexPointerToElement(pVert, &pFloat); - *pFloat++ = StringConverter::parseReal(xmlElem->Attribute("u")); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("u").value()); break; case VET_FLOAT2: - if (!xmlElem->Attribute("v")) + if (!xmlElem.attribute("v")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'v' attribute not found.", "XMLMeshSerializer::readGeometry"); elem.baseVertexPointerToElement(pVert, &pFloat); - *pFloat++ = StringConverter::parseReal(xmlElem->Attribute("u")); - *pFloat++ = StringConverter::parseReal(xmlElem->Attribute("v")); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("u").value()); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("v").value()); break; case VET_FLOAT3: - if (!xmlElem->Attribute("v")) + if (!xmlElem.attribute("v")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'v' attribute not found.", "XMLMeshSerializer::readGeometry"); - if (!xmlElem->Attribute("w")) + if (!xmlElem.attribute("w")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'w' attribute not found.", "XMLMeshSerializer::readGeometry"); elem.baseVertexPointerToElement(pVert, &pFloat); - *pFloat++ = StringConverter::parseReal(xmlElem->Attribute("u")); - *pFloat++ = StringConverter::parseReal(xmlElem->Attribute("v")); - *pFloat++ = StringConverter::parseReal(xmlElem->Attribute("w")); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("u").value()); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("v").value()); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("w").value()); break; case VET_FLOAT4: - if (!xmlElem->Attribute("v")) + if (!xmlElem.attribute("v")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'v' attribute not found.", "XMLMeshSerializer::readGeometry"); - if (!xmlElem->Attribute("w")) + if (!xmlElem.attribute("w")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'w' attribute not found.", "XMLMeshSerializer::readGeometry"); - if (!xmlElem->Attribute("x")) + if (!xmlElem.attribute("x")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'x' attribute not found.", "XMLMeshSerializer::readGeometry"); elem.baseVertexPointerToElement(pVert, &pFloat); - *pFloat++ = StringConverter::parseReal(xmlElem->Attribute("u")); - *pFloat++ = StringConverter::parseReal(xmlElem->Attribute("v")); - *pFloat++ = StringConverter::parseReal(xmlElem->Attribute("w")); - *pFloat++ = StringConverter::parseReal(xmlElem->Attribute("x")); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("u").value()); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("v").value()); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("w").value()); + *pFloat++ = StringConverter::parseReal(xmlElem.attribute("x").value()); break; case VET_SHORT1: elem.baseVertexPointerToElement(pVert, &pShort); - *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem->Attribute("u"))); + *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem.attribute("u").value())); break; case VET_SHORT2: - if (!xmlElem->Attribute("v")) + if (!xmlElem.attribute("v")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'v' attribute not found.", "XMLMeshSerializer::readGeometry"); elem.baseVertexPointerToElement(pVert, &pShort); - *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem->Attribute("u"))); - *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem->Attribute("v"))); + *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem.attribute("u").value())); + *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem.attribute("v").value())); break; case VET_SHORT3: - if (!xmlElem->Attribute("v")) + if (!xmlElem.attribute("v")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'v' attribute not found.", "XMLMeshSerializer::readGeometry"); - if (!xmlElem->Attribute("w")) + if (!xmlElem.attribute("w")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'w' attribute not found.", "XMLMeshSerializer::readGeometry"); elem.baseVertexPointerToElement(pVert, &pShort); - *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem->Attribute("u"))); - *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem->Attribute("v"))); - *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem->Attribute("w"))); + *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem.attribute("u").value())); + *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem.attribute("v").value())); + *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem.attribute("w").value())); break; case VET_SHORT4: - if (!xmlElem->Attribute("v")) + if (!xmlElem.attribute("v")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'v' attribute not found.", "XMLMeshSerializer::readGeometry"); - if (!xmlElem->Attribute("w")) + if (!xmlElem.attribute("w")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'w' attribute not found.", "XMLMeshSerializer::readGeometry"); - if (!xmlElem->Attribute("x")) + if (!xmlElem.attribute("x")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'x' attribute not found.", "XMLMeshSerializer::readGeometry"); elem.baseVertexPointerToElement(pVert, &pShort); - *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem->Attribute("u"))); - *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem->Attribute("v"))); - *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem->Attribute("w"))); - *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem->Attribute("x"))); + *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem.attribute("u").value())); + *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem.attribute("v").value())); + *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem.attribute("w").value())); + *pShort++ = static_cast(65535.0f * StringConverter::parseReal(xmlElem.attribute("x").value())); break; case VET_UBYTE4: - if (!xmlElem->Attribute("v")) + if (!xmlElem.attribute("v")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'v' attribute not found.", "XMLMeshSerializer::readGeometry"); - if (!xmlElem->Attribute("w")) + if (!xmlElem.attribute("w")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'w' attribute not found.", "XMLMeshSerializer::readGeometry"); - if (!xmlElem->Attribute("x")) + if (!xmlElem.attribute("x")) OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Texcoord 'x' attribute not found.", "XMLMeshSerializer::readGeometry"); elem.baseVertexPointerToElement(pVert, &pChar); // round off instead of just truncating -- avoids magnifying rounding errors - *pChar++ = static_cast(0.5f + 255.0f * StringConverter::parseReal(xmlElem->Attribute("u"))); - *pChar++ = static_cast(0.5f + 255.0f * StringConverter::parseReal(xmlElem->Attribute("v"))); - *pChar++ = static_cast(0.5f + 255.0f * StringConverter::parseReal(xmlElem->Attribute("w"))); - *pChar++ = static_cast(0.5f + 255.0f * StringConverter::parseReal(xmlElem->Attribute("x"))); + *pChar++ = static_cast(0.5f + 255.0f * StringConverter::parseReal(xmlElem.attribute("u").value())); + *pChar++ = static_cast(0.5f + 255.0f * StringConverter::parseReal(xmlElem.attribute("v").value())); + *pChar++ = static_cast(0.5f + 255.0f * StringConverter::parseReal(xmlElem.attribute("w").value())); + *pChar++ = static_cast(0.5f + 255.0f * StringConverter::parseReal(xmlElem.attribute("x").value())); break; case VET_COLOUR: { elem.baseVertexPointerToElement(pVert, &pCol); - ColourValue cv = StringConverter::parseColourValue(xmlElem->Attribute("u")); + ColourValue cv = StringConverter::parseColourValue(xmlElem.attribute("u").value()); *pCol++ = VertexElement::convertColourValue(cv, mColourElementType); } break; @@ -1351,7 +1301,7 @@ namespace Ogre { case VET_COLOUR_ABGR: { elem.baseVertexPointerToElement(pVert, &pCol); - ColourValue cv = StringConverter::parseColourValue(xmlElem->Attribute("u")); + ColourValue cv = StringConverter::parseColourValue(xmlElem.attribute("u").value()); *pCol++ = VertexElement::convertColourValue(cv, elem.getType()); } break; @@ -1393,26 +1343,22 @@ namespace Ogre { LogManager::getSingleton().logMessage("Geometry done..."); } //--------------------------------------------------------------------- - void XMLMeshSerializer::readSkeletonLink(TiXmlElement* mSkelNode) + void XMLMeshSerializer::readSkeletonLink(pugi::xml_node& mSkelNode) { - mMesh->setSkeletonName(mSkelNode->Attribute("name")); + mMesh->setSkeletonName(mSkelNode.attribute("name").value()); } //--------------------------------------------------------------------- - void XMLMeshSerializer::readBoneAssignments(TiXmlElement* mBoneAssignmentsNode) + void XMLMeshSerializer::readBoneAssignments(pugi::xml_node& mBoneAssignmentsNode) { LogManager::getSingleton().logMessage("Reading bone assignments..."); // Iterate over all children (vertexboneassignment entries) - for (TiXmlElement* elem = mBoneAssignmentsNode->FirstChildElement(); - elem != 0; elem = elem->NextSiblingElement()) + for (pugi::xml_node& elem : mBoneAssignmentsNode.children()) { VertexBoneAssignment vba; - vba.vertexIndex = StringConverter::parseInt( - elem->Attribute("vertexindex")); - vba.boneIndex = StringConverter::parseInt( - elem->Attribute("boneindex")); - vba.weight= StringConverter::parseReal( - elem->Attribute("weight")); + vba.vertexIndex = StringConverter::parseInt(elem.attribute("vertexindex").value()); + vba.boneIndex = StringConverter::parseInt(elem.attribute("boneindex").value()); + vba.weight = StringConverter::parseReal(elem.attribute("weight").value()); mMesh->addBoneAssignment(vba); } @@ -1420,19 +1366,18 @@ namespace Ogre { LogManager::getSingleton().logMessage("Bone assignments done."); } //--------------------------------------------------------------------- - void XMLMeshSerializer::readTextureAliases(TiXmlElement* mTextureAliasesNode, SubMesh* subMesh) + void XMLMeshSerializer::readTextureAliases(pugi::xml_node& mTextureAliasesNode, SubMesh* subMesh) { LogManager::getSingleton().logMessage("Reading sub mesh texture aliases..."); // Iterate over all children (texture entries) - for (TiXmlElement* elem = mTextureAliasesNode->FirstChildElement(); - elem != 0; elem = elem->NextSiblingElement()) + for (pugi::xml_node& elem : mTextureAliasesNode.children()) { // pass alias and texture name to submesh // read attribute "alias" - String alias = elem->Attribute("alias"); + String alias = elem.attribute("alias").value(); // read attribute "name" - String name = elem->Attribute("name"); + String name = elem.attribute("name").value(); subMesh->addTextureAlias(alias, name); } @@ -1440,16 +1385,15 @@ namespace Ogre { LogManager::getSingleton().logMessage("Texture aliases done."); } //--------------------------------------------------------------------- - void XMLMeshSerializer::readSubMeshNames(TiXmlElement* mMeshNamesNode, Mesh *sm) + void XMLMeshSerializer::readSubMeshNames(pugi::xml_node& mMeshNamesNode, Mesh *sm) { LogManager::getSingleton().logMessage("Reading mesh names..."); // Iterate over all children (vertexboneassignment entries) - for (TiXmlElement* elem = mMeshNamesNode->FirstChildElement(); - elem != 0; elem = elem->NextSiblingElement()) + for (pugi::xml_node& elem : mMeshNamesNode.children()) { - String meshName = elem->Attribute("name"); - int index = StringConverter::parseInt(elem->Attribute("index")); + String meshName = elem.attribute("name").value(); + int index = StringConverter::parseInt(elem.attribute("index").value()); sm->nameSubMesh(meshName, index); } @@ -1457,37 +1401,32 @@ namespace Ogre { LogManager::getSingleton().logMessage("Mesh names done."); } //--------------------------------------------------------------------- - void XMLMeshSerializer::readBoneAssignments(TiXmlElement* mBoneAssignmentsNode, SubMesh* sm) + void XMLMeshSerializer::readBoneAssignments(pugi::xml_node& mBoneAssignmentsNode, SubMesh* sm) { LogManager::getSingleton().logMessage("Reading bone assignments..."); // Iterate over all children (vertexboneassignment entries) - for (TiXmlElement* elem = mBoneAssignmentsNode->FirstChildElement(); - elem != 0; elem = elem->NextSiblingElement()) + for (pugi::xml_node& elem : mBoneAssignmentsNode.children()) { VertexBoneAssignment vba; - vba.vertexIndex = StringConverter::parseInt( - elem->Attribute("vertexindex")); - vba.boneIndex = StringConverter::parseInt( - elem->Attribute("boneindex")); - vba.weight= StringConverter::parseReal( - elem->Attribute("weight")); + vba.vertexIndex = StringConverter::parseInt(elem.attribute("vertexindex").value()); + vba.boneIndex = StringConverter::parseInt(elem.attribute("boneindex").value()); + vba.weight = StringConverter::parseReal(elem.attribute("weight").value()); sm->addBoneAssignment(vba); } LogManager::getSingleton().logMessage("Bone assignments done."); } //--------------------------------------------------------------------- - void XMLMeshSerializer::writeLodInfo(TiXmlElement* mMeshNode, const Mesh* pMesh) + void XMLMeshSerializer::writeLodInfo(pugi::xml_node& mMeshNode, const Mesh* pMesh) { - TiXmlElement* lodNode = - mMeshNode->InsertEndChild(TiXmlElement("levelofdetail"))->ToElement(); + pugi::xml_node lodNode = mMeshNode.append_child("levelofdetail"); const LodStrategy *strategy = pMesh->getLodStrategy(); unsigned short numLvls = pMesh->getNumLodLevels(); bool manual = pMesh->hasManualLodLevel(); - lodNode->SetAttribute("strategy", strategy->getName()); - lodNode->SetAttribute("numlevels", StringConverter::toString(numLvls)); - lodNode->SetAttribute("manual", StringConverter::toString(manual)); + lodNode.append_attribute("strategy") = strategy->getName().c_str(); + lodNode.append_attribute("numlevels") = StringConverter::toString(numLvls).c_str(); + lodNode.append_attribute("manual") = StringConverter::toString(manual).c_str(); // Iterate from level 1, not 0 (full detail) for (unsigned short i = 1; i < numLvls; ++i) @@ -1505,61 +1444,56 @@ namespace Ogre { } //--------------------------------------------------------------------- - void XMLMeshSerializer::writeSubMeshNames(TiXmlElement* mMeshNode, const Mesh* m) + void XMLMeshSerializer::writeSubMeshNames(pugi::xml_node& mMeshNode, const Mesh* m) { const Mesh::SubMeshNameMap& nameMap = m->getSubMeshNameMap(); if (nameMap.empty()) return; // do nothing - TiXmlElement* namesNode = - mMeshNode->InsertEndChild(TiXmlElement("submeshnames"))->ToElement(); + pugi::xml_node namesNode = mMeshNode.append_child("submeshnames"); Mesh::SubMeshNameMap::const_iterator i, iend; iend = nameMap.end(); for (i = nameMap.begin(); i != iend; ++i) { - TiXmlElement* subNameNode = - namesNode->InsertEndChild(TiXmlElement("submeshname"))->ToElement(); + pugi::xml_node subNameNode = namesNode.append_child("submeshname"); - subNameNode->SetAttribute("name", i->first); - subNameNode->SetAttribute("index", - StringConverter::toString(i->second)); + subNameNode.append_attribute("name") = i->first.c_str(); + subNameNode.append_attribute("index") = + StringConverter::toString(i->second).c_str(); } } //--------------------------------------------------------------------- - void XMLMeshSerializer::writeLodUsageManual(TiXmlElement* usageNode, + void XMLMeshSerializer::writeLodUsageManual(pugi::xml_node& usageNode, unsigned short levelNum, const MeshLodUsage& usage) { - TiXmlElement* manualNode = - usageNode->InsertEndChild(TiXmlElement("lodmanual"))->ToElement(); + pugi::xml_node manualNode = usageNode.append_child("lodmanual"); - manualNode->SetAttribute("value", - StringConverter::toString(usage.userValue)); - manualNode->SetAttribute("meshname", usage.manualName); + manualNode.append_attribute("value") = + StringConverter::toString(usage.userValue).c_str(); + manualNode.append_attribute("meshname") = usage.manualName.c_str(); } //--------------------------------------------------------------------- - void XMLMeshSerializer::writeLodUsageGenerated(TiXmlElement* usageNode, + void XMLMeshSerializer::writeLodUsageGenerated(pugi::xml_node& usageNode, unsigned short levelNum, const MeshLodUsage& usage, const Mesh* pMesh) { - TiXmlElement* generatedNode = - usageNode->InsertEndChild(TiXmlElement("lodgenerated"))->ToElement(); - generatedNode->SetAttribute("value", - StringConverter::toString(usage.userValue)); + pugi::xml_node generatedNode = usageNode.append_child("lodgenerated"); + generatedNode.append_attribute("value") = + StringConverter::toString(usage.userValue).c_str(); // Iterate over submeshes at this level size_t numsubs = pMesh->getNumSubMeshes(); for (size_t subi = 0; subi < numsubs; ++subi) { - TiXmlElement* subNode = - generatedNode->InsertEndChild(TiXmlElement("lodfacelist"))->ToElement(); + pugi::xml_node subNode = generatedNode.append_child("lodfacelist"); SubMesh* sub = pMesh->getSubMesh(subi); - subNode->SetAttribute("submeshindex", StringConverter::toString(subi)); + subNode.append_attribute("submeshindex") = StringConverter::toString(subi).c_str(); // NB level - 1 because SubMeshes don't store the first index in geometry IndexData* facedata = sub->mLodFaceList[levelNum - 1]; - subNode->SetAttribute("numfaces", StringConverter::toString(facedata->indexCount / 3)); + subNode.append_attribute("numfaces") = StringConverter::toString(facedata->indexCount / 3).c_str(); if (facedata->indexCount > 0) { @@ -1585,19 +1519,19 @@ namespace Ogre { for (size_t f = 0; f < facedata->indexCount; f += 3) { - TiXmlElement* faceNode = - subNode->InsertEndChild(TiXmlElement("face"))->ToElement(); + pugi::xml_node faceNode = + subNode.append_child("face"); if (use32BitIndexes) { - faceNode->SetAttribute("v1", StringConverter::toString(*pInt++)); - faceNode->SetAttribute("v2", StringConverter::toString(*pInt++)); - faceNode->SetAttribute("v3", StringConverter::toString(*pInt++)); + faceNode.append_attribute("v1") = StringConverter::toString(*pInt++).c_str(); + faceNode.append_attribute("v2") = StringConverter::toString(*pInt++).c_str(); + faceNode.append_attribute("v3") = StringConverter::toString(*pInt++).c_str(); } else { - faceNode->SetAttribute("v1", StringConverter::toString(*pShort++)); - faceNode->SetAttribute("v2", StringConverter::toString(*pShort++)); - faceNode->SetAttribute("v3", StringConverter::toString(*pShort++)); + faceNode.append_attribute("v1") = StringConverter::toString(*pShort++).c_str(); + faceNode.append_attribute("v2") = StringConverter::toString(*pShort++).c_str(); + faceNode.append_attribute("v3") = StringConverter::toString(*pShort++).c_str(); } } @@ -1609,9 +1543,9 @@ namespace Ogre { } //--------------------------------------------------------------------- - void XMLMeshSerializer::writeExtremes(TiXmlElement* mMeshNode, const Mesh* m) + void XMLMeshSerializer::writeExtremes(pugi::xml_node& mMeshNode, const Mesh* m) { - TiXmlElement* extremesNode = NULL; + pugi::xml_node extremesNode; size_t submeshCount = m->getNumSubMeshes(); for (size_t idx = 0; idx < submeshCount; ++idx) { @@ -1620,31 +1554,29 @@ namespace Ogre { continue; // do nothing if (!extremesNode) - extremesNode = mMeshNode->InsertEndChild(TiXmlElement("extremes"))->ToElement(); + extremesNode = mMeshNode.append_child("extremes"); - TiXmlElement* submeshNode = - extremesNode->InsertEndChild(TiXmlElement("submesh_extremes"))->ToElement(); + pugi::xml_node submeshNode = extremesNode.append_child("submesh_extremes"); - submeshNode->SetAttribute("index", StringConverter::toString(idx)); + submeshNode.append_attribute("index") = StringConverter::toString(idx).c_str(); for (std::vector::const_iterator v = sm->extremityPoints.begin (); v != sm->extremityPoints.end (); ++v) { - TiXmlElement* vert = submeshNode->InsertEndChild( - TiXmlElement("position"))->ToElement(); - vert->SetAttribute("x", StringConverter::toString(v->x)); - vert->SetAttribute("y", StringConverter::toString(v->y)); - vert->SetAttribute("z", StringConverter::toString(v->z)); + pugi::xml_node vert = submeshNode.append_child("position"); + vert.append_attribute("x") = StringConverter::toString(v->x).c_str(); + vert.append_attribute("y") = StringConverter::toString(v->y).c_str(); + vert.append_attribute("z") = StringConverter::toString(v->z).c_str(); } } } //--------------------------------------------------------------------- - void XMLMeshSerializer::readLodInfo(TiXmlElement* lodNode) + void XMLMeshSerializer::readLodInfo(pugi::xml_node& lodNode) { LogManager::getSingleton().logMessage("Parsing LOD information..."); - const char* val = lodNode->Attribute("strategy"); + const char* val = lodNode.attribute("strategy").as_string(NULL); // This attribute is optional to maintain backwards compatibility if (val) { @@ -1653,11 +1585,11 @@ namespace Ogre { mMesh->setLodStrategy(strategy); } - val = lodNode->Attribute("numlevels"); + val = lodNode.attribute("numlevels").value(); unsigned short numLevels = static_cast( StringConverter::parseUnsignedInt(val)); - val = lodNode->Attribute("manual"); + val = lodNode.attribute("manual").value(); StringConverter::parseBool(val); // Set up the basic structures @@ -1665,18 +1597,16 @@ namespace Ogre { // Parse the detail, start from 1 (the first sub-level of detail) unsigned short i = 1; - TiXmlElement* usageElem = lodNode->FirstChildElement(); - while (usageElem) + for (auto usageElem : lodNode.children()) { - if (usageElem->ValueStr() == "lodmanual") + if (usageElem.name() == String("lodmanual")) { readLodUsageManual(usageElem, i); } - else if (usageElem->ValueStr() == "lodgenerated") + else if (usageElem.name() == String("lodgenerated")) { readLodUsageGenerated(usageElem, i); } - usageElem = usageElem->NextSiblingElement(); ++i; } @@ -1684,15 +1614,15 @@ namespace Ogre { } //--------------------------------------------------------------------- - void XMLMeshSerializer::readLodUsageManual(TiXmlElement* manualNode, unsigned short index) + void XMLMeshSerializer::readLodUsageManual(pugi::xml_node& manualNode, unsigned short index) { MeshLodUsage usage; - const char* val = manualNode->Attribute("value"); + const char* val = manualNode.attribute("value").as_string(NULL); // If value attribute not found check for old name if (!val) { - val = manualNode->Attribute("fromdepthsquared"); + val = manualNode.attribute("fromdepthsquared").as_string(NULL); if (val) LogManager::getSingleton().logWarning("'fromdepthsquared' attribute has been renamed to 'value'."); // user values are non-squared @@ -1703,7 +1633,7 @@ namespace Ogre { usage.userValue = StringConverter::parseReal(val); } usage.value = mMesh->getLodStrategy()->transformUserValue(usage.userValue); - usage.manualName = manualNode->Attribute("meshname"); + usage.manualName = manualNode.attribute("meshname").value(); usage.edgeData = NULL; // Generate for mixed @@ -1717,15 +1647,15 @@ namespace Ogre { mMesh->_setLodUsage(index, usage); } //--------------------------------------------------------------------- - void XMLMeshSerializer::readLodUsageGenerated(TiXmlElement* genNode, unsigned short index) + void XMLMeshSerializer::readLodUsageGenerated(pugi::xml_node& genNode, unsigned short index) { MeshLodUsage usage; - const char* val = genNode->Attribute("value"); + const char* val = genNode.attribute("value").as_string(NULL); // If value attribute not found check for old name if (!val) { - val = genNode->Attribute("fromdepthsquared"); + val = genNode.attribute("fromdepthsquared").value(); if (val) LogManager::getSingleton().logWarning("'fromdepthsquared' attribute has been renamed to 'value'."); // user values are non-squared @@ -1743,13 +1673,13 @@ namespace Ogre { mMesh->_setLodUsage(index, usage); // Read submesh face lists - TiXmlElement* faceListElem = genNode->FirstChildElement("lodfacelist"); + HardwareIndexBufferSharedPtr ibuf; - while (faceListElem) + for (pugi::xml_node faceListElem : genNode.children("lodfacelist")) { - val = faceListElem->Attribute("submeshindex"); + val = faceListElem.attribute("submeshindex").value(); unsigned short subidx = StringConverter::parseUnsignedInt(val); - val = faceListElem->Attribute("numfaces"); + val = faceListElem.attribute("numfaces").value(); unsigned short numFaces = StringConverter::parseUnsignedInt(val); if (numFaces) { @@ -1775,25 +1705,25 @@ namespace Ogre { pShort = static_cast( ibuf->lock(HardwareBuffer::HBL_DISCARD)); } - TiXmlElement* faceElem = faceListElem->FirstChildElement("face"); - for (unsigned int face = 0; face < numFaces; ++face, faceElem = faceElem->NextSiblingElement()) + pugi::xml_node faceElem = faceListElem.child("face"); + for (unsigned int face = 0; face < numFaces; ++face, faceElem = faceElem.next_sibling()) { if (use32bitindexes) { - val = faceElem->Attribute("v1"); + val = faceElem.attribute("v1").value(); *pInt++ = StringConverter::parseUnsignedInt(val); - val = faceElem->Attribute("v2"); + val = faceElem.attribute("v2").value(); *pInt++ = StringConverter::parseUnsignedInt(val); - val = faceElem->Attribute("v3"); + val = faceElem.attribute("v3").value(); *pInt++ = StringConverter::parseUnsignedInt(val); } else { - val = faceElem->Attribute("v1"); + val = faceElem.attribute("v1").value(); *pShort++ = StringConverter::parseUnsignedInt(val); - val = faceElem->Attribute("v2"); + val = faceElem.attribute("v2").value(); *pShort++ = StringConverter::parseUnsignedInt(val); - val = faceElem->Attribute("v3"); + val = faceElem.attribute("v3").value(); *pShort++ = StringConverter::parseUnsignedInt(val); } @@ -1806,31 +1736,27 @@ namespace Ogre { facedata->indexStart = 0; facedata->indexBuffer = ibuf; mMesh->_setSubMeshLodFaceList(subidx, index, facedata); - - faceListElem = faceListElem->NextSiblingElement(); } } //----------------------------------------------------------------------------- - void XMLMeshSerializer::readExtremes(TiXmlElement* extremesNode, Mesh *m) + void XMLMeshSerializer::readExtremes(pugi::xml_node& extremesNode, Mesh *m) { LogManager::getSingleton().logMessage("Reading extremes..."); // Iterate over all children (submesh_extreme list) - for (TiXmlElement* elem = extremesNode->FirstChildElement(); - elem != 0; elem = elem->NextSiblingElement()) + for (pugi::xml_node& elem : extremesNode.children()) { - int index = StringConverter::parseInt(elem->Attribute("index")); + int index = StringConverter::parseInt(elem.attribute("index").value()); SubMesh *sm = m->getSubMesh(index); sm->extremityPoints.clear (); - for (TiXmlElement* vert = elem->FirstChildElement(); - vert != 0; vert = vert->NextSiblingElement()) + for (pugi::xml_node& vert : elem.children()) { Vector3 v; - v.x = StringConverter::parseReal(vert->Attribute("x")); - v.y = StringConverter::parseReal(vert->Attribute("y")); - v.z = StringConverter::parseReal(vert->Attribute("z")); + v.x = StringConverter::parseReal(vert.attribute("x").value()); + v.y = StringConverter::parseReal(vert.attribute("y").value()); + v.z = StringConverter::parseReal(vert.attribute("z").value()); sm->extremityPoints.push_back (v); } } @@ -1838,13 +1764,13 @@ namespace Ogre { LogManager::getSingleton().logMessage("Extremes done."); } //----------------------------------------------------------------------------- - void XMLMeshSerializer::readPoses(TiXmlElement* posesNode, Mesh *m) + void XMLMeshSerializer::readPoses(pugi::xml_node& posesNode, Mesh *m) { - TiXmlElement* poseNode = posesNode->FirstChildElement("pose"); - while (poseNode) + + for (pugi::xml_node poseNode : posesNode.children("pose")) { - const char* target = poseNode->Attribute("target"); + const char* target = poseNode.attribute("target").as_string(NULL); if (!target) { OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, @@ -1859,7 +1785,7 @@ namespace Ogre { else { // submesh, get index - const char* val = poseNode->Attribute("index"); + const char* val = poseNode.attribute("index").as_string(NULL); if (!val) { OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, @@ -1873,29 +1799,27 @@ namespace Ogre { } String name; - const char* val = poseNode->Attribute("name"); + const char* val = poseNode.attribute("name").as_string(NULL); if (val) name = val; Pose* pose = m->createPose(targetID, name); - TiXmlElement* poseOffsetNode = poseNode->FirstChildElement("poseoffset"); - while (poseOffsetNode) + for (pugi::xml_node poseOffsetNode : poseNode.children("poseoffset")) { - uint index = StringConverter::parseUnsignedInt( - poseOffsetNode->Attribute("index")); + uint index = StringConverter::parseUnsignedInt(poseOffsetNode.attribute("index").value()); Vector3 offset; - offset.x = StringConverter::parseReal(poseOffsetNode->Attribute("x")); - offset.y = StringConverter::parseReal(poseOffsetNode->Attribute("y")); - offset.z = StringConverter::parseReal(poseOffsetNode->Attribute("z")); + offset.x = StringConverter::parseReal(poseOffsetNode.attribute("x").value()); + offset.y = StringConverter::parseReal(poseOffsetNode.attribute("y").value()); + offset.z = StringConverter::parseReal(poseOffsetNode.attribute("z").value()); - if (poseOffsetNode->Attribute("nx") && - poseOffsetNode->Attribute("ny") && - poseOffsetNode->Attribute("nz")) + if (poseOffsetNode.attribute("nx").value() && + poseOffsetNode.attribute("ny").value() && + poseOffsetNode.attribute("nz").value()) { Vector3 normal; - normal.x = StringConverter::parseReal(poseOffsetNode->Attribute("nx")); - normal.y = StringConverter::parseReal(poseOffsetNode->Attribute("ny")); - normal.z = StringConverter::parseReal(poseOffsetNode->Attribute("nz")); + normal.x = StringConverter::parseReal(poseOffsetNode.attribute("nx").value()); + normal.y = StringConverter::parseReal(poseOffsetNode.attribute("ny").value()); + normal.z = StringConverter::parseReal(poseOffsetNode.attribute("nz").value()); pose->addVertex(index, offset, normal); } @@ -1903,56 +1827,45 @@ namespace Ogre { { pose->addVertex(index, offset); } - - poseOffsetNode = poseOffsetNode->NextSiblingElement(); - } - - poseNode = poseNode->NextSiblingElement(); - } } //----------------------------------------------------------------------------- - void XMLMeshSerializer::readAnimations(TiXmlElement* mAnimationsNode, Mesh *pMesh) + void XMLMeshSerializer::readAnimations(pugi::xml_node& mAnimationsNode, Mesh *pMesh) { - TiXmlElement* animElem = mAnimationsNode->FirstChildElement("animation"); - while (animElem) + for (pugi::xml_node animElem : mAnimationsNode.children("animation")) { - String name = animElem->Attribute("name"); - const char* charLen = animElem->Attribute("length"); + String name = animElem.attribute("name").value(); + const char* charLen = animElem.attribute("length").as_string(NULL); Real len = StringConverter::parseReal(charLen); Animation* anim = pMesh->createAnimation(name, len); - TiXmlElement* baseInfoNode = animElem->FirstChildElement("baseinfo"); + pugi::xml_node baseInfoNode = animElem.child("baseinfo"); if (baseInfoNode) { - String baseName = baseInfoNode->Attribute("baseanimationname"); - Real baseTime = StringConverter::parseReal(baseInfoNode->Attribute("basekeyframetime")); + String baseName = baseInfoNode.attribute("baseanimationname").value(); + Real baseTime = StringConverter::parseReal(baseInfoNode.attribute("basekeyframetime").value()); anim->setUseBaseKeyFrame(true, baseTime, baseName); } - TiXmlElement* tracksNode = animElem->FirstChildElement("tracks"); + pugi::xml_node tracksNode = animElem.child("tracks"); if (tracksNode) { readTracks(tracksNode, pMesh, anim); } - - animElem = animElem->NextSiblingElement(); - } } //----------------------------------------------------------------------------- - void XMLMeshSerializer::readTracks(TiXmlElement* tracksNode, Mesh *m, Animation* anim) + void XMLMeshSerializer::readTracks(pugi::xml_node& tracksNode, Mesh *m, Animation* anim) { - TiXmlElement* trackNode = tracksNode->FirstChildElement("track"); - while (trackNode) + for (pugi::xml_node trackNode : tracksNode.children("track")) { - String target = trackNode->Attribute("target"); + String target = trackNode.attribute("target").value(); unsigned short targetID; VertexData* vertexData = 0; if(target == "mesh") @@ -1963,7 +1876,7 @@ namespace Ogre { else { // submesh, get index - const char* val = trackNode->Attribute("index"); + const char* val = trackNode.attribute("index").as_string(NULL); if (!val) { OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, @@ -1988,7 +1901,7 @@ namespace Ogre { // Get type VertexAnimationType animType = VAT_NONE; - String strAnimType = trackNode->Attribute("type"); + String strAnimType = trackNode.attribute("type").value(); if (strAnimType == "morph") { animType = VAT_MORPH; @@ -2008,7 +1921,7 @@ namespace Ogre { VertexAnimationTrack* track = anim->createVertexTrack(targetID, vertexData, animType); - TiXmlElement* keyframesNode = trackNode->FirstChildElement("keyframes"); + pugi::xml_node keyframesNode = trackNode.child("keyframes"); if (keyframesNode) { if (track->getAnimationType() == VAT_MORPH) @@ -2020,18 +1933,15 @@ namespace Ogre { readPoseKeyFrames(keyframesNode, track); } } - - trackNode = trackNode->NextSiblingElement(); } } //----------------------------------------------------------------------------- - void XMLMeshSerializer::readMorphKeyFrames(TiXmlElement* keyframesNode, + void XMLMeshSerializer::readMorphKeyFrames(pugi::xml_node& keyframesNode, VertexAnimationTrack* track, size_t vertexCount) { - TiXmlElement* keyNode = keyframesNode->FirstChildElement("keyframe"); - while (keyNode) + for (pugi::xml_node keyNode : keyframesNode.children("keyframe")) { - const char* val = keyNode->Attribute("time"); + const char* val = keyNode.attribute("time").as_string(NULL); if (!val) { OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, @@ -2042,7 +1952,7 @@ namespace Ogre { VertexMorphKeyFrame* kf = track->createVertexMorphKeyFrame(time); - bool includesNormals = keyNode->FirstChildElement("normal") != 0; + bool includesNormals = keyNode.child("normal"); size_t vertexSize = sizeof(float) * (includesNormals ? 6 : 3); // create a vertex buffer @@ -2055,8 +1965,8 @@ namespace Ogre { vbuf->lock(HardwareBuffer::HBL_DISCARD)); - TiXmlElement* posNode = keyNode->FirstChildElement("position"); - TiXmlElement* normNode = keyNode->FirstChildElement("normal"); + pugi::xml_node posNode = keyNode.child("position"); + pugi::xml_node normNode = keyNode.child("normal"); for (size_t v = 0; v < vertexCount; ++v) { if (!posNode) @@ -2067,12 +1977,9 @@ namespace Ogre { } - *pFloat++ = StringConverter::parseReal( - posNode->Attribute("x")); - *pFloat++ = StringConverter::parseReal( - posNode->Attribute("y")); - *pFloat++ = StringConverter::parseReal( - posNode->Attribute("z")); + *pFloat++ = StringConverter::parseReal(posNode.attribute("x").value()); + *pFloat++ = StringConverter::parseReal(posNode.attribute("y").value()); + *pFloat++ = StringConverter::parseReal(posNode.attribute("z").value()); if (includesNormals) { @@ -2084,36 +1991,29 @@ namespace Ogre { } - *pFloat++ = StringConverter::parseReal( - normNode->Attribute("x")); - *pFloat++ = StringConverter::parseReal( - normNode->Attribute("y")); - *pFloat++ = StringConverter::parseReal( - normNode->Attribute("z")); - normNode = normNode->NextSiblingElement("normal"); + *pFloat++ = StringConverter::parseReal(normNode.attribute("x").value()); + *pFloat++ = StringConverter::parseReal(normNode.attribute("y").value()); + *pFloat++ = StringConverter::parseReal(normNode.attribute("z").value()); + normNode = normNode.next_sibling("normal"); } - posNode = posNode->NextSiblingElement("position"); + posNode = posNode.next_sibling("position"); } vbuf->unlock(); kf->setVertexBuffer(vbuf); - - - keyNode = keyNode->NextSiblingElement(); } } //----------------------------------------------------------------------------- - void XMLMeshSerializer::readPoseKeyFrames(TiXmlElement* keyframesNode, VertexAnimationTrack* track) + void XMLMeshSerializer::readPoseKeyFrames(pugi::xml_node& keyframesNode, VertexAnimationTrack* track) { - TiXmlElement* keyNode = keyframesNode->FirstChildElement("keyframe"); - while (keyNode) + for (pugi::xml_node keyNode : keyframesNode.children("keyframe")) { - const char* val = keyNode->Attribute("time"); + const char* val = keyNode.attribute("time").as_string(NULL); if (!val) { OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, @@ -2125,10 +2025,9 @@ namespace Ogre { VertexPoseKeyFrame* kf = track->createVertexPoseKeyFrame(time); // Read all pose references - TiXmlElement* poseRefNode = keyNode->FirstChildElement("poseref"); - while (poseRefNode) + for (pugi::xml_node poseRefNode : keyNode.children("poseref")) { - const char* attr = poseRefNode->Attribute("poseindex"); + const char* attr = poseRefNode.attribute("poseindex").as_string(NULL); if (!attr) { OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, @@ -2137,50 +2036,44 @@ namespace Ogre { } unsigned short poseIndex = StringConverter::parseUnsignedInt(attr); Real influence = 1.0f; - attr = poseRefNode->Attribute("influence"); + attr = poseRefNode.attribute("influence").as_string(NULL); if (attr) { influence = StringConverter::parseReal(attr); } kf->addPoseReference(poseIndex, influence); - - poseRefNode = poseRefNode->NextSiblingElement(); } - - keyNode = keyNode->NextSiblingElement(); } } //----------------------------------------------------------------------------- - void XMLMeshSerializer::writePoses(TiXmlElement* meshNode, const Mesh* m) + void XMLMeshSerializer::writePoses(pugi::xml_node& meshNode, const Mesh* m) { if (m->getPoseList().empty()) return; - TiXmlElement* posesNode = - meshNode->InsertEndChild(TiXmlElement("poses"))->ToElement(); + pugi::xml_node posesNode = meshNode.append_child("poses"); PoseList::const_iterator it; for( it = m->getPoseList().begin(); it != m->getPoseList().end(); ++it) { const Pose* pose = *it; - TiXmlElement* poseNode = - posesNode->InsertEndChild(TiXmlElement("pose"))->ToElement(); + pugi::xml_node poseNode = posesNode.append_child("pose"); unsigned short target = pose->getTarget(); if (target == 0) { // Main mesh - poseNode->SetAttribute("target", "mesh"); + poseNode.append_attribute("target") = "mesh"; } else { // Submesh - rebase index - poseNode->SetAttribute("target", "submesh"); - poseNode->SetAttribute("index", - StringConverter::toString(target - 1)); + poseNode.append_attribute("target") = "submesh"; + poseNode.append_attribute("index") = + StringConverter::toString(target - 1).c_str(); } - poseNode->SetAttribute("name", pose->getName()); + poseNode.append_attribute("name") = pose->getName().c_str(); bool includesNormals = !pose->getNormals().empty(); @@ -2188,23 +2081,22 @@ namespace Ogre { Pose::ConstNormalsIterator nit = pose->getNormalsIterator(); while (vit.hasMoreElements()) { - TiXmlElement* poseOffsetElement = poseNode->InsertEndChild( - TiXmlElement("poseoffset"))->ToElement(); + pugi::xml_node poseOffsetElement = poseNode.append_child("poseoffset"); - poseOffsetElement->SetAttribute("index", - StringConverter::toString(vit.peekNextKey())); + poseOffsetElement.append_attribute("index") = + StringConverter::toString(vit.peekNextKey()).c_str(); Vector3 offset = vit.getNext(); - poseOffsetElement->SetAttribute("x", StringConverter::toString(offset.x)); - poseOffsetElement->SetAttribute("y", StringConverter::toString(offset.y)); - poseOffsetElement->SetAttribute("z", StringConverter::toString(offset.z)); + poseOffsetElement.append_attribute("x") = StringConverter::toString(offset.x).c_str(); + poseOffsetElement.append_attribute("y") = StringConverter::toString(offset.y).c_str(); + poseOffsetElement.append_attribute("z") = StringConverter::toString(offset.z).c_str(); if (includesNormals) { Vector3 normal = nit.getNext(); - poseOffsetElement->SetAttribute("nx", StringConverter::toString(normal.x)); - poseOffsetElement->SetAttribute("ny", StringConverter::toString(normal.y)); - poseOffsetElement->SetAttribute("nz", StringConverter::toString(normal.z)); + poseOffsetElement.append_attribute("nx") = StringConverter::toString(normal.x).c_str(); + poseOffsetElement.append_attribute("ny") = StringConverter::toString(normal.y).c_str(); + poseOffsetElement.append_attribute("nz") = StringConverter::toString(normal.z).c_str(); } @@ -2216,63 +2108,60 @@ namespace Ogre { } //----------------------------------------------------------------------------- - void XMLMeshSerializer::writeAnimations(TiXmlElement* meshNode, const Mesh* m) + void XMLMeshSerializer::writeAnimations(pugi::xml_node& meshNode, const Mesh* m) { // Skip if no animation if (!m->hasVertexAnimation()) return; - TiXmlElement* animationsNode = - meshNode->InsertEndChild(TiXmlElement("animations"))->ToElement(); + pugi::xml_node animationsNode = meshNode.append_child("animations"); for (unsigned short a = 0; a < m->getNumAnimations(); ++a) { Animation* anim = m->getAnimation(a); - TiXmlElement* animNode = - animationsNode->InsertEndChild(TiXmlElement("animation"))->ToElement(); - animNode->SetAttribute("name", anim->getName()); - animNode->SetAttribute("length", - StringConverter::toString(anim->getLength())); + pugi::xml_node animNode = + animationsNode.append_child("animation"); + animNode.append_attribute("name") = anim->getName().c_str(); + animNode.append_attribute("length") = + StringConverter::toString(anim->getLength()).c_str(); // Optional base keyframe information if (anim->getUseBaseKeyFrame()) { - TiXmlElement* baseInfoNode = - animNode->InsertEndChild(TiXmlElement("baseinfo"))->ToElement(); - baseInfoNode->SetAttribute("baseanimationname", anim->getBaseKeyFrameAnimationName()); - baseInfoNode->SetAttribute("basekeyframetime", StringConverter::toString(anim->getBaseKeyFrameTime())); + pugi::xml_node baseInfoNode = + animNode.append_child("baseinfo"); + baseInfoNode.append_attribute("baseanimationname") = anim->getBaseKeyFrameAnimationName().c_str(); + baseInfoNode.append_attribute("basekeyframetime") = StringConverter::toString(anim->getBaseKeyFrameTime()).c_str(); } - TiXmlElement* tracksNode = - animNode->InsertEndChild(TiXmlElement("tracks"))->ToElement(); + pugi::xml_node tracksNode = animNode.append_child("tracks"); Animation::VertexTrackIterator iter = anim->getVertexTrackIterator(); while(iter.hasMoreElements()) { const VertexAnimationTrack* track = iter.getNext(); - TiXmlElement* trackNode = - tracksNode->InsertEndChild(TiXmlElement("track"))->ToElement(); + pugi::xml_node trackNode = tracksNode.append_child("track"); unsigned short targetID = track->getHandle(); if (targetID == 0) { - trackNode->SetAttribute("target", "mesh"); + trackNode.append_attribute("target") = "mesh"; } else { - trackNode->SetAttribute("target", "submesh"); - trackNode->SetAttribute("index", - StringConverter::toString(targetID-1)); + trackNode.append_attribute("target") = "submesh"; + trackNode.append_attribute("index") = + StringConverter::toString(targetID-1).c_str(); } if (track->getAnimationType() == VAT_MORPH) { - trackNode->SetAttribute("type", "morph"); + trackNode.append_attribute("type") = "morph"; writeMorphKeyFrames(trackNode, track); } else { - trackNode->SetAttribute("type", "pose"); + trackNode.append_attribute("type") = "pose"; writePoseKeyFrames(trackNode, track); } @@ -2283,20 +2172,18 @@ namespace Ogre { } //----------------------------------------------------------------------------- - void XMLMeshSerializer::writeMorphKeyFrames(TiXmlElement* trackNode, const VertexAnimationTrack* track) + void XMLMeshSerializer::writeMorphKeyFrames(pugi::xml_node& trackNode, const VertexAnimationTrack* track) { - TiXmlElement* keyframesNode = - trackNode->InsertEndChild(TiXmlElement("keyframes"))->ToElement(); + pugi::xml_node keyframesNode = trackNode.append_child("keyframes"); size_t vertexCount = track->getAssociatedVertexData()->vertexCount; for (unsigned short k = 0; k < track->getNumKeyFrames(); ++k) { VertexMorphKeyFrame* kf = track->getVertexMorphKeyFrame(k); - TiXmlElement* keyNode = - keyframesNode->InsertEndChild(TiXmlElement("keyframe"))->ToElement(); - keyNode->SetAttribute("time", - StringConverter::toString(kf->getTime())); + pugi::xml_node keyNode = keyframesNode.append_child("keyframe"); + keyNode.append_attribute("time") = + StringConverter::toString(kf->getTime()).c_str(); HardwareVertexBufferSharedPtr vbuf = kf->getVertexBuffer(); @@ -2307,50 +2194,45 @@ namespace Ogre { for (size_t v = 0; v < vertexCount; ++v) { - TiXmlElement* posNode = - keyNode->InsertEndChild(TiXmlElement("position"))->ToElement(); - posNode->SetAttribute("x", StringConverter::toString(*pFloat++)); - posNode->SetAttribute("y", StringConverter::toString(*pFloat++)); - posNode->SetAttribute("z", StringConverter::toString(*pFloat++)); + pugi::xml_node posNode = keyNode.append_child("position"); + posNode.append_attribute("x") = StringConverter::toString(*pFloat++).c_str(); + posNode.append_attribute("y") = StringConverter::toString(*pFloat++).c_str(); + posNode.append_attribute("z") = StringConverter::toString(*pFloat++).c_str(); if (includesNormals) { - TiXmlElement* normNode = - keyNode->InsertEndChild(TiXmlElement("normal"))->ToElement(); - normNode->SetAttribute("x", StringConverter::toString(*pFloat++)); - normNode->SetAttribute("y", StringConverter::toString(*pFloat++)); - normNode->SetAttribute("z", StringConverter::toString(*pFloat++)); + pugi::xml_node normNode = keyNode.append_child("normal"); + normNode.append_attribute("x") = StringConverter::toString(*pFloat++).c_str(); + normNode.append_attribute("y") = StringConverter::toString(*pFloat++).c_str(); + normNode.append_attribute("z") = StringConverter::toString(*pFloat++).c_str(); } } } } //----------------------------------------------------------------------------- - void XMLMeshSerializer::writePoseKeyFrames(TiXmlElement* trackNode, const VertexAnimationTrack* track) + void XMLMeshSerializer::writePoseKeyFrames(pugi::xml_node& trackNode, const VertexAnimationTrack* track) { - TiXmlElement* keyframesNode = - trackNode->InsertEndChild(TiXmlElement("keyframes"))->ToElement(); + pugi::xml_node keyframesNode = trackNode.append_child("keyframes"); for (unsigned short k = 0; k < track->getNumKeyFrames(); ++k) { VertexPoseKeyFrame* kf = track->getVertexPoseKeyFrame(k); - TiXmlElement* keyNode = - keyframesNode->InsertEndChild(TiXmlElement("keyframe"))->ToElement(); - keyNode->SetAttribute("time", - StringConverter::toString(kf->getTime())); + pugi::xml_node keyNode = keyframesNode.append_child("keyframe"); + keyNode.append_attribute("time") = + StringConverter::toString(kf->getTime()).c_str(); VertexPoseKeyFrame::PoseRefList::const_iterator poseIt = kf->getPoseReferences().begin(); for (;poseIt != kf->getPoseReferences().end(); ++poseIt) { const VertexPoseKeyFrame::PoseRef& poseRef = *poseIt; - TiXmlElement* poseRefNode = - keyNode->InsertEndChild(TiXmlElement("poseref"))->ToElement(); + pugi::xml_node poseRefNode = keyNode.append_child("poseref"); - poseRefNode->SetAttribute("poseindex", - StringConverter::toString(poseRef.poseIndex)); - poseRefNode->SetAttribute("influence", - StringConverter::toString(poseRef.influence)); + poseRefNode.append_attribute("poseindex") = + StringConverter::toString(poseRef.poseIndex).c_str(); + poseRefNode.append_attribute("influence") = + StringConverter::toString(poseRef.influence).c_str(); } diff --git a/Tools/XMLConverter/src/OgreXMLSkeletonSerializer.cpp b/Tools/XMLConverter/src/OgreXMLSkeletonSerializer.cpp index 65c7d61b109..8d239e6144c 100644 --- a/Tools/XMLConverter/src/OgreXMLSkeletonSerializer.cpp +++ b/Tools/XMLConverter/src/OgreXMLSkeletonSerializer.cpp @@ -56,15 +56,15 @@ namespace Ogre { { LogManager::getSingleton().logMessage("XMLSkeletonSerializer: reading XML data from " + filename + "..."); - mXMLDoc = new TiXmlDocument(filename); - mXMLDoc->LoadFile(); + pugi::xml_document mXMLDoc; + mXMLDoc.load_file(filename.c_str()); - TiXmlElement* elem; + pugi::xml_node elem; - TiXmlElement* rootElem = mXMLDoc->RootElement(); + pugi::xml_node rootElem = mXMLDoc.document_element(); // Optional blend mode - const char* blendModeStr = rootElem->Attribute("blendmode"); + const char* blendModeStr = rootElem.attribute("blendmode").as_string(NULL); if (blendModeStr) { if (String(blendModeStr) == "cumulative") @@ -76,25 +76,25 @@ namespace Ogre { // Bones - elem = rootElem->FirstChildElement("bones"); + elem = rootElem.child("bones"); if (elem) { readBones(pSkeleton, elem); - elem = rootElem->FirstChildElement("bonehierarchy"); + elem = rootElem.child("bonehierarchy"); if (elem) { createHierarchy(pSkeleton, elem) ; - elem = rootElem->FirstChildElement("bones"); + elem = rootElem.child("bones"); if (elem) { readBones2(pSkeleton, elem); - elem = rootElem->FirstChildElement("animations"); + elem = rootElem.child("animations"); if (elem) { readAnimations(pSkeleton, elem); } - elem = rootElem->FirstChildElement("animationlinks"); + elem = rootElem.child("animationlinks"); if (elem) { readSkeletonAnimationLinks(pSkeleton, elem); @@ -108,60 +108,58 @@ namespace Ogre { //--------------------------------------------------------------------- // sets names - void XMLSkeletonSerializer::readBones(Skeleton* skel, TiXmlElement* mBonesNode) + void XMLSkeletonSerializer::readBones(Skeleton* skel, pugi::xml_node& mBonesNode) { LogManager::getSingleton().logMessage("XMLSkeletonSerializer: Reading Bones name..."); Quaternion quat ; - for (TiXmlElement* bonElem = mBonesNode->FirstChildElement(); - bonElem != 0; bonElem = bonElem->NextSiblingElement()) + for (pugi::xml_node& bonElem : mBonesNode.children()) { - String name = bonElem->Attribute("name"); - int id = StringConverter::parseInt(bonElem->Attribute("id")); + String name = bonElem.attribute("name").value(); + int id = StringConverter::parseInt(bonElem.attribute("id").value()); skel->createBone(name,id) ; } } // --------------------------------------------------------- // set positions and orientations. - void XMLSkeletonSerializer::readBones2(Skeleton* skel, TiXmlElement* mBonesNode) + void XMLSkeletonSerializer::readBones2(Skeleton* skel, pugi::xml_node& mBonesNode) { LogManager::getSingleton().logMessage("XMLSkeletonSerializer: Reading Bones data..."); Bone* btmp ; Quaternion quat ; - for (TiXmlElement* bonElem = mBonesNode->FirstChildElement(); - bonElem != 0; bonElem = bonElem->NextSiblingElement()) + for (pugi::xml_node& bonElem : mBonesNode.children()) { - String name = bonElem->Attribute("name"); -// int id = StringConverter::parseInt(bonElem->Attribute("id")); + String name = bonElem.attribute("name").value(); +// int id = StringConverter::parseInt(bonElem.attribute("id").c_str(); - TiXmlElement* posElem = bonElem->FirstChildElement("position"); - TiXmlElement* rotElem = bonElem->FirstChildElement("rotation"); - TiXmlElement* axisElem = rotElem->FirstChildElement("axis"); - TiXmlElement* scaleElem = bonElem->FirstChildElement("scale"); + pugi::xml_node posElem = bonElem.child("position"); + pugi::xml_node rotElem = bonElem.child("rotation"); + pugi::xml_node axisElem = rotElem.child("axis"); + pugi::xml_node scaleElem = bonElem.child("scale"); Vector3 pos; Vector3 axis; Radian angle ; Vector3 scale; - pos.x = StringConverter::parseReal(posElem->Attribute("x")); - pos.y = StringConverter::parseReal(posElem->Attribute("y")); - pos.z = StringConverter::parseReal(posElem->Attribute("z")); + pos.x = StringConverter::parseReal(posElem.attribute("x").value()); + pos.y = StringConverter::parseReal(posElem.attribute("y").value()); + pos.z = StringConverter::parseReal(posElem.attribute("z").value()); - angle = Radian(StringConverter::parseReal(rotElem->Attribute("angle"))); + angle = Radian(StringConverter::parseReal(rotElem.attribute("angle").value())); - axis.x = StringConverter::parseReal(axisElem->Attribute("x")); - axis.y = StringConverter::parseReal(axisElem->Attribute("y")); - axis.z = StringConverter::parseReal(axisElem->Attribute("z")); + axis.x = StringConverter::parseReal(axisElem.attribute("x").value()); + axis.y = StringConverter::parseReal(axisElem.attribute("y").value()); + axis.z = StringConverter::parseReal(axisElem.attribute("z").value()); // Optional scale if (scaleElem) { // Uniform scale or per axis? - const char* factorAttrib = scaleElem->Attribute("factor"); + const char* factorAttrib = scaleElem.attribute("factor").as_string(NULL); if (factorAttrib) { // Uniform scale @@ -172,17 +170,17 @@ namespace Ogre { { // axis scale scale = Vector3::UNIT_SCALE; - const char* factorString = scaleElem->Attribute("x"); + const char* factorString = scaleElem.attribute("x").as_string(NULL); if (factorString) { scale.x = StringConverter::parseReal(factorString); } - factorString = scaleElem->Attribute("y"); + factorString = scaleElem.attribute("y").value(); if (factorString) { scale.y = StringConverter::parseReal(factorString); } - factorString = scaleElem->Attribute("z"); + factorString = scaleElem.attribute("z").value(); if (factorString) { scale.z = StringConverter::parseReal(factorString); @@ -210,7 +208,7 @@ namespace Ogre { } // bones } //------------------------------------------------------------------- - void XMLSkeletonSerializer::createHierarchy(Skeleton* skel, TiXmlElement* mHierNode) { + void XMLSkeletonSerializer::createHierarchy(Skeleton* skel, pugi::xml_node& mHierNode) { LogManager::getSingleton().logMessage("XMLSkeletonSerializer: Reading Hierarchy data..."); @@ -219,39 +217,39 @@ namespace Ogre { String boneName ; String parentName ; - for (TiXmlElement* hierElem = mHierNode->FirstChildElement() ; hierElem != 0; hierElem = hierElem->NextSiblingElement()) + for (pugi::xml_node& hierElem : mHierNode.children()) { - boneName = hierElem->Attribute("bone"); - parentName = hierElem->Attribute("parent"); + boneName = hierElem.attribute("bone").value(); + parentName = hierElem.attribute("parent").value(); bone = skel->getBone(boneName); parent = skel->getBone(parentName); parent ->addChild(bone) ; - //LogManager::getSingleton().logMessage("XMLSkeletonSerialiser: lien: " + parent->getName() + "->" + bone->getName()); + //LogManager::getSingleton().logMessage("XMLSkeletonSerialiser: lien: " + parent->getName() + "->" + bone->getName().c_str(); } } //--------------------------------------------------------------------- - void XMLSkeletonSerializer::readAnimations(Skeleton* skel, TiXmlElement* mAnimNode) { + void XMLSkeletonSerializer::readAnimations(Skeleton* skel, pugi::xml_node& mAnimNode) { Animation * anim ; NodeAnimationTrack * track ; LogManager::getSingleton().logMessage("XMLSkeletonSerializer: Reading Animations data..."); - for (TiXmlElement* animElem = mAnimNode->FirstChildElement("animation"); animElem != 0; animElem = animElem->NextSiblingElement()) + for (pugi::xml_node& animElem : mAnimNode.children("animation")) { - String name = animElem->Attribute("name"); - Real length = StringConverter::parseReal(animElem->Attribute("length")); + String name = animElem.attribute("name").value(); + Real length = StringConverter::parseReal(animElem.attribute("length").value()); anim = skel->createAnimation(name,length); anim->setInterpolationMode(Animation::IM_LINEAR) ; //LogManager::getSingleton().logMessage("Animation: nom: " + name + " et longueur: " // + StringConverter::toString(length) ); - TiXmlElement* baseInfoNode = animElem->FirstChildElement("baseinfo"); + pugi::xml_node baseInfoNode = animElem.child("baseinfo"); if (baseInfoNode) { - String baseName = baseInfoNode->Attribute("baseanimationname"); - Real baseTime = StringConverter::parseReal(baseInfoNode->Attribute("basekeyframetime")); + String baseName = baseInfoNode.attribute("baseanimationname").value(); + Real baseTime = StringConverter::parseReal(baseInfoNode.attribute("basekeyframetime").value()); anim->setUseBaseKeyFrame(true, baseTime, baseName); } @@ -259,16 +257,16 @@ namespace Ogre { // lecture des tracks int trackIndex = 0; - TiXmlElement* tracksNode = animElem->FirstChildElement("tracks"); + pugi::xml_node tracksNode = animElem.child("tracks"); - for (TiXmlElement* trackElem = tracksNode->FirstChildElement("track"); trackElem != 0; trackElem = trackElem->NextSiblingElement()) + for (pugi::xml_node& trackElem : tracksNode.children("track")) { - String boneName = trackElem->Attribute("bone"); + String boneName = trackElem.attribute("bone").value(); //LogManager::getSingleton().logMessage("Track sur le bone: " + boneName ); track = anim->createNodeTrack(trackIndex++,skel->getBone(boneName)); - readKeyFrames(track, trackElem->FirstChildElement("keyframes")); + readKeyFrames(track, trackElem.child("keyframes")); } } @@ -276,12 +274,12 @@ namespace Ogre { } //--------------------------------------------------------------------- - void XMLSkeletonSerializer::readKeyFrames(NodeAnimationTrack* track, TiXmlElement* mKeyfNode) { + void XMLSkeletonSerializer::readKeyFrames(NodeAnimationTrack* track, const pugi::xml_node& mKeyfNode) { TransformKeyFrame* kf ; Quaternion q ; - for (TiXmlElement* keyfElem = mKeyfNode->FirstChildElement("keyframe"); keyfElem != 0; keyfElem = keyfElem->NextSiblingElement()) + for (pugi::xml_node& keyfElem : mKeyfNode.children("keyframe")) { Vector3 trans; Vector3 axis; @@ -289,43 +287,43 @@ namespace Ogre { Real time; // Get time and create keyframe - time = StringConverter::parseReal(keyfElem->Attribute("time")); + time = StringConverter::parseReal(keyfElem.attribute("time").value()); kf = track->createNodeKeyFrame(time); // Optional translate - TiXmlElement* transElem = keyfElem->FirstChildElement("translate"); + pugi::xml_node transElem = keyfElem.child("translate"); if (transElem) { - trans.x = StringConverter::parseReal(transElem->Attribute("x")); - trans.y = StringConverter::parseReal(transElem->Attribute("y")); - trans.z = StringConverter::parseReal(transElem->Attribute("z")); + trans.x = StringConverter::parseReal(transElem.attribute("x").value()); + trans.y = StringConverter::parseReal(transElem.attribute("y").value()); + trans.z = StringConverter::parseReal(transElem.attribute("z").value()); kf->setTranslate(trans) ; } // Optional rotate - TiXmlElement* rotElem = keyfElem->FirstChildElement("rotate"); + pugi::xml_node rotElem = keyfElem.child("rotate"); if (rotElem) { - TiXmlElement* axisElem = rotElem->FirstChildElement("axis"); + pugi::xml_node axisElem = rotElem.child("axis"); if (!axisElem) { OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Missing 'axis' element " "expected under parent 'rotate'", "MXLSkeletonSerializer::readKeyFrames"); } - angle = Radian(StringConverter::parseReal(rotElem->Attribute("angle"))); + angle = Radian(StringConverter::parseReal(rotElem.attribute("angle").value())); - axis.x = StringConverter::parseReal(axisElem->Attribute("x")); - axis.y = StringConverter::parseReal(axisElem->Attribute("y")); - axis.z = StringConverter::parseReal(axisElem->Attribute("z")); + axis.x = StringConverter::parseReal(axisElem.attribute("x").value()); + axis.y = StringConverter::parseReal(axisElem.attribute("y").value()); + axis.z = StringConverter::parseReal(axisElem.attribute("z").value()); q.FromAngleAxis(angle,axis); kf->setRotation(q) ; } // Optional scale - TiXmlElement* scaleElem = keyfElem->FirstChildElement("scale"); + pugi::xml_node scaleElem = keyfElem.child("scale"); if (scaleElem) { // Uniform scale or per axis? - const char* factorAttrib = scaleElem->Attribute("factor"); + const char* factorAttrib = scaleElem.attribute("factor").as_string(NULL); if (factorAttrib) { // Uniform scale @@ -336,17 +334,17 @@ namespace Ogre { { // axis scale Real xs = 1.0f, ys = 1.0f, zs=1.0f; - const char* factorString = scaleElem->Attribute("x"); + const char* factorString = scaleElem.attribute("x").as_string(NULL); if(factorString) { xs = StringConverter::parseReal(factorString); } - factorString = scaleElem->Attribute("y"); + factorString = scaleElem.attribute("y").value(); if(factorString) { ys = StringConverter::parseReal(factorString); } - factorString = scaleElem->Attribute("z"); + factorString = scaleElem.attribute("z").value(); if(factorString) { zs = StringConverter::parseReal(factorString); @@ -376,16 +374,15 @@ namespace Ogre { LogManager::getSingleton().logMessage("XMLSkeletonSerializer writing " " skeleton data to " + filename + "..."); - mXMLDoc = new TiXmlDocument(); - mXMLDoc->InsertEndChild(TiXmlElement("skeleton")); - TiXmlElement* rootNode = mXMLDoc->RootElement(); + pugi::xml_document mXMLDoc; + pugi::xml_node rootNode = mXMLDoc.append_child("skeleton"); LogManager::getSingleton().logMessage("Populating DOM..."); // Write main skeleton data LogManager::getSingleton().logMessage("Exporting bones.."); - writeSkeleton(pSkeleton); + writeSkeleton(pSkeleton, rootNode); LogManager::getSingleton().logMessage("Bones exported."); // Write all animations @@ -393,9 +390,8 @@ namespace Ogre { String msg = "Exporting animations, count=" + StringConverter::toString(numAnims); LogManager::getSingleton().logMessage(msg); - TiXmlElement* animsNode = - rootNode->InsertEndChild(TiXmlElement("animations"))->ToElement(); - + pugi::xml_node animsNode = rootNode.append_child("animations"); + for (unsigned short i = 0; i < numAnims; ++i) { Animation* pAnim = pSkeleton->getAnimation(i); @@ -412,8 +408,7 @@ namespace Ogre { if (linkIt.hasMoreElements()) { LogManager::getSingleton().logMessage("Exporting animation links."); - TiXmlElement* linksNode = - rootNode->InsertEndChild(TiXmlElement("animationlinks"))->ToElement(); + pugi::xml_node linksNode = rootNode.append_child("animationlinks"); while(linkIt.hasMoreElements()) { const LinkedSkeletonAnimationSource& link = linkIt.getNext(); @@ -424,7 +419,7 @@ namespace Ogre { LogManager::getSingleton().logMessage("DOM populated, writing XML file.."); // Write out to a file - if(! mXMLDoc->SaveFile(filename) ) + if(! mXMLDoc.save_file(filename.c_str()) ) { LogManager::getSingleton().logMessage("XMLSkeletonSerializer failed writing the XML file.", LML_CRITICAL); } @@ -432,21 +427,15 @@ namespace Ogre { { LogManager::getSingleton().logMessage("XMLSkeletonSerializer export successful."); } - - delete mXMLDoc; - } //--------------------------------------------------------------------- - void XMLSkeletonSerializer::writeSkeleton(const Skeleton* pSkel) + void XMLSkeletonSerializer::writeSkeleton(const Skeleton* pSkel, pugi::xml_node& rootNode) { - TiXmlElement* rootNode = mXMLDoc->RootElement(); - // Blend mode String blendModeStr = pSkel->getBlendMode() == ANIMBLEND_CUMULATIVE ? "cumulative" : "average"; - rootNode->SetAttribute("blendmode", blendModeStr); + rootNode.append_attribute("blendmode") = blendModeStr.c_str(); - TiXmlElement* bonesElem = - rootNode->InsertEndChild(TiXmlElement("bones"))->ToElement(); + pugi::xml_node bonesElem = rootNode.append_child("bones"); unsigned short numBones = pSkel->getNumBones(); LogManager::getSingleton().logMessage("There are " + StringConverter::toString(numBones) + " bones."); @@ -459,8 +448,7 @@ namespace Ogre { } // Write parents - TiXmlElement* hierElem = - rootNode->InsertEndChild(TiXmlElement("bonehierarchy"))->ToElement(); + pugi::xml_node hierElem = rootNode.append_child("bonehierarchy"); for (i = 0; i < numBones; ++i) { Bone* pBone = pSkel->getBone(i); @@ -476,95 +464,85 @@ namespace Ogre { } //--------------------------------------------------------------------- - void XMLSkeletonSerializer::writeBone(TiXmlElement* bonesElement, const Bone* pBone) + void XMLSkeletonSerializer::writeBone(pugi::xml_node& bonesElement, const Bone* pBone) { - TiXmlElement* boneElem = - bonesElement->InsertEndChild(TiXmlElement("bone"))->ToElement(); + pugi::xml_node boneElem = bonesElement.append_child("bone"); - // Bone name & handle - boneElem->SetAttribute("id", - StringConverter::toString(pBone->getHandle())); - boneElem->SetAttribute("name", pBone->getName()); + boneElem.append_attribute("id") = StringConverter::toString(pBone->getHandle()).c_str(); + boneElem.append_attribute("name") = pBone->getName().c_str(); // Position - TiXmlElement* subNode = - boneElem->InsertEndChild(TiXmlElement("position"))->ToElement(); + pugi::xml_node subNode = boneElem.append_child("position"); Vector3 pos = pBone->getPosition(); - subNode->SetAttribute("x", StringConverter::toString(pos.x)); - subNode->SetAttribute("y", StringConverter::toString(pos.y)); - subNode->SetAttribute("z", StringConverter::toString(pos.z)); + subNode.append_attribute("x") = StringConverter::toString(pos.x).c_str(); + subNode.append_attribute("y") = StringConverter::toString(pos.y).c_str(); + subNode.append_attribute("z") = StringConverter::toString(pos.z).c_str(); // Orientation subNode = - boneElem->InsertEndChild(TiXmlElement("rotation"))->ToElement(); + boneElem.append_child("rotation"); // Show Quaternion as angle / axis Radian angle; Vector3 axis; pBone->getOrientation().ToAngleAxis(angle, axis); - TiXmlElement* axisNode = - subNode->InsertEndChild(TiXmlElement("axis"))->ToElement(); - subNode->SetAttribute("angle", StringConverter::toString(angle.valueRadians())); - axisNode->SetAttribute("x", StringConverter::toString(axis.x)); - axisNode->SetAttribute("y", StringConverter::toString(axis.y)); - axisNode->SetAttribute("z", StringConverter::toString(axis.z)); + pugi::xml_node axisNode = subNode.append_child("axis"); + subNode.append_attribute("angle") = StringConverter::toString(angle.valueRadians()).c_str(); + axisNode.append_attribute("x") = StringConverter::toString(axis.x).c_str(); + axisNode.append_attribute("y") = StringConverter::toString(axis.y).c_str(); + axisNode.append_attribute("z") = StringConverter::toString(axis.z).c_str(); // Scale optional Vector3 scale = pBone->getScale(); if (scale != Vector3::UNIT_SCALE) { - TiXmlElement* scaleNode = - boneElem->InsertEndChild(TiXmlElement("scale"))->ToElement(); - scaleNode->SetAttribute("x", StringConverter::toString(scale.x)); - scaleNode->SetAttribute("y", StringConverter::toString(scale.y)); - scaleNode->SetAttribute("z", StringConverter::toString(scale.z)); + pugi::xml_node scaleNode = boneElem.append_child("scale"); + scaleNode.append_attribute("x") = StringConverter::toString(scale.x).c_str(); + scaleNode.append_attribute("y") = StringConverter::toString(scale.y).c_str(); + scaleNode.append_attribute("z") = StringConverter::toString(scale.z).c_str(); } } //--------------------------------------------------------------------- // - // Modifications effectuées: + // Modifications effectu�es: // // on stoque les noms et pas les Id. c'est plus lisibles. - void XMLSkeletonSerializer::writeBoneParent(TiXmlElement* boneHierarchyNode, + void XMLSkeletonSerializer::writeBoneParent(pugi::xml_node& boneHierarchyNode, String boneName, String parentName) { - TiXmlElement* boneParentNode = - boneHierarchyNode->InsertEndChild(TiXmlElement("boneparent"))->ToElement(); + pugi::xml_node boneParentNode = boneHierarchyNode.append_child("boneparent"); /* - boneParentNode->SetAttribute("boneid", StringConverter::toString(boneId)); - boneParentNode->SetAttribute("parentid", StringConverter::toString(parentId)); + boneParentNode.append_attribute("boneid") = StringConverter::toString(boneId).c_str(); + boneParentNode.append_attribute("parentid") = StringConverter::toString(parentId).c_str(); */ // Modifications: on stoque les noms./ - boneParentNode->SetAttribute("bone", boneName); - boneParentNode->SetAttribute("parent", parentName); + boneParentNode.append_attribute("bone") = boneName.c_str(); + boneParentNode.append_attribute("parent") = parentName.c_str(); } //--------------------------------------------------------------------- - void XMLSkeletonSerializer::writeAnimation(TiXmlElement* animsNode, + void XMLSkeletonSerializer::writeAnimation(pugi::xml_node& animsNode, const Animation* anim) { - TiXmlElement* animNode = - animsNode->InsertEndChild(TiXmlElement("animation"))->ToElement(); + pugi::xml_node animNode = animsNode.append_child("animation"); - animNode->SetAttribute("name", anim->getName()); - animNode->SetAttribute("length", StringConverter::toString(anim->getLength())); + animNode.append_attribute("name") = anim->getName().c_str(); + animNode.append_attribute("length") = StringConverter::toString(anim->getLength()).c_str(); // Optional base keyframe information if (anim->getUseBaseKeyFrame()) { - TiXmlElement* baseInfoNode = - animNode->InsertEndChild(TiXmlElement("baseinfo"))->ToElement(); - baseInfoNode->SetAttribute("baseanimationname", anim->getBaseKeyFrameAnimationName()); - baseInfoNode->SetAttribute("basekeyframetime", StringConverter::toString(anim->getBaseKeyFrameTime())); + pugi::xml_node baseInfoNode = animNode.append_child("baseinfo"); + baseInfoNode.append_attribute("baseanimationname") = anim->getBaseKeyFrameAnimationName().c_str(); + baseInfoNode.append_attribute("basekeyframetime") = StringConverter::toString(anim->getBaseKeyFrameTime()).c_str(); } // Write all tracks - TiXmlElement* tracksNode = - animNode->InsertEndChild(TiXmlElement("tracks"))->ToElement(); + pugi::xml_node tracksNode = animNode.append_child("tracks"); Animation::NodeTrackIterator trackIt = anim->getNodeTrackIterator(); while (trackIt.hasMoreElements()) @@ -574,89 +552,81 @@ namespace Ogre { } //--------------------------------------------------------------------- - void XMLSkeletonSerializer::writeAnimationTrack(TiXmlElement* tracksNode, + void XMLSkeletonSerializer::writeAnimationTrack(pugi::xml_node& tracksNode, const NodeAnimationTrack* track) { - TiXmlElement* trackNode = - tracksNode->InsertEndChild(TiXmlElement("track"))->ToElement(); - - + pugi::xml_node trackNode = tracksNode.append_child("track"); + // unsigned short boneIndex : Index of bone to apply to Bone* bone = (Bone*)track->getAssociatedNode(); //unsigned short boneid = bone->getHandle(); String boneName = bone->getName(); - trackNode->SetAttribute("bone", boneName); + trackNode.append_attribute("bone") = boneName.c_str(); // Write all keyframes - TiXmlElement* keysNode = - trackNode->InsertEndChild(TiXmlElement("keyframes"))->ToElement(); + pugi::xml_node keysNode = + trackNode.append_child("keyframes"); for (unsigned short i = 0; i < track->getNumKeyFrames(); ++i) { writeKeyFrame(keysNode, track->getNodeKeyFrame(i)); } } //--------------------------------------------------------------------- - void XMLSkeletonSerializer::writeKeyFrame(TiXmlElement* keysNode, + void XMLSkeletonSerializer::writeKeyFrame(pugi::xml_node& keysNode, const TransformKeyFrame* key) { - TiXmlElement* keyNode = - keysNode->InsertEndChild(TiXmlElement("keyframe"))->ToElement(); + pugi::xml_node keyNode = keysNode.append_child("keyframe"); - keyNode->SetAttribute("time", StringConverter::toString(key->getTime())); + keyNode.append_attribute("time") = StringConverter::toString(key->getTime()).c_str(); - TiXmlElement* transNode = - keyNode->InsertEndChild(TiXmlElement("translate"))->ToElement(); + pugi::xml_node transNode = + keyNode.append_child("translate"); Vector3 trans = key->getTranslate(); - transNode->SetAttribute("x", StringConverter::toString(trans.x)); - transNode->SetAttribute("y", StringConverter::toString(trans.y)); - transNode->SetAttribute("z", StringConverter::toString(trans.z)); + transNode.append_attribute("x") = StringConverter::toString(trans.x).c_str(); + transNode.append_attribute("y") = StringConverter::toString(trans.y).c_str(); + transNode.append_attribute("z") = StringConverter::toString(trans.z).c_str(); - TiXmlElement* rotNode = - keyNode->InsertEndChild(TiXmlElement("rotate"))->ToElement(); + pugi::xml_node rotNode = keyNode.append_child("rotate"); // Show Quaternion as angle / axis Radian angle; Vector3 axis; key->getRotation().ToAngleAxis(angle, axis); - TiXmlElement* axisNode = - rotNode->InsertEndChild(TiXmlElement("axis"))->ToElement(); - rotNode->SetAttribute("angle", StringConverter::toString(angle.valueRadians())); - axisNode->SetAttribute("x", StringConverter::toString(axis.x)); - axisNode->SetAttribute("y", StringConverter::toString(axis.y)); - axisNode->SetAttribute("z", StringConverter::toString(axis.z)); + pugi::xml_node axisNode = rotNode.append_child("axis"); + rotNode.append_attribute("angle") = StringConverter::toString(angle.valueRadians()).c_str(); + axisNode.append_attribute("x") = StringConverter::toString(axis.x).c_str(); + axisNode.append_attribute("y") = StringConverter::toString(axis.y).c_str(); + axisNode.append_attribute("z") = StringConverter::toString(axis.z).c_str(); // Scale optional if (key->getScale() != Vector3::UNIT_SCALE) { - TiXmlElement* scaleNode = - keyNode->InsertEndChild(TiXmlElement("scale"))->ToElement(); + pugi::xml_node scaleNode = keyNode.append_child("scale"); - scaleNode->SetAttribute("x", StringConverter::toString(key->getScale().x)); - scaleNode->SetAttribute("y", StringConverter::toString(key->getScale().y)); - scaleNode->SetAttribute("z", StringConverter::toString(key->getScale().z)); + scaleNode.append_attribute("x") = StringConverter::toString(key->getScale().x).c_str(); + scaleNode.append_attribute("y") = StringConverter::toString(key->getScale().y).c_str(); + scaleNode.append_attribute("z") = StringConverter::toString(key->getScale().z).c_str(); } } //--------------------------------------------------------------------- - void XMLSkeletonSerializer::writeSkeletonAnimationLink(TiXmlElement* linksNode, + void XMLSkeletonSerializer::writeSkeletonAnimationLink(pugi::xml_node& linksNode, const LinkedSkeletonAnimationSource& link) { - TiXmlElement* linkNode = - linksNode->InsertEndChild(TiXmlElement("animationlink"))->ToElement(); - linkNode->SetAttribute("skeletonName", link.skeletonName); - linkNode->SetAttribute("scale", StringConverter::toString(link.scale)); + pugi::xml_node linkNode = linksNode.append_child("animationlink"); + linkNode.append_attribute("skeletonName") = link.skeletonName.c_str(); + linkNode.append_attribute("scale") = StringConverter::toString(link.scale).c_str(); } //--------------------------------------------------------------------- void XMLSkeletonSerializer::readSkeletonAnimationLinks(Skeleton* skel, - TiXmlElement* linksNode) + pugi::xml_node& linksNode) { LogManager::getSingleton().logMessage("XMLSkeletonSerializer: Reading Animations links..."); - for (TiXmlElement* linkElem = linksNode->FirstChildElement("animationlink"); - linkElem != 0; linkElem = linkElem->NextSiblingElement()) + for (pugi::xml_node& linkElem : linksNode.children("animationlink")) { - String skelName = linkElem->Attribute("skeletonName"); - const char* strScale = linkElem->Attribute("scale"); + String skelName = linkElem.attribute("skeletonName").value(); + const char* strScale = linkElem.attribute("scale").as_string(NULL); Real scale; // Scale optional if (strScale == 0) diff --git a/Tools/XMLConverter/src/main.cpp b/Tools/XMLConverter/src/main.cpp index 67e4ec5a7db..97ade6914b0 100644 --- a/Tools/XMLConverter/src/main.cpp +++ b/Tools/XMLConverter/src/main.cpp @@ -387,18 +387,17 @@ void XMLToBinary(XmlOptions opts) { // Read root element and decide from there what type String response; - TiXmlDocument* doc = new TiXmlDocument(opts.source); + pugi::xml_document doc; + // Some double-parsing here but never mind - if (!doc->LoadFile()) + if (!doc.load_file(opts.source.c_str())) { cout << "Unable to open file " << opts.source << " - fatal error." << endl; - delete doc; exit (1); } - TiXmlElement* root = doc->RootElement(); - if (!stricmp(root->Value(), "mesh")) + pugi::xml_node root = doc.document_element(); + if (!stricmp(root.name(), "mesh")) { - delete doc; MeshPtr newMesh = MeshManager::getSingleton().createManual("conversion", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); VertexElementType colourElementType; @@ -476,9 +475,8 @@ void XMLToBinary(XmlOptions opts) MeshManager::getSingleton().remove("conversion", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); } - else if (!stricmp(root->Value(), "skeleton")) + else if (!stricmp(root.name(), "skeleton")) { - delete doc; SkeletonPtr newSkel = SkeletonManager::getSingleton().create("conversion", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); xmlSkeletonSerializer->importSkeleton(opts.source, newSkel.get()); @@ -492,11 +490,6 @@ void XMLToBinary(XmlOptions opts) SkeletonManager::getSingleton().remove("conversion", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); } - else - { - delete doc; - } - } void skeletonToXML(XmlOptions opts) diff --git a/Tools/XMLConverter/src/tinystr.cpp b/Tools/XMLConverter/src/tinystr.cpp deleted file mode 100644 index 06657682051..00000000000 --- a/Tools/XMLConverter/src/tinystr.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - - -#ifndef TIXML_USE_STL - -#include "tinystr.h" - -// Error value for find primitive -const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); - - -// Null rep. -TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; - - -void TiXmlString::reserve (size_type cap) -{ - if (cap > capacity()) - { - TiXmlString tmp; - tmp.init(length(), cap); - memcpy(tmp.start(), data(), length()); - swap(tmp); - } -} - - -TiXmlString& TiXmlString::assign(const char* str, size_type len) -{ - size_type cap = capacity(); - if (len > cap || cap > 3*(len + 8)) - { - TiXmlString tmp; - tmp.init(len); - memcpy(tmp.start(), str, len); - swap(tmp); - } - else - { - memmove(start(), str, len); - set_size(len); - } - return *this; -} - - -TiXmlString& TiXmlString::append(const char* str, size_type len) -{ - size_type newsize = length() + len; - if (newsize > capacity()) - { - reserve (newsize + capacity()); - } - memmove(finish(), str, len); - set_size(newsize); - return *this; -} - - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) -{ - TiXmlString tmp; - tmp.reserve(a.length() + b.length()); - tmp += a; - tmp += b; - return tmp; -} - -TiXmlString operator + (const TiXmlString & a, const char* b) -{ - TiXmlString tmp; - TiXmlString::size_type b_len = static_cast( strlen(b) ); - tmp.reserve(a.length() + b_len); - tmp += a; - tmp.append(b, b_len); - return tmp; -} - -TiXmlString operator + (const char* a, const TiXmlString & b) -{ - TiXmlString tmp; - TiXmlString::size_type a_len = static_cast( strlen(a) ); - tmp.reserve(a_len + b.length()); - tmp.append(a, a_len); - tmp += b; - return tmp; -} - - -#endif // TIXML_USE_STL diff --git a/Tools/XMLConverter/src/tinyxml.cpp b/Tools/XMLConverter/src/tinyxml.cpp deleted file mode 100644 index 9c161dfcb93..00000000000 --- a/Tools/XMLConverter/src/tinyxml.cpp +++ /dev/null @@ -1,1886 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code by Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#include - -#ifdef TIXML_USE_STL -#include -#include -#endif - -#include "tinyxml.h" - -FILE* TiXmlFOpen( const char* filename, const char* mode ); - -bool TiXmlBase::condenseWhiteSpace = true; - -// Microsoft compiler security -FILE* TiXmlFOpen( const char* filename, const char* mode ) -{ - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - FILE* fp = 0; - errno_t err = fopen_s( &fp, filename, mode ); - if ( !err && fp ) - return fp; - return 0; - #else - return fopen( filename, mode ); - #endif -} - -void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) -{ - int i=0; - - while( i<(int)str.length() ) - { - unsigned char c = (unsigned char) str[i]; - - if ( c == '&' - && i < ( (int)str.length() - 2 ) - && str[i+1] == '#' - && str[i+2] == 'x' ) - { - // Hexadecimal character reference. - // Pass through unchanged. - // © -- copyright symbol, for example. - // - // The -1 is a bug fix from Rob Laveaux. It keeps - // an overflow from happening if there is no ';'. - // There are actually 2 ways to exit this loop - - // while fails (error case) and break (semicolon found). - // However, there is no mechanism (currently) for - // this function to return an error. - while ( i<(int)str.length()-1 ) - { - outString->append( str.c_str() + i, 1 ); - ++i; - if ( str[i] == ';' ) - break; - } - } - else if ( c == '&' ) - { - outString->append( entity[0].str, entity[0].strLength ); - ++i; - } - else if ( c == '<' ) - { - outString->append( entity[1].str, entity[1].strLength ); - ++i; - } - else if ( c == '>' ) - { - outString->append( entity[2].str, entity[2].strLength ); - ++i; - } - else if ( c == '\"' ) - { - outString->append( entity[3].str, entity[3].strLength ); - ++i; - } - else if ( c == '\'' ) - { - outString->append( entity[4].str, entity[4].strLength ); - ++i; - } - else if ( c < 32 ) - { - // Easy pass at non-alpha/numeric/symbol - // Below 32 is symbolic. - char buf[ 32 ]; - - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); - #else - sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); - #endif - - //*ME: warning C4267: convert 'size_t' to 'int' - //*ME: Int-Cast to make compiler happy ... - outString->append( buf, (int)strlen( buf ) ); - ++i; - } - else - { - //char realc = (char) c; - //outString->append( &realc, 1 ); - *outString += (char) c; // somewhat more efficient function call. - ++i; - } - } -} - - -TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() -{ - parent = 0; - type = _type; - firstChild = 0; - lastChild = 0; - prev = 0; - next = 0; -} - - -TiXmlNode::~TiXmlNode() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } -} - - -void TiXmlNode::CopyTo( TiXmlNode* target ) const -{ - target->SetValue (value.c_str() ); - target->userData = userData; - target->location = location; -} - - -void TiXmlNode::Clear() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } - - firstChild = 0; - lastChild = 0; -} - - -TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) -{ - assert( node->parent == 0 || node->parent == this ); - assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); - - if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - delete node; - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - node->parent = this; - - node->prev = lastChild; - node->next = 0; - - if ( lastChild ) - lastChild->next = node; - else - firstChild = node; // it was an empty list. - - lastChild = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) -{ - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - - return LinkEndChild( node ); -} - - -TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) -{ - if ( !beforeThis || beforeThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->next = beforeThis; - node->prev = beforeThis->prev; - if ( beforeThis->prev ) - { - beforeThis->prev->next = node; - } - else - { - assert( firstChild == beforeThis ); - firstChild = node; - } - beforeThis->prev = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) -{ - if ( !afterThis || afterThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->prev = afterThis; - node->next = afterThis->next; - if ( afterThis->next ) - { - afterThis->next->prev = node; - } - else - { - assert( lastChild == afterThis ); - lastChild = node; - } - afterThis->next = node; - return node; -} - - -TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) -{ - if ( !replaceThis ) - return 0; - - if ( replaceThis->parent != this ) - return 0; - - if ( withThis.ToDocument() ) { - // A document can never be a child. Thanks to Noam. - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = withThis.Clone(); - if ( !node ) - return 0; - - node->next = replaceThis->next; - node->prev = replaceThis->prev; - - if ( replaceThis->next ) - replaceThis->next->prev = node; - else - lastChild = node; - - if ( replaceThis->prev ) - replaceThis->prev->next = node; - else - firstChild = node; - - delete replaceThis; - node->parent = this; - return node; -} - - -bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) -{ - if ( !removeThis ) { - return false; - } - - if ( removeThis->parent != this ) - { - assert( 0 ); - return false; - } - - if ( removeThis->next ) - removeThis->next->prev = removeThis->prev; - else - lastChild = removeThis->prev; - - if ( removeThis->prev ) - removeThis->prev->next = removeThis->next; - else - firstChild = removeThis->next; - - delete removeThis; - return true; -} - -const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = firstChild; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = lastChild; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild(); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling(); - } -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild( val ); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling( val ); - } -} - - -const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = next; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = prev; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -void TiXmlElement::RemoveAttribute( const char * name ) -{ - #ifdef TIXML_USE_STL - TIXML_STRING str( name ); - TiXmlAttribute* node = attributeSet.Find( str ); - #else - TiXmlAttribute* node = attributeSet.Find( name ); - #endif - if ( node ) - { - attributeSet.Remove( node ); - delete node; - } -} - -const TiXmlElement* TiXmlNode::FirstChildElement() const -{ - const TiXmlNode* node; - - for ( node = FirstChild(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = FirstChild( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement() const -{ - const TiXmlNode* node; - - for ( node = NextSibling(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = NextSibling( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlDocument* TiXmlNode::GetDocument() const -{ - const TiXmlNode* node; - - for( node = this; node; node = node->parent ) - { - if ( node->ToDocument() ) - return node->ToDocument(); - } - return 0; -} - - -TiXmlElement::TiXmlElement (const char * _value) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} - - -#ifdef TIXML_USE_STL -TiXmlElement::TiXmlElement( const std::string& _value ) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} -#endif - - -TiXmlElement::TiXmlElement( const TiXmlElement& copy) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) -{ - firstChild = lastChild = 0; - copy.CopyTo( this ); -} - - -TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base ) -{ - ClearThis(); - base.CopyTo( this ); - return *this; -} - - -TiXmlElement::~TiXmlElement() -{ - ClearThis(); -} - - -void TiXmlElement::ClearThis() -{ - Clear(); - while( attributeSet.First() ) - { - TiXmlAttribute* node = attributeSet.First(); - attributeSet.Remove( node ); - delete node; - } -} - - -const char* TiXmlElement::Attribute( const char* name ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - return node->Value(); - return 0; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( attrib ) - return &attrib->ValueStr(); - return 0; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, int* i ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const char* result = 0; - - if ( attrib ) { - result = attrib->Value(); - if ( i ) { - attrib->QueryIntValue( i ); - } - } - return result; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const std::string* result = 0; - - if ( attrib ) { - result = &attrib->ValueStr(); - if ( i ) { - attrib->QueryIntValue( i ); - } - } - return result; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, double* d ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const char* result = 0; - - if ( attrib ) { - result = attrib->Value(); - if ( d ) { - attrib->QueryDoubleValue( d ); - } - } - return result; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const std::string* result = 0; - - if ( attrib ) { - result = &attrib->ValueStr(); - if ( d ) { - attrib->QueryDoubleValue( d ); - } - } - return result; -} -#endif - - -int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryIntValue( ival ); -} - - -int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* value ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - int ival = 0; - int result = node->QueryIntValue( &ival ); - *value = (unsigned)ival; - return result; -} - - -int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - int result = TIXML_WRONG_TYPE; - if ( StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) ) - { - *bval = true; - result = TIXML_SUCCESS; - } - else if ( StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) ) - { - *bval = false; - result = TIXML_SUCCESS; - } - return result; -} - - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryIntValue( ival ); -} -#endif - - -int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryDoubleValue( dval ); -} - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const -{ - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryDoubleValue( dval ); -} -#endif - - -void TiXmlElement::SetAttribute( const char * name, int val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetIntValue( val ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& name, int val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetIntValue( val ); - } -} -#endif - - -void TiXmlElement::SetDoubleAttribute( const char * name, double val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetDoubleValue( val ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetDoubleValue( val ); - } -} -#endif - - -void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname ); - if ( attrib ) { - attrib->SetValue( cvalue ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name ); - if ( attrib ) { - attrib->SetValue( _value ); - } -} -#endif - - -void TiXmlElement::Print( FILE* cfile, int depth ) const -{ - int i; - assert( cfile ); - for ( i=0; iNext() ) - { - fprintf( cfile, " " ); - attrib->Print( cfile, depth ); - } - - // There are 3 different formatting approaches: - // 1) An element without children is printed as a node - // 2) An element with only a text child is printed as text - // 3) An element with children is printed on multiple lines. - TiXmlNode* node; - if ( !firstChild ) - { - fprintf( cfile, " />" ); - } - else if ( firstChild == lastChild && firstChild->ToText() ) - { - fprintf( cfile, ">" ); - firstChild->Print( cfile, depth + 1 ); - fprintf( cfile, "", value.c_str() ); - } - else - { - fprintf( cfile, ">" ); - - for ( node = firstChild; node; node=node->NextSibling() ) - { - if ( !node->ToText() ) - { - fprintf( cfile, "\n" ); - } - node->Print( cfile, depth+1 ); - } - fprintf( cfile, "\n" ); - for( i=0; i", value.c_str() ); - } -} - - -void TiXmlElement::CopyTo( TiXmlElement* target ) const -{ - // superclass: - TiXmlNode::CopyTo( target ); - - // Element class: - // Clone the attributes, then clone the children. - const TiXmlAttribute* attribute = 0; - for( attribute = attributeSet.First(); - attribute; - attribute = attribute->Next() ) - { - target->SetAttribute( attribute->Name(), attribute->Value() ); - } - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - -bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this, attributeSet.First() ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -TiXmlNode* TiXmlElement::Clone() const -{ - TiXmlElement* clone = new TiXmlElement( Value() ); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -const char* TiXmlElement::GetText() const -{ - const TiXmlNode* child = this->FirstChild(); - if ( child ) { - const TiXmlText* childText = child->ToText(); - if ( childText ) { - return childText->Value(); - } - } - return 0; -} - - -TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - ClearError(); -} - -TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} - - -#ifdef TIXML_USE_STL -TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} -#endif - - -TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) -{ - copy.CopyTo( this ); -} - - -TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy ) -{ - Clear(); - copy.CopyTo( this ); - return *this; -} - - -bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) -{ - return LoadFile( Value(), encoding ); -} - - -bool TiXmlDocument::SaveFile() const -{ - return SaveFile( Value() ); -} - -bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) -{ - TIXML_STRING filename( _filename ); - value = filename; - - // reading in binary mode so that tinyxml can normalize the EOL - FILE* file = TiXmlFOpen( value.c_str (), "rb" ); - - if ( file ) - { - bool result = LoadFile( file, encoding ); - fclose( file ); - return result; - } - else - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } -} - -bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) -{ - if ( !file ) - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Delete the existing data: - Clear(); - location.Clear(); - - // Get the file size, so we can pre-allocate the string. HUGE speed impact. - long length = 0; - fseek( file, 0, SEEK_END ); - length = ftell( file ); - fseek( file, 0, SEEK_SET ); - - // Strange case, but good to handle up front. - if ( length <= 0 ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Subtle bug here. TinyXml did use fgets. But from the XML spec: - // 2.11 End-of-Line Handling - // - // - // ...the XML processor MUST behave as if it normalized all line breaks in external - // parsed entities (including the document entity) on input, before parsing, by translating - // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to - // a single #xA character. - // - // - // It is not clear fgets does that, and certainly isn't clear it works cross platform. - // Generally, you expect fgets to translate from the convention of the OS to the c/unix - // convention, and not work generally. - - /* - while( fgets( buf, sizeof(buf), file ) ) - { - data += buf; - } - */ - - char* buf = new char[ length+1 ]; - buf[0] = 0; - - if ( fread( buf, length, 1, file ) != 1 ) { - delete [] buf; - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Process the buffer in place to normalize new lines. (See comment above.) - // Copies from the 'p' to 'q' pointer, where p can advance faster if - // a newline-carriage return is hit. - // - // Wikipedia: - // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or - // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)... - // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others - // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS - // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9 - - const char* p = buf; // the read head - char* q = buf; // the write head - const char CR = 0x0d; - const char LF = 0x0a; - - buf[length] = 0; - while( *p ) { - assert( p < (buf+length) ); - assert( q <= (buf+length) ); - assert( q <= p ); - - if ( *p == CR ) { - *q++ = LF; - p++; - if ( *p == LF ) { // check for CR+LF (and skip LF) - p++; - } - } - else { - *q++ = *p++; - } - } - assert( q <= (buf+length) ); - *q = 0; - - Parse( buf, 0, encoding ); - - delete [] buf; - return !Error(); -} - - -bool TiXmlDocument::SaveFile( const char * filename ) const -{ - // The old c stuff lives on... - FILE* fp = TiXmlFOpen( filename, "w" ); - if ( fp ) - { - bool result = SaveFile( fp ); - fclose( fp ); - return result; - } - return false; -} - - -bool TiXmlDocument::SaveFile( FILE* fp ) const -{ - if ( useMicrosoftBOM ) - { - const unsigned char TIXML_UTF_LEAD_0 = 0xefU; - const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; - const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - - fputc( TIXML_UTF_LEAD_0, fp ); - fputc( TIXML_UTF_LEAD_1, fp ); - fputc( TIXML_UTF_LEAD_2, fp ); - } - Print( fp, 0 ); - return (ferror(fp) == 0); -} - - -void TiXmlDocument::CopyTo( TiXmlDocument* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->error = error; - target->errorId = errorId; - target->errorDesc = errorDesc; - target->tabsize = tabsize; - target->errorLocation = errorLocation; - target->useMicrosoftBOM = useMicrosoftBOM; - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - - -TiXmlNode* TiXmlDocument::Clone() const -{ - TiXmlDocument* clone = new TiXmlDocument(); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlDocument::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - node->Print( cfile, depth ); - fprintf( cfile, "\n" ); - } -} - - -bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -const TiXmlAttribute* TiXmlAttribute::Next() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} - -/* -TiXmlAttribute* TiXmlAttribute::Next() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} -*/ - -const TiXmlAttribute* TiXmlAttribute::Previous() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} - -/* -TiXmlAttribute* TiXmlAttribute::Previous() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} -*/ - -void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - TIXML_STRING n, v; - - EncodeString( name, &n ); - EncodeString( value, &v ); - - if (value.find ('\"') == TIXML_STRING::npos) { - if ( cfile ) { - fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; - } - } - else { - if ( cfile ) { - fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; - } - } -} - - -int TiXmlAttribute::QueryIntValue( int* ival ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -int TiXmlAttribute::QueryDoubleValue( double* dval ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -void TiXmlAttribute::SetIntValue( int _value ) -{ - char buf [64]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); - #else - sprintf (buf, "%d", _value); - #endif - SetValue (buf); -} - -void TiXmlAttribute::SetDoubleValue( double _value ) -{ - char buf [256]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value); - #else - sprintf (buf, "%g", _value); - #endif - SetValue (buf); -} - -int TiXmlAttribute::IntValue() const -{ - return atoi (value.c_str ()); -} - -double TiXmlAttribute::DoubleValue() const -{ - return atof (value.c_str ()); -} - - -TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) -{ - copy.CopyTo( this ); -} - - -TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base ) -{ - Clear(); - base.CopyTo( this ); - return *this; -} - - -void TiXmlComment::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlComment::CopyTo( TiXmlComment* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlComment::Clone() const -{ - TiXmlComment* clone = new TiXmlComment(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlText::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - if ( cdata ) - { - int i; - fprintf( cfile, "\n" ); - for ( i=0; i\n", value.c_str() ); // unformatted output - } - else - { - TIXML_STRING buffer; - EncodeString( value, &buffer ); - fprintf( cfile, "%s", buffer.c_str() ); - } -} - - -void TiXmlText::CopyTo( TiXmlText* target ) const -{ - TiXmlNode::CopyTo( target ); - target->cdata = cdata; -} - - -bool TiXmlText::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlText::Clone() const -{ - TiXmlText* clone = 0; - clone = new TiXmlText( "" ); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlDeclaration::TiXmlDeclaration( const char * _version, - const char * _encoding, - const char * _standalone ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} - - -#ifdef TIXML_USE_STL -TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} -#endif - - -TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) -{ - copy.CopyTo( this ); -} - - -TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) -{ - Clear(); - copy.CopyTo( this ); - return *this; -} - - -void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - if ( cfile ) fprintf( cfile, "" ); - if ( str ) (*str) += "?>"; -} - - -void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->version = version; - target->encoding = encoding; - target->standalone = standalone; -} - - -bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlDeclaration::Clone() const -{ - TiXmlDeclaration* clone = new TiXmlDeclaration(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlUnknown::Print( FILE* cfile, int depth ) const -{ - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlUnknown::Clone() const -{ - TiXmlUnknown* clone = new TiXmlUnknown(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlAttributeSet::TiXmlAttributeSet() -{ - sentinel.next = &sentinel; - sentinel.prev = &sentinel; -} - - -TiXmlAttributeSet::~TiXmlAttributeSet() -{ - assert( sentinel.next == &sentinel ); - assert( sentinel.prev == &sentinel ); -} - - -void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) -{ - #ifdef TIXML_USE_STL - assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. - #else - assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. - #endif - - addMe->next = &sentinel; - addMe->prev = sentinel.prev; - - sentinel.prev->next = addMe; - sentinel.prev = addMe; -} - -void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) -{ - TiXmlAttribute* node; - - for( node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node == removeMe ) - { - node->prev->next = node->next; - node->next->prev = node->prev; - node->next = 0; - node->prev = 0; - return; - } - } - assert( 0 ); // we tried to remove a non-linked attribute. -} - - -#ifdef TIXML_USE_STL -TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node->name == name ) - return node; - } - return 0; -} - -TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name ) -{ - TiXmlAttribute* attrib = Find( _name ); - if ( !attrib ) { - attrib = new TiXmlAttribute(); - Add( attrib ); - attrib->SetName( _name ); - } - return attrib; -} -#endif - - -TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( strcmp( node->name.c_str(), name ) == 0 ) - return node; - } - return 0; -} - - -TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) -{ - TiXmlAttribute* attrib = Find( _name ); - if ( !attrib ) { - attrib = new TiXmlAttribute(); - Add( attrib ); - attrib->SetName( _name ); - } - return attrib; -} - - -#ifdef TIXML_USE_STL -std::istream& operator>> (std::istream & in, TiXmlNode & base) -{ - TIXML_STRING tag; - tag.reserve( 8 * 1000 ); - base.StreamIn( &in, &tag ); - - base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); - return in; -} -#endif - - -#ifdef TIXML_USE_STL -std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out << printer.Str(); - - return out; -} - - -std::string& operator<< (std::string& out, const TiXmlNode& base ) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out.append( printer.Str() ); - - return out; -} -#endif - - -TiXmlHandle TiXmlHandle::FirstChild() const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement() const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild(); - for ( i=0; - child && iNextSibling(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild( value ); - for ( i=0; - child && iNextSibling( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement(); - for ( i=0; - child && iNextSiblingElement(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement( value ); - for ( i=0; - child && iNextSiblingElement( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) -{ - DoIndent(); - buffer += "<"; - buffer += element.Value(); - - for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) - { - buffer += " "; - attrib->Print( 0, 0, &buffer ); - } - - if ( !element.FirstChild() ) - { - buffer += " />"; - DoLineBreak(); - } - else - { - buffer += ">"; - if ( element.FirstChild()->ToText() - && element.LastChild() == element.FirstChild() - && element.FirstChild()->ToText()->CDATA() == false ) - { - simpleTextPrint = true; - // no DoLineBreak()! - } - else - { - DoLineBreak(); - } - } - ++depth; - return true; -} - - -bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) -{ - --depth; - if ( !element.FirstChild() ) - { - // nothing. - } - else - { - if ( simpleTextPrint ) - { - simpleTextPrint = false; - } - else - { - DoIndent(); - } - buffer += ""; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlText& text ) -{ - if ( text.CDATA() ) - { - DoIndent(); - buffer += ""; - DoLineBreak(); - } - else if ( simpleTextPrint ) - { - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - } - else - { - DoIndent(); - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) -{ - DoIndent(); - declaration.Print( 0, 0, &buffer ); - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlComment& comment ) -{ - DoIndent(); - buffer += ""; - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) -{ - DoIndent(); - buffer += "<"; - buffer += unknown.Value(); - buffer += ">"; - DoLineBreak(); - return true; -} - diff --git a/Tools/XMLConverter/src/tinyxmlerror.cpp b/Tools/XMLConverter/src/tinyxmlerror.cpp deleted file mode 100644 index 538c21d0bd9..00000000000 --- a/Tools/XMLConverter/src/tinyxmlerror.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#include "tinyxml.h" - -// The goal of the seperate error file is to make the first -// step towards localization. tinyxml (currently) only supports -// english error messages, but the could now be translated. -// -// It also cleans up the code a bit. -// - -const char* TiXmlBase::errorString[ TiXmlBase::TIXML_ERROR_STRING_COUNT ] = -{ - "No error", - "Error", - "Failed to open file", - "Error parsing Element.", - "Failed to read Element name", - "Error reading Element value.", - "Error reading Attributes.", - "Error: empty tag.", - "Error reading end tag.", - "Error parsing Unknown.", - "Error parsing Comment.", - "Error parsing Declaration.", - "Error document empty.", - "Error null (0) or unexpected EOF found in input stream.", - "Error parsing CDATA.", - "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.", -}; diff --git a/Tools/XMLConverter/src/tinyxmlparser.cpp b/Tools/XMLConverter/src/tinyxmlparser.cpp deleted file mode 100644 index 81b7eae96be..00000000000 --- a/Tools/XMLConverter/src/tinyxmlparser.cpp +++ /dev/null @@ -1,1638 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code by Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#include -#include - -#include "tinyxml.h" - -//#define DEBUG_PARSER -#if defined( DEBUG_PARSER ) -# if defined( DEBUG ) && defined( _MSC_VER ) -# include -# define TIXML_LOG OutputDebugString -# else -# define TIXML_LOG printf -# endif -#endif - -// Note tha "PutString" hardcodes the same list. This -// is less flexible than it appears. Changing the entries -// or order will break putstring. -TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] = -{ - { "&", 5, '&' }, - { "<", 4, '<' }, - { ">", 4, '>' }, - { """, 6, '\"' }, - { "'", 6, '\'' } -}; - -// Bunch of unicode info at: -// http://www.unicode.org/faq/utf_bom.html -// Including the basic of this table, which determines the #bytes in the -// sequence from the lead byte. 1 placed for invalid sequences -- -// although the result will be junk, pass it through as much as possible. -// Beware of the non-characters in UTF-8: -// ef bb bf (Microsoft "lead bytes") -// ef bf be -// ef bf bf - -const unsigned char TIXML_UTF_LEAD_0 = 0xefU; -const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; -const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - -const int TiXmlBase::utf8ByteTable[256] = -{ - // 0 1 2 3 4 5 6 7 8 9 a b c d e f - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 - 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte - 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid -}; - - -void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) -{ - const unsigned long BYTE_MASK = 0xBF; - const unsigned long BYTE_MARK = 0x80; - const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - - if (input < 0x80) - *length = 1; - else if ( input < 0x800 ) - *length = 2; - else if ( input < 0x10000 ) - *length = 3; - else if ( input < 0x200000 ) - *length = 4; - else - { *length = 0; return; } // This code won't covert this correctly anyway. - - output += *length; - - // Scary scary fall throughs. - switch (*length) - { - case 4: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 3: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 2: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 1: - --output; - *output = (char)(input | FIRST_BYTE_MARK[*length]); - } -} - - -/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalpha( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalpha( anyByte ); -// } -} - - -/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalnum( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalnum( anyByte ); -// } -} - - -class TiXmlParsingData -{ - friend class TiXmlDocument; - public: - void Stamp( const char* now, TiXmlEncoding encoding ); - - const TiXmlCursor& Cursor() const { return cursor; } - - private: - // Only used by the document! - TiXmlParsingData( const char* start, int _tabsize, int row, int col ) - { - assert( start ); - stamp = start; - tabsize = _tabsize; - cursor.row = row; - cursor.col = col; - } - - TiXmlCursor cursor; - const char* stamp; - int tabsize; -}; - - -void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) -{ - assert( now ); - - // Do nothing if the tabsize is 0. - if ( tabsize < 1 ) - { - return; - } - - // Get the current row, column. - int row = cursor.row; - int col = cursor.col; - const char* p = stamp; - assert( p ); - - while ( p < now ) - { - // Treat p as unsigned, so we have a happy compiler. - const unsigned char* pU = (const unsigned char*)p; - - // Code contributed by Fletcher Dunn: (modified by lee) - switch (*pU) { - case 0: - // We *should* never get here, but in case we do, don't - // advance past the terminating null character, ever - return; - - case '\r': - // bump down to the next line - ++row; - col = 0; - // Eat the character - ++p; - - // Check for \r\n sequence, and treat this as a single character - if (*p == '\n') { - ++p; - } - break; - - case '\n': - // bump down to the next line - ++row; - col = 0; - - // Eat the character - ++p; - - // Check for \n\r sequence, and treat this as a single - // character. (Yes, this bizarre thing does occur still - // on some arcane platforms...) - if (*p == '\r') { - ++p; - } - break; - - case '\t': - // Eat the character - ++p; - - // Skip to next tab stop - col = (col / tabsize + 1) * tabsize; - break; - - case TIXML_UTF_LEAD_0: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( *(p+1) && *(p+2) ) - { - // In these cases, don't advance the column. These are - // 0-width spaces. - if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) - p += 3; - else - { p +=3; ++col; } // A normal character. - } - } - else - { - ++p; - ++col; - } - break; - - default: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // Eat the 1 to 4 byte utf8 character. - int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; - if ( step == 0 ) - step = 1; // Error case from bad encoding, but handle gracefully. - p += step; - - // Just advance one column, of course. - ++col; - } - else - { - ++p; - ++col; - } - break; - } - } - cursor.row = row; - cursor.col = col; - assert( cursor.row >= -1 ); - assert( cursor.col >= -1 ); - stamp = p; - assert( stamp ); -} - - -const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) -{ - if ( !p || !*p ) - { - return 0; - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - while ( *p ) - { - const unsigned char* pU = (const unsigned char*)p; - - // Skip the stupid Microsoft UTF-8 Byte order marks - if ( *(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==TIXML_UTF_LEAD_1 - && *(pU+2)==TIXML_UTF_LEAD_2 ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbeU ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbfU ) - { - p += 3; - continue; - } - - if ( IsWhiteSpace( *p ) ) // Still using old rules for white space. - ++p; - else - break; - } - } - else - { - while ( *p && IsWhiteSpace( *p ) ) - ++p; - } - - return p; -} - -#ifdef TIXML_USE_STL -/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) -{ - for( ;; ) - { - if ( !in->good() ) return false; - - int c = in->peek(); - // At this scope, we can't get to a document. So fail silently. - if ( !IsWhiteSpace( c ) || c <= 0 ) - return true; - - *tag += (char) in->get(); - } -} - -/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) -{ - //assert( character > 0 && character < 128 ); // else it won't work in utf-8 - while ( in->good() ) - { - int c = in->peek(); - if ( c == character ) - return true; - if ( c <= 0 ) // Silent failure: can't get document at this scope - return false; - - in->get(); - *tag += (char) c; - } - return false; -} -#endif - -// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The -// "assign" optimization removes over 10% of the execution time. -// -const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) -{ - // Oddly, not supported on some comilers, - //name->clear(); - // So use this: - *name = ""; - assert( p ); - - // Names start with letters or underscores. - // Of course, in unicode, tinyxml has no idea what a letter *is*. The - // algorithm is generous. - // - // After that, they can be letters, underscores, numbers, - // hyphens, or colons. (Colons are valid ony for namespaces, - // but tinyxml can't tell namespaces from names.) - if ( p && *p - && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) - { - const char* start = p; - while( p && *p - && ( IsAlphaNum( (unsigned char ) *p, encoding ) - || *p == '_' - || *p == '-' - || *p == '.' - || *p == ':' ) ) - { - //(*name) += *p; // expensive - ++p; - } - if ( p-start > 0 ) { - name->assign( start, p-start ); - } - return p; - } - return 0; -} - -const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) -{ - // Presume an entity, and pull it out. - TIXML_STRING ent; - int i; - *length = 0; - - if ( *(p+1) && *(p+1) == '#' && *(p+2) ) - { - unsigned long ucs = 0; - ptrdiff_t delta = 0; - unsigned mult = 1; - - if ( *(p+2) == 'x' ) - { - // Hexadecimal. - if ( !*(p+3) ) return 0; - - const char* q = p+3; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != 'x' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else if ( *q >= 'a' && *q <= 'f' ) - ucs += mult * (*q - 'a' + 10); - else if ( *q >= 'A' && *q <= 'F' ) - ucs += mult * (*q - 'A' + 10 ); - else - return 0; - mult *= 16; - --q; - } - } - else - { - // Decimal. - if ( !*(p+2) ) return 0; - - const char* q = p+2; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != '#' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else - return 0; - mult *= 10; - --q; - } - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // convert the UCS to UTF-8 - ConvertUTF32ToUTF8( ucs, value, length ); - } - else - { - *value = (char)ucs; - *length = 1; - } - return p + delta + 1; - } - - // Now try to match it. - for( i=0; iappend( cArr, len ); - } - } - else - { - bool whitespace = false; - - // Remove leading white space: - p = SkipWhiteSpace( p, encoding ); - while ( p && *p - && !StringEqual( p, endTag, caseInsensitive, encoding ) ) - { - if ( *p == '\r' || *p == '\n' ) - { - whitespace = true; - ++p; - } - else if ( IsWhiteSpace( *p ) ) - { - whitespace = true; - ++p; - } - else - { - // If we've found whitespace, add it before the - // new character. Any whitespace just becomes a space. - if ( whitespace ) - { - (*text) += ' '; - whitespace = false; - } - int len; - char cArr[4] = { 0, 0, 0, 0 }; - p = GetChar( p, cArr, &len, encoding ); - if ( len == 1 ) - (*text) += cArr[0]; // more efficient - else - text->append( cArr, len ); - } - } - } - if ( p && *p ) - p += strlen( endTag ); - return ( p && *p ) ? p : 0; -} - -#ifdef TIXML_USE_STL - -void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - // The basic issue with a document is that we don't know what we're - // streaming. Read something presumed to be a tag (and hope), then - // identify it, and call the appropriate stream method on the tag. - // - // This "pre-streaming" will never read the closing ">" so the - // sub-tag can orient itself. - - if ( !StreamTo( in, '<', tag ) ) - { - SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - while ( in->good() ) - { - int tagIndex = (int) tag->length(); - while ( in->good() && in->peek() != '>' ) - { - int c = in->get(); - if ( c <= 0 ) - { - SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - break; - } - (*tag) += (char) c; - } - - if ( in->good() ) - { - // We now have something we presume to be a node of - // some sort. Identify it, and call the node to - // continue streaming. - TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); - - if ( node ) - { - node->StreamIn( in, tag ); - bool isElement = node->ToElement() != 0; - delete node; - node = 0; - - // If this is the root element, we're done. Parsing will be - // done by the >> operator. - if ( isElement ) - { - return; - } - } - else - { - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - } - } - // We should have returned sooner. - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); -} - -#endif - -const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) -{ - ClearError(); - - // Parse away, at the document level. Since a document - // contains nothing but other tags, most of what happens - // here is skipping white space. - if ( !p || !*p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - // Note that, for a document, this needs to come - // before the while space skip, so that parsing - // starts from the pointer we are given. - location.Clear(); - if ( prevData ) - { - location.row = prevData->cursor.row; - location.col = prevData->cursor.col; - } - else - { - location.row = 0; - location.col = 0; - } - TiXmlParsingData data( p, TabSize(), location.row, location.col ); - location = data.Cursor(); - - if ( encoding == TIXML_ENCODING_UNKNOWN ) - { - // Check for the Microsoft UTF-8 lead bytes. - const unsigned char* pU = (const unsigned char*)p; - if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 - && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 - && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) - { - encoding = TIXML_ENCODING_UTF8; - useMicrosoftBOM = true; - } - } - - p = SkipWhiteSpace( p, encoding ); - if ( !p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - while ( p && *p ) - { - TiXmlNode* node = Identify( p, encoding ); - if ( node ) - { - p = node->Parse( p, &data, encoding ); - LinkEndChild( node ); - } - else - { - break; - } - - // Did we get encoding info? - if ( encoding == TIXML_ENCODING_UNKNOWN - && node->ToDeclaration() ) - { - TiXmlDeclaration* dec = node->ToDeclaration(); - const char* enc = dec->Encoding(); - assert( enc ); - - if ( *enc == 0 ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice - else - encoding = TIXML_ENCODING_LEGACY; - } - - p = SkipWhiteSpace( p, encoding ); - } - - // Was this empty? - if ( !firstChild ) { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); - return 0; - } - - // All is well. - return p; -} - -void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - // The first error in a chain is more accurate - don't set again! - if ( error ) - return; - - assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); - error = true; - errorId = err; - errorDesc = errorString[ errorId ]; - - errorLocation.Clear(); - if ( pError && data ) - { - data->Stamp( pError, encoding ); - errorLocation = data->Cursor(); - } -} - - -TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) -{ - TiXmlNode* returnNode = 0; - - p = SkipWhiteSpace( p, encoding ); - if( !p || !*p || *p != '<' ) - { - return 0; - } - - p = SkipWhiteSpace( p, encoding ); - - if ( !p || !*p ) - { - return 0; - } - - // What is this thing? - // - Elements start with a letter or underscore, but xml is reserved. - // - Comments: "; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - if ( document ) - document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // [ 1475201 ] TinyXML parses entities in comments - // Oops - ReadText doesn't work, because we don't want to parse the entities. - // p = ReadText( p, &value, false, endTag, false, encoding ); - // - // from the XML spec: - /* - [Definition: Comments may appear anywhere in a document outside other markup; in addition, - they may appear within the document type declaration at places allowed by the grammar. - They are not part of the document's character data; an XML processor MAY, but need not, - make it possible for an application to retrieve the text of comments. For compatibility, - the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity - references MUST NOT be recognized within comments. - - An example of a comment: - - - */ - - value = ""; - // Keep all the white space. - while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) - { - value.append( p, 1 ); - ++p; - } - if ( p && *p ) - p += strlen( endTag ); - - return p; -} - - -const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) return 0; - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - // Read the name, the '=' and the value. - const char* pErr = p; - p = ReadName( p, &name, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); - return 0; - } - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p || *p != '=' ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - ++p; // skip '=' - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - const char* end; - const char SINGLE_QUOTE = '\''; - const char DOUBLE_QUOTE = '\"'; - - if ( *p == SINGLE_QUOTE ) - { - ++p; - end = "\'"; // single quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else if ( *p == DOUBLE_QUOTE ) - { - ++p; - end = "\""; // double quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else - { - // All attribute values should be in single or double quotes. - // But this is such a common error that the parser will try - // its best, even without them. - value = ""; - while ( p && *p // existence - && !IsWhiteSpace( *p ) // whitespace - && *p != '/' && *p != '>' ) // tag end - { - if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { - // [ 1451649 ] Attribute values with trailing quotes not handled correctly - // We did not have an opening quote but seem to have a - // closing one. Give up and throw an error. - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - value += *p; - ++p; - } - } - return p; -} - -#ifdef TIXML_USE_STL -void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->peek(); - if ( !cdata && (c == '<' ) ) - { - return; - } - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - (*tag) += (char) c; - in->get(); // "commits" the peek made above - - if ( cdata && c == '>' && tag->size() >= 3 ) { - size_t len = tag->size(); - if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { - // terminator of cdata. - return; - } - } - } -} -#endif - -const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - value = ""; - TiXmlDocument* document = GetDocument(); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - - const char* const startTag = ""; - - if ( cdata || StringEqual( p, startTag, false, encoding ) ) - { - cdata = true; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - if ( document ) - document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // Keep all the white space, ignore the encoding, etc. - while ( p && *p - && !StringEqual( p, endTag, false, encoding ) - ) - { - value += *p; - ++p; - } - - TIXML_STRING dummy; - p = ReadText( p, &dummy, false, endTag, false, encoding ); - return p; - } - else - { - bool ignoreWhite = true; - - const char* end = "<"; - p = ReadText( p, &value, ignoreWhite, end, false, encoding ); - if ( p && *p ) - return p-1; // don't truncate the '<' - return 0; - } -} - -#ifdef TIXML_USE_STL -void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - (*tag) += (char) c; - - if ( c == '>' ) - { - // All is well. - return; - } - } -} -#endif - -const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) -{ - p = SkipWhiteSpace( p, _encoding ); - // Find the beginning, find the end, and look for - // the stuff in-between. - TiXmlDocument* document = GetDocument(); - if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); - return 0; - } - if ( data ) - { - data->Stamp( p, _encoding ); - location = data->Cursor(); - } - p += 5; - - version = ""; - encoding = ""; - standalone = ""; - - while ( p && *p ) - { - if ( *p == '>' ) - { - ++p; - return p; - } - - p = SkipWhiteSpace( p, _encoding ); - if ( StringEqual( p, "version", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - version = attrib.Value(); - } - else if ( StringEqual( p, "encoding", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - encoding = attrib.Value(); - } - else if ( StringEqual( p, "standalone", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - standalone = attrib.Value(); - } - else - { - // Read over whatever it is. - while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) - ++p; - } - } - return 0; -} - -bool TiXmlText::Blank() const -{ - for ( unsigned i=0; i