1593 lines
29 KiB
C++
1593 lines
29 KiB
C++
|
/*
|
||
|
www.sourceforge.net/projects/tinyxml
|
||
|
Original code (2.0 and earlier )copyright (c) 2000-2002 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 <ctype.h>
|
||
|
#include "tinyxml.h"
|
||
|
|
||
|
#ifdef TIXML_USE_STL
|
||
|
#include <sstream>
|
||
|
#endif
|
||
|
|
||
|
|
||
|
bool TiXmlBase::condenseWhiteSpace = false;
|
||
|
|
||
|
void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream )
|
||
|
{
|
||
|
TIXML_STRING buffer;
|
||
|
PutString( str, &buffer );
|
||
|
(*stream) << buffer;
|
||
|
}
|
||
|
|
||
|
void TiXmlBase::PutString( 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 ];
|
||
|
sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
|
||
|
//*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;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// <-- Strange class for a bug fix. Search for STL_STRING_BUG
|
||
|
TiXmlBase::StringToBuffer::StringToBuffer( const TIXML_STRING& str )
|
||
|
{
|
||
|
buffer = new char[ str.length()+1 ];
|
||
|
if ( buffer )
|
||
|
{
|
||
|
strcpy( buffer, str.c_str() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlBase::StringToBuffer::~StringToBuffer()
|
||
|
{
|
||
|
delete [] buffer;
|
||
|
}
|
||
|
// End strange bug fix. -->
|
||
|
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
|
||
|
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 )
|
||
|
{
|
||
|
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 )
|
||
|
{
|
||
|
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;
|
||
|
|
||
|
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;
|
||
|
|
||
|
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->parent != this )
|
||
|
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->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 ( node->SValue() == _value )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode* TiXmlNode::FirstChild( const char * _value )
|
||
|
{
|
||
|
TiXmlNode* node;
|
||
|
for ( node = firstChild; node; node = node->next )
|
||
|
{
|
||
|
if ( node->SValue() == _value )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
|
||
|
{
|
||
|
const TiXmlNode* node;
|
||
|
for ( node = lastChild; node; node = node->prev )
|
||
|
{
|
||
|
if ( node->SValue() == _value )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TiXmlNode* TiXmlNode::LastChild( const char * _value )
|
||
|
{
|
||
|
TiXmlNode* node;
|
||
|
for ( node = lastChild; node; node = node->prev )
|
||
|
{
|
||
|
if ( node->SValue() == _value )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
|
||
|
{
|
||
|
if ( !previous )
|
||
|
{
|
||
|
return FirstChild();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
assert( previous->parent == this );
|
||
|
return previous->NextSibling();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous )
|
||
|
{
|
||
|
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 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous )
|
||
|
{
|
||
|
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 ( node->SValue() == _value )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TiXmlNode* TiXmlNode::NextSibling( const char * _value )
|
||
|
{
|
||
|
TiXmlNode* node;
|
||
|
for ( node = next; node; node = node->next )
|
||
|
{
|
||
|
if ( node->SValue() == _value )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
|
||
|
{
|
||
|
const TiXmlNode* node;
|
||
|
for ( node = prev; node; node = node->prev )
|
||
|
{
|
||
|
if ( node->SValue() == _value )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TiXmlNode* TiXmlNode::PreviousSibling( const char * _value )
|
||
|
{
|
||
|
TiXmlNode* node;
|
||
|
for ( node = prev; node; node = node->prev )
|
||
|
{
|
||
|
if ( node->SValue() == _value )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void TiXmlElement::RemoveAttribute( const char * name )
|
||
|
{
|
||
|
TiXmlAttribute* node = attributeSet.Find( name );
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
TiXmlElement* TiXmlNode::FirstChildElement()
|
||
|
{
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
TiXmlElement* TiXmlNode::FirstChildElement( const char * _value )
|
||
|
{
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
TiXmlElement* TiXmlNode::NextSiblingElement()
|
||
|
{
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value )
|
||
|
{
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
TiXmlDocument* TiXmlNode::GetDocument()
|
||
|
{
|
||
|
TiXmlNode* node;
|
||
|
|
||
|
for( node = this; node; node = node->parent )
|
||
|
{
|
||
|
if ( node->ToDocument() )
|
||
|
return node->ToDocument();
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TiXmlElement::TiXmlElement (const char * _value)
|
||
|
: TiXmlNode( TiXmlNode::ELEMENT )
|
||
|
{
|
||
|
firstChild = lastChild = 0;
|
||
|
value = _value;
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef TIXML_USE_STL
|
||
|
TiXmlElement::TiXmlElement( const std::string& _value )
|
||
|
: TiXmlNode( TiXmlNode::ELEMENT )
|
||
|
{
|
||
|
firstChild = lastChild = 0;
|
||
|
value = _value;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
TiXmlElement::TiXmlElement( const TiXmlElement& copy)
|
||
|
: TiXmlNode( TiXmlNode::ELEMENT )
|
||
|
{
|
||
|
firstChild = lastChild = 0;
|
||
|
copy.CopyTo( this );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlElement::operator=( const TiXmlElement& base )
|
||
|
{
|
||
|
ClearThis();
|
||
|
base.CopyTo( 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;
|
||
|
}
|
||
|
|
||
|
|
||
|
const char * TiXmlElement::Attribute( const char * name, int* i ) const
|
||
|
{
|
||
|
const char * s = Attribute( name );
|
||
|
if ( i )
|
||
|
{
|
||
|
if ( s )
|
||
|
*i = atoi( s );
|
||
|
else
|
||
|
*i = 0;
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
|
||
|
const char * TiXmlElement::Attribute( const char * name, double* d ) const
|
||
|
{
|
||
|
const char * s = Attribute( name );
|
||
|
if ( d )
|
||
|
{
|
||
|
if ( s )
|
||
|
*d = atof( s );
|
||
|
else
|
||
|
*d = 0;
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
|
||
|
int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
|
||
|
{
|
||
|
const TiXmlAttribute* node = attributeSet.Find( name );
|
||
|
if ( !node )
|
||
|
return TIXML_NO_ATTRIBUTE;
|
||
|
|
||
|
return node->QueryIntValue( ival );
|
||
|
}
|
||
|
|
||
|
|
||
|
int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
|
||
|
{
|
||
|
const TiXmlAttribute* node = attributeSet.Find( name );
|
||
|
if ( !node )
|
||
|
return TIXML_NO_ATTRIBUTE;
|
||
|
|
||
|
return node->QueryDoubleValue( dval );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlElement::SetAttribute( const char * name, int val )
|
||
|
{
|
||
|
char buf[64];
|
||
|
sprintf( buf, "%d", val );
|
||
|
SetAttribute( name, buf );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlElement::SetDoubleAttribute( const char * name, double val )
|
||
|
{
|
||
|
char buf[256];
|
||
|
sprintf( buf, "%f", val );
|
||
|
SetAttribute( name, buf );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlElement::SetAttribute( const char * name, const char * _value )
|
||
|
{
|
||
|
TiXmlAttribute* node = attributeSet.Find( name );
|
||
|
if ( node )
|
||
|
{
|
||
|
node->SetValue( _value );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
|
||
|
if ( attrib )
|
||
|
{
|
||
|
attributeSet.Add( attrib );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TiXmlDocument* document = GetDocument();
|
||
|
if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void TiXmlElement::Print( FILE* cfile, int depth ) const
|
||
|
{
|
||
|
int i;
|
||
|
for ( i=0; i<depth; i++ )
|
||
|
{
|
||
|
fprintf( cfile, " " );
|
||
|
}
|
||
|
|
||
|
fprintf( cfile, "<%s", value.c_str() );
|
||
|
|
||
|
const TiXmlAttribute* attrib;
|
||
|
for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
|
||
|
{
|
||
|
fprintf( cfile, " " );
|
||
|
attrib->Print( cfile, depth );
|
||
|
}
|
||
|
|
||
|
// There are 3 different formatting approaches:
|
||
|
// 1) An element without children is printed as a <foo /> node
|
||
|
// 2) An element with only a text child is printed as <foo> text </foo>
|
||
|
// 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, "</%s>", 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<depth; ++i )
|
||
|
fprintf( cfile, " " );
|
||
|
fprintf( cfile, "</%s>", value.c_str() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void TiXmlElement::StreamOut( TIXML_OSTREAM * stream ) const
|
||
|
{
|
||
|
(*stream) << "<" << value;
|
||
|
|
||
|
const TiXmlAttribute* attrib;
|
||
|
for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
|
||
|
{
|
||
|
(*stream) << " ";
|
||
|
attrib->StreamOut( stream );
|
||
|
}
|
||
|
|
||
|
// If this node has children, give it a closing tag. Else
|
||
|
// make it an empty tag.
|
||
|
TiXmlNode* node;
|
||
|
if ( firstChild )
|
||
|
{
|
||
|
(*stream) << ">";
|
||
|
|
||
|
for ( node = firstChild; node; node=node->NextSibling() )
|
||
|
{
|
||
|
node->StreamOut( stream );
|
||
|
}
|
||
|
(*stream) << "</" << value << ">";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
(*stream) << " />";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
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() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode* TiXmlElement::Clone() const
|
||
|
{
|
||
|
TiXmlElement* clone = new TiXmlElement( Value() );
|
||
|
if ( !clone )
|
||
|
return 0;
|
||
|
|
||
|
CopyTo( clone );
|
||
|
return clone;
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
|
||
|
{
|
||
|
tabsize = 4;
|
||
|
ClearError();
|
||
|
}
|
||
|
|
||
|
TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
|
||
|
{
|
||
|
tabsize = 4;
|
||
|
value = documentName;
|
||
|
ClearError();
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef TIXML_USE_STL
|
||
|
TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
|
||
|
{
|
||
|
tabsize = 4;
|
||
|
value = documentName;
|
||
|
ClearError();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
|
||
|
{
|
||
|
copy.CopyTo( this );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlDocument::operator=( const TiXmlDocument& copy )
|
||
|
{
|
||
|
Clear();
|
||
|
copy.CopyTo( this );
|
||
|
}
|
||
|
|
||
|
|
||
|
bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
|
||
|
{
|
||
|
// See STL_STRING_BUG below.
|
||
|
StringToBuffer buf( value );
|
||
|
|
||
|
if ( buf.buffer && LoadFile( buf.buffer, encoding ) )
|
||
|
return true;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool TiXmlDocument::SaveFile() const
|
||
|
{
|
||
|
// See STL_STRING_BUG below.
|
||
|
StringToBuffer buf( value );
|
||
|
|
||
|
if ( buf.buffer && SaveFile( buf.buffer ) )
|
||
|
return true;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool TiXmlDocument::LoadFile( const char* filename, TiXmlEncoding encoding )
|
||
|
{
|
||
|
// Delete the existing data:
|
||
|
Clear();
|
||
|
location.Clear();
|
||
|
|
||
|
// There was a really terrifying little bug here. The code:
|
||
|
// value = filename
|
||
|
// in the STL case, cause the assignment method of the std::string to
|
||
|
// be called. What is strange, is that the std::string had the same
|
||
|
// address as it's c_str() method, and so bad things happen. Looks
|
||
|
// like a bug in the Microsoft STL implementation.
|
||
|
// See STL_STRING_BUG above.
|
||
|
// Fixed with the StringToBuffer class.
|
||
|
value = filename;
|
||
|
|
||
|
FILE* file = fopen( value.c_str (), "r" );
|
||
|
|
||
|
if ( file )
|
||
|
{
|
||
|
// 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 )
|
||
|
{
|
||
|
fclose( file );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// If we have a file, assume it is all one big XML file, and read it in.
|
||
|
// The document parser may decide the document ends sooner than the entire file, however.
|
||
|
TIXML_STRING data;
|
||
|
data.reserve( length );
|
||
|
|
||
|
const int BUF_SIZE = 2048;
|
||
|
char buf[BUF_SIZE];
|
||
|
|
||
|
while( fgets( buf, BUF_SIZE, file ) )
|
||
|
{
|
||
|
data += buf;
|
||
|
}
|
||
|
fclose( file );
|
||
|
|
||
|
Parse( data.c_str(), 0, encoding );
|
||
|
|
||
|
if ( Error() )
|
||
|
return false;
|
||
|
else
|
||
|
return true;
|
||
|
}
|
||
|
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool TiXmlDocument::SaveFile( const char * filename ) const
|
||
|
{
|
||
|
// The old c stuff lives on...
|
||
|
FILE* fp = fopen( filename, "w" );
|
||
|
if ( fp )
|
||
|
{
|
||
|
Print( fp, 0 );
|
||
|
fclose( fp );
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
|
||
|
{
|
||
|
TiXmlNode::CopyTo( target );
|
||
|
|
||
|
target->error = error;
|
||
|
target->errorDesc = errorDesc.c_str ();
|
||
|
|
||
|
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
|
||
|
{
|
||
|
const TiXmlNode* node;
|
||
|
for ( node=FirstChild(); node; node=node->NextSibling() )
|
||
|
{
|
||
|
node->Print( cfile, depth );
|
||
|
fprintf( cfile, "\n" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) const
|
||
|
{
|
||
|
const TiXmlNode* node;
|
||
|
for ( node=FirstChild(); node; node=node->NextSibling() )
|
||
|
{
|
||
|
node->StreamOut( out );
|
||
|
|
||
|
// Special rule for streams: stop after the root element.
|
||
|
// The stream in code will only read one element, so don't
|
||
|
// write more than one.
|
||
|
if ( node->ToElement() )
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
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*/ ) const
|
||
|
{
|
||
|
TIXML_STRING n, v;
|
||
|
|
||
|
PutString( name, &n );
|
||
|
PutString( value, &v );
|
||
|
|
||
|
if (value.find ('\"') == TIXML_STRING::npos)
|
||
|
fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
|
||
|
else
|
||
|
fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlAttribute::StreamOut( TIXML_OSTREAM * stream ) const
|
||
|
{
|
||
|
if (value.find( '\"' ) != TIXML_STRING::npos)
|
||
|
{
|
||
|
PutString( name, stream );
|
||
|
(*stream) << "=" << "'";
|
||
|
PutString( value, stream );
|
||
|
(*stream) << "'";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PutString( name, stream );
|
||
|
(*stream) << "=" << "\"";
|
||
|
PutString( value, stream );
|
||
|
(*stream) << "\"";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int TiXmlAttribute::QueryIntValue( int* ival ) const
|
||
|
{
|
||
|
if ( sscanf( value.c_str(), "%d", ival ) == 1 )
|
||
|
return TIXML_SUCCESS;
|
||
|
return TIXML_WRONG_TYPE;
|
||
|
}
|
||
|
|
||
|
int TiXmlAttribute::QueryDoubleValue( double* dval ) const
|
||
|
{
|
||
|
if ( sscanf( value.c_str(), "%lf", dval ) == 1 )
|
||
|
return TIXML_SUCCESS;
|
||
|
return TIXML_WRONG_TYPE;
|
||
|
}
|
||
|
|
||
|
void TiXmlAttribute::SetIntValue( int _value )
|
||
|
{
|
||
|
char buf [64];
|
||
|
sprintf (buf, "%d", _value);
|
||
|
SetValue (buf);
|
||
|
}
|
||
|
|
||
|
void TiXmlAttribute::SetDoubleValue( double _value )
|
||
|
{
|
||
|
char buf [256];
|
||
|
sprintf (buf, "%lf", _value);
|
||
|
SetValue (buf);
|
||
|
}
|
||
|
|
||
|
const int TiXmlAttribute::IntValue() const
|
||
|
{
|
||
|
return atoi (value.c_str ());
|
||
|
}
|
||
|
|
||
|
const double TiXmlAttribute::DoubleValue() const
|
||
|
{
|
||
|
return atof (value.c_str ());
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
|
||
|
{
|
||
|
copy.CopyTo( this );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlComment::operator=( const TiXmlComment& base )
|
||
|
{
|
||
|
Clear();
|
||
|
base.CopyTo( this );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlComment::Print( FILE* cfile, int depth ) const
|
||
|
{
|
||
|
for ( int i=0; i<depth; i++ )
|
||
|
{
|
||
|
fputs( " ", cfile );
|
||
|
}
|
||
|
fprintf( cfile, "<!--%s-->", value.c_str() );
|
||
|
}
|
||
|
|
||
|
void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const
|
||
|
{
|
||
|
(*stream) << "<!--";
|
||
|
//PutString( value, stream );
|
||
|
(*stream) << value;
|
||
|
(*stream) << "-->";
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlComment::CopyTo( TiXmlComment* target ) const
|
||
|
{
|
||
|
TiXmlNode::CopyTo( target );
|
||
|
}
|
||
|
|
||
|
|
||
|
TiXmlNode* TiXmlComment::Clone() const
|
||
|
{
|
||
|
TiXmlComment* clone = new TiXmlComment();
|
||
|
|
||
|
if ( !clone )
|
||
|
return 0;
|
||
|
|
||
|
CopyTo( clone );
|
||
|
return clone;
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlText::Print( FILE* cfile, int /*depth*/ ) const
|
||
|
{
|
||
|
TIXML_STRING buffer;
|
||
|
PutString( value, &buffer );
|
||
|
fprintf( cfile, "%s", buffer.c_str() );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const
|
||
|
{
|
||
|
PutString( value, stream );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlText::CopyTo( TiXmlText* target ) const
|
||
|
{
|
||
|
TiXmlNode::CopyTo( target );
|
||
|
}
|
||
|
|
||
|
|
||
|
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::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::DECLARATION )
|
||
|
{
|
||
|
version = _version;
|
||
|
encoding = _encoding;
|
||
|
standalone = _standalone;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
|
||
|
: TiXmlNode( TiXmlNode::DECLARATION )
|
||
|
{
|
||
|
copy.CopyTo( this );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
|
||
|
{
|
||
|
Clear();
|
||
|
copy.CopyTo( this );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/ ) const
|
||
|
{
|
||
|
fprintf (cfile, "<?xml ");
|
||
|
|
||
|
if ( !version.empty() )
|
||
|
fprintf (cfile, "version=\"%s\" ", version.c_str ());
|
||
|
if ( !encoding.empty() )
|
||
|
fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
|
||
|
if ( !standalone.empty() )
|
||
|
fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
|
||
|
fprintf (cfile, "?>");
|
||
|
}
|
||
|
|
||
|
void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const
|
||
|
{
|
||
|
(*stream) << "<?xml ";
|
||
|
|
||
|
if ( !version.empty() )
|
||
|
{
|
||
|
(*stream) << "version=\"";
|
||
|
PutString( version, stream );
|
||
|
(*stream) << "\" ";
|
||
|
}
|
||
|
if ( !encoding.empty() )
|
||
|
{
|
||
|
(*stream) << "encoding=\"";
|
||
|
PutString( encoding, stream );
|
||
|
(*stream ) << "\" ";
|
||
|
}
|
||
|
if ( !standalone.empty() )
|
||
|
{
|
||
|
(*stream) << "standalone=\"";
|
||
|
PutString( standalone, stream );
|
||
|
(*stream) << "\" ";
|
||
|
}
|
||
|
(*stream) << "?>";
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
|
||
|
{
|
||
|
TiXmlNode::CopyTo( target );
|
||
|
|
||
|
target->version = version;
|
||
|
target->encoding = encoding;
|
||
|
target->standalone = standalone;
|
||
|
}
|
||
|
|
||
|
|
||
|
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<depth; i++ )
|
||
|
fprintf( cfile, " " );
|
||
|
fprintf( cfile, "<%s>", value.c_str() );
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const
|
||
|
{
|
||
|
(*stream) << "<" << value << ">"; // Don't use entities here! It is unknown.
|
||
|
}
|
||
|
|
||
|
|
||
|
void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
|
||
|
{
|
||
|
TiXmlNode::CopyTo( target );
|
||
|
}
|
||
|
|
||
|
|
||
|
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 )
|
||
|
{
|
||
|
assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set.
|
||
|
|
||
|
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.
|
||
|
}
|
||
|
|
||
|
const TiXmlAttribute* TiXmlAttributeSet::Find( const char * name ) const
|
||
|
{
|
||
|
const TiXmlAttribute* node;
|
||
|
|
||
|
for( node = sentinel.next; node != &sentinel; node = node->next )
|
||
|
{
|
||
|
if ( node->name == name )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
TiXmlAttribute* TiXmlAttributeSet::Find( const char * name )
|
||
|
{
|
||
|
TiXmlAttribute* node;
|
||
|
|
||
|
for( node = sentinel.next; node != &sentinel; node = node->next )
|
||
|
{
|
||
|
if ( node->name == name )
|
||
|
return node;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#ifdef TIXML_USE_STL
|
||
|
TIXML_ISTREAM & operator >> (TIXML_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
|
||
|
|
||
|
|
||
|
TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base)
|
||
|
{
|
||
|
base.StreamOut (& out);
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef TIXML_USE_STL
|
||
|
std::string & operator<< (std::string& out, const TiXmlNode& base )
|
||
|
{
|
||
|
std::ostringstream os_stream( std::ostringstream::out );
|
||
|
base.StreamOut( &os_stream );
|
||
|
|
||
|
out.append( os_stream.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 && i<count;
|
||
|
child = child->NextSibling(), ++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 && i<count;
|
||
|
child = child->NextSibling( 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 && i<count;
|
||
|
child = child->NextSiblingElement(), ++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 && i<count;
|
||
|
child = child->NextSiblingElement( value ), ++i )
|
||
|
{
|
||
|
// nothing
|
||
|
}
|
||
|
if ( child )
|
||
|
return TiXmlHandle( child );
|
||
|
}
|
||
|
return TiXmlHandle( 0 );
|
||
|
}
|