ferencd@0: /* ferencd@0: www.sourceforge.net/projects/tinyxml ferencd@0: Original code by Lee Thomason (www.grinninglizard.com) ferencd@0: ferencd@0: This software is provided 'as-is', without any express or implied ferencd@0: warranty. In no event will the authors be held liable for any ferencd@0: damages arising from the use of this software. ferencd@0: ferencd@0: Permission is granted to anyone to use this software for any ferencd@0: purpose, including commercial applications, and to alter it and ferencd@0: redistribute it freely, subject to the following restrictions: ferencd@0: ferencd@0: 1. The origin of this software must not be misrepresented; you must ferencd@0: not claim that you wrote the original software. If you use this ferencd@0: software in a product, an acknowledgment in the product documentation ferencd@0: would be appreciated but is not required. ferencd@0: ferencd@0: 2. Altered source versions must be plainly marked as such, and ferencd@0: must not be misrepresented as being the original software. ferencd@0: ferencd@0: 3. This notice may not be removed or altered from any source ferencd@0: distribution. ferencd@0: */ ferencd@0: #ifdef _MSC_VER ferencd@0: #define _CRT_SECURE_NO_WARNINGS ferencd@0: #define _CRT_SECURE_NO_DEPRECATE ferencd@0: #endif ferencd@0: ferencd@0: #include ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: #include ferencd@0: #include ferencd@0: #endif ferencd@0: ferencd@0: #include "tinyxml.h" ferencd@0: ferencd@0: FILE* TiXmlFOpen( const char* filename, const char* mode ); ferencd@0: ferencd@0: bool TiXmlBase::condenseWhiteSpace = true; ferencd@0: ferencd@0: // Microsoft compiler security ferencd@0: FILE* TiXmlFOpen( const char* filename, const char* mode ) ferencd@0: { ferencd@0: #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) ferencd@0: FILE* fp = 0; ferencd@0: errno_t err = fopen_s( &fp, filename, mode ); ferencd@0: if ( !err && fp ) ferencd@0: return fp; ferencd@0: return 0; ferencd@0: #else ferencd@0: return fopen( filename, mode ); ferencd@0: #endif ferencd@0: } ferencd@0: ferencd@0: void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) ferencd@0: { ferencd@0: int i=0; ferencd@0: ferencd@0: while( i(str.length()) ) ferencd@0: { ferencd@0: unsigned char c = static_cast(str[i]); ferencd@0: ferencd@0: if ( c == '&' ferencd@0: && i < ( static_cast(str.length()) - 2 ) ferencd@0: && str[i+1] == '#' ferencd@0: && str[i+2] == 'x' ) ferencd@0: { ferencd@0: // Hexadecimal character reference. ferencd@0: // Pass through unchanged. ferencd@0: // © -- copyright symbol, for example. ferencd@0: // ferencd@0: // The -1 is a bug fix from Rob Laveaux. It keeps ferencd@0: // an overflow from happening if there is no ';'. ferencd@0: // There are actually 2 ways to exit this loop - ferencd@0: // while fails (error case) and break (semicolon found). ferencd@0: // However, there is no mechanism (currently) for ferencd@0: // this function to return an error. ferencd@0: while ( i(str.length()) -1 ) ferencd@0: { ferencd@0: outString->append( str.c_str() + i, 1 ); ferencd@0: ++i; ferencd@0: if ( str[i] == ';' ) ferencd@0: break; ferencd@0: } ferencd@0: } ferencd@0: else if ( c == '&' ) ferencd@0: { ferencd@0: outString->append( entity[0].str, entity[0].strLength ); ferencd@0: ++i; ferencd@0: } ferencd@0: else if ( c == '<' ) ferencd@0: { ferencd@0: outString->append( entity[1].str, entity[1].strLength ); ferencd@0: ++i; ferencd@0: } ferencd@0: else if ( c == '>' ) ferencd@0: { ferencd@0: outString->append( entity[2].str, entity[2].strLength ); ferencd@0: ++i; ferencd@0: } ferencd@0: else if ( c == '\"' ) ferencd@0: { ferencd@0: outString->append( entity[3].str, entity[3].strLength ); ferencd@0: ++i; ferencd@0: } ferencd@0: else if ( c == '\'' ) ferencd@0: { ferencd@0: outString->append( entity[4].str, entity[4].strLength ); ferencd@0: ++i; ferencd@0: } ferencd@0: else if ( c < 32 ) ferencd@0: { ferencd@0: // Easy pass at non-alpha/numeric/symbol ferencd@0: // Below 32 is symbolic. ferencd@0: char buf[ 32 ]; ferencd@0: ferencd@0: #if defined(TIXML_SNPRINTF) ferencd@0: TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", static_cast ( c & 0xff ) ); ferencd@0: #else ferencd@0: sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); ferencd@0: #endif ferencd@0: ferencd@0: //*ME: warning C4267: convert 'size_t' to 'int' ferencd@0: //*ME: Int-Cast to make compiler happy ... ferencd@0: outString->append( buf, static_cast(strlen(buf)) ); ferencd@0: ++i; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: //char realc = (char) c; ferencd@0: //outString->append( &realc, 1 ); ferencd@0: *outString += static_cast(c); // somewhat more efficient function call. ferencd@0: ++i; ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() ferencd@0: { ferencd@0: parent = 0; ferencd@0: type = _type; ferencd@0: firstChild = 0; ferencd@0: lastChild = 0; ferencd@0: prev = 0; ferencd@0: next = 0; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlNode::~TiXmlNode() ferencd@0: { ferencd@0: TiXmlNode* node = firstChild; ferencd@0: TiXmlNode* temp = 0; ferencd@0: ferencd@0: while ( node ) ferencd@0: { ferencd@0: temp = node; ferencd@0: node = node->next; ferencd@0: delete temp; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: void TiXmlNode::CopyTo( TiXmlNode* target ) const ferencd@0: { ferencd@0: target->SetValue (value.c_str() ); ferencd@0: target->userData = userData; ferencd@0: target->location = location; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: void TiXmlNode::Clear() ferencd@0: { ferencd@0: TiXmlNode* node = firstChild; ferencd@0: TiXmlNode* temp = 0; ferencd@0: ferencd@0: while ( node ) ferencd@0: { ferencd@0: temp = node; ferencd@0: node = node->next; ferencd@0: delete temp; ferencd@0: } ferencd@0: ferencd@0: firstChild = 0; ferencd@0: lastChild = 0; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) ferencd@0: { ferencd@0: assert( node->parent == 0 || node->parent == this ); ferencd@0: assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); ferencd@0: ferencd@0: if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT ) ferencd@0: { ferencd@0: delete node; ferencd@0: if ( GetDocument() ) ferencd@0: GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: node->parent = this; ferencd@0: ferencd@0: node->prev = lastChild; ferencd@0: node->next = 0; ferencd@0: ferencd@0: if ( lastChild ) ferencd@0: lastChild->next = node; ferencd@0: else ferencd@0: firstChild = node; // it was an empty list. ferencd@0: ferencd@0: lastChild = node; ferencd@0: return node; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) ferencd@0: { ferencd@0: if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) ferencd@0: { ferencd@0: if ( GetDocument() ) ferencd@0: GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); ferencd@0: return 0; ferencd@0: } ferencd@0: TiXmlNode* node = addThis.Clone(); ferencd@0: if ( !node ) ferencd@0: return 0; ferencd@0: ferencd@0: return LinkEndChild( node ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) ferencd@0: { ferencd@0: if ( !beforeThis || beforeThis->parent != this ) { ferencd@0: return 0; ferencd@0: } ferencd@0: if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) ferencd@0: { ferencd@0: if ( GetDocument() ) ferencd@0: GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: TiXmlNode* node = addThis.Clone(); ferencd@0: if ( !node ) ferencd@0: return 0; ferencd@0: node->parent = this; ferencd@0: ferencd@0: node->next = beforeThis; ferencd@0: node->prev = beforeThis->prev; ferencd@0: if ( beforeThis->prev ) ferencd@0: { ferencd@0: beforeThis->prev->next = node; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: assert( firstChild == beforeThis ); ferencd@0: firstChild = node; ferencd@0: } ferencd@0: beforeThis->prev = node; ferencd@0: return node; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) ferencd@0: { ferencd@0: if ( !afterThis || afterThis->parent != this ) { ferencd@0: return 0; ferencd@0: } ferencd@0: if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) ferencd@0: { ferencd@0: if ( GetDocument() ) ferencd@0: GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: TiXmlNode* node = addThis.Clone(); ferencd@0: if ( !node ) ferencd@0: return 0; ferencd@0: node->parent = this; ferencd@0: ferencd@0: node->prev = afterThis; ferencd@0: node->next = afterThis->next; ferencd@0: if ( afterThis->next ) ferencd@0: { ferencd@0: afterThis->next->prev = node; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: assert( lastChild == afterThis ); ferencd@0: lastChild = node; ferencd@0: } ferencd@0: afterThis->next = node; ferencd@0: return node; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) ferencd@0: { ferencd@0: if ( !replaceThis ) ferencd@0: return 0; ferencd@0: ferencd@0: if ( replaceThis->parent != this ) ferencd@0: return 0; ferencd@0: ferencd@0: if ( withThis.ToDocument() ) { ferencd@0: // A document can never be a child. Thanks to Noam. ferencd@0: TiXmlDocument* document = GetDocument(); ferencd@0: if ( document ) ferencd@0: document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: TiXmlNode* node = withThis.Clone(); ferencd@0: if ( !node ) ferencd@0: return 0; ferencd@0: ferencd@0: node->next = replaceThis->next; ferencd@0: node->prev = replaceThis->prev; ferencd@0: ferencd@0: if ( replaceThis->next ) ferencd@0: replaceThis->next->prev = node; ferencd@0: else ferencd@0: lastChild = node; ferencd@0: ferencd@0: if ( replaceThis->prev ) ferencd@0: replaceThis->prev->next = node; ferencd@0: else ferencd@0: firstChild = node; ferencd@0: ferencd@0: delete replaceThis; ferencd@0: node->parent = this; ferencd@0: return node; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) ferencd@0: { ferencd@0: if ( !removeThis ) { ferencd@0: return false; ferencd@0: } ferencd@0: ferencd@0: if ( removeThis->parent != this ) ferencd@0: { ferencd@0: assert( 0 ); ferencd@0: return false; ferencd@0: } ferencd@0: ferencd@0: if ( removeThis->next ) ferencd@0: removeThis->next->prev = removeThis->prev; ferencd@0: else ferencd@0: lastChild = removeThis->prev; ferencd@0: ferencd@0: if ( removeThis->prev ) ferencd@0: removeThis->prev->next = removeThis->next; ferencd@0: else ferencd@0: firstChild = removeThis->next; ferencd@0: ferencd@0: delete removeThis; ferencd@0: return true; ferencd@0: } ferencd@0: ferencd@0: const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const ferencd@0: { ferencd@0: const TiXmlNode* node; ferencd@0: for ( node = firstChild; node; node = node->next ) ferencd@0: { ferencd@0: if ( strcmp( node->Value(), _value ) == 0 ) ferencd@0: return node; ferencd@0: } ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const ferencd@0: { ferencd@0: const TiXmlNode* node; ferencd@0: for ( node = lastChild; node; node = node->prev ) ferencd@0: { ferencd@0: if ( strcmp( node->Value(), _value ) == 0 ) ferencd@0: return node; ferencd@0: } ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const ferencd@0: { ferencd@0: if ( !previous ) ferencd@0: { ferencd@0: return FirstChild(); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: assert( previous->parent == this ); ferencd@0: return previous->NextSibling(); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const ferencd@0: { ferencd@0: if ( !previous ) ferencd@0: { ferencd@0: return FirstChild( val ); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: assert( previous->parent == this ); ferencd@0: return previous->NextSibling( val ); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const ferencd@0: { ferencd@0: const TiXmlNode* node; ferencd@0: for ( node = next; node; node = node->next ) ferencd@0: { ferencd@0: if ( strcmp( node->Value(), _value ) == 0 ) ferencd@0: return node; ferencd@0: } ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const ferencd@0: { ferencd@0: const TiXmlNode* node; ferencd@0: for ( node = prev; node; node = node->prev ) ferencd@0: { ferencd@0: if ( strcmp( node->Value(), _value ) == 0 ) ferencd@0: return node; ferencd@0: } ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: void TiXmlElement::RemoveAttribute( const char * name ) ferencd@0: { ferencd@0: #ifdef TIXML_USE_STL ferencd@0: TIXML_STRING str( name ); ferencd@0: TiXmlAttribute* node = attributeSet.Find( str ); ferencd@0: #else ferencd@0: TiXmlAttribute* node = attributeSet.Find( name ); ferencd@0: #endif ferencd@0: if ( node ) ferencd@0: { ferencd@0: attributeSet.Remove( node ); ferencd@0: delete node; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: const TiXmlElement* TiXmlNode::FirstChildElement() const ferencd@0: { ferencd@0: const TiXmlNode* node; ferencd@0: ferencd@0: for ( node = FirstChild(); ferencd@0: node; ferencd@0: node = node->NextSibling() ) ferencd@0: { ferencd@0: if ( node->ToElement() ) ferencd@0: return node->ToElement(); ferencd@0: } ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const ferencd@0: { ferencd@0: const TiXmlNode* node; ferencd@0: ferencd@0: for ( node = FirstChild( _value ); ferencd@0: node; ferencd@0: node = node->NextSibling( _value ) ) ferencd@0: { ferencd@0: if ( node->ToElement() ) ferencd@0: return node->ToElement(); ferencd@0: } ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: const TiXmlElement* TiXmlNode::NextSiblingElement() const ferencd@0: { ferencd@0: const TiXmlNode* node; ferencd@0: ferencd@0: for ( node = NextSibling(); ferencd@0: node; ferencd@0: node = node->NextSibling() ) ferencd@0: { ferencd@0: if ( node->ToElement() ) ferencd@0: return node->ToElement(); ferencd@0: } ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const ferencd@0: { ferencd@0: const TiXmlNode* node; ferencd@0: ferencd@0: for ( node = NextSibling( _value ); ferencd@0: node; ferencd@0: node = node->NextSibling( _value ) ) ferencd@0: { ferencd@0: if ( node->ToElement() ) ferencd@0: return node->ToElement(); ferencd@0: } ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: const TiXmlDocument* TiXmlNode::GetDocument() const ferencd@0: { ferencd@0: const TiXmlNode* node; ferencd@0: ferencd@0: for( node = this; node; node = node->parent ) ferencd@0: { ferencd@0: if ( node->ToDocument() ) ferencd@0: return node->ToDocument(); ferencd@0: } ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlElement::TiXmlElement (const char * _value) ferencd@0: : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) ferencd@0: { ferencd@0: firstChild = lastChild = 0; ferencd@0: value = _value; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: TiXmlElement::TiXmlElement( const std::string& _value ) ferencd@0: : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) ferencd@0: { ferencd@0: firstChild = lastChild = 0; ferencd@0: value = _value; ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: ferencd@0: TiXmlElement::TiXmlElement( const TiXmlElement& copy) ferencd@0: : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) ferencd@0: { ferencd@0: firstChild = lastChild = 0; ferencd@0: copy.CopyTo( this ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base ) ferencd@0: { ferencd@0: ClearThis(); ferencd@0: base.CopyTo( this ); ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlElement::~TiXmlElement() ferencd@0: { ferencd@0: ClearThis(); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: void TiXmlElement::ClearThis() ferencd@0: { ferencd@0: Clear(); ferencd@0: while( attributeSet.First() ) ferencd@0: { ferencd@0: TiXmlAttribute* node = attributeSet.First(); ferencd@0: attributeSet.Remove( node ); ferencd@0: delete node; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: const char* TiXmlElement::Attribute( const char* name ) const ferencd@0: { ferencd@0: const TiXmlAttribute* node = attributeSet.Find( name ); ferencd@0: if ( node ) ferencd@0: return node->Value(); ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: const std::string* TiXmlElement::Attribute( const std::string& name ) const ferencd@0: { ferencd@0: const TiXmlAttribute* attrib = attributeSet.Find( name ); ferencd@0: if ( attrib ) ferencd@0: return &attrib->ValueStr(); ferencd@0: return 0; ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: ferencd@0: const char* TiXmlElement::Attribute( const char* name, int* i ) const ferencd@0: { ferencd@0: const TiXmlAttribute* attrib = attributeSet.Find( name ); ferencd@0: const char* result = 0; ferencd@0: ferencd@0: if ( attrib ) { ferencd@0: result = attrib->Value(); ferencd@0: if ( i ) { ferencd@0: attrib->QueryIntValue( i ); ferencd@0: } ferencd@0: } ferencd@0: return result; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const ferencd@0: { ferencd@0: const TiXmlAttribute* attrib = attributeSet.Find( name ); ferencd@0: const std::string* result = 0; ferencd@0: ferencd@0: if ( attrib ) { ferencd@0: result = &attrib->ValueStr(); ferencd@0: if ( i ) { ferencd@0: attrib->QueryIntValue( i ); ferencd@0: } ferencd@0: } ferencd@0: return result; ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: ferencd@0: const char* TiXmlElement::Attribute( const char* name, double* d ) const ferencd@0: { ferencd@0: const TiXmlAttribute* attrib = attributeSet.Find( name ); ferencd@0: const char* result = 0; ferencd@0: ferencd@0: if ( attrib ) { ferencd@0: result = attrib->Value(); ferencd@0: if ( d ) { ferencd@0: attrib->QueryDoubleValue( d ); ferencd@0: } ferencd@0: } ferencd@0: return result; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const ferencd@0: { ferencd@0: const TiXmlAttribute* attrib = attributeSet.Find( name ); ferencd@0: const std::string* result = 0; ferencd@0: ferencd@0: if ( attrib ) { ferencd@0: result = &attrib->ValueStr(); ferencd@0: if ( d ) { ferencd@0: attrib->QueryDoubleValue( d ); ferencd@0: } ferencd@0: } ferencd@0: return result; ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: ferencd@0: int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const ferencd@0: { ferencd@0: const TiXmlAttribute* attrib = attributeSet.Find( name ); ferencd@0: if ( !attrib ) ferencd@0: return TIXML_NO_ATTRIBUTE; ferencd@0: return attrib->QueryIntValue( ival ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* pvalue ) const ferencd@0: { ferencd@0: const TiXmlAttribute* node = attributeSet.Find( name ); ferencd@0: if ( !node ) ferencd@0: return TIXML_NO_ATTRIBUTE; ferencd@0: ferencd@0: int ival = 0; ferencd@0: int result = node->QueryIntValue( &ival ); ferencd@0: *pvalue = static_cast(ival); ferencd@0: return result; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const ferencd@0: { ferencd@0: const TiXmlAttribute* node = attributeSet.Find( name ); ferencd@0: if ( !node ) ferencd@0: return TIXML_NO_ATTRIBUTE; ferencd@0: ferencd@0: int result = TIXML_WRONG_TYPE; ferencd@0: if ( StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN ) ferencd@0: || StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN ) ferencd@0: || StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) ) ferencd@0: { ferencd@0: *bval = true; ferencd@0: result = TIXML_SUCCESS; ferencd@0: } ferencd@0: else if ( StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN ) ferencd@0: || StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN ) ferencd@0: || StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) ) ferencd@0: { ferencd@0: *bval = false; ferencd@0: result = TIXML_SUCCESS; ferencd@0: } ferencd@0: return result; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const ferencd@0: { ferencd@0: const TiXmlAttribute* attrib = attributeSet.Find( name ); ferencd@0: if ( !attrib ) ferencd@0: return TIXML_NO_ATTRIBUTE; ferencd@0: return attrib->QueryIntValue( ival ); ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: ferencd@0: int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const ferencd@0: { ferencd@0: const TiXmlAttribute* attrib = attributeSet.Find( name ); ferencd@0: if ( !attrib ) ferencd@0: return TIXML_NO_ATTRIBUTE; ferencd@0: return attrib->QueryDoubleValue( dval ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const ferencd@0: { ferencd@0: const TiXmlAttribute* attrib = attributeSet.Find( name ); ferencd@0: if ( !attrib ) ferencd@0: return TIXML_NO_ATTRIBUTE; ferencd@0: return attrib->QueryDoubleValue( dval ); ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: ferencd@0: void TiXmlElement::SetAttribute( const char * name, int val ) ferencd@0: { ferencd@0: TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); ferencd@0: if ( attrib ) { ferencd@0: attrib->SetIntValue( val ); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: void TiXmlElement::SetAttribute( const std::string& name, int val ) ferencd@0: { ferencd@0: TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); ferencd@0: if ( attrib ) { ferencd@0: attrib->SetIntValue( val ); ferencd@0: } ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: ferencd@0: void TiXmlElement::SetDoubleAttribute( const char * name, double val ) ferencd@0: { ferencd@0: TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); ferencd@0: if ( attrib ) { ferencd@0: attrib->SetDoubleValue( val ); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) ferencd@0: { ferencd@0: TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); ferencd@0: if ( attrib ) { ferencd@0: attrib->SetDoubleValue( val ); ferencd@0: } ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: ferencd@0: void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) ferencd@0: { ferencd@0: TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname ); ferencd@0: if ( attrib ) { ferencd@0: attrib->SetValue( cvalue ); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value ) ferencd@0: { ferencd@0: TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name ); ferencd@0: if ( attrib ) { ferencd@0: attrib->SetValue( _value ); ferencd@0: } ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: ferencd@0: void TiXmlElement::Print( FILE* cfile, int depth ) const ferencd@0: { ferencd@0: int i; ferencd@0: assert( cfile ); ferencd@0: for ( i=0; iNext() ) ferencd@0: { ferencd@0: fprintf( cfile, " " ); ferencd@0: attrib->Print( cfile, depth ); ferencd@0: } ferencd@0: ferencd@0: // There are 3 different formatting approaches: ferencd@0: // 1) An element without children is printed as a node ferencd@0: // 2) An element with only a text child is printed as text ferencd@0: // 3) An element with children is printed on multiple lines. ferencd@0: TiXmlNode* node; ferencd@0: if ( !firstChild ) ferencd@0: { ferencd@0: fprintf( cfile, " />" ); ferencd@0: } ferencd@0: else if ( firstChild == lastChild && firstChild->ToText() ) ferencd@0: { ferencd@0: fprintf( cfile, ">" ); ferencd@0: firstChild->Print( cfile, depth + 1 ); ferencd@0: fprintf( cfile, "", value.c_str() ); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: fprintf( cfile, ">" ); ferencd@0: ferencd@0: for ( node = firstChild; node; node=node->NextSibling() ) ferencd@0: { ferencd@0: if ( !node->ToText() ) ferencd@0: { ferencd@0: fprintf( cfile, "\n" ); ferencd@0: } ferencd@0: node->Print( cfile, depth+1 ); ferencd@0: } ferencd@0: fprintf( cfile, "\n" ); ferencd@0: for( i=0; i", value.c_str() ); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: void TiXmlElement::Print(std::string &target, int depth) const ferencd@0: { ferencd@0: int i; ferencd@0: for ( i=0; iNext() ) ferencd@0: { ferencd@0: target += " "; ferencd@0: std::string temp; ferencd@0: attrib->Print( temp, depth ); ferencd@0: target += temp; ferencd@0: } ferencd@0: ferencd@0: // There are 3 different formatting approaches: ferencd@0: // 1) An element without children is printed as a node ferencd@0: // 2) An element with only a text child is printed as text ferencd@0: // 3) An element with children is printed on multiple lines. ferencd@0: TiXmlNode* node; ferencd@0: if ( !firstChild ) ferencd@0: { ferencd@0: target += " />" ; ferencd@0: } ferencd@0: else if ( firstChild == lastChild && firstChild->ToText() ) ferencd@0: { ferencd@0: target += ">"; ferencd@0: std::string temp; ferencd@0: firstChild->Print( temp, depth + 1 ); ferencd@0: target += temp; ferencd@0: target += "<"; ferencd@0: target += value.c_str(); ferencd@0: target += ">"; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: target += ">"; ferencd@0: ferencd@0: for ( node = firstChild; node; node=node->NextSibling() ) ferencd@0: { ferencd@0: if ( !node->ToText() ) ferencd@0: { ferencd@0: target += "\n"; ferencd@0: } ferencd@0: std::string temp; ferencd@0: node->Print( temp, depth+1 ); ferencd@0: target += temp; ferencd@0: } ferencd@0: target += "\n"; ferencd@0: for( i=0; iNext() ) ferencd@0: { ferencd@0: target->SetAttribute( attribute->Name(), attribute->Value() ); ferencd@0: } ferencd@0: ferencd@0: TiXmlNode* node = 0; ferencd@0: for ( node = firstChild; node; node = node->NextSibling() ) ferencd@0: { ferencd@0: target->LinkEndChild( node->Clone() ); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const ferencd@0: { ferencd@0: if ( visitor->VisitEnter( *this, attributeSet.First() ) ) ferencd@0: { ferencd@0: for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) ferencd@0: { ferencd@0: if ( !node->Accept( visitor ) ) ferencd@0: break; ferencd@0: } ferencd@0: } ferencd@0: return visitor->VisitExit( *this ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlNode* TiXmlElement::Clone() const ferencd@0: { ferencd@0: TiXmlElement* clone = new TiXmlElement( Value() ); ferencd@0: if ( !clone ) ferencd@0: return 0; ferencd@0: ferencd@0: CopyTo( clone ); ferencd@0: return clone; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: const char* TiXmlElement::GetText() const ferencd@0: { ferencd@0: const TiXmlNode* child = this->FirstChild(); ferencd@0: if ( child ) { ferencd@0: const TiXmlText* childText = child->ToText(); ferencd@0: if ( childText ) { ferencd@0: return childText->Value(); ferencd@0: } ferencd@0: } ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) ferencd@0: { ferencd@0: tabsize = 4; ferencd@0: useMicrosoftBOM = false; ferencd@0: ClearError(); ferencd@0: } ferencd@0: ferencd@0: TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) ferencd@0: { ferencd@0: tabsize = 4; ferencd@0: useMicrosoftBOM = false; ferencd@0: value = documentName; ferencd@0: ClearError(); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) ferencd@0: { ferencd@0: tabsize = 4; ferencd@0: useMicrosoftBOM = false; ferencd@0: value = documentName; ferencd@0: ClearError(); ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: ferencd@0: TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) ferencd@0: { ferencd@0: copy.CopyTo( this ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy ) ferencd@0: { ferencd@0: Clear(); ferencd@0: copy.CopyTo( this ); ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) ferencd@0: { ferencd@0: return LoadFile( Value(), encoding ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: bool TiXmlDocument::SaveFile() const ferencd@0: { ferencd@0: return SaveFile( Value() ); ferencd@0: } ferencd@0: ferencd@0: bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) ferencd@0: { ferencd@0: TIXML_STRING filename( _filename ); ferencd@0: value = filename; ferencd@0: ferencd@0: // reading in binary mode so that tinyxml can normalize the EOL ferencd@0: FILE* file = TiXmlFOpen( value.c_str (), "rb" ); ferencd@0: ferencd@0: if ( file ) ferencd@0: { ferencd@0: bool result = LoadFile( file, encoding ); ferencd@0: fclose( file ); ferencd@0: return result; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); ferencd@0: return false; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) ferencd@0: { ferencd@0: if ( !file ) ferencd@0: { ferencd@0: SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); ferencd@0: return false; ferencd@0: } ferencd@0: ferencd@0: // Delete the existing data: ferencd@0: Clear(); ferencd@0: location.Clear(); ferencd@0: ferencd@0: // Get the file size, so we can pre-allocate the string. HUGE speed impact. ferencd@0: long length = 0; ferencd@0: fseek( file, 0, SEEK_END ); ferencd@0: length = ftell( file ); ferencd@0: fseek( file, 0, SEEK_SET ); ferencd@0: ferencd@0: // Strange case, but good to handle up front. ferencd@0: if ( length <= 0 ) ferencd@0: { ferencd@0: SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); ferencd@0: return false; ferencd@0: } ferencd@0: ferencd@0: // Subtle bug here. TinyXml did use fgets. But from the XML spec: ferencd@0: // 2.11 End-of-Line Handling ferencd@0: // ferencd@0: // ferencd@0: // ...the XML processor MUST behave as if it normalized all line breaks in external ferencd@0: // parsed entities (including the document entity) on input, before parsing, by translating ferencd@0: // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to ferencd@0: // a single #xA character. ferencd@0: // ferencd@0: // ferencd@0: // It is not clear fgets does that, and certainly isn't clear it works cross platform. ferencd@0: // Generally, you expect fgets to translate from the convention of the OS to the c/unix ferencd@0: // convention, and not work generally. ferencd@0: ferencd@0: /* ferencd@0: while( fgets( buf, sizeof(buf), file ) ) ferencd@0: { ferencd@0: data += buf; ferencd@0: } ferencd@0: */ ferencd@0: ferencd@0: char* buf = new char[ length+1 ]; ferencd@0: buf[0] = 0; ferencd@0: ferencd@0: if ( fread( buf, length, 1, file ) != 1 ) { ferencd@0: delete [] buf; ferencd@0: SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); ferencd@0: return false; ferencd@0: } ferencd@0: ferencd@0: // Process the buffer in place to normalize new lines. (See comment above.) ferencd@0: // Copies from the 'p' to 'q' pointer, where p can advance faster if ferencd@0: // a newline-carriage return is hit. ferencd@0: // ferencd@0: // Wikipedia: ferencd@0: // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or ferencd@0: // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)... ferencd@0: // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others ferencd@0: // * 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 ferencd@0: // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9 ferencd@0: ferencd@0: buf[length] = 0; ferencd@0: FixLineFeeds(buf, length); ferencd@0: ferencd@0: Parse( buf, 0, encoding ); ferencd@0: ferencd@0: delete [] buf; ferencd@0: return !Error(); ferencd@0: } ferencd@0: ferencd@0: char* TiXmlDocument::FixLineFeeds(char *buf, size_t length) ferencd@0: { ferencd@0: const char* p = buf; // the read head ferencd@0: char* q = buf; // the write head ferencd@0: const char CR = 0x0d; ferencd@0: const char LF = 0x0a; ferencd@0: ferencd@0: while( *p ) { ferencd@0: assert( p < (buf+length) ); ferencd@0: assert( q <= (buf+length) ); ferencd@0: assert( q <= p ); ferencd@0: ferencd@0: if ( *p == CR ) { ferencd@0: *q++ = LF; ferencd@0: p++; ferencd@0: if ( *p == LF ) { // check for CR+LF (and skip LF) ferencd@0: p++; ferencd@0: } ferencd@0: } ferencd@0: else { ferencd@0: *q++ = *p++; ferencd@0: } ferencd@0: } ferencd@0: assert( q <= (buf+length) ); ferencd@0: *q = 0; ferencd@0: return q; ferencd@0: ferencd@0: } ferencd@0: ferencd@0: bool TiXmlDocument::FromMemory(const char* source, TiXmlEncoding encoding) ferencd@0: { ferencd@0: size_t len = strlen(source); ferencd@0: char *tmp = reinterpret_cast(calloc(sizeof(char), len + 1)); ferencd@0: strncpy(tmp, source, len); ferencd@0: FixLineFeeds(tmp, len); ferencd@0: Parse( tmp, 0, encoding ); ferencd@0: free (tmp); ferencd@0: return !Error(); ferencd@0: } ferencd@0: ferencd@0: bool TiXmlDocument::SaveFile( const char * filename ) const ferencd@0: { ferencd@0: // The old c stuff lives on... ferencd@0: FILE* fp = TiXmlFOpen( filename, "w" ); ferencd@0: if ( fp ) ferencd@0: { ferencd@0: bool result = SaveFile( fp ); ferencd@0: fclose( fp ); ferencd@0: return result; ferencd@0: } ferencd@0: return false; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: bool TiXmlDocument::SaveFile( FILE* fp ) const ferencd@0: { ferencd@0: if ( useMicrosoftBOM ) ferencd@0: { ferencd@0: const unsigned char TIXML_UTF_LEAD_0 = 0xefU; ferencd@0: const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; ferencd@0: const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; ferencd@0: ferencd@0: fputc( TIXML_UTF_LEAD_0, fp ); ferencd@0: fputc( TIXML_UTF_LEAD_1, fp ); ferencd@0: fputc( TIXML_UTF_LEAD_2, fp ); ferencd@0: } ferencd@0: Print( fp, 0 ); ferencd@0: return (ferror(fp) == 0); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: void TiXmlDocument::CopyTo( TiXmlDocument* target ) const ferencd@0: { ferencd@0: TiXmlNode::CopyTo( target ); ferencd@0: ferencd@0: target->error = error; ferencd@0: target->errorId = errorId; ferencd@0: target->errorDesc = errorDesc; ferencd@0: target->tabsize = tabsize; ferencd@0: target->errorLocation = errorLocation; ferencd@0: target->useMicrosoftBOM = useMicrosoftBOM; ferencd@0: ferencd@0: TiXmlNode* node = 0; ferencd@0: for ( node = firstChild; node; node = node->NextSibling() ) ferencd@0: { ferencd@0: target->LinkEndChild( node->Clone() ); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlNode* TiXmlDocument::Clone() const ferencd@0: { ferencd@0: TiXmlDocument* clone = new TiXmlDocument(); ferencd@0: if ( !clone ) ferencd@0: return 0; ferencd@0: ferencd@0: CopyTo( clone ); ferencd@0: return clone; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: void TiXmlDocument::Print( FILE* cfile, int depth ) const ferencd@0: { ferencd@0: assert( cfile ); ferencd@0: for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) ferencd@0: { ferencd@0: node->Print( cfile, depth ); ferencd@0: fprintf( cfile, "\n" ); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: void TiXmlDocument::Print( std::string& target, int depth ) const ferencd@0: { ferencd@0: ferencd@0: for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) ferencd@0: { ferencd@0: std::string temp; ferencd@0: node->Print( temp, depth ); ferencd@0: temp += "\n"; ferencd@0: target += temp; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const ferencd@0: { ferencd@0: if ( visitor->VisitEnter( *this ) ) ferencd@0: { ferencd@0: for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) ferencd@0: { ferencd@0: if ( !node->Accept( visitor ) ) ferencd@0: break; ferencd@0: } ferencd@0: } ferencd@0: return visitor->VisitExit( *this ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: const TiXmlAttribute* TiXmlAttribute::Next() const ferencd@0: { ferencd@0: // We are using knowledge of the sentinel. The sentinel ferencd@0: // have a value or name. ferencd@0: if ( next->value.empty() && next->name.empty() ) ferencd@0: return 0; ferencd@0: return next; ferencd@0: } ferencd@0: ferencd@0: /* ferencd@0: TiXmlAttribute* TiXmlAttribute::Next() ferencd@0: { ferencd@0: // We are using knowledge of the sentinel. The sentinel ferencd@0: // have a value or name. ferencd@0: if ( next->value.empty() && next->name.empty() ) ferencd@0: return 0; ferencd@0: return next; ferencd@0: } ferencd@0: */ ferencd@0: ferencd@0: const TiXmlAttribute* TiXmlAttribute::Previous() const ferencd@0: { ferencd@0: // We are using knowledge of the sentinel. The sentinel ferencd@0: // have a value or name. ferencd@0: if ( prev->value.empty() && prev->name.empty() ) ferencd@0: return 0; ferencd@0: return prev; ferencd@0: } ferencd@0: ferencd@0: /* ferencd@0: TiXmlAttribute* TiXmlAttribute::Previous() ferencd@0: { ferencd@0: // We are using knowledge of the sentinel. The sentinel ferencd@0: // have a value or name. ferencd@0: if ( prev->value.empty() && prev->name.empty() ) ferencd@0: return 0; ferencd@0: return prev; ferencd@0: } ferencd@0: */ ferencd@0: ferencd@0: void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const ferencd@0: { ferencd@0: TIXML_STRING n, v; ferencd@0: ferencd@0: EncodeString( name, &n ); ferencd@0: EncodeString( value, &v ); ferencd@0: ferencd@0: if (value.find ('\"') == TIXML_STRING::npos) { ferencd@0: if ( cfile ) { ferencd@0: fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); ferencd@0: } ferencd@0: if ( str ) { ferencd@0: (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; ferencd@0: } ferencd@0: } ferencd@0: else { ferencd@0: if ( cfile ) { ferencd@0: fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); ferencd@0: } ferencd@0: if ( str ) { ferencd@0: (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: void TiXmlAttribute::Print( std::string& target, int /*depth*/) const ferencd@0: { ferencd@0: TIXML_STRING n, v; ferencd@0: ferencd@0: EncodeString( name, &n ); ferencd@0: EncodeString( value, &v ); ferencd@0: ferencd@0: if (value.find ('\"') == TIXML_STRING::npos) ferencd@0: { ferencd@0: { ferencd@0: std::stringstream ss; ferencd@0: ss << n.c_str() << "=\"" <", value.c_str() ); ferencd@0: } ferencd@0: ferencd@0: void TiXmlComment::Print( std::string& target, int depth ) const ferencd@0: { ferencd@0: ferencd@0: for ( int i=0; iVisit( *this ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlNode* TiXmlComment::Clone() const ferencd@0: { ferencd@0: TiXmlComment* clone = new TiXmlComment(); ferencd@0: ferencd@0: if ( !clone ) ferencd@0: return 0; ferencd@0: ferencd@0: CopyTo( clone ); ferencd@0: return clone; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: void TiXmlText::Print( FILE* cfile, int depth ) const ferencd@0: { ferencd@0: assert( cfile ); ferencd@0: if ( cdata ) ferencd@0: { ferencd@0: int i; ferencd@0: fprintf( cfile, "\n" ); ferencd@0: for ( i=0; i\n", value.c_str() ); // unformatted output ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: TIXML_STRING buffer; ferencd@0: EncodeString( value, &buffer ); ferencd@0: fprintf( cfile, "%s", buffer.c_str() ); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: void TiXmlText::Print(std::string& target, int depth ) const ferencd@0: { ferencd@0: if ( cdata ) ferencd@0: { ferencd@0: int i; ferencd@0: target += "\n"; ferencd@0: for ( i=0; i\n"; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: TIXML_STRING buffer; ferencd@0: EncodeString( value, &buffer ); ferencd@0: target += buffer.c_str() ; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: void TiXmlText::CopyTo( TiXmlText* target ) const ferencd@0: { ferencd@0: TiXmlNode::CopyTo( target ); ferencd@0: target->cdata = cdata; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: bool TiXmlText::Accept( TiXmlVisitor* visitor ) const ferencd@0: { ferencd@0: return visitor->Visit( *this ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlNode* TiXmlText::Clone() const ferencd@0: { ferencd@0: TiXmlText* clone = 0; ferencd@0: clone = new TiXmlText( "" ); ferencd@0: ferencd@0: if ( !clone ) ferencd@0: return 0; ferencd@0: ferencd@0: CopyTo( clone ); ferencd@0: return clone; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlDeclaration::TiXmlDeclaration( const char * _version, ferencd@0: const char * _encoding, ferencd@0: const char * _standalone ) ferencd@0: : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) ferencd@0: { ferencd@0: version = _version; ferencd@0: encoding = _encoding; ferencd@0: standalone = _standalone; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, ferencd@0: const std::string& _encoding, ferencd@0: const std::string& _standalone ) ferencd@0: : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) ferencd@0: { ferencd@0: version = _version; ferencd@0: encoding = _encoding; ferencd@0: standalone = _standalone; ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: ferencd@0: TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) ferencd@0: : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) ferencd@0: { ferencd@0: copy.CopyTo( this ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) ferencd@0: { ferencd@0: Clear(); ferencd@0: copy.CopyTo( this ); ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const ferencd@0: { ferencd@0: if ( cfile ) fprintf( cfile, "" ); ferencd@0: if ( str ) (*str) += "?>"; ferencd@0: } ferencd@0: ferencd@0: void TiXmlDeclaration::Print( std::string& target, int /*depth*/) const ferencd@0: { ferencd@0: target += ""; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const ferencd@0: { ferencd@0: TiXmlNode::CopyTo( target ); ferencd@0: ferencd@0: target->version = version; ferencd@0: target->encoding = encoding; ferencd@0: target->standalone = standalone; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const ferencd@0: { ferencd@0: return visitor->Visit( *this ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlNode* TiXmlDeclaration::Clone() const ferencd@0: { ferencd@0: TiXmlDeclaration* clone = new TiXmlDeclaration(); ferencd@0: ferencd@0: if ( !clone ) ferencd@0: return 0; ferencd@0: ferencd@0: CopyTo( clone ); ferencd@0: return clone; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: void TiXmlUnknown::Print( FILE* cfile, int depth ) const ferencd@0: { ferencd@0: for ( int i=0; i", value.c_str() ); ferencd@0: } ferencd@0: ferencd@0: void TiXmlUnknown::Print( std::string& target, int depth ) const ferencd@0: { ferencd@0: for ( int i=0; i"; ferencd@0: } ferencd@0: ferencd@0: void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const ferencd@0: { ferencd@0: TiXmlNode::CopyTo( target ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const ferencd@0: { ferencd@0: return visitor->Visit( *this ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlNode* TiXmlUnknown::Clone() const ferencd@0: { ferencd@0: TiXmlUnknown* clone = new TiXmlUnknown(); ferencd@0: ferencd@0: if ( !clone ) ferencd@0: return 0; ferencd@0: ferencd@0: CopyTo( clone ); ferencd@0: return clone; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlAttributeSet::TiXmlAttributeSet() ferencd@0: { ferencd@0: sentinel.next = &sentinel; ferencd@0: sentinel.prev = &sentinel; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlAttributeSet::~TiXmlAttributeSet() ferencd@0: { ferencd@0: assert( sentinel.next == &sentinel ); ferencd@0: assert( sentinel.prev == &sentinel ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) ferencd@0: { ferencd@0: #ifdef TIXML_USE_STL ferencd@0: assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. ferencd@0: #else ferencd@0: assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. ferencd@0: #endif ferencd@0: ferencd@0: addMe->next = &sentinel; ferencd@0: addMe->prev = sentinel.prev; ferencd@0: ferencd@0: sentinel.prev->next = addMe; ferencd@0: sentinel.prev = addMe; ferencd@0: } ferencd@0: ferencd@0: void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) ferencd@0: { ferencd@0: TiXmlAttribute* node; ferencd@0: ferencd@0: for( node = sentinel.next; node && node != &sentinel; node = node->next ) ferencd@0: { ferencd@0: if ( node == removeMe && node) ferencd@0: { ferencd@0: node->prev->next = node->next; ferencd@0: node->next->prev = node->prev; ferencd@0: node->next = 0; ferencd@0: node->prev = 0; ferencd@0: return; ferencd@0: } ferencd@0: } ferencd@0: assert( 0 ); // we tried to remove a non-linked attribute. ferencd@0: } ferencd@0: ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const ferencd@0: { ferencd@0: for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) ferencd@0: { ferencd@0: if ( node->name == name ) ferencd@0: return node; ferencd@0: } ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name ) ferencd@0: { ferencd@0: TiXmlAttribute* attrib = Find( _name ); ferencd@0: if ( !attrib ) { ferencd@0: attrib = new TiXmlAttribute(); ferencd@0: Add( attrib ); ferencd@0: attrib->SetName( _name ); ferencd@0: } ferencd@0: return attrib; ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: ferencd@0: TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const ferencd@0: { ferencd@0: for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) ferencd@0: { ferencd@0: if ( strcmp( node->name.c_str(), name ) == 0 ) ferencd@0: return node; ferencd@0: } ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) ferencd@0: { ferencd@0: TiXmlAttribute* attrib = Find( _name ); ferencd@0: if ( !attrib ) { ferencd@0: attrib = new TiXmlAttribute(); ferencd@0: Add( attrib ); ferencd@0: attrib->SetName( _name ); ferencd@0: } ferencd@0: return attrib; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: std::istream& operator>> (std::istream & in, TiXmlNode & base) ferencd@0: { ferencd@0: TIXML_STRING tag; ferencd@0: tag.reserve( 8 * 1000 ); ferencd@0: base.StreamIn( &in, &tag ); ferencd@0: ferencd@0: base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); ferencd@0: return in; ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: ferencd@0: #ifdef TIXML_USE_STL ferencd@0: std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) ferencd@0: { ferencd@0: TiXmlPrinter printer; ferencd@0: printer.SetStreamPrinting(); ferencd@0: base.Accept( &printer ); ferencd@0: out << printer.Str(); ferencd@0: ferencd@0: return out; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: std::string& operator<< (std::string& out, const TiXmlNode& base ) ferencd@0: { ferencd@0: TiXmlPrinter printer; ferencd@0: printer.SetStreamPrinting(); ferencd@0: base.Accept( &printer ); ferencd@0: out.append( printer.Str() ); ferencd@0: ferencd@0: return out; ferencd@0: } ferencd@0: #endif ferencd@0: ferencd@0: ferencd@0: TiXmlHandle TiXmlHandle::FirstChild() const ferencd@0: { ferencd@0: if ( node ) ferencd@0: { ferencd@0: TiXmlNode* child = node->FirstChild(); ferencd@0: if ( child ) ferencd@0: return TiXmlHandle( child ); ferencd@0: } ferencd@0: return TiXmlHandle( 0 ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const ferencd@0: { ferencd@0: if ( node ) ferencd@0: { ferencd@0: TiXmlNode* child = node->FirstChild( value ); ferencd@0: if ( child ) ferencd@0: return TiXmlHandle( child ); ferencd@0: } ferencd@0: return TiXmlHandle( 0 ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlHandle TiXmlHandle::FirstChildElement() const ferencd@0: { ferencd@0: if ( node ) ferencd@0: { ferencd@0: TiXmlElement* child = node->FirstChildElement(); ferencd@0: if ( child ) ferencd@0: return TiXmlHandle( child ); ferencd@0: } ferencd@0: return TiXmlHandle( 0 ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const ferencd@0: { ferencd@0: if ( node ) ferencd@0: { ferencd@0: TiXmlElement* child = node->FirstChildElement( value ); ferencd@0: if ( child ) ferencd@0: return TiXmlHandle( child ); ferencd@0: } ferencd@0: return TiXmlHandle( 0 ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlHandle TiXmlHandle::Child( int count ) const ferencd@0: { ferencd@0: if ( node ) ferencd@0: { ferencd@0: int i; ferencd@0: TiXmlNode* child = node->FirstChild(); ferencd@0: for ( i=0; ferencd@0: child && iNextSibling(), ++i ) ferencd@0: { ferencd@0: // nothing ferencd@0: } ferencd@0: if ( child ) ferencd@0: return TiXmlHandle( child ); ferencd@0: } ferencd@0: return TiXmlHandle( 0 ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const ferencd@0: { ferencd@0: if ( node ) ferencd@0: { ferencd@0: int i; ferencd@0: TiXmlNode* child = node->FirstChild( value ); ferencd@0: for ( i=0; ferencd@0: child && iNextSibling( value ), ++i ) ferencd@0: { ferencd@0: // nothing ferencd@0: } ferencd@0: if ( child ) ferencd@0: return TiXmlHandle( child ); ferencd@0: } ferencd@0: return TiXmlHandle( 0 ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlHandle TiXmlHandle::ChildElement( int count ) const ferencd@0: { ferencd@0: if ( node ) ferencd@0: { ferencd@0: int i; ferencd@0: TiXmlElement* child = node->FirstChildElement(); ferencd@0: for ( i=0; ferencd@0: child && iNextSiblingElement(), ++i ) ferencd@0: { ferencd@0: // nothing ferencd@0: } ferencd@0: if ( child ) ferencd@0: return TiXmlHandle( child ); ferencd@0: } ferencd@0: return TiXmlHandle( 0 ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const ferencd@0: { ferencd@0: if ( node ) ferencd@0: { ferencd@0: int i; ferencd@0: TiXmlElement* child = node->FirstChildElement( value ); ferencd@0: for ( i=0; ferencd@0: child && iNextSiblingElement( value ), ++i ) ferencd@0: { ferencd@0: // nothing ferencd@0: } ferencd@0: if ( child ) ferencd@0: return TiXmlHandle( child ); ferencd@0: } ferencd@0: return TiXmlHandle( 0 ); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) ferencd@0: { ferencd@0: return true; ferencd@0: } ferencd@0: ferencd@0: bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) ferencd@0: { ferencd@0: return true; ferencd@0: } ferencd@0: ferencd@0: bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) ferencd@0: { ferencd@0: DoIndent(); ferencd@0: buffer += "<"; ferencd@0: buffer += element.Value(); ferencd@0: ferencd@0: for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) ferencd@0: { ferencd@0: buffer += " "; ferencd@0: attrib->Print( 0, 0, &buffer ); ferencd@0: } ferencd@0: ferencd@0: if ( !element.FirstChild() ) ferencd@0: { ferencd@0: buffer += " />"; ferencd@0: DoLineBreak(); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: buffer += ">"; ferencd@0: if ( element.FirstChild()->ToText() ferencd@0: && element.LastChild() == element.FirstChild() ferencd@0: && element.FirstChild()->ToText()->CDATA() == false ) ferencd@0: { ferencd@0: simpleTextPrint = true; ferencd@0: // no DoLineBreak()! ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: DoLineBreak(); ferencd@0: } ferencd@0: } ferencd@0: ++depth; ferencd@0: return true; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) ferencd@0: { ferencd@0: --depth; ferencd@0: if ( !element.FirstChild() ) ferencd@0: { ferencd@0: // nothing. ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: if ( simpleTextPrint ) ferencd@0: { ferencd@0: simpleTextPrint = false; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: DoIndent(); ferencd@0: } ferencd@0: buffer += ""; ferencd@0: DoLineBreak(); ferencd@0: } ferencd@0: return true; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: bool TiXmlPrinter::Visit( const TiXmlText& text ) ferencd@0: { ferencd@0: if ( text.CDATA() ) ferencd@0: { ferencd@0: DoIndent(); ferencd@0: buffer += ""; ferencd@0: DoLineBreak(); ferencd@0: } ferencd@0: else if ( simpleTextPrint ) ferencd@0: { ferencd@0: TIXML_STRING str; ferencd@0: TiXmlBase::EncodeString( text.ValueTStr(), &str ); ferencd@0: buffer += str; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: DoIndent(); ferencd@0: TIXML_STRING str; ferencd@0: TiXmlBase::EncodeString( text.ValueTStr(), &str ); ferencd@0: buffer += str; ferencd@0: DoLineBreak(); ferencd@0: } ferencd@0: return true; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) ferencd@0: { ferencd@0: DoIndent(); ferencd@0: declaration.Print( 0, 0, &buffer ); ferencd@0: DoLineBreak(); ferencd@0: return true; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: bool TiXmlPrinter::Visit( const TiXmlComment& comment ) ferencd@0: { ferencd@0: DoIndent(); ferencd@0: buffer += ""; ferencd@0: DoLineBreak(); ferencd@0: return true; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) ferencd@0: { ferencd@0: DoIndent(); ferencd@0: buffer += "<"; ferencd@0: buffer += unknown.Value(); ferencd@0: buffer += ">"; ferencd@0: DoLineBreak(); ferencd@0: return true; ferencd@0: } ferencd@0: