// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // * Neither the name of NVIDIA CORPORATION nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Copyright (c) 2008-2018 NVIDIA Corporation. All rights reserved. // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. #ifndef PX_XML_IMPL_H #define PX_XML_IMPL_H #include "SnXmlMemoryPool.h" #include "PsString.h" #include "foundation/PxMemory.h" namespace physx { namespace Sn { typedef CMemoryPoolManager TMemoryPoolManager; namespace snXmlImpl { inline PxU32 strLen( const char* inStr ) { PxU32 len = 0; if ( inStr ) { while ( *inStr ) { ++len; ++inStr; } } return len; } } inline const char* copyStr( PxAllocatorCallback& inAllocator, const char* inStr ) { if ( inStr && *inStr ) { PxU32 theLen = snXmlImpl::strLen( inStr ); //The memory will never be released by repx. If you want it released, you need to pass in a custom allocator //that tracks all allocations and releases unreleased allocations yourself. char* dest = reinterpret_cast( inAllocator.allocate( theLen + 1, "Repx::const char*", __FILE__, __LINE__ ) ); PxMemCopy( dest, inStr, theLen ); dest[theLen] = 0; return dest; } return ""; } template inline const char* copyStr( TManagerType* inMgr, const char* inStr ) { if ( inStr && *inStr ) { PxU32 theLen = snXmlImpl::strLen( inStr ); char* dest = reinterpret_cast( inMgr->allocate( theLen + 1 ) ); PxMemCopy( dest, inStr, theLen ); dest[theLen] = 0; return dest; } return ""; } inline void releaseStr( TMemoryPoolManager* inMgr, const char* inStr, PxU32 ) { if ( inStr && *inStr ) { inMgr->deallocate( reinterpret_cast< PxU8* >( const_cast( inStr ) ) ); } } inline void releaseStr( TMemoryPoolManager* inMgr, const char* inStr ) { if ( inStr && *inStr ) { PxU32 theLen = snXmlImpl::strLen( inStr ); releaseStr( inMgr, inStr, theLen ); } } struct XmlNode { const char* mName; //Never released until all collections are released const char* mData; //Never released until all collections are released XmlNode* mNextSibling; XmlNode* mPreviousSibling; XmlNode* mFirstChild; XmlNode* mParent; XmlNode( const XmlNode& ); XmlNode& operator=( const XmlNode& ); PX_INLINE void initPtrs() { mNextSibling = NULL; mPreviousSibling = NULL; mFirstChild = NULL; mParent = NULL; } PX_INLINE XmlNode( const char* inName = "", const char* inData = "" ) : mName( inName ) , mData( inData ) { initPtrs(); } void addChild( XmlNode* inItem ) { inItem->mParent = this; if ( mFirstChild == NULL ) mFirstChild = inItem; else { XmlNode* theNode = mFirstChild; //Follow the chain till the end. while( theNode->mNextSibling != NULL ) theNode = theNode->mNextSibling; theNode->mNextSibling = inItem; inItem->mPreviousSibling = theNode; } } PX_INLINE XmlNode* findChildByName( const char* inName ) { for ( XmlNode* theNode = mFirstChild; theNode; theNode = theNode->mNextSibling ) { XmlNode* theRepXNode = theNode; if ( physx::shdfnd::stricmp( theRepXNode->mName, inName ) == 0 ) return theNode; } return NULL; } PX_INLINE void orphan() { if ( mParent ) { if ( mParent->mFirstChild == this ) mParent->mFirstChild = mNextSibling; } if ( mPreviousSibling ) mPreviousSibling->mNextSibling = mNextSibling; if ( mNextSibling ) mNextSibling->mPreviousSibling = mPreviousSibling; if ( mFirstChild ) mFirstChild->mParent = NULL; initPtrs(); } }; inline XmlNode* allocateRepXNode( TMemoryPoolManager* inManager, const char* inName, const char* inData ) { XmlNode* retval = inManager->allocate(); retval->mName = copyStr( inManager, inName ); retval->mData = copyStr( inManager, inData ); return retval; } inline void release( TMemoryPoolManager* inManager, XmlNode* inNode ) { //We *don't* release the strings associated with the node //because they could be shared. Instead, we just let them 'leak' //in some sense, at least until the memory manager itself is deleted. //DO NOT UNCOMMENT THE LINES BELOW!! //releaseStr( inManager, inNode->mName ); //releaseStr( inManager, inNode->mData ); inManager->deallocate( inNode ); } static PX_INLINE void releaseNodeAndChildren( TMemoryPoolManager* inManager, XmlNode* inNode ) { if ( inNode->mFirstChild ) { XmlNode* childNode( inNode->mFirstChild ); while( childNode ) { XmlNode* _node( childNode ); childNode = _node->mNextSibling; releaseNodeAndChildren( inManager, _node ); } } inNode->orphan(); release( inManager, inNode ); } static XmlNode* copyRepXNodeAndSiblings( TMemoryPoolManager* inManager, const XmlNode* inNode, XmlNode* inParent ); static XmlNode* copyRepXNode( TMemoryPoolManager* inManager, const XmlNode* inNode, XmlNode* inParent = NULL ) { XmlNode* newNode( allocateRepXNode( inManager, NULL, NULL ) ); newNode->mName = inNode->mName; //Some light structural sharing newNode->mData = inNode->mData; //Some light structural sharing newNode->mParent = inParent; if ( inNode->mFirstChild ) newNode->mFirstChild = copyRepXNodeAndSiblings( inManager, inNode->mFirstChild, newNode ); return newNode; } static XmlNode* copyRepXNodeAndSiblings( TMemoryPoolManager* inManager, const XmlNode* inNode, XmlNode* inParent ) { XmlNode* sibling = inNode->mNextSibling; if ( sibling ) sibling = copyRepXNodeAndSiblings( inManager, sibling, inParent ); XmlNode* newNode = copyRepXNode( inManager, inNode, inParent ); newNode->mNextSibling = sibling; if ( sibling ) sibling->mPreviousSibling = newNode; return newNode; } inline bool isBigEndian() { int i = 1; return *(reinterpret_cast(&i))==0; } struct NameStackEntry { const char* mName; bool mOpen; NameStackEntry( const char* nm ) : mName( nm ), mOpen( false ) {} }; typedef PxProfileArray TNameStack; } } #endif