diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:10:11 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:10:11 +0200 |
commit | c0cdb2ad99a1e2a6ade5ce76c91177a79258e669 (patch) | |
tree | 4701a015385d9a6a5a4ba99a8f1f5d400fff26b1 /shared/tinyxml | |
parent | 3.13 (diff) | |
download | FreeFileSync-c0cdb2ad99a1e2a6ade5ce76c91177a79258e669.tar.gz FreeFileSync-c0cdb2ad99a1e2a6ade5ce76c91177a79258e669.tar.bz2 FreeFileSync-c0cdb2ad99a1e2a6ade5ce76c91177a79258e669.zip |
3.14
Diffstat (limited to 'shared/tinyxml')
-rw-r--r-- | shared/tinyxml/tinystr.cpp | 6 | ||||
-rw-r--r-- | shared/tinyxml/tinystr.h | 460 | ||||
-rw-r--r-- | shared/tinyxml/tinyxml.cpp | 56 | ||||
-rw-r--r-- | shared/tinyxml/tinyxml.h | 2631 | ||||
-rw-r--r-- | shared/tinyxml/tinyxmlparser.cpp | 252 | ||||
-rw-r--r-- | shared/tinyxml/xmltest.cpp | 2595 |
6 files changed, 3016 insertions, 2984 deletions
diff --git a/shared/tinyxml/tinystr.cpp b/shared/tinyxml/tinystr.cpp index 2b9b5467..86377ad1 100644 --- a/shared/tinyxml/tinystr.cpp +++ b/shared/tinyxml/tinystr.cpp @@ -83,7 +83,7 @@ TiXmlString& TiXmlString::append(const char* str, size_type len) } -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) +TiXmlString operator + (const TiXmlString& a, const TiXmlString& b) { TiXmlString tmp; tmp.reserve(a.length() + b.length()); @@ -92,7 +92,7 @@ TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) return tmp; } -TiXmlString operator + (const TiXmlString & a, const char* b) +TiXmlString operator + (const TiXmlString& a, const char* b) { TiXmlString tmp; TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) ); @@ -102,7 +102,7 @@ TiXmlString operator + (const TiXmlString & a, const char* b) return tmp; } -TiXmlString operator + (const char* a, const TiXmlString & b) +TiXmlString operator + (const char* a, const TiXmlString& b) { TiXmlString tmp; TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) ); diff --git a/shared/tinyxml/tinystr.h b/shared/tinyxml/tinystr.h index 3c2aa9d5..b11407a4 100644 --- a/shared/tinyxml/tinystr.h +++ b/shared/tinyxml/tinystr.h @@ -47,13 +47,13 @@ distribution. used. Be nice to old compilers and macro it here: */ #if defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - #define TIXML_EXPLICIT explicit +// Microsoft visual studio, version 6 and higher. +#define TIXML_EXPLICIT explicit #elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - #define TIXML_EXPLICIT explicit +// GCC version 3 and higher.s +#define TIXML_EXPLICIT explicit #else - #define TIXML_EXPLICIT +#define TIXML_EXPLICIT #endif @@ -66,229 +66,229 @@ distribution. */ class TiXmlString { - public : - // The size type used - typedef size_t size_type; - - // Error value for find primitive - static const size_type npos; // = -1; - - - // TiXmlString empty constructor - TiXmlString () : rep_(&nullrep_) - { - } - - // TiXmlString copy constructor - TiXmlString ( const TiXmlString & copy) : rep_(0) - { - init(copy.length()); - memcpy(start(), copy.data(), length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) - { - init( static_cast<size_type>( strlen(copy) )); - memcpy(start(), copy, length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) - { - init(len); - memcpy(start(), str, len); - } - - // TiXmlString destructor - ~TiXmlString () - { - quit(); - } - - // = operator - TiXmlString& operator = (const char * copy) - { - return assign( copy, (size_type)strlen(copy)); - } - - // = operator - TiXmlString& operator = (const TiXmlString & copy) - { - return assign(copy.start(), copy.length()); - } - - - // += operator. Maps to append - TiXmlString& operator += (const char * suffix) - { - return append(suffix, static_cast<size_type>( strlen(suffix) )); - } - - // += operator. Maps to append - TiXmlString& operator += (char single) - { - return append(&single, 1); - } - - // += operator. Maps to append - TiXmlString& operator += (const TiXmlString & suffix) - { - return append(suffix.data(), suffix.length()); - } - - - // Convert a TiXmlString into a null-terminated char * - const char * c_str () const { return rep_->str; } - - // Convert a TiXmlString into a char * (need not be null terminated). - const char * data () const { return rep_->str; } - - // Return the length of a TiXmlString - size_type length () const { return rep_->size; } - - // Alias for length() - size_type size () const { return rep_->size; } - - // Checks if a TiXmlString is empty - bool empty () const { return rep_->size == 0; } - - // Return capacity of string - size_type capacity () const { return rep_->capacity; } - - - // single char extraction - const char& at (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // [] operator - char& operator [] (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // find a char in a string. Return TiXmlString::npos if not found - size_type find (char lookup) const - { - return find(lookup, 0); - } - - // find a char in a string from an offset. Return TiXmlString::npos if not found - size_type find (char tofind, size_type offset) const - { - if (offset >= length()) return npos; - - for (const char* p = c_str() + offset; *p != '\0'; ++p) - { - if (*p == tofind) return static_cast< size_type >( p - c_str() ); - } - return npos; - } - - void clear () - { - //Lee: - //The original was just too strange, though correct: - // TiXmlString().swap(*this); - //Instead use the quit & re-init: - quit(); - init(0,0); - } - - /* Function to reserve a big amount of data when we know we'll need it. Be aware that this - function DOES NOT clear the content of the TiXmlString if any exists. - */ - void reserve (size_type cap); - - TiXmlString& assign (const char* str, size_type len); - - TiXmlString& append (const char* str, size_type len); - - void swap (TiXmlString& other) - { - Rep* r = rep_; - rep_ = other.rep_; - other.rep_ = r; - } - - private: - - void init(size_type sz) { init(sz, sz); } - void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } - char* start() const { return rep_->str; } - char* finish() const { return rep_->str + rep_->size; } - - struct Rep - { - size_type size, capacity; - char str[1]; - }; - - void init(size_type sz, size_type cap) - { - if (cap) - { - // Lee: the original form: - // rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap)); - // doesn't work in some cases of new being overloaded. Switching - // to the normal allocation, although use an 'int' for systems - // that are overly picky about structure alignment. - const size_type bytesNeeded = sizeof(Rep) + cap; - const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); - rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] ); - - rep_->str[ rep_->size = sz ] = '\0'; - rep_->capacity = cap; - } - else - { - rep_ = &nullrep_; - } - } - - void quit() - { - if (rep_ != &nullrep_) - { - // The rep_ is really an array of ints. (see the allocator, above). - // Cast it back before delete, so the compiler won't incorrectly call destructors. - delete [] ( reinterpret_cast<int*>( rep_ ) ); - } - } - - Rep * rep_; - static Rep nullrep_; +public : + // The size type used + typedef size_t size_type; + + // Error value for find primitive + static const size_type npos; // = -1; + + + // TiXmlString empty constructor + TiXmlString () : rep_(&nullrep_) + { + } + + // TiXmlString copy constructor + TiXmlString ( const TiXmlString& copy) : rep_(0) + { + init(copy.length()); + memcpy(start(), copy.data(), length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char* copy) : rep_(0) + { + init( static_cast<size_type>( strlen(copy) )); + memcpy(start(), copy, length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char* str, size_type len) : rep_(0) + { + init(len); + memcpy(start(), str, len); + } + + // TiXmlString destructor + ~TiXmlString () + { + quit(); + } + + // = operator + TiXmlString& operator = (const char* copy) + { + return assign( copy, (size_type)strlen(copy)); + } + + // = operator + TiXmlString& operator = (const TiXmlString& copy) + { + return assign(copy.start(), copy.length()); + } + + + // += operator. Maps to append + TiXmlString& operator += (const char* suffix) + { + return append(suffix, static_cast<size_type>( strlen(suffix) )); + } + + // += operator. Maps to append + TiXmlString& operator += (char single) + { + return append(&single, 1); + } + + // += operator. Maps to append + TiXmlString& operator += (const TiXmlString& suffix) + { + return append(suffix.data(), suffix.length()); + } + + + // Convert a TiXmlString into a null-terminated char * + const char* c_str () const { return rep_->str; } + + // Convert a TiXmlString into a char * (need not be null terminated). + const char* data () const { return rep_->str; } + + // Return the length of a TiXmlString + size_type length () const { return rep_->size; } + + // Alias for length() + size_type size () const { return rep_->size; } + + // Checks if a TiXmlString is empty + bool empty () const { return rep_->size == 0; } + + // Return capacity of string + size_type capacity () const { return rep_->capacity; } + + + // single char extraction + const char& at (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // [] operator + char& operator [] (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // find a char in a string. Return TiXmlString::npos if not found + size_type find (char lookup) const + { + return find(lookup, 0); + } + + // find a char in a string from an offset. Return TiXmlString::npos if not found + size_type find (char tofind, size_type offset) const + { + if (offset >= length()) return npos; + + for (const char* p = c_str() + offset; *p != '\0'; ++p) + { + if (*p == tofind) return static_cast< size_type >( p - c_str() ); + } + return npos; + } + + void clear () + { + //Lee: + //The original was just too strange, though correct: + // TiXmlString().swap(*this); + //Instead use the quit & re-init: + quit(); + init(0,0); + } + + /* Function to reserve a big amount of data when we know we'll need it. Be aware that this + function DOES NOT clear the content of the TiXmlString if any exists. + */ + void reserve (size_type cap); + + TiXmlString& assign (const char* str, size_type len); + + TiXmlString& append (const char* str, size_type len); + + void swap (TiXmlString& other) + { + Rep* r = rep_; + rep_ = other.rep_; + other.rep_ = r; + } + +private: + + void init(size_type sz) { init(sz, sz); } + void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } + char* start() const { return rep_->str; } + char* finish() const { return rep_->str + rep_->size; } + + struct Rep + { + size_type size, capacity; + char str[1]; + }; + + void init(size_type sz, size_type cap) + { + if (cap) + { + // Lee: the original form: + // rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap)); + // doesn't work in some cases of new being overloaded. Switching + // to the normal allocation, although use an 'int' for systems + // that are overly picky about structure alignment. + const size_type bytesNeeded = sizeof(Rep) + cap; + const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); + rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] ); + + rep_->str[ rep_->size = sz ] = '\0'; + rep_->capacity = cap; + } + else + { + rep_ = &nullrep_; + } + } + + void quit() + { + if (rep_ != &nullrep_) + { + // The rep_ is really an array of ints. (see the allocator, above). + // Cast it back before delete, so the compiler won't incorrectly call destructors. + delete [] ( reinterpret_cast<int*>( rep_ ) ); + } + } + + Rep* rep_; + static Rep nullrep_; } ; -inline bool operator == (const TiXmlString & a, const TiXmlString & b) +inline bool operator == (const TiXmlString& a, const TiXmlString& b) { - return ( a.length() == b.length() ) // optimization on some platforms - && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare + return ( a.length() == b.length() ) // optimization on some platforms + && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare } -inline bool operator < (const TiXmlString & a, const TiXmlString & b) +inline bool operator < (const TiXmlString& a, const TiXmlString& b) { - return strcmp(a.c_str(), b.c_str()) < 0; + return strcmp(a.c_str(), b.c_str()) < 0; } -inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } -inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } -inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } -inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } +inline bool operator != (const TiXmlString& a, const TiXmlString& b) { return !(a == b); } +inline bool operator > (const TiXmlString& a, const TiXmlString& b) { return b < a; } +inline bool operator <= (const TiXmlString& a, const TiXmlString& b) { return !(b < a); } +inline bool operator >= (const TiXmlString& a, const TiXmlString& b) { return !(a < b); } -inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } -inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } -inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } -inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } +inline bool operator == (const TiXmlString& a, const char* b) { return strcmp(a.c_str(), b) == 0; } +inline bool operator == (const char* a, const TiXmlString& b) { return b == a; } +inline bool operator != (const TiXmlString& a, const char* b) { return !(a == b); } +inline bool operator != (const char* a, const TiXmlString& b) { return !(b == a); } -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); -TiXmlString operator + (const TiXmlString & a, const char* b); -TiXmlString operator + (const char* a, const TiXmlString & b); +TiXmlString operator + (const TiXmlString& a, const TiXmlString& b); +TiXmlString operator + (const TiXmlString& a, const char* b); +TiXmlString operator + (const char* a, const TiXmlString& b); /* @@ -299,19 +299,19 @@ class TiXmlOutStream : public TiXmlString { public : - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const TiXmlString & in) - { - *this += in; - return *this; - } - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const char * in) - { - *this += in; - return *this; - } + // TiXmlOutStream << operator. + TiXmlOutStream& operator << (const TiXmlString& in) + { + *this += in; + return *this; + } + + // TiXmlOutStream << operator. + TiXmlOutStream& operator << (const char* in) + { + *this += in; + return *this; + } } ; diff --git a/shared/tinyxml/tinyxml.cpp b/shared/tinyxml/tinyxml.cpp index 9a13c32b..2b8f17a8 100644 --- a/shared/tinyxml/tinyxml.cpp +++ b/shared/tinyxml/tinyxml.cpp @@ -57,10 +57,10 @@ void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) { unsigned char c = (unsigned char) str[i]; - if ( c == '&' - && i < ( (int)str.length() - 2 ) - && str[i+1] == '#' - && str[i+2] == 'x' ) + if (c == '&' + && i < ( (int)str.length() - 2 ) + && str[i+1] == '#' + && str[i+2] == 'x' ) { // Hexadecimal character reference. // Pass through unchanged. @@ -358,7 +358,7 @@ bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) return true; } -const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const +const TiXmlNode* TiXmlNode::FirstChild( const char* _value ) const { const TiXmlNode* node; for ( node = firstChild; node; node = node->next ) @@ -370,7 +370,7 @@ const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const } -const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const +const TiXmlNode* TiXmlNode::LastChild( const char* _value ) const { const TiXmlNode* node; for ( node = lastChild; node; node = node->prev ) @@ -396,7 +396,7 @@ const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const } -const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const +const TiXmlNode* TiXmlNode::IterateChildren( const char* val, const TiXmlNode* previous ) const { if ( !previous ) { @@ -410,7 +410,7 @@ const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* } -const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const +const TiXmlNode* TiXmlNode::NextSibling( const char* _value ) const { const TiXmlNode* node; for ( node = next; node; node = node->next ) @@ -422,7 +422,7 @@ const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const } -const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const +const TiXmlNode* TiXmlNode::PreviousSibling( const char* _value ) const { const TiXmlNode* node; for ( node = prev; node; node = node->prev ) @@ -434,7 +434,7 @@ const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const } -void TiXmlElement::RemoveAttribute( const char * name ) +void TiXmlElement::RemoveAttribute( const char* name ) { #ifdef TIXML_USE_STL TIXML_STRING str( name ); @@ -464,7 +464,7 @@ const TiXmlElement* TiXmlNode::FirstChildElement() const } -const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const +const TiXmlElement* TiXmlNode::FirstChildElement( const char* _value ) const { const TiXmlNode* node; @@ -494,7 +494,7 @@ const TiXmlElement* TiXmlNode::NextSiblingElement() const } -const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const +const TiXmlElement* TiXmlNode::NextSiblingElement( const char* _value ) const { const TiXmlNode* node; @@ -522,7 +522,7 @@ const TiXmlDocument* TiXmlNode::GetDocument() const } -TiXmlElement::TiXmlElement (const char * _value) +TiXmlElement::TiXmlElement (const char* _value) : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) { firstChild = lastChild = 0; @@ -705,7 +705,7 @@ int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) #endif -void TiXmlElement::SetAttribute( const char * name, int val ) +void TiXmlElement::SetAttribute( const char* name, int val ) { TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); if ( attrib ) @@ -727,7 +727,7 @@ void TiXmlElement::SetAttribute( const std::string& name, int val ) #endif -void TiXmlElement::SetDoubleAttribute( const char * name, double val ) +void TiXmlElement::SetDoubleAttribute( const char* name, double val ) { TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); if ( attrib ) @@ -749,7 +749,7 @@ void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) #endif -void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) +void TiXmlElement::SetAttribute( const char* cname, const char* cvalue ) { TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname ); if ( attrib ) @@ -895,7 +895,7 @@ TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) ClearError(); } -TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +TiXmlDocument::TiXmlDocument( const char* documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) { tabsize = 4; useMicrosoftBOM = false; @@ -1063,7 +1063,7 @@ bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) } -bool TiXmlDocument::SaveFile( const char * filename ) const +bool TiXmlDocument::SaveFile( const char* filename ) const { // The old c stuff lives on... FILE* fp = TiXmlFOpen( filename, "w" ); @@ -1370,9 +1370,9 @@ TiXmlNode* TiXmlText::Clone() const } -TiXmlDeclaration::TiXmlDeclaration( const char * _version, - const char * _encoding, - const char * _standalone ) +TiXmlDeclaration::TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ) : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) { version = _version; @@ -1606,7 +1606,7 @@ TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) #ifdef TIXML_USE_STL -std::istream& operator>> (std::istream & in, TiXmlNode & base) +std::istream& operator>> (std::istream& in, TiXmlNode& base) { TIXML_STRING tag; tag.reserve( 8 * 1000 ); @@ -1619,7 +1619,7 @@ std::istream& operator>> (std::istream & in, TiXmlNode & base) #ifdef TIXML_USE_STL -std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) +std::ostream& operator<< (std::ostream& out, const TiXmlNode& base) { TiXmlPrinter printer; printer.SetStreamPrinting(); @@ -1654,7 +1654,7 @@ TiXmlHandle TiXmlHandle::FirstChild() const } -TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const +TiXmlHandle TiXmlHandle::FirstChild( const char* value ) const { if ( node ) { @@ -1678,7 +1678,7 @@ TiXmlHandle TiXmlHandle::FirstChildElement() const } -TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const +TiXmlHandle TiXmlHandle::FirstChildElement( const char* value ) const { if ( node ) { @@ -1796,9 +1796,9 @@ bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute else { buffer += ">"; - if ( element.FirstChild()->ToText() - && element.LastChild() == element.FirstChild() - && element.FirstChild()->ToText()->CDATA() == false ) + if (element.FirstChild()->ToText() + && element.LastChild() == element.FirstChild() + && element.FirstChild()->ToText()->CDATA() == false ) { simpleTextPrint = true; // no DoLineBreak()! diff --git a/shared/tinyxml/tinyxml.h b/shared/tinyxml/tinyxml.h index 01822911..226415c9 100644 --- a/shared/tinyxml/tinyxml.h +++ b/shared/tinyxml/tinyxml.h @@ -44,13 +44,13 @@ distribution. #endif #ifdef TIXML_USE_STL - #include <string> - #include <iostream> - #include <sstream> - #define TIXML_STRING std::string +#include <string> +#include <iostream> +#include <sstream> +#define TIXML_STRING std::string #else - #include "tinystr.h" - #define TIXML_STRING TiXmlString +#include "tinystr.h" +#define TIXML_STRING TiXmlString #endif // Deprecated library function hell. Compilers want to use the @@ -60,25 +60,25 @@ distribution. #define TIXML_SAFE #ifdef TIXML_SAFE - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - // Microsoft visual studio, version 2005 and higher. - #define TIXML_SNPRINTF _snprintf_s - #define TIXML_SSCANF sscanf_s - #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - //#pragma message( "Using _sn* functions." ) - #define TIXML_SNPRINTF _snprintf - #define TIXML_SSCANF sscanf - #elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - //#warning( "Using sn* functions." ) - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf - #else - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf - #endif -#endif +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) +// Microsoft visual studio, version 2005 and higher. +#define TIXML_SNPRINTF _snprintf_s +#define TIXML_SSCANF sscanf_s +#elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) +// Microsoft visual studio, version 6 and higher. +//#pragma message( "Using _sn* functions." ) +#define TIXML_SNPRINTF _snprintf +#define TIXML_SSCANF sscanf +#elif defined(__GNUC__) && (__GNUC__ >= 3 ) +// GCC version 3 and higher.s +//#warning( "Using sn* functions." ) +#define TIXML_SNPRINTF snprintf +#define TIXML_SSCANF sscanf +#else +#define TIXML_SNPRINTF snprintf +#define TIXML_SSCANF sscanf +#endif +#endif class TiXmlDocument; class TiXmlElement; @@ -93,16 +93,16 @@ const int TIXML_MAJOR_VERSION = 2; const int TIXML_MINOR_VERSION = 6; const int TIXML_PATCH_VERSION = 1; -/* Internal structure for tracking location of items +/* Internal structure for tracking location of items in the XML file. */ struct TiXmlCursor { - TiXmlCursor() { Clear(); } - void Clear() { row = col = -1; } + TiXmlCursor() { Clear(); } + void Clear() { row = col = -1; } - int row; // 0 based. - int col; // 0 based. + int row; // 0 based. + int col; // 0 based. }; @@ -116,7 +116,7 @@ struct TiXmlCursor If you return 'true' from a Visit method, recursive parsing will continue. If you return false, <b>no children of this node or its sibilings</b> will be Visited. - All flavors of Visit methods have a default implementation that returns 'true' (continue + All flavors of Visit methods have a default implementation that returns 'true' (continue visiting). You need to only override methods that are interesting to you. Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. @@ -128,43 +128,43 @@ struct TiXmlCursor class TiXmlVisitor { public: - virtual ~TiXmlVisitor() {} - - /// Visit a document. - virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } - /// Visit a document. - virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } - - /// Visit an element. - virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } - /// Visit an element. - virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } - - /// Visit a declaration - virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } - /// Visit a text node - virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } - /// Visit a comment node - virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } - /// Visit an unknow node - virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } + virtual ~TiXmlVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } + /// Visit a document. + virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } + + /// Visit an element. + virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } + /// Visit an element. + virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } + + /// Visit a declaration + virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } + /// Visit a text node + virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } + /// Visit a comment node + virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } + /// Visit an unknow node + virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } }; // Only used by Attribute::Query functions -enum -{ - TIXML_SUCCESS, - TIXML_NO_ATTRIBUTE, - TIXML_WRONG_TYPE +enum +{ + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE }; // Used by the parsing routines. enum TiXmlEncoding { - TIXML_ENCODING_UNKNOWN, - TIXML_ENCODING_UTF8, - TIXML_ENCODING_LEGACY + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY }; const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; @@ -193,224 +193,225 @@ const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; */ class TiXmlBase { - friend class TiXmlNode; - friend class TiXmlElement; - friend class TiXmlDocument; + friend class TiXmlNode; + friend class TiXmlElement; + friend class TiXmlDocument; public: - TiXmlBase() : userData(0) {} - virtual ~TiXmlBase() {} - - /** All TinyXml classes can print themselves to a filestream - or the string class (TiXmlString in non-STL mode, std::string - in STL mode.) Either or both cfile and str can be null. - - This is a formatted print, and will insert - tabs and newlines. - - (For an unformatted stream, use the << operator.) - */ - virtual void Print( FILE* cfile, int depth ) const = 0; - - /** The world does not agree on whether white space should be kept or - not. In order to make everyone happy, these global, static functions - are provided to set whether or not TinyXml will condense all white space - into a single space or not. The default is to condense. Note changing this - value is not thread safe. - */ - static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } - - /// Return the current white space setting. - static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } - - /** Return the position, in the original source file, of this node or attribute. - The row and column are 1-based. (That is the first row and first column is - 1,1). If the returns values are 0 or less, then the parser does not have - a row and column value. - - Generally, the row and column value will be set when the TiXmlDocument::Load(), - TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set - when the DOM was created from operator>>. - - The values reflect the initial load. Once the DOM is modified programmatically - (by adding or changing nodes and attributes) the new values will NOT update to - reflect changes in the document. - - There is a minor performance cost to computing the row and column. Computation - can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. - - @sa TiXmlDocument::SetTabSize() - */ - int Row() const { return location.row + 1; } - int Column() const { return location.col + 1; } ///< See Row() - - void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. - void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. - const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. - - // Table that returs, for a given lead byte, the total number of bytes - // in the UTF-8 sequence. - static const int utf8ByteTable[256]; - - virtual const char* Parse( const char* p, - TiXmlParsingData* data, - TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; - - /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, - or they will be transformed into entities! - */ - static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); - - enum - { - TIXML_NO_ERROR = 0, - TIXML_ERROR, - TIXML_ERROR_OPENING_FILE, - TIXML_ERROR_PARSING_ELEMENT, - TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, - TIXML_ERROR_READING_ELEMENT_VALUE, - TIXML_ERROR_READING_ATTRIBUTES, - TIXML_ERROR_PARSING_EMPTY, - TIXML_ERROR_READING_END_TAG, - TIXML_ERROR_PARSING_UNKNOWN, - TIXML_ERROR_PARSING_COMMENT, - TIXML_ERROR_PARSING_DECLARATION, - TIXML_ERROR_DOCUMENT_EMPTY, - TIXML_ERROR_EMBEDDED_NULL, - TIXML_ERROR_PARSING_CDATA, - TIXML_ERROR_DOCUMENT_TOP_ONLY, - - TIXML_ERROR_STRING_COUNT - }; + TiXmlBase() : userData(0) {} + virtual ~TiXmlBase() {} + + /** All TinyXml classes can print themselves to a filestream + or the string class (TiXmlString in non-STL mode, std::string + in STL mode.) Either or both cfile and str can be null. + + This is a formatted print, and will insert + tabs and newlines. + + (For an unformatted stream, use the << operator.) + */ + virtual void Print( FILE* cfile, int depth ) const = 0; + + /** The world does not agree on whether white space should be kept or + not. In order to make everyone happy, these global, static functions + are provided to set whether or not TinyXml will condense all white space + into a single space or not. The default is to condense. Note changing this + value is not thread safe. + */ + static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } + + /// Return the current white space setting. + static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } + + /** Return the position, in the original source file, of this node or attribute. + The row and column are 1-based. (That is the first row and first column is + 1,1). If the returns values are 0 or less, then the parser does not have + a row and column value. + + Generally, the row and column value will be set when the TiXmlDocument::Load(), + TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set + when the DOM was created from operator>>. + + The values reflect the initial load. Once the DOM is modified programmatically + (by adding or changing nodes and attributes) the new values will NOT update to + reflect changes in the document. + + There is a minor performance cost to computing the row and column. Computation + can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. + + @sa TiXmlDocument::SetTabSize() + */ + int Row() const { return location.row + 1; } + int Column() const { return location.col + 1; } ///< See Row() + + void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. + void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. + const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. + + // Table that returs, for a given lead byte, the total number of bytes + // in the UTF-8 sequence. + static const int utf8ByteTable[256]; + + virtual const char* Parse( const char* p, + TiXmlParsingData* data, + TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; + + /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, + or they will be transformed into entities! + */ + static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); + + enum + { + TIXML_NO_ERROR = 0, + TIXML_ERROR, + TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_PARSING_ELEMENT, + TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, + TIXML_ERROR_READING_ELEMENT_VALUE, + TIXML_ERROR_READING_ATTRIBUTES, + TIXML_ERROR_PARSING_EMPTY, + TIXML_ERROR_READING_END_TAG, + TIXML_ERROR_PARSING_UNKNOWN, + TIXML_ERROR_PARSING_COMMENT, + TIXML_ERROR_PARSING_DECLARATION, + TIXML_ERROR_DOCUMENT_EMPTY, + TIXML_ERROR_EMBEDDED_NULL, + TIXML_ERROR_PARSING_CDATA, + TIXML_ERROR_DOCUMENT_TOP_ONLY, + + TIXML_ERROR_STRING_COUNT + }; protected: - static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); + static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); - inline static bool IsWhiteSpace( char c ) - { - return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); - } - inline static bool IsWhiteSpace( int c ) - { - if ( c < 256 ) - return IsWhiteSpace( (char) c ); - return false; // Again, only truly correct for English/Latin...but usually works. - } + inline static bool IsWhiteSpace( char c ) + { + return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); + } + inline static bool IsWhiteSpace( int c ) + { + if ( c < 256 ) + return IsWhiteSpace( (char) c ); + return false; // Again, only truly correct for English/Latin...but usually works. + } - #ifdef TIXML_USE_STL - static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); - static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); - #endif - - /* Reads an XML name into the string provided. Returns - a pointer just past the last character of the name, - or 0 if the function has an error. - */ - static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); - - /* Reads text. Returns a pointer past the given end tag. - Wickedly complex options, but it keeps the (sensitive) code in one place. - */ - static const char* ReadText( const char* in, // where to start - TIXML_STRING* text, // the string read - bool ignoreWhiteSpace, // whether to keep the white space - const char* endTag, // what ends this text - bool ignoreCase, // whether to ignore case in the end tag - TiXmlEncoding encoding ); // the current encoding - - // If an entity has been found, transform it into a character. - static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); - - // Get a character, while interpreting entities. - // The length can be from 0 to 4 bytes. - inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) - { - assert( p ); - if ( encoding == TIXML_ENCODING_UTF8 ) - { - *length = utf8ByteTable[ *((const unsigned char*)p) ]; - assert( *length >= 0 && *length < 5 ); - } - else - { - *length = 1; - } - - if ( *length == 1 ) - { - if ( *p == '&' ) - return GetEntity( p, _value, length, encoding ); - *_value = *p; - return p+1; - } - else if ( *length ) - { - //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), - // and the null terminator isn't needed - for( int i=0; p[i] && i<*length; ++i ) { - _value[i] = p[i]; - } - return p + (*length); - } - else - { - // Not valid text. - return 0; - } - } - - // Return true if the next characters in the stream are any of the endTag sequences. - // Ignore case only works for english, and should only be relied on when comparing - // to English words: StringEqual( p, "version", true ) is fine. - static bool StringEqual( const char* p, - const char* endTag, - bool ignoreCase, - TiXmlEncoding encoding ); - - static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; +#ifdef TIXML_USE_STL + static bool StreamWhiteSpace( std::istream* in, TIXML_STRING* tag ); + static bool StreamTo( std::istream* in, int character, TIXML_STRING* tag ); +#endif - TiXmlCursor location; + /* Reads an XML name into the string provided. Returns + a pointer just past the last character of the name, + or 0 if the function has an error. + */ + static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); + + /* Reads text. Returns a pointer past the given end tag. + Wickedly complex options, but it keeps the (sensitive) code in one place. + */ + static const char* ReadText( const char* in, // where to start + TIXML_STRING* text, // the string read + bool ignoreWhiteSpace, // whether to keep the white space + const char* endTag, // what ends this text + bool ignoreCase, // whether to ignore case in the end tag + TiXmlEncoding encoding ); // the current encoding + + // If an entity has been found, transform it into a character. + static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); + + // Get a character, while interpreting entities. + // The length can be from 0 to 4 bytes. + inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) + { + assert( p ); + if ( encoding == TIXML_ENCODING_UTF8 ) + { + *length = utf8ByteTable[ *((const unsigned char*)p) ]; + assert( *length >= 0 && *length < 5 ); + } + else + { + *length = 1; + } + + if ( *length == 1 ) + { + if ( *p == '&' ) + return GetEntity( p, _value, length, encoding ); + *_value = *p; + return p+1; + } + else if ( *length ) + { + //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), + // and the null terminator isn't needed + for( int i=0; p[i] && i<*length; ++i ) + { + _value[i] = p[i]; + } + return p + (*length); + } + else + { + // Not valid text. + return 0; + } + } + + // Return true if the next characters in the stream are any of the endTag sequences. + // Ignore case only works for english, and should only be relied on when comparing + // to English words: StringEqual( p, "version", true ) is fine. + static bool StringEqual( const char* p, + const char* endTag, + bool ignoreCase, + TiXmlEncoding encoding ); + + static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; + + TiXmlCursor location; /// Field containing a generic user pointer - void* userData; - - // None of these methods are reliable for any language except English. - // Good for approximation, not great for accuracy. - static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); - static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); - inline static int ToLower( int v, TiXmlEncoding encoding ) - { - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( v < 128 ) return tolower( v ); - return v; - } - else - { - return tolower( v ); - } - } - static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + void* userData; + + // None of these methods are reliable for any language except English. + // Good for approximation, not great for accuracy. + static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); + static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); + inline static int ToLower( int v, TiXmlEncoding encoding ) + { + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( v < 128 ) return tolower( v ); + return v; + } + else + { + return tolower( v ); + } + } + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); private: - TiXmlBase( const TiXmlBase& ); // not implemented. - void operator=( const TiXmlBase& base ); // not allowed. - - struct Entity - { - const char* str; - unsigned int strLength; - char chr; - }; - enum - { - NUM_ENTITY = 5, - MAX_ENTITY_LENGTH = 6 - - }; - static Entity entity[ NUM_ENTITY ]; - static bool condenseWhiteSpace; + TiXmlBase( const TiXmlBase& ); // not implemented. + void operator=( const TiXmlBase& base ); // not allowed. + + struct Entity + { + const char* str; + unsigned int strLength; + char chr; + }; + enum + { + NUM_ENTITY = 5, + MAX_ENTITY_LENGTH = 6 + + }; + static Entity entity[ NUM_ENTITY ]; + static bool condenseWhiteSpace; }; @@ -422,350 +423,361 @@ private: */ class TiXmlNode : public TiXmlBase { - friend class TiXmlDocument; - friend class TiXmlElement; + friend class TiXmlDocument; + friend class TiXmlElement; public: - #ifdef TIXML_USE_STL - - /** An input stream operator, for every class. Tolerant of newlines and - formatting, but doesn't expect them. - */ - friend std::istream& operator >> (std::istream& in, TiXmlNode& base); - - /** An output stream operator, for every class. Note that this outputs - without any newlines or formatting, as opposed to Print(), which - includes tabs and new lines. - - The operator<< and operator>> are not completely symmetric. Writing - a node to a stream is very well defined. You'll get a nice stream - of output, without any extra whitespace or newlines. - - But reading is not as well defined. (As it always is.) If you create - a TiXmlElement (for example) and read that from an input stream, - the text needs to define an element or junk will result. This is - true of all input streams, but it's worth keeping in mind. - - A TiXmlDocument will read nodes until it reads a root element, and - all the children of that root element. - */ - friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); - - /// Appends the XML node or attribute to a std::string. - friend std::string& operator<< (std::string& out, const TiXmlNode& base ); - - #endif - - /** The types of XML nodes supported by TinyXml. (All the - unsupported types are picked up by UNKNOWN.) - */ - enum NodeType - { - TINYXML_DOCUMENT, - TINYXML_ELEMENT, - TINYXML_COMMENT, - TINYXML_UNKNOWN, - TINYXML_TEXT, - TINYXML_DECLARATION, - TINYXML_TYPECOUNT - }; - - virtual ~TiXmlNode(); - - /** The meaning of 'value' changes for the specific type of - TiXmlNode. - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - - The subclasses will wrap this function. - */ - const char *Value() const { return value.c_str (); } - - #ifdef TIXML_USE_STL - /** Return Value() as a std::string. If you only use STL, - this is more efficient than calling Value(). - Only available in STL mode. - */ - const std::string& ValueStr() const { return value; } - #endif - - const TIXML_STRING& ValueTStr() const { return value; } - - /** Changes the value of the node. Defined as: - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - */ - void SetValue(const char * _value) { value = _value;} - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Delete all the children of this node. Does not affect 'this'. - void Clear(); - - /// One step up the DOM. - TiXmlNode* Parent() { return parent; } - const TiXmlNode* Parent() const { return parent; } - - const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. - TiXmlNode* FirstChild() { return firstChild; } - const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. - /// The first child of this node with the matching 'value'. Will be null if none found. - TiXmlNode* FirstChild( const char * _value ) { - // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) - // call the method, cast the return back to non-const. - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); - } - const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. - TiXmlNode* LastChild() { return lastChild; } - - const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. - TiXmlNode* LastChild( const char * _value ) { - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); - } +#ifdef TIXML_USE_STL - #ifdef TIXML_USE_STL - const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. - #endif - - /** An alternate way to walk the children of a node. - One way to iterate over nodes is: - @verbatim - for( child = parent->FirstChild(); child; child = child->NextSibling() ) - @endverbatim - - IterateChildren does the same thing with the syntax: - @verbatim - child = 0; - while( child = parent->IterateChildren( child ) ) - @endverbatim - - IterateChildren takes the previous child as input and finds - the next one. If the previous child is null, it returns the - first. IterateChildren will return null when done. - */ - const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); - } + /** An input stream operator, for every class. Tolerant of newlines and + formatting, but doesn't expect them. + */ + friend std::istream& operator >> (std::istream& in, TiXmlNode& base); - /// This flavor of IterateChildren searches for children with a particular 'value' - const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); - } + /** An output stream operator, for every class. Note that this outputs + without any newlines or formatting, as opposed to Print(), which + includes tabs and new lines. - #ifdef TIXML_USE_STL - const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - #endif + The operator<< and operator>> are not completely symmetric. Writing + a node to a stream is very well defined. You'll get a nice stream + of output, without any extra whitespace or newlines. - /** Add a new node related to this. Adds a child past the LastChild. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); + But reading is not as well defined. (As it always is.) If you create + a TiXmlElement (for example) and read that from an input stream, + the text needs to define an element or junk will result. This is + true of all input streams, but it's worth keeping in mind. + A TiXmlDocument will read nodes until it reads a root element, and + all the children of that root element. + */ + friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); - /** Add a new node related to this. Adds a child past the LastChild. + /// Appends the XML node or attribute to a std::string. + friend std::string& operator<< (std::string& out, const TiXmlNode& base ); - NOTE: the node to be added is passed by pointer, and will be - henceforth owned (and deleted) by tinyXml. This method is efficient - and avoids an extra copy, but should be used with care as it - uses a different memory model than the other insert functions. +#endif - @sa InsertEndChild - */ - TiXmlNode* LinkEndChild( TiXmlNode* addThis ); + /** The types of XML nodes supported by TinyXml. (All the + unsupported types are picked up by UNKNOWN.) + */ + enum NodeType + { + TINYXML_DOCUMENT, + TINYXML_ELEMENT, + TINYXML_COMMENT, + TINYXML_UNKNOWN, + TINYXML_TEXT, + TINYXML_DECLARATION, + TINYXML_TYPECOUNT + }; + + virtual ~TiXmlNode(); + + /** The meaning of 'value' changes for the specific type of + TiXmlNode. + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + + The subclasses will wrap this function. + */ + const char* Value() const { return value.c_str (); } - /** Add a new node related to this. Adds a child before the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); +#ifdef TIXML_USE_STL + /** Return Value() as a std::string. If you only use STL, + this is more efficient than calling Value(). + Only available in STL mode. + */ + const std::string& ValueStr() const { return value; } +#endif - /** Add a new node related to this. Adds a child after the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); + const TIXML_STRING& ValueTStr() const { return value; } - /** Replace a child of this node. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); + /** Changes the value of the node. Defined as: + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + void SetValue(const char* _value) { value = _value;} - /// Delete a child of this node. - bool RemoveChild( TiXmlNode* removeThis ); +#ifdef TIXML_USE_STL + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } +#endif - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling() const { return prev; } - TiXmlNode* PreviousSibling() { return prev; } + /// Delete all the children of this node. Does not affect 'this'. + void Clear(); + + /// One step up the DOM. + TiXmlNode* Parent() { return parent; } + const TiXmlNode* Parent() const { return parent; } + + const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. + TiXmlNode* FirstChild() { return firstChild; } + const TiXmlNode* FirstChild( const char* value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. + /// The first child of this node with the matching 'value'. Will be null if none found. + TiXmlNode* FirstChild( const char* _value ) + { + // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) + // call the method, cast the return back to non-const. + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); + } + const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. + TiXmlNode* LastChild() { return lastChild; } + + const TiXmlNode* LastChild( const char* value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. + TiXmlNode* LastChild( const char* _value ) + { + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); + } - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling( const char * ) const; - TiXmlNode* PreviousSibling( const char *_prev ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); - } +#ifdef TIXML_USE_STL + const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. +#endif - #ifdef TIXML_USE_STL - const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Navigate to a sibling node. - const TiXmlNode* NextSibling() const { return next; } - TiXmlNode* NextSibling() { return next; } - - /// Navigate to a sibling node with the given 'value'. - const TiXmlNode* NextSibling( const char * ) const; - TiXmlNode* NextSibling( const char* _next ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); - } + /** An alternate way to walk the children of a node. + One way to iterate over nodes is: + @verbatim + for( child = parent->FirstChild(); child; child = child->NextSibling() ) + @endverbatim + + IterateChildren does the same thing with the syntax: + @verbatim + child = 0; + while( child = parent->IterateChildren( child ) ) + @endverbatim + + IterateChildren takes the previous child as input and finds + the next one. If the previous child is null, it returns the + first. IterateChildren will return null when done. + */ + const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const TiXmlNode* previous ) + { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); + } + + /// This flavor of IterateChildren searches for children with a particular 'value' + const TiXmlNode* IterateChildren( const char* value, const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const char* _value, const TiXmlNode* previous ) + { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); + } - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement() const; - TiXmlElement* NextSiblingElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); - } +#ifdef TIXML_USE_STL + const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. +#endif - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement( const char * ) const; - TiXmlElement* NextSiblingElement( const char *_next ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); - } + /** Add a new node related to this. Adds a child past the LastChild. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); - #ifdef TIXML_USE_STL - const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - #endif - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement() const; - TiXmlElement* FirstChildElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); - } + /** Add a new node related to this. Adds a child past the LastChild. - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement( const char * _value ) const; - TiXmlElement* FirstChildElement( const char * _value ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); - } + NOTE: the node to be added is passed by pointer, and will be + henceforth owned (and deleted) by tinyXml. This method is efficient + and avoids an extra copy, but should be used with care as it + uses a different memory model than the other insert functions. - #ifdef TIXML_USE_STL - const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /** Query the type (as an enumerated value, above) of this node. - The possible types are: DOCUMENT, ELEMENT, COMMENT, - UNKNOWN, TEXT, and DECLARATION. - */ - int Type() const { return type; } - - /** Return a pointer to the Document this node lives in. - Returns null if not in a document. - */ - const TiXmlDocument* GetDocument() const; - TiXmlDocument* GetDocument() { - return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); - } + @sa InsertEndChild + */ + TiXmlNode* LinkEndChild( TiXmlNode* addThis ); - /// Returns true if this node has no children. - bool NoChildren() const { return !firstChild; } + /** Add a new node related to this. Adds a child before the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); - virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + /** Add a new node related to this. Adds a child after the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); - virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + /** Replace a child of this node. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); - /** Create an exact duplicate of this node and return it. The memory must be deleted - by the caller. - */ - virtual TiXmlNode* Clone() const = 0; + /// Delete a child of this node. + bool RemoveChild( TiXmlNode* removeThis ); - /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the - XML tree will be conditionally visited and the host will be called back - via the TiXmlVisitor interface. + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling() const { return prev; } + TiXmlNode* PreviousSibling() { return prev; } - This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse - the XML for the callbacks, so the performance of TinyXML is unchanged by using this - interface versus any other.) + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling( const char* ) const; + TiXmlNode* PreviousSibling( const char* _prev ) + { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); + } - The interface has been based on ideas from: +#ifdef TIXML_USE_STL + const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. +#endif - - http://www.saxproject.org/ - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + /// Navigate to a sibling node. + const TiXmlNode* NextSibling() const { return next; } + TiXmlNode* NextSibling() { return next; } + + /// Navigate to a sibling node with the given 'value'. + const TiXmlNode* NextSibling( const char* ) const; + TiXmlNode* NextSibling( const char* _next ) + { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement() const; + TiXmlElement* NextSiblingElement() + { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement( const char* ) const; + TiXmlElement* NextSiblingElement( const char* _next ) + { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); + } - Which are both good references for "visiting". +#ifdef TIXML_USE_STL + const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. +#endif + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement() const; + TiXmlElement* FirstChildElement() + { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); + } - An example of using Accept(): - @verbatim - TiXmlPrinter printer; - tinyxmlDoc.Accept( &printer ); - const char* xmlcstr = printer.CStr(); - @endverbatim - */ - virtual bool Accept( TiXmlVisitor* visitor ) const = 0; + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement( const char* _value ) const; + TiXmlElement* FirstChildElement( const char* _value ) + { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); + } + +#ifdef TIXML_USE_STL + const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. +#endif + + /** Query the type (as an enumerated value, above) of this node. + The possible types are: DOCUMENT, ELEMENT, COMMENT, + UNKNOWN, TEXT, and DECLARATION. + */ + int Type() const { return type; } + + /** Return a pointer to the Document this node lives in. + Returns null if not in a document. + */ + const TiXmlDocument* GetDocument() const; + TiXmlDocument* GetDocument() + { + return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); + } + + /// Returns true if this node has no children. + bool NoChildren() const { return !firstChild; } + + virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + /** Create an exact duplicate of this node and return it. The memory must be deleted + by the caller. + */ + virtual TiXmlNode* Clone() const = 0; + + /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the TiXmlVisitor interface. + + This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + TiXmlPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( TiXmlVisitor* visitor ) const = 0; protected: - TiXmlNode( NodeType _type ); + TiXmlNode( NodeType _type ); - // Copy to the allocated object. Shared functionality between Clone, Copy constructor, - // and the assignment operator. - void CopyTo( TiXmlNode* target ) const; + // Copy to the allocated object. Shared functionality between Clone, Copy constructor, + // and the assignment operator. + void CopyTo( TiXmlNode* target ) const; - #ifdef TIXML_USE_STL - // The real work of the input operator. - virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; - #endif +#ifdef TIXML_USE_STL + // The real work of the input operator. + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; +#endif - // Figure out what is at *p, and parse it. Returns null if it is not an xml node. - TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); + // Figure out what is at *p, and parse it. Returns null if it is not an xml node. + TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); - TiXmlNode* parent; - NodeType type; + TiXmlNode* parent; + NodeType type; - TiXmlNode* firstChild; - TiXmlNode* lastChild; + TiXmlNode* firstChild; + TiXmlNode* lastChild; - TIXML_STRING value; + TIXML_STRING value; - TiXmlNode* prev; - TiXmlNode* next; + TiXmlNode* prev; + TiXmlNode* next; private: - TiXmlNode( const TiXmlNode& ); // not implemented. - void operator=( const TiXmlNode& base ); // not allowed. + TiXmlNode( const TiXmlNode& ); // not implemented. + void operator=( const TiXmlNode& base ); // not allowed. }; @@ -778,119 +790,122 @@ private: */ class TiXmlAttribute : public TiXmlBase { - friend class TiXmlAttributeSet; + friend class TiXmlAttributeSet; public: - /// Construct an empty attribute. - TiXmlAttribute() : TiXmlBase() - { - document = 0; - prev = next = 0; - } + /// Construct an empty attribute. + TiXmlAttribute() : TiXmlBase() + { + document = 0; + prev = next = 0; + } - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlAttribute( const std::string& _name, const std::string& _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - #endif +#ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlAttribute( const std::string& _name, const std::string& _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } +#endif - /// Construct an attribute with a name and value. - TiXmlAttribute( const char * _name, const char * _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } + /// Construct an attribute with a name and value. + TiXmlAttribute( const char* _name, const char* _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + + const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. + const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. +#ifdef TIXML_USE_STL + const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. +#endif + int IntValue() const; ///< Return the value of this attribute, converted to an integer. + double DoubleValue() const; ///< Return the value of this attribute, converted to a double. - const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. - const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. - #ifdef TIXML_USE_STL - const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. - #endif - int IntValue() const; ///< Return the value of this attribute, converted to an integer. - double DoubleValue() const; ///< Return the value of this attribute, converted to a double. - - // Get the tinyxml string representation - const TIXML_STRING& NameTStr() const { return name; } - - /** QueryIntValue examines the value string. It is an alternative to the - IntValue() method with richer error checking. - If the value is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. - - A specialized but useful call. Note that for success it returns 0, - which is the opposite of almost all other TinyXml calls. - */ - int QueryIntValue( int* _value ) const; - /// QueryDoubleValue examines the value string. See QueryIntValue(). - int QueryDoubleValue( double* _value ) const; - - void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. - void SetValue( const char* _value ) { value = _value; } ///< Set the value. - - void SetIntValue( int _value ); ///< Set the value from an integer. - void SetDoubleValue( double _value ); ///< Set the value from a double. - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetName( const std::string& _name ) { name = _name; } - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Get the next sibling attribute in the DOM. Returns null at end. - const TiXmlAttribute* Next() const; - TiXmlAttribute* Next() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); - } + // Get the tinyxml string representation + const TIXML_STRING& NameTStr() const { return name; } - /// Get the previous sibling attribute in the DOM. Returns null at beginning. - const TiXmlAttribute* Previous() const; - TiXmlAttribute* Previous() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); - } + /** QueryIntValue examines the value string. It is an alternative to the + IntValue() method with richer error checking. + If the value is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. - bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } - bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } - bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } + A specialized but useful call. Note that for success it returns 0, + which is the opposite of almost all other TinyXml calls. + */ + int QueryIntValue( int* _value ) const; + /// QueryDoubleValue examines the value string. See QueryIntValue(). + int QueryDoubleValue( double* _value ) const; - /* Attribute parsing starts: first letter of the name - returns: the next char after the value end quote - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. + void SetValue( const char* _value ) { value = _value; } ///< Set the value. - // Prints this Attribute to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + void SetIntValue( int _value ); ///< Set the value from an integer. + void SetDoubleValue( double _value ); ///< Set the value from a double. - // [internal use] - // Set the document pointer so the attribute can report errors. - void SetDocument( TiXmlDocument* doc ) { document = doc; } +#ifdef TIXML_USE_STL + /// STL std::string form. + void SetName( const std::string& _name ) { name = _name; } + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } +#endif + + /// Get the next sibling attribute in the DOM. Returns null at end. + const TiXmlAttribute* Next() const; + TiXmlAttribute* Next() + { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); + } + + /// Get the previous sibling attribute in the DOM. Returns null at beginning. + const TiXmlAttribute* Previous() const; + TiXmlAttribute* Previous() + { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); + } + + bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } + bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } + bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } + + /* Attribute parsing starts: first letter of the name + returns: the next char after the value end quote + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + // Prints this Attribute to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const + { + Print( cfile, depth, 0 ); + } + void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + + // [internal use] + // Set the document pointer so the attribute can report errors. + void SetDocument( TiXmlDocument* doc ) { document = doc; } private: - TiXmlAttribute( const TiXmlAttribute& ); // not implemented. - void operator=( const TiXmlAttribute& base ); // not allowed. - - TiXmlDocument* document; // A pointer back to a document, for error reporting. - TIXML_STRING name; - TIXML_STRING value; - TiXmlAttribute* prev; - TiXmlAttribute* next; + TiXmlAttribute( const TiXmlAttribute& ); // not implemented. + void operator=( const TiXmlAttribute& base ); // not allowed. + + TiXmlDocument* document; // A pointer back to a document, for error reporting. + TIXML_STRING name; + TIXML_STRING value; + TiXmlAttribute* prev; + TiXmlAttribute* next; }; /* A class used to manage a group of attributes. It is only used internally, both by the ELEMENT and the DECLARATION. - + The set can be changed transparent to the Element and Declaration classes that use it, but NOT transparent to the Attribute which has to implement a next() and previous() method. Which makes @@ -903,33 +918,33 @@ private: class TiXmlAttributeSet { public: - TiXmlAttributeSet(); - ~TiXmlAttributeSet(); + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); - void Add( TiXmlAttribute* attribute ); - void Remove( TiXmlAttribute* attribute ); + void Add( TiXmlAttribute* attribute ); + void Remove( TiXmlAttribute* attribute ); - const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - TiXmlAttribute* Find( const char* _name ) const; - TiXmlAttribute* FindOrCreate( const char* _name ); + TiXmlAttribute* Find( const char* _name ) const; + TiXmlAttribute* FindOrCreate( const char* _name ); # ifdef TIXML_USE_STL - TiXmlAttribute* Find( const std::string& _name ) const; - TiXmlAttribute* FindOrCreate( const std::string& _name ); + TiXmlAttribute* Find( const std::string& _name ) const; + TiXmlAttribute* FindOrCreate( const std::string& _name ); # endif private: - //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), - //*ME: this class must be also use a hidden/disabled copy-constructor !!! - TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed - void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) + //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), + //*ME: this class must be also use a hidden/disabled copy-constructor !!! + TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed + void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) - TiXmlAttribute sentinel; + TiXmlAttribute sentinel; }; @@ -940,213 +955,217 @@ private: class TiXmlElement : public TiXmlNode { public: - /// Construct an element. - TiXmlElement (const char * in_value); - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlElement( const std::string& _value ); - #endif - - TiXmlElement( const TiXmlElement& ); - - void operator=( const TiXmlElement& base ); - - virtual ~TiXmlElement(); - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - */ - const char* Attribute( const char* name ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an integer, - the integer value will be put in the return 'i', if 'i' - is non-null. - */ - const char* Attribute( const char* name, int* i ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an double, - the double value will be put in the return 'd', if 'd' - is non-null. - */ - const char* Attribute( const char* name, double* d ) const; - - /** QueryIntAttribute examines the attribute - it is an alternative to the - Attribute() method with richer error checking. - If the attribute is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. If the attribute - does not exist, then TIXML_NO_ATTRIBUTE is returned. - */ - int QueryIntAttribute( const char* name, int* _value ) const; - /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). - int QueryDoubleAttribute( const char* name, double* _value ) const; - /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). - int QueryFloatAttribute( const char* name, float* _value ) const { - double d; - int result = QueryDoubleAttribute( name, &d ); - if ( result == TIXML_SUCCESS ) { - *_value = (float)d; - } - return result; - } + /// Construct an element. + TiXmlElement (const char* in_value); - #ifdef TIXML_USE_STL - /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). - int QueryStringAttribute( const char* name, std::string* _value ) const { - const char* cstr = Attribute( name ); - if ( cstr ) { - *_value = std::string( cstr ); - return TIXML_SUCCESS; - } - return TIXML_NO_ATTRIBUTE; - } +#ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlElement( const std::string& _value ); +#endif - /** Template form of the attribute query which will try to read the - attribute into the specified type. Very easy, very powerful, but - be careful to make sure to call this with the correct type. - - NOTE: This method doesn't work correctly for 'string' types that contain spaces. + TiXmlElement( const TiXmlElement& ); + + void operator=( const TiXmlElement& base ); + + virtual ~TiXmlElement(); + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + */ + const char* Attribute( const char* name ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an integer, + the integer value will be put in the return 'i', if 'i' + is non-null. + */ + const char* Attribute( const char* name, int* i ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an double, + the double value will be put in the return 'd', if 'd' + is non-null. + */ + const char* Attribute( const char* name, double* d ) const; + + /** QueryIntAttribute examines the attribute - it is an alternative to the + Attribute() method with richer error checking. + If the attribute is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. If the attribute + does not exist, then TIXML_NO_ATTRIBUTE is returned. + */ + int QueryIntAttribute( const char* name, int* _value ) const; + /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). + int QueryDoubleAttribute( const char* name, double* _value ) const; + /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). + int QueryFloatAttribute( const char* name, float* _value ) const + { + double d; + int result = QueryDoubleAttribute( name, &d ); + if ( result == TIXML_SUCCESS ) + { + *_value = (float)d; + } + return result; + } - @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE - */ - template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - std::stringstream sstream( node->ValueStr() ); - sstream >> *outValue; - if ( !sstream.fail() ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; - } +#ifdef TIXML_USE_STL + /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). + int QueryStringAttribute( const char* name, std::string* _value ) const + { + const char* cstr = Attribute( name ); + if ( cstr ) + { + *_value = std::string( cstr ); + return TIXML_SUCCESS; + } + return TIXML_NO_ATTRIBUTE; + } + + /** Template form of the attribute query which will try to read the + attribute into the specified type. Very easy, very powerful, but + be careful to make sure to call this with the correct type. + + NOTE: This method doesn't work correctly for 'string' types that contain spaces. + + @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE + */ + template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + std::stringstream sstream( node->ValueStr() ); + sstream >> *outValue; + if ( !sstream.fail() ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; + } + + int QueryValueAttribute( const std::string& name, std::string* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + *outValue = node->ValueStr(); + return TIXML_SUCCESS; + } +#endif - int QueryValueAttribute( const std::string& name, std::string* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - *outValue = node->ValueStr(); - return TIXML_SUCCESS; - } - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char* name, const char * _value ); - - #ifdef TIXML_USE_STL - const std::string* Attribute( const std::string& name ) const; - const std::string* Attribute( const std::string& name, int* i ) const; - const std::string* Attribute( const std::string& name, double* d ) const; - int QueryIntAttribute( const std::string& name, int* _value ) const; - int QueryDoubleAttribute( const std::string& name, double* _value ) const; - - /// STL std::string form. - void SetAttribute( const std::string& name, const std::string& _value ); - ///< STL std::string form. - void SetAttribute( const std::string& name, int _value ); - ///< STL std::string form. - void SetDoubleAttribute( const std::string& name, double value ); - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char * name, int value ); - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetDoubleAttribute( const char * name, double value ); - - /** Deletes an attribute with the given name. - */ - void RemoveAttribute( const char * name ); - #ifdef TIXML_USE_STL - void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. - #endif - - const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. - TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } - const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. - TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, GetText() is limited compared to getting the TiXmlText child - and accessing it directly. - - If the first child of 'this' is a TiXmlText, the GetText() - returns the character string of the Text node, else null is returned. - - This is a convenient method for getting the text of simple contained text: - @verbatim - <foo>This is text</foo> - const char* str = fooElement->GetText(); - @endverbatim - - 'str' will be a pointer to "This is text". - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - <foo><b>This is text</b></foo> - @endverbatim - - then the value of str would be null. The first child node isn't a text node, it is - another element. From this XML: - @verbatim - <foo>This is <b>text</b></foo> - @endverbatim - GetText() will return "This is ". - - WARNING: GetText() accesses a child node - don't become confused with the - similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are - safe type casts on the referenced node. - */ - const char* GetText() const; - - /// Creates a new Element and returns it - the returned element is a copy. - virtual TiXmlNode* Clone() const; - // Print the Element to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: next char past '<' - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char* name, const char* _value ); + +#ifdef TIXML_USE_STL + const std::string* Attribute( const std::string& name ) const; + const std::string* Attribute( const std::string& name, int* i ) const; + const std::string* Attribute( const std::string& name, double* d ) const; + int QueryIntAttribute( const std::string& name, int* _value ) const; + int QueryDoubleAttribute( const std::string& name, double* _value ) const; + + /// STL std::string form. + void SetAttribute( const std::string& name, const std::string& _value ); + ///< STL std::string form. + void SetAttribute( const std::string& name, int _value ); + ///< STL std::string form. + void SetDoubleAttribute( const std::string& name, double value ); +#endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char* name, int value ); + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetDoubleAttribute( const char* name, double value ); + + /** Deletes an attribute with the given name. + */ + void RemoveAttribute( const char* name ); +#ifdef TIXML_USE_STL + void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. +#endif + + const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. + TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } + const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. + TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the TiXmlText child + and accessing it directly. + + If the first child of 'this' is a TiXmlText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + <foo>This is text</foo> + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + <foo><b>This is text</b></foo> + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + <foo>This is <b>text</b></foo> + @endverbatim + GetText() will return "This is ". + + WARNING: GetText() accesses a child node - don't become confused with the + similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are + safe type casts on the referenced node. + */ + const char* GetText() const; + + /// Creates a new Element and returns it - the returned element is a copy. + virtual TiXmlNode* Clone() const; + // Print the Element to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: next char past '<' + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; protected: - void CopyTo( TiXmlElement* target ) const; - void ClearThis(); // like clear, but initializes 'this' object as well + void CopyTo( TiXmlElement* target ) const; + void ClearThis(); // like clear, but initializes 'this' object as well - // Used to be public [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - /* [internal use] - Reads the "value" of the element -- another element, or text. - This should terminate with the current end tag. - */ - const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + // Used to be public [internal use] +#ifdef TIXML_USE_STL + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ); +#endif + /* [internal use] + Reads the "value" of the element -- another element, or text. + This should terminate with the current end tag. + */ + const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); private: - TiXmlAttributeSet attributeSet; + TiXmlAttributeSet attributeSet; }; @@ -1155,110 +1174,111 @@ private: class TiXmlComment : public TiXmlNode { public: - /// Constructs an empty comment. - TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} - /// Construct a comment from text. - TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { - SetValue( _value ); - } - TiXmlComment( const TiXmlComment& ); - void operator=( const TiXmlComment& base ); - - virtual ~TiXmlComment() {} - - /// Returns a copy of this Comment. - virtual TiXmlNode* Clone() const; - // Write this Comment to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: at the ! of the !-- - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; + /// Constructs an empty comment. + TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} + /// Construct a comment from text. + TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) + { + SetValue( _value ); + } + TiXmlComment( const TiXmlComment& ); + void operator=( const TiXmlComment& base ); + + virtual ~TiXmlComment() {} + + /// Returns a copy of this Comment. + virtual TiXmlNode* Clone() const; + // Write this Comment to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: at the ! of the !-- + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; protected: - void CopyTo( TiXmlComment* target ) const; + void CopyTo( TiXmlComment* target ) const; - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif -// virtual void StreamOut( TIXML_OSTREAM * out ) const; + // used to be public +#ifdef TIXML_USE_STL + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ); +#endif + // virtual void StreamOut( TIXML_OSTREAM * out ) const; private: }; -/** XML text. A text node can have 2 ways to output the next. "normal" output +/** XML text. A text node can have 2 ways to output the next. "normal" output and CDATA. It will default to the mode it was parsed from the XML file and - you generally want to leave it alone, but you can change the output mode with + you generally want to leave it alone, but you can change the output mode with SetCDATA() and query it with CDATA(). */ class TiXmlText : public TiXmlNode { - friend class TiXmlElement; + friend class TiXmlElement; public: - /** Constructor for text element. By default, it is treated as - normal, encoded text. If you want it be output as a CDATA text - element, set the parameter _cdata to 'true' - */ - TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) - { - SetValue( initValue ); - cdata = false; - } - virtual ~TiXmlText() {} + /** Constructor for text element. By default, it is treated as + normal, encoded text. If you want it be output as a CDATA text + element, set the parameter _cdata to 'true' + */ + TiXmlText (const char* initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + { + SetValue( initValue ); + cdata = false; + } + virtual ~TiXmlText() {} - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) - { - SetValue( initValue ); - cdata = false; - } - #endif +#ifdef TIXML_USE_STL + /// Constructor. + TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + { + SetValue( initValue ); + cdata = false; + } +#endif - TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } - void operator=( const TiXmlText& base ) { base.CopyTo( this ); } + TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } + void operator=( const TiXmlText& base ) { base.CopyTo( this ); } - // Write this text object to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; + // Write this text object to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; - /// Queries whether this represents text using a CDATA section. - bool CDATA() const { return cdata; } - /// Turns on or off a CDATA representation of text. - void SetCDATA( bool _cdata ) { cdata = _cdata; } + /// Queries whether this represents text using a CDATA section. + bool CDATA() const { return cdata; } + /// Turns on or off a CDATA representation of text. + void SetCDATA( bool _cdata ) { cdata = _cdata; } - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; protected : - /// [internal use] Creates a new Element and returns it. - virtual TiXmlNode* Clone() const; - void CopyTo( TiXmlText* target ) const; + /// [internal use] Creates a new Element and returns it. + virtual TiXmlNode* Clone() const; + void CopyTo( TiXmlText* target ) const; - bool Blank() const; // returns true if all white space and new lines - // [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif + bool Blank() const; // returns true if all white space and new lines + // [internal use] +#ifdef TIXML_USE_STL + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ); +#endif private: - bool cdata; // true if this should be input and output as a CDATA style text element + bool cdata; // true if this should be input and output as a CDATA style text element }; @@ -1278,62 +1298,63 @@ private: class TiXmlDeclaration : public TiXmlNode { public: - /// Construct an empty declaration. - TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} + /// Construct an empty declaration. + TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} #ifdef TIXML_USE_STL - /// Constructor. - TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ); + /// Constructor. + TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ); #endif - /// Construct. - TiXmlDeclaration( const char* _version, - const char* _encoding, - const char* _standalone ); - - TiXmlDeclaration( const TiXmlDeclaration& copy ); - void operator=( const TiXmlDeclaration& copy ); - - virtual ~TiXmlDeclaration() {} - - /// Version. Will return an empty string if none was found. - const char *Version() const { return version.c_str (); } - /// Encoding. Will return an empty string if none was found. - const char *Encoding() const { return encoding.c_str (); } - /// Is this a standalone document? - const char *Standalone() const { return standalone.c_str (); } - - /// Creates a copy of this Declaration and returns it. - virtual TiXmlNode* Clone() const; - // Print this declaration to a FILE stream. - virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); + + TiXmlDeclaration( const TiXmlDeclaration& copy ); + void operator=( const TiXmlDeclaration& copy ); - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + virtual ~TiXmlDeclaration() {} - virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + /// Version. Will return an empty string if none was found. + const char* Version() const { return version.c_str (); } + /// Encoding. Will return an empty string if none was found. + const char* Encoding() const { return encoding.c_str (); } + /// Is this a standalone document? + const char* Standalone() const { return standalone.c_str (); } - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; + /// Creates a copy of this Declaration and returns it. + virtual TiXmlNode* Clone() const; + // Print this declaration to a FILE stream. + virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + virtual void Print( FILE* cfile, int depth ) const + { + Print( cfile, depth, 0 ); + } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; protected: - void CopyTo( TiXmlDeclaration* target ) const; - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public +#ifdef TIXML_USE_STL + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ); +#endif private: - TIXML_STRING version; - TIXML_STRING encoding; - TIXML_STRING standalone; + TIXML_STRING version; + TIXML_STRING encoding; + TIXML_STRING standalone; }; @@ -1347,32 +1368,32 @@ private: class TiXmlUnknown : public TiXmlNode { public: - TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} - virtual ~TiXmlUnknown() {} + TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} + virtual ~TiXmlUnknown() {} - TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } - void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } + void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } - /// Creates a copy of this Unknown and returns it. - virtual TiXmlNode* Clone() const; - // Print this Unknown to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; + /// Creates a copy of this Unknown and returns it. + virtual TiXmlNode* Clone() const; + // Print this Unknown to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; protected: - void CopyTo( TiXmlUnknown* target ) const; + void CopyTo( TiXmlUnknown* target ) const; - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif +#ifdef TIXML_USE_STL + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ); +#endif private: @@ -1386,165 +1407,167 @@ private: class TiXmlDocument : public TiXmlNode { public: - /// Create an empty document, that has no name. - TiXmlDocument(); - /// Create a document with a name. The name of the document is also the filename of the xml. - TiXmlDocument( const char * documentName ); - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlDocument( const std::string& documentName ); - #endif - - TiXmlDocument( const TiXmlDocument& copy ); - void operator=( const TiXmlDocument& copy ); - - virtual ~TiXmlDocument() {} - - /** Load a file using the current document value. - Returns true if successful. Will delete any existing - document data before loading. - */ - bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the current document value. Returns true if successful. - bool SaveFile() const; - /// Load a file using the given filename. Returns true if successful. - bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given filename. Returns true if successful. - bool SaveFile( const char * filename ) const; - /** Load a file using the given FILE*. Returns true if successful. Note that this method - doesn't stream - the entire object pointed at by the FILE* - will be interpreted as an XML file. TinyXML doesn't stream in XML from the current - file location. Streaming may be added in the future. - */ - bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given FILE*. Returns true if successful. - bool SaveFile( FILE* ) const; - - #ifdef TIXML_USE_STL - bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. - { - return LoadFile( filename.c_str(), encoding ); - } - bool SaveFile( const std::string& filename ) const ///< STL std::string version. - { - return SaveFile( filename.c_str() ); - } - #endif - - /** Parse the given null terminated block of xml data. Passing in an encoding to this - method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml - to use that encoding, regardless of what TinyXml might otherwise try to detect. - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - - /** Get the root element -- the only top level element -- of the document. - In well formed XML, there should only be one. TinyXml is tolerant of - multiple elements at the document level. - */ - const TiXmlElement* RootElement() const { return FirstChildElement(); } - TiXmlElement* RootElement() { return FirstChildElement(); } - - /** If an error occurs, Error will be set to true. Also, - - The ErrorId() will contain the integer identifier of the error (not generally useful) - - The ErrorDesc() method will return the name of the error. (very useful) - - The ErrorRow() and ErrorCol() will return the location of the error (if known) - */ - bool Error() const { return error; } - - /// Contains a textual (english) description of the error if one occurs. - const char * ErrorDesc() const { return errorDesc.c_str (); } - - /** Generally, you probably want the error string ( ErrorDesc() ). But if you - prefer the ErrorId, this function will fetch it. - */ - int ErrorId() const { return errorId; } - - /** Returns the location (if known) of the error. The first column is column 1, - and the first row is row 1. A value of 0 means the row and column wasn't applicable - (memory errors, for example, have no row/column) or the parser lost the error. (An - error in the error reporting, in that case.) - - @sa SetTabSize, Row, Column - */ - int ErrorRow() const { return errorLocation.row+1; } - int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() - - /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) - to report the correct values for row and column. It does not change the output - or input in any way. - - By calling this method, with a tab size - greater than 0, the row and column of each node and attribute is stored - when the file is loaded. Very useful for tracking the DOM back in to - the source file. - - The tab size is required for calculating the location of nodes. If not - set, the default of 4 is used. The tabsize is set per document. Setting - the tabsize to 0 disables row/column tracking. - - Note that row and column tracking is not supported when using operator>>. - - The tab size needs to be enabled before the parse or load. Correct usage: - @verbatim - TiXmlDocument doc; - doc.SetTabSize( 8 ); - doc.Load( "myfile.xml" ); - @endverbatim - - @sa Row, Column - */ - void SetTabSize( int _tabsize ) { tabsize = _tabsize; } - - int TabSize() const { return tabsize; } - - /** If you have handled the error, it can be reset with this call. The error - state is automatically cleared if you Parse a new XML block. - */ - void ClearError() { error = false; - errorId = 0; - errorDesc = ""; - errorLocation.row = errorLocation.col = 0; - //errorLocation.last = 0; - } - - /** Write the document to standard out using formatted printing ("pretty print"). */ - void Print() const { Print( stdout, 0 ); } - - /* Write the document to a string using formatted printing ("pretty print"). This - will allocate a character array (new char[]) and return it as a pointer. The - calling code pust call delete[] on the return char* to avoid a memory leak. - */ - //char* PrintToMemory() const; - - /// Print this Document to a FILE stream. - virtual void Print( FILE* cfile, int depth = 0 ) const; - // [internal use] - void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - - virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; + /// Create an empty document, that has no name. + TiXmlDocument(); + /// Create a document with a name. The name of the document is also the filename of the xml. + TiXmlDocument( const char* documentName ); + +#ifdef TIXML_USE_STL + /// Constructor. + TiXmlDocument( const std::string& documentName ); +#endif + + TiXmlDocument( const TiXmlDocument& copy ); + void operator=( const TiXmlDocument& copy ); + + virtual ~TiXmlDocument() {} + + /** Load a file using the current document value. + Returns true if successful. Will delete any existing + document data before loading. + */ + bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the current document value. Returns true if successful. + bool SaveFile() const; + /// Load a file using the given filename. Returns true if successful. + bool LoadFile( const char* filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given filename. Returns true if successful. + bool SaveFile( const char* filename ) const; + /** Load a file using the given FILE*. Returns true if successful. Note that this method + doesn't stream - the entire object pointed at by the FILE* + will be interpreted as an XML file. TinyXML doesn't stream in XML from the current + file location. Streaming may be added in the future. + */ + bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given FILE*. Returns true if successful. + bool SaveFile( FILE* ) const; + +#ifdef TIXML_USE_STL + bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. + { + return LoadFile( filename.c_str(), encoding ); + } + bool SaveFile( const std::string& filename ) const ///< STL std::string version. + { + return SaveFile( filename.c_str() ); + } +#endif + + /** Parse the given null terminated block of xml data. Passing in an encoding to this + method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml + to use that encoding, regardless of what TinyXml might otherwise try to detect. + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + + /** Get the root element -- the only top level element -- of the document. + In well formed XML, there should only be one. TinyXml is tolerant of + multiple elements at the document level. + */ + const TiXmlElement* RootElement() const { return FirstChildElement(); } + TiXmlElement* RootElement() { return FirstChildElement(); } + + /** If an error occurs, Error will be set to true. Also, + - The ErrorId() will contain the integer identifier of the error (not generally useful) + - The ErrorDesc() method will return the name of the error. (very useful) + - The ErrorRow() and ErrorCol() will return the location of the error (if known) + */ + bool Error() const { return error; } + + /// Contains a textual (english) description of the error if one occurs. + const char* ErrorDesc() const { return errorDesc.c_str (); } + + /** Generally, you probably want the error string ( ErrorDesc() ). But if you + prefer the ErrorId, this function will fetch it. + */ + int ErrorId() const { return errorId; } + + /** Returns the location (if known) of the error. The first column is column 1, + and the first row is row 1. A value of 0 means the row and column wasn't applicable + (memory errors, for example, have no row/column) or the parser lost the error. (An + error in the error reporting, in that case.) + + @sa SetTabSize, Row, Column + */ + int ErrorRow() const { return errorLocation.row+1; } + int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() + + /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) + to report the correct values for row and column. It does not change the output + or input in any way. + + By calling this method, with a tab size + greater than 0, the row and column of each node and attribute is stored + when the file is loaded. Very useful for tracking the DOM back in to + the source file. + + The tab size is required for calculating the location of nodes. If not + set, the default of 4 is used. The tabsize is set per document. Setting + the tabsize to 0 disables row/column tracking. + + Note that row and column tracking is not supported when using operator>>. + + The tab size needs to be enabled before the parse or load. Correct usage: + @verbatim + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Load( "myfile.xml" ); + @endverbatim + + @sa Row, Column + */ + void SetTabSize( int _tabsize ) { tabsize = _tabsize; } + + int TabSize() const { return tabsize; } + + /** If you have handled the error, it can be reset with this call. The error + state is automatically cleared if you Parse a new XML block. + */ + void ClearError() + { + error = false; + errorId = 0; + errorDesc = ""; + errorLocation.row = errorLocation.col = 0; + //errorLocation.last = 0; + } + + /** Write the document to standard out using formatted printing ("pretty print"). */ + void Print() const { Print( stdout, 0 ); } + + /* Write the document to a string using formatted printing ("pretty print"). This + will allocate a character array (new char[]) and return it as a pointer. The + calling code pust call delete[] on the return char* to avoid a memory leak. + */ + //char* PrintToMemory() const; + + /// Print this Document to a FILE stream. + virtual void Print( FILE* cfile, int depth = 0 ) const; + // [internal use] + void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + + virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; protected : - // [internal use] - virtual TiXmlNode* Clone() const; - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif + // [internal use] + virtual TiXmlNode* Clone() const; +#ifdef TIXML_USE_STL + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ); +#endif private: - void CopyTo( TiXmlDocument* target ) const; - - bool error; - int errorId; - TIXML_STRING errorDesc; - int tabsize; - TiXmlCursor errorLocation; - bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. + void CopyTo( TiXmlDocument* target ) const; + + bool error; + int errorId; + TIXML_STRING errorDesc; + int tabsize; + TiXmlCursor errorLocation; + bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. }; @@ -1563,7 +1586,7 @@ private: <Document> @endverbatim - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very easy to write a *lot* of code that looks like: @verbatim @@ -1583,7 +1606,7 @@ private: @endverbatim And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity - of such code. A TiXmlHandle checks for null pointers so it is perfectly safe + of such code. A TiXmlHandle checks for null pointers so it is perfectly safe and correct to use: @verbatim @@ -1604,7 +1627,7 @@ private: What they should not be used for is iteration: @verbatim - int i=0; + int i=0; while ( true ) { TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); @@ -1615,8 +1638,8 @@ private: } @endverbatim - It seems reasonable, but it is in fact two embedded while loops. The Child method is - a linear walk to find the element, so this code would iterate much more than it needs + It seems reasonable, but it is in fact two embedded while loops. The Child method is + a linear walk to find the element, so this code would iterate much more than it needs to. Instead, prefer: @verbatim @@ -1631,80 +1654,80 @@ private: class TiXmlHandle { public: - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } - /// Copy constructor - TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } - TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } - - /// Return a handle to the first child node. - TiXmlHandle FirstChild() const; - /// Return a handle to the first child node with the given name. - TiXmlHandle FirstChild( const char * value ) const; - /// Return a handle to the first child element. - TiXmlHandle FirstChildElement() const; - /// Return a handle to the first child element with the given name. - TiXmlHandle FirstChildElement( const char * value ) const; - - /** Return a handle to the "index" child with the given name. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( const char* value, int index ) const; - /** Return a handle to the "index" child. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( int index ) const; - /** Return a handle to the "index" child element with the given name. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( const char* value, int index ) const; - /** Return a handle to the "index" child element. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( int index ) const; - - #ifdef TIXML_USE_STL - TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } - TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } - - TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } - TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } - #endif - - /** Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* ToNode() const { return node; } - /** Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } - /** Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } - /** Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } - - /** @deprecated use ToNode. - Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* Node() const { return ToNode(); } - /** @deprecated use ToElement. - Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* Element() const { return ToElement(); } - /** @deprecated use ToText() - Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* Text() const { return ToText(); } - /** @deprecated use ToUnknown() - Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* Unknown() const { return ToUnknown(); } + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } + /// Copy constructor + TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } + TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } + + /// Return a handle to the first child node. + TiXmlHandle FirstChild() const; + /// Return a handle to the first child node with the given name. + TiXmlHandle FirstChild( const char* value ) const; + /// Return a handle to the first child element. + TiXmlHandle FirstChildElement() const; + /// Return a handle to the first child element with the given name. + TiXmlHandle FirstChildElement( const char* value ) const; + + /** Return a handle to the "index" child with the given name. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( const char* value, int index ) const; + /** Return a handle to the "index" child. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( int index ) const; + /** Return a handle to the "index" child element with the given name. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( const char* value, int index ) const; + /** Return a handle to the "index" child element. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( int index ) const; + +#ifdef TIXML_USE_STL + TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } + TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } + + TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } + TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } +#endif + + /** Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* ToNode() const { return node; } + /** Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } + /** Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } + /** Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } + + /** @deprecated use ToNode. + Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* Node() const { return ToNode(); } + /** @deprecated use ToElement. + Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* Element() const { return ToElement(); } + /** @deprecated use ToText() + Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* Text() const { return ToText(); } + /** @deprecated use ToUnknown() + Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* Unknown() const { return ToUnknown(); } private: - TiXmlNode* node; + TiXmlNode* node; }; @@ -1730,64 +1753,68 @@ private: class TiXmlPrinter : public TiXmlVisitor { public: - TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), - buffer(), indent( " " ), lineBreak( "\n" ) {} - - virtual bool VisitEnter( const TiXmlDocument& doc ); - virtual bool VisitExit( const TiXmlDocument& doc ); - - virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); - virtual bool VisitExit( const TiXmlElement& element ); - - virtual bool Visit( const TiXmlDeclaration& declaration ); - virtual bool Visit( const TiXmlText& text ); - virtual bool Visit( const TiXmlComment& comment ); - virtual bool Visit( const TiXmlUnknown& unknown ); - - /** Set the indent characters for printing. By default 4 spaces - but tab (\t) is also useful, or null/empty string for no indentation. - */ - void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } - /// Query the indention string. - const char* Indent() { return indent.c_str(); } - /** Set the line breaking string. By default set to newline (\n). - Some operating systems prefer other characters, or can be - set to the null/empty string for no indenation. - */ - void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } - /// Query the current line breaking string. - const char* LineBreak() { return lineBreak.c_str(); } - - /** Switch over to "stream printing" which is the most dense formatting without - linebreaks. Common when the XML is needed for network transmission. - */ - void SetStreamPrinting() { indent = ""; - lineBreak = ""; - } - /// Return the result. - const char* CStr() { return buffer.c_str(); } - /// Return the length of the result string. - size_t Size() { return buffer.size(); } - - #ifdef TIXML_USE_STL - /// Return the result. - const std::string& Str() { return buffer; } - #endif + TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), + buffer(), indent( " " ), lineBreak( "\n" ) {} + + virtual bool VisitEnter( const TiXmlDocument& doc ); + virtual bool VisitExit( const TiXmlDocument& doc ); + + virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); + virtual bool VisitExit( const TiXmlElement& element ); + + virtual bool Visit( const TiXmlDeclaration& declaration ); + virtual bool Visit( const TiXmlText& text ); + virtual bool Visit( const TiXmlComment& comment ); + virtual bool Visit( const TiXmlUnknown& unknown ); + + /** Set the indent characters for printing. By default 4 spaces + but tab (\t) is also useful, or null/empty string for no indentation. + */ + void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } + /// Query the indention string. + const char* Indent() { return indent.c_str(); } + /** Set the line breaking string. By default set to newline (\n). + Some operating systems prefer other characters, or can be + set to the null/empty string for no indenation. + */ + void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } + /// Query the current line breaking string. + const char* LineBreak() { return lineBreak.c_str(); } + + /** Switch over to "stream printing" which is the most dense formatting without + linebreaks. Common when the XML is needed for network transmission. + */ + void SetStreamPrinting() + { + indent = ""; + lineBreak = ""; + } + /// Return the result. + const char* CStr() { return buffer.c_str(); } + /// Return the length of the result string. + size_t Size() { return buffer.size(); } -private: - void DoIndent() { - for( int i=0; i<depth; ++i ) - buffer += indent; - } - void DoLineBreak() { - buffer += lineBreak; - } +#ifdef TIXML_USE_STL + /// Return the result. + const std::string& Str() { return buffer; } +#endif - int depth; - bool simpleTextPrint; - TIXML_STRING buffer; - TIXML_STRING indent; - TIXML_STRING lineBreak; +private: + void DoIndent() + { + for( int i=0; i<depth; ++i ) + buffer += indent; + } + void DoLineBreak() + { + buffer += lineBreak; + } + + int depth; + bool simpleTextPrint; + TIXML_STRING buffer; + TIXML_STRING indent; + TIXML_STRING lineBreak; }; diff --git a/shared/tinyxml/tinyxmlparser.cpp b/shared/tinyxml/tinyxmlparser.cpp index 92bee64d..ea691fd4 100644 --- a/shared/tinyxml/tinyxmlparser.cpp +++ b/shared/tinyxml/tinyxmlparser.cpp @@ -110,21 +110,21 @@ void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* leng // Scary scary fall throughs. switch (*length) { - case 4: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 3: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 2: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 1: - --output; - *output = (char)(input | FIRST_BYTE_MARK[*length]); + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); } } @@ -136,17 +136,17 @@ void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* leng // to figure out alhabetical vs. not across encoding. So take a very // conservative approach. -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { + // if ( encoding == TIXML_ENCODING_UTF8 ) + // { if ( anyByte < 127 ) return isalpha( anyByte ); else return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalpha( anyByte ); -// } + // } + // else + // { + // return isalpha( anyByte ); + // } } @@ -157,17 +157,17 @@ void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* leng // to figure out alhabetical vs. not across encoding. So take a very // conservative approach. -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { + // if ( encoding == TIXML_ENCODING_UTF8 ) + // { if ( anyByte < 127 ) return isalnum( anyByte ); else return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalnum( anyByte ); -// } + // } + // else + // { + // return isalnum( anyByte ); + // } } @@ -223,95 +223,95 @@ void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) // Code contributed by Fletcher Dunn: (modified by lee) switch (*pU) { - case 0: - // We *should* never get here, but in case we do, don't - // advance past the terminating null character, ever - return; - - case '\r': - // bump down to the next line - ++row; - col = 0; - // Eat the character - ++p; + case 0: + // We *should* never get here, but in case we do, don't + // advance past the terminating null character, ever + return; - // Check for \r\n sequence, and treat this as a single character - if (*p == '\n') - { + case '\r': + // bump down to the next line + ++row; + col = 0; + // Eat the character ++p; - } - break; - case '\n': - // bump down to the next line - ++row; - col = 0; + // Check for \r\n sequence, and treat this as a single character + if (*p == '\n') + { + ++p; + } + break; - // Eat the character - ++p; + case '\n': + // bump down to the next line + ++row; + col = 0; - // Check for \n\r sequence, and treat this as a single - // character. (Yes, this bizarre thing does occur still - // on some arcane platforms...) - if (*p == '\r') - { + // Eat the character ++p; - } - break; - case '\t': - // Eat the character - ++p; + // Check for \n\r sequence, and treat this as a single + // character. (Yes, this bizarre thing does occur still + // on some arcane platforms...) + if (*p == '\r') + { + ++p; + } + break; - // Skip to next tab stop - col = (col / tabsize + 1) * tabsize; - break; + case '\t': + // Eat the character + ++p; - case TIXML_UTF_LEAD_0: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( *(p+1) && *(p+2) ) + // Skip to next tab stop + col = (col / tabsize + 1) * tabsize; + break; + + case TIXML_UTF_LEAD_0: + if ( encoding == TIXML_ENCODING_UTF8 ) { - // In these cases, don't advance the column. These are - // 0-width spaces. - if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) - p += 3; - else + if ( *(p+1) && *(p+2) ) { - p +=3; // A normal character. - ++col; + // In these cases, don't advance the column. These are + // 0-width spaces. + if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) + p += 3; + else + { + p +=3; // A normal character. + ++col; + } } } - } - else - { - ++p; - ++col; - } - break; + else + { + ++p; + ++col; + } + break; - default: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // Eat the 1 to 4 byte utf8 character. - int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; - if ( step == 0 ) - step = 1; // Error case from bad encoding, but handle gracefully. - p += step; - - // Just advance one column, of course. - ++col; - } - else - { - ++p; - ++col; - } - break; + default: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // Eat the 1 to 4 byte utf8 character. + int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; + if ( step == 0 ) + step = 1; // Error case from bad encoding, but handle gracefully. + p += step; + + // Just advance one column, of course. + ++col; + } + else + { + ++p; + ++col; + } + break; } } cursor.row = row; @@ -374,7 +374,7 @@ const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) } #ifdef TIXML_USE_STL -/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) +/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream* in, TIXML_STRING* tag ) { for( ;; ) { @@ -389,7 +389,7 @@ const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) } } -/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) +/*static*/ bool TiXmlBase::StreamTo( std::istream* in, int character, TIXML_STRING* tag ) { //assert( character > 0 && character < 128 ); // else it won't work in utf-8 while ( in->good() ) @@ -410,7 +410,7 @@ const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) // One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The // "assign" optimization removes over 10% of the execution time. // -const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) +const char* TiXmlBase::ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ) { // Oddly, not supported on some comilers, //name->clear(); @@ -425,8 +425,8 @@ const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncodi // After that, they can be letters, underscores, numbers, // hyphens, or colons. (Colons are valid ony for namespaces, // but tinyxml can't tell namespaces from names.) - if ( p && *p - && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) + if (p && *p + && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) { const char* start = p; while( p && *p @@ -585,15 +585,15 @@ bool TiXmlBase::StringEqual( const char* p, } const char* TiXmlBase::ReadText( const char* p, - TIXML_STRING * text, + TIXML_STRING* text, bool trimWhiteSpace, const char* endTag, bool caseInsensitive, TiXmlEncoding encoding ) { *text = ""; - if ( !trimWhiteSpace // certain tags always keep whitespace - || !condenseWhiteSpace ) // if true, whitespace is always kept + if (!trimWhiteSpace // certain tags always keep whitespace + || !condenseWhiteSpace ) // if true, whitespace is always kept { // Keep all the white space. while ( p && *p @@ -651,7 +651,7 @@ const char* TiXmlBase::ReadText( const char* p, #ifdef TIXML_USE_STL -void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) +void TiXmlDocument::StreamIn( std::istream* in, TIXML_STRING* tag ) { // The basic issue with a document is that we don't know what we're // streaming. Read something presumed to be a tag (and hope), then @@ -778,8 +778,8 @@ const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiX } // Did we get encoding info? - if ( encoding == TIXML_ENCODING_UNKNOWN - && node->ToDeclaration() ) + if (encoding == TIXML_ENCODING_UNKNOWN + && node->ToDeclaration() ) { TiXmlDeclaration* dec = node->ToDeclaration(); const char* enc = dec->Encoding(); @@ -888,8 +888,8 @@ TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) #endif returnNode = new TiXmlUnknown(); } - else if ( IsAlpha( *(p+1), encoding ) - || *(p+1) == '_' ) + else if (IsAlpha( *(p+1), encoding ) + || *(p+1) == '_' ) { #ifdef DEBUG_PARSER TIXML_LOG( "XML parsing Element\n" ); @@ -914,7 +914,7 @@ TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) #ifdef TIXML_USE_STL -void TiXmlElement::StreamIn (std::istream * in, TIXML_STRING * tag) +void TiXmlElement::StreamIn (std::istream* in, TIXML_STRING* tag) { // We're called with some amount of pre-parsing. That is, some of "this" // element is in "tag". Go ahead and stream to the closing ">" @@ -939,8 +939,8 @@ void TiXmlElement::StreamIn (std::istream * in, TIXML_STRING * tag) // Okay...if we are a "/>" tag, then we're done. We've read a complete tag. // If not, identify and stream. - if ( tag->at( tag->length() - 1 ) == '>' - && tag->at( tag->length() - 2 ) == '/' ) + if (tag->at( tag->length() - 1 ) == '>' + && tag->at( tag->length() - 2 ) == '/' ) { // All good! return; @@ -1265,7 +1265,7 @@ const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXm #ifdef TIXML_USE_STL -void TiXmlUnknown::StreamIn( std::istream * in, TIXML_STRING * tag ) +void TiXmlUnknown::StreamIn( std::istream* in, TIXML_STRING* tag ) { while ( in->good() ) { @@ -1323,7 +1323,7 @@ const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc } #ifdef TIXML_USE_STL -void TiXmlComment::StreamIn( std::istream * in, TIXML_STRING * tag ) +void TiXmlComment::StreamIn( std::istream* in, TIXML_STRING* tag ) { while ( in->good() ) { @@ -1339,8 +1339,8 @@ void TiXmlComment::StreamIn( std::istream * in, TIXML_STRING * tag ) (*tag) += (char) c; if ( c == '>' - && tag->at( tag->length() - 2 ) == '-' - && tag->at( tag->length() - 3 ) == '-' ) + && tag->at( tag->length() - 2 ) == '-' + && tag->at( tag->length() - 3 ) == '-' ) { // All is well. return; @@ -1479,7 +1479,7 @@ const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlE } #ifdef TIXML_USE_STL -void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) +void TiXmlText::StreamIn( std::istream* in, TIXML_STRING* tag ) { while ( in->good() ) { @@ -1563,7 +1563,7 @@ const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncodi } #ifdef TIXML_USE_STL -void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) +void TiXmlDeclaration::StreamIn( std::istream* in, TIXML_STRING* tag ) { while ( in->good() ) { diff --git a/shared/tinyxml/xmltest.cpp b/shared/tinyxml/xmltest.cpp index 7cd6faca..b4d3551c 100644 --- a/shared/tinyxml/xmltest.cpp +++ b/shared/tinyxml/xmltest.cpp @@ -4,17 +4,17 @@ #ifdef TIXML_USE_STL - #include <iostream> - #include <sstream> - using namespace std; +#include <iostream> +#include <sstream> +using namespace std; #else - #include <stdio.h> +#include <stdio.h> #endif #if defined( WIN32 ) && defined( TUNE ) - #include <crtdbg.h> - _CrtMemState startMemState; - _CrtMemState endMemState; +#include <crtdbg.h> +_CrtMemState startMemState; +_CrtMemState endMemState; #endif #include "tinyxml.h" @@ -29,43 +29,43 @@ static int gFail = 0; bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho ) { - bool pass = !strcmp( expected, found ); - if ( pass ) - printf ("[pass]"); - else - printf ("[fail]"); - - if ( noEcho ) - printf (" %s\n", testString); - else - printf (" %s [%s][%s]\n", testString, expected, found); - - if ( pass ) - ++gPass; - else - ++gFail; - return pass; + bool pass = !strcmp( expected, found ); + if ( pass ) + printf ("[pass]"); + else + printf ("[fail]"); + + if ( noEcho ) + printf (" %s\n", testString); + else + printf (" %s [%s][%s]\n", testString, expected, found); + + if ( pass ) + ++gPass; + else + ++gFail; + return pass; } bool XmlTest( const char* testString, int expected, int found, bool noEcho ) { - bool pass = ( expected == found ); - if ( pass ) - printf ("[pass]"); - else - printf ("[fail]"); - - if ( noEcho ) - printf (" %s\n", testString); - else - printf (" %s [%d][%d]\n", testString, expected, found); - - if ( pass ) - ++gPass; - else - ++gFail; - return pass; + bool pass = ( expected == found ); + if ( pass ) + printf ("[pass]"); + else + printf ("[fail]"); + + if ( noEcho ) + printf (" %s\n", testString); + else + printf (" %s [%d][%d]\n", testString, expected, found); + + if ( pass ) + ++gPass; + else + ++gFail; + return pass; } @@ -79,910 +79,914 @@ bool XmlTest( const char* testString, int expected, int found, bool noEcho ) int main() { - // - // We start with the 'demoStart' todo list. Process it. And - // should hopefully end up with the todo list as illustrated. - // - const char* demoStart = - "<?xml version=\"1.0\" standalone='no' >\n" - "<!-- Our to do list data -->" - "<ToDo>\n" - "<!-- Do I need a secure PDA? -->\n" - "<Item priority=\"1\" distance='close'> Go to the <bold>Toy store!</bold></Item>" - "<Item priority=\"2\" distance='none'> Do bills </Item>" - "<Item priority=\"2\" distance='far & back'> Look for Evil Dinosaurs! </Item>" - "</ToDo>"; - - { - - #ifdef TIXML_USE_STL - // What the todo list should look like after processing. - // In stream (no formatting) representation. - const char* demoEnd = - "<?xml version=\"1.0\" standalone=\"no\" ?>" - "<!-- Our to do list data -->" - "<ToDo>" - "<!-- Do I need a secure PDA? -->" - "<Item priority=\"2\" distance=\"close\">Go to the" - "<bold>Toy store!" - "</bold>" - "</Item>" - "<Item priority=\"1\" distance=\"far\">Talk to:" - "<Meeting where=\"School\">" - "<Attendee name=\"Marple\" position=\"teacher\" />" - "<Attendee name=\"Voel\" position=\"counselor\" />" - "</Meeting>" - "<Meeting where=\"Lunch\" />" - "</Item>" - "<Item priority=\"2\" distance=\"here\">Do bills" - "</Item>" - "</ToDo>"; - #endif - - // The example parses from the character string (above): - #if defined( WIN32 ) && defined( TUNE ) - _CrtMemCheckpoint( &startMemState ); - #endif - - { - // Write to a file and read it back, to check file I/O. - - TiXmlDocument doc( "demotest.xml" ); - doc.Parse( demoStart ); - - if ( doc.Error() ) - { - printf( "Error in %s: %s\n", doc.Value(), doc.ErrorDesc() ); - exit( 1 ); - } - doc.SaveFile(); - } - - TiXmlDocument doc( "demotest.xml" ); - bool loadOkay = doc.LoadFile(); - - if ( !loadOkay ) - { - printf( "Could not load test file 'demotest.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc() ); - exit( 1 ); - } - - printf( "** Demo doc read from disk: ** \n\n" ); - printf( "** Printing via doc.Print **\n" ); - doc.Print( stdout ); - - { - printf( "** Printing via TiXmlPrinter **\n" ); - TiXmlPrinter printer; - doc.Accept( &printer ); - fprintf( stdout, "%s", printer.CStr() ); - } - #ifdef TIXML_USE_STL - { - printf( "** Printing via operator<< **\n" ); - std::cout << doc; - } - #endif - TiXmlNode* node = 0; - TiXmlElement* todoElement = 0; - TiXmlElement* itemElement = 0; - - - // -------------------------------------------------------- - // An example of changing existing attributes, and removing - // an element from the document. - // -------------------------------------------------------- - - // Get the "ToDo" element. - // It is a child of the document, and can be selected by name. - node = doc.FirstChild( "ToDo" ); - assert( node ); - todoElement = node->ToElement(); - assert( todoElement ); - - // Going to the toy store is now our second priority... - // So set the "priority" attribute of the first item in the list. - node = todoElement->FirstChildElement(); // This skips the "PDA" comment. - assert( node ); - itemElement = node->ToElement(); - assert( itemElement ); - itemElement->SetAttribute( "priority", 2 ); - - // Change the distance to "doing bills" from - // "none" to "here". It's the next sibling element. - itemElement = itemElement->NextSiblingElement(); - assert( itemElement ); - itemElement->SetAttribute( "distance", "here" ); - - // Remove the "Look for Evil Dinosaurs!" item. - // It is 1 more sibling away. We ask the parent to remove - // a particular child. - itemElement = itemElement->NextSiblingElement(); - todoElement->RemoveChild( itemElement ); - - itemElement = 0; - - // -------------------------------------------------------- - // What follows is an example of created elements and text - // nodes and adding them to the document. - // -------------------------------------------------------- - - // Add some meetings. - TiXmlElement item( "Item" ); - item.SetAttribute( "priority", "1" ); - item.SetAttribute( "distance", "far" ); - - TiXmlText text( "Talk to:" ); - - TiXmlElement meeting1( "Meeting" ); - meeting1.SetAttribute( "where", "School" ); - - TiXmlElement meeting2( "Meeting" ); - meeting2.SetAttribute( "where", "Lunch" ); - - TiXmlElement attendee1( "Attendee" ); - attendee1.SetAttribute( "name", "Marple" ); - attendee1.SetAttribute( "position", "teacher" ); - - TiXmlElement attendee2( "Attendee" ); - attendee2.SetAttribute( "name", "Voel" ); - attendee2.SetAttribute( "position", "counselor" ); - - // Assemble the nodes we've created: - meeting1.InsertEndChild( attendee1 ); - meeting1.InsertEndChild( attendee2 ); - - item.InsertEndChild( text ); - item.InsertEndChild( meeting1 ); - item.InsertEndChild( meeting2 ); - - // And add the node to the existing list after the first child. - node = todoElement->FirstChild( "Item" ); - assert( node ); - itemElement = node->ToElement(); - assert( itemElement ); - - todoElement->InsertAfterChild( itemElement, item ); - - printf( "\n** Demo doc processed: ** \n\n" ); - doc.Print( stdout ); - - - #ifdef TIXML_USE_STL - printf( "** Demo doc processed to stream: ** \n\n" ); - cout << doc << endl << endl; - #endif - - // -------------------------------------------------------- - // Different tests...do we have what we expect? - // -------------------------------------------------------- - - int count = 0; - TiXmlElement* element; - - ////////////////////////////////////////////////////// - - #ifdef TIXML_USE_STL - cout << "** Basic structure. **\n"; - ostringstream outputStream( ostringstream::out ); - outputStream << doc; - XmlTest( "Output stream correct.", string( demoEnd ).c_str(), - outputStream.str().c_str(), true ); - #endif - - node = doc.RootElement(); - assert( node ); - XmlTest( "Root element exists.", true, ( node != 0 && node->ToElement() ) ); - XmlTest ( "Root element value is 'ToDo'.", "ToDo", node->Value()); - - node = node->FirstChild(); - XmlTest( "First child exists & is a comment.", true, ( node != 0 && node->ToComment() ) ); - node = node->NextSibling(); - XmlTest( "Sibling element exists & is an element.", true, ( node != 0 && node->ToElement() ) ); - XmlTest ( "Value is 'Item'.", "Item", node->Value() ); - - node = node->FirstChild(); - XmlTest ( "First child exists.", true, ( node != 0 && node->ToText() ) ); - XmlTest ( "Value is 'Go to the'.", "Go to the", node->Value() ); - - - ////////////////////////////////////////////////////// - printf ("\n** Iterators. **\n"); - - // Walk all the top level nodes of the document. - count = 0; - for( node = doc.FirstChild(); - node; - node = node->NextSibling() ) - { - count++; - } - XmlTest( "Top level nodes, using First / Next.", 3, count ); - - count = 0; - for( node = doc.LastChild(); - node; - node = node->PreviousSibling() ) - { - count++; - } - XmlTest( "Top level nodes, using Last / Previous.", 3, count ); - - // Walk all the top level nodes of the document, - // using a different syntax. - count = 0; - for( node = doc.IterateChildren( 0 ); - node; - node = doc.IterateChildren( node ) ) - { - count++; - } - XmlTest( "Top level nodes, using IterateChildren.", 3, count ); - - // Walk all the elements in a node. - count = 0; - for( element = todoElement->FirstChildElement(); - element; - element = element->NextSiblingElement() ) - { - count++; - } - XmlTest( "Children of the 'ToDo' element, using First / Next.", - 3, count ); - - // Walk all the elements in a node by value. - count = 0; - for( node = todoElement->FirstChild( "Item" ); - node; - node = node->NextSibling( "Item" ) ) - { - count++; - } - XmlTest( "'Item' children of the 'ToDo' element, using First/Next.", 3, count ); - - count = 0; - for( node = todoElement->LastChild( "Item" ); - node; - node = node->PreviousSibling( "Item" ) ) - { - count++; - } - XmlTest( "'Item' children of the 'ToDo' element, using Last/Previous.", 3, count ); - - #ifdef TIXML_USE_STL - { - cout << "\n** Parsing. **\n"; - istringstream parse0( "<Element0 attribute0='foo0' attribute1= noquotes attribute2 = '>' />" ); - TiXmlElement element0( "default" ); - parse0 >> element0; - - XmlTest ( "Element parsed, value is 'Element0'.", "Element0", element0.Value() ); - XmlTest ( "Reads attribute 'attribute0=\"foo0\"'.", "foo0", element0.Attribute( "attribute0" )); - XmlTest ( "Reads incorrectly formatted 'attribute1=noquotes'.", "noquotes", element0.Attribute( "attribute1" ) ); - XmlTest ( "Read attribute with entity value '>'.", ">", element0.Attribute( "attribute2" ) ); - } - #endif - - { - const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n" - "<passages count=\"006\" formatversion=\"20020620\">\n" - " <wrong error>\n" - "</passages>"; - - TiXmlDocument docTest; - docTest.Parse( error ); - XmlTest( "Error row", docTest.ErrorRow(), 3 ); - XmlTest( "Error column", docTest.ErrorCol(), 17 ); - //printf( "error=%d id='%s' row %d col%d\n", (int) doc.Error(), doc.ErrorDesc(), doc.ErrorRow()+1, doc.ErrorCol() + 1 ); - - } - - #ifdef TIXML_USE_STL - { - ////////////////////////////////////////////////////// - cout << "\n** Streaming. **\n"; - - // Round trip check: stream in, then stream back out to verify. The stream - // out has already been checked, above. We use the output - - istringstream inputStringStream( outputStream.str() ); - TiXmlDocument document0; - - inputStringStream >> document0; - - ostringstream outputStream0( ostringstream::out ); - outputStream0 << document0; - - XmlTest( "Stream round trip correct.", string( demoEnd ).c_str(), - outputStream0.str().c_str(), true ); - - std::string str; - str << document0; - - XmlTest( "String printing correct.", string( demoEnd ).c_str(), - str.c_str(), true ); - } - #endif - } - - { - const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />"; - - TiXmlDocument doc; - doc.Parse( str ); - - TiXmlElement* ele = doc.FirstChildElement(); - - int iVal, result; - double dVal; - - result = ele->QueryDoubleAttribute( "attr0", &dVal ); - XmlTest( "Query attribute: int as double", result, TIXML_SUCCESS ); - XmlTest( "Query attribute: int as double", (int)dVal, 1 ); - result = ele->QueryDoubleAttribute( "attr1", &dVal ); - XmlTest( "Query attribute: double as double", (int)dVal, 2 ); - result = ele->QueryIntAttribute( "attr1", &iVal ); - XmlTest( "Query attribute: double as int", result, TIXML_SUCCESS ); - XmlTest( "Query attribute: double as int", iVal, 2 ); - result = ele->QueryIntAttribute( "attr2", &iVal ); - XmlTest( "Query attribute: not a number", result, TIXML_WRONG_TYPE ); - result = ele->QueryIntAttribute( "bar", &iVal ); - XmlTest( "Query attribute: does not exist", result, TIXML_NO_ATTRIBUTE ); - } - - { - const char* str = "<doc/>"; - - TiXmlDocument doc; - doc.Parse( str ); - - TiXmlElement* ele = doc.FirstChildElement(); - - int iVal; - double dVal; - - ele->SetAttribute( "str", "strValue" ); - ele->SetAttribute( "int", 1 ); - ele->SetDoubleAttribute( "double", -1.0 ); - - const char* cStr = ele->Attribute( "str" ); - ele->QueryIntAttribute( "int", &iVal ); - ele->QueryDoubleAttribute( "double", &dVal ); - - XmlTest( "Attribute round trip. c-string.", "strValue", cStr ); - XmlTest( "Attribute round trip. int.", 1, iVal ); - XmlTest( "Attribute round trip. double.", -1, (int)dVal ); - } - - { - const char* str = "\t<?xml version=\"1.0\" standalone=\"no\" ?>\t<room doors='2'>\n" - "</room>"; - - TiXmlDocument doc; - doc.SetTabSize( 8 ); - doc.Parse( str ); - - TiXmlHandle docHandle( &doc ); - TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" ); - - assert( docHandle.Node() ); - assert( roomHandle.Element() ); - - TiXmlElement* room = roomHandle.Element(); - assert( room ); - TiXmlAttribute* doors = room->FirstAttribute(); - assert( doors ); - - XmlTest( "Location tracking: Tab 8: room row", room->Row(), 1 ); - XmlTest( "Location tracking: Tab 8: room col", room->Column(), 49 ); - XmlTest( "Location tracking: Tab 8: doors row", doors->Row(), 1 ); - XmlTest( "Location tracking: Tab 8: doors col", doors->Column(), 55 ); - } - - { - const char* str = "\t<?xml version=\"1.0\" standalone=\"no\" ?>\t<room doors='2'>\n" - " <!-- Silly example -->\n" - " <door wall='north'>A great door!</door>\n" - "\t<door wall='east'/>" - "</room>"; - - TiXmlDocument doc; - doc.Parse( str ); - - TiXmlHandle docHandle( &doc ); - TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" ); - TiXmlHandle commentHandle = docHandle.FirstChildElement( "room" ).FirstChild(); - TiXmlHandle textHandle = docHandle.FirstChildElement( "room" ).ChildElement( "door", 0 ).FirstChild(); - TiXmlHandle door0Handle = docHandle.FirstChildElement( "room" ).ChildElement( 0 ); - TiXmlHandle door1Handle = docHandle.FirstChildElement( "room" ).ChildElement( 1 ); - - assert( docHandle.Node() ); - assert( roomHandle.Element() ); - assert( commentHandle.Node() ); - assert( textHandle.Text() ); - assert( door0Handle.Element() ); - assert( door1Handle.Element() ); - - TiXmlDeclaration* declaration = doc.FirstChild()->ToDeclaration(); - assert( declaration ); - TiXmlElement* room = roomHandle.Element(); - assert( room ); - TiXmlAttribute* doors = room->FirstAttribute(); - assert( doors ); - TiXmlText* text = textHandle.Text(); - TiXmlComment* comment = commentHandle.Node()->ToComment(); - assert( comment ); - TiXmlElement* door0 = door0Handle.Element(); - TiXmlElement* door1 = door1Handle.Element(); - - XmlTest( "Location tracking: Declaration row", declaration->Row(), 1 ); - XmlTest( "Location tracking: Declaration col", declaration->Column(), 5 ); - XmlTest( "Location tracking: room row", room->Row(), 1 ); - XmlTest( "Location tracking: room col", room->Column(), 45 ); - XmlTest( "Location tracking: doors row", doors->Row(), 1 ); - XmlTest( "Location tracking: doors col", doors->Column(), 51 ); - XmlTest( "Location tracking: Comment row", comment->Row(), 2 ); - XmlTest( "Location tracking: Comment col", comment->Column(), 3 ); - XmlTest( "Location tracking: text row", text->Row(), 3 ); - XmlTest( "Location tracking: text col", text->Column(), 24 ); - XmlTest( "Location tracking: door0 row", door0->Row(), 3 ); - XmlTest( "Location tracking: door0 col", door0->Column(), 5 ); - XmlTest( "Location tracking: door1 row", door1->Row(), 4 ); - XmlTest( "Location tracking: door1 col", door1->Column(), 5 ); - } - - - // -------------------------------------------------------- - // UTF-8 testing. It is important to test: - // 1. Making sure name, value, and text read correctly - // 2. Row, Col functionality - // 3. Correct output - // -------------------------------------------------------- - printf ("\n** UTF-8 **\n"); - { - TiXmlDocument doc( "utf8test.xml" ); - doc.LoadFile(); - if ( doc.Error() && doc.ErrorId() == TiXmlBase::TIXML_ERROR_OPENING_FILE ) { - printf( "WARNING: File 'utf8test.xml' not found.\n" - "(Are you running the test from the wrong directory?)\n" - "Could not test UTF-8 functionality.\n" ); - } - else - { - TiXmlHandle docH( &doc ); - // Get the attribute "value" from the "Russian" element and check it. - TiXmlElement* element = docH.FirstChildElement( "document" ).FirstChildElement( "Russian" ).Element(); - const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU, - 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 }; - - XmlTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ), true ); - XmlTest( "UTF-8: Russian value row.", 4, element->Row() ); - XmlTest( "UTF-8: Russian value column.", 5, element->Column() ); - - const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U, - 0xd1U, 0x81U, 0xd1U, 0x81U, - 0xd0U, 0xbaU, 0xd0U, 0xb8U, - 0xd0U, 0xb9U, 0 }; - const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>"; - - TiXmlText* text = docH.FirstChildElement( "document" ).FirstChildElement( (const char*) russianElementName ).Child( 0 ).Text(); - XmlTest( "UTF-8: Browsing russian element name.", - russianText, - text->Value(), - true ); - XmlTest( "UTF-8: Russian element name row.", 7, text->Row() ); - XmlTest( "UTF-8: Russian element name column.", 47, text->Column() ); - - TiXmlDeclaration* dec = docH.Child( 0 ).Node()->ToDeclaration(); - XmlTest( "UTF-8: Declaration column.", 1, dec->Column() ); - XmlTest( "UTF-8: Document column.", 1, doc.Column() ); - - // Now try for a round trip. - doc.SaveFile( "utf8testout.xml" ); - - // Check the round trip. - char savedBuf[256]; - char verifyBuf[256]; - int okay = 1; - - FILE* saved = fopen( "utf8testout.xml", "r" ); - FILE* verify = fopen( "utf8testverify.xml", "r" ); - if ( saved && verify ) - { - while ( fgets( verifyBuf, 256, verify ) ) - { - fgets( savedBuf, 256, saved ); - if ( strcmp( verifyBuf, savedBuf ) ) - { - okay = 0; - break; - } - } - fclose( saved ); - fclose( verify ); - } - XmlTest( "UTF-8: Verified multi-language round trip.", 1, okay ); - - // On most Western machines, this is an element that contains - // the word "resume" with the correct accents, in a latin encoding. - // It will be something else completely on non-wester machines, - // which is why TinyXml is switching to UTF-8. - const char latin[] = "<element>r\x82sum\x82</element>"; - - TiXmlDocument latinDoc; - latinDoc.Parse( latin, 0, TIXML_ENCODING_LEGACY ); - - text = latinDoc.FirstChildElement()->FirstChild()->ToText(); - XmlTest( "Legacy encoding: Verify text element.", "r\x82sum\x82", text->Value() ); - } - } - - ////////////////////// - // Copy and assignment - ////////////////////// - printf ("\n** Copy and Assignment **\n"); - { - TiXmlElement element( "foo" ); - element.Parse( "<element name='value' />", 0, TIXML_ENCODING_UNKNOWN ); - - TiXmlElement elementCopy( element ); - TiXmlElement elementAssign( "foo" ); - elementAssign.Parse( "<incorrect foo='bar'/>", 0, TIXML_ENCODING_UNKNOWN ); - elementAssign = element; - - XmlTest( "Copy/Assign: element copy #1.", "element", elementCopy.Value() ); - XmlTest( "Copy/Assign: element copy #2.", "value", elementCopy.Attribute( "name" ) ); - XmlTest( "Copy/Assign: element assign #1.", "element", elementAssign.Value() ); - XmlTest( "Copy/Assign: element assign #2.", "value", elementAssign.Attribute( "name" ) ); - XmlTest( "Copy/Assign: element assign #3.", true, ( 0 == elementAssign.Attribute( "foo" )) ); - - TiXmlComment comment; - comment.Parse( "<!--comment-->", 0, TIXML_ENCODING_UNKNOWN ); - TiXmlComment commentCopy( comment ); - TiXmlComment commentAssign; - commentAssign = commentCopy; - XmlTest( "Copy/Assign: comment copy.", "comment", commentCopy.Value() ); - XmlTest( "Copy/Assign: comment assign.", "comment", commentAssign.Value() ); - - TiXmlUnknown unknown; - unknown.Parse( "<[unknown]>", 0, TIXML_ENCODING_UNKNOWN ); - TiXmlUnknown unknownCopy( unknown ); - TiXmlUnknown unknownAssign; - unknownAssign.Parse( "incorrect", 0, TIXML_ENCODING_UNKNOWN ); - unknownAssign = unknownCopy; - XmlTest( "Copy/Assign: unknown copy.", "[unknown]", unknownCopy.Value() ); - XmlTest( "Copy/Assign: unknown assign.", "[unknown]", unknownAssign.Value() ); - - TiXmlText text( "TextNode" ); - TiXmlText textCopy( text ); - TiXmlText textAssign( "incorrect" ); - textAssign = text; - XmlTest( "Copy/Assign: text copy.", "TextNode", textCopy.Value() ); - XmlTest( "Copy/Assign: text assign.", "TextNode", textAssign.Value() ); - - TiXmlDeclaration dec; - dec.Parse( "<?xml version='1.0' encoding='UTF-8'?>", 0, TIXML_ENCODING_UNKNOWN ); - TiXmlDeclaration decCopy( dec ); - TiXmlDeclaration decAssign; - decAssign = dec; - - XmlTest( "Copy/Assign: declaration copy.", "UTF-8", decCopy.Encoding() ); - XmlTest( "Copy/Assign: text assign.", "UTF-8", decAssign.Encoding() ); - - TiXmlDocument doc; - elementCopy.InsertEndChild( textCopy ); - doc.InsertEndChild( decAssign ); - doc.InsertEndChild( elementCopy ); - doc.InsertEndChild( unknownAssign ); - - TiXmlDocument docCopy( doc ); - TiXmlDocument docAssign; - docAssign = docCopy; - - #ifdef TIXML_USE_STL - std::string original, copy, assign; - original << doc; - copy << docCopy; - assign << docAssign; - XmlTest( "Copy/Assign: document copy.", original.c_str(), copy.c_str(), true ); - XmlTest( "Copy/Assign: document assign.", original.c_str(), assign.c_str(), true ); - - #endif - } - - ////////////////////////////////////////////////////// + // + // We start with the 'demoStart' todo list. Process it. And + // should hopefully end up with the todo list as illustrated. + // + const char* demoStart = + "<?xml version=\"1.0\" standalone='no' >\n" + "<!-- Our to do list data -->" + "<ToDo>\n" + "<!-- Do I need a secure PDA? -->\n" + "<Item priority=\"1\" distance='close'> Go to the <bold>Toy store!</bold></Item>" + "<Item priority=\"2\" distance='none'> Do bills </Item>" + "<Item priority=\"2\" distance='far & back'> Look for Evil Dinosaurs! </Item>" + "</ToDo>"; + + { + +#ifdef TIXML_USE_STL + // What the todo list should look like after processing. + // In stream (no formatting) representation. + const char* demoEnd = + "<?xml version=\"1.0\" standalone=\"no\" ?>" + "<!-- Our to do list data -->" + "<ToDo>" + "<!-- Do I need a secure PDA? -->" + "<Item priority=\"2\" distance=\"close\">Go to the" + "<bold>Toy store!" + "</bold>" + "</Item>" + "<Item priority=\"1\" distance=\"far\">Talk to:" + "<Meeting where=\"School\">" + "<Attendee name=\"Marple\" position=\"teacher\" />" + "<Attendee name=\"Voel\" position=\"counselor\" />" + "</Meeting>" + "<Meeting where=\"Lunch\" />" + "</Item>" + "<Item priority=\"2\" distance=\"here\">Do bills" + "</Item>" + "</ToDo>"; +#endif + + // The example parses from the character string (above): +#if defined( WIN32 ) && defined( TUNE ) + _CrtMemCheckpoint( &startMemState ); +#endif + + { + // Write to a file and read it back, to check file I/O. + + TiXmlDocument doc( "demotest.xml" ); + doc.Parse( demoStart ); + + if ( doc.Error() ) + { + printf( "Error in %s: %s\n", doc.Value(), doc.ErrorDesc() ); + exit( 1 ); + } + doc.SaveFile(); + } + + TiXmlDocument doc( "demotest.xml" ); + bool loadOkay = doc.LoadFile(); + + if ( !loadOkay ) + { + printf( "Could not load test file 'demotest.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc() ); + exit( 1 ); + } + + printf( "** Demo doc read from disk: ** \n\n" ); + printf( "** Printing via doc.Print **\n" ); + doc.Print( stdout ); + + { + printf( "** Printing via TiXmlPrinter **\n" ); + TiXmlPrinter printer; + doc.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + } #ifdef TIXML_USE_STL - printf ("\n** Parsing, no Condense Whitespace **\n"); - TiXmlBase::SetCondenseWhiteSpace( false ); - { - istringstream parse1( "<start>This is \ntext</start>" ); - TiXmlElement text1( "text" ); - parse1 >> text1; - - XmlTest ( "Condense white space OFF.", "This is \ntext", - text1.FirstChild()->Value(), - true ); - } - TiXmlBase::SetCondenseWhiteSpace( true ); + { + printf( "** Printing via operator<< **\n" ); + std::cout << doc; + } #endif + TiXmlNode* node = 0; + TiXmlElement* todoElement = 0; + TiXmlElement* itemElement = 0; + + + // -------------------------------------------------------- + // An example of changing existing attributes, and removing + // an element from the document. + // -------------------------------------------------------- + + // Get the "ToDo" element. + // It is a child of the document, and can be selected by name. + node = doc.FirstChild( "ToDo" ); + assert( node ); + todoElement = node->ToElement(); + assert( todoElement ); + + // Going to the toy store is now our second priority... + // So set the "priority" attribute of the first item in the list. + node = todoElement->FirstChildElement(); // This skips the "PDA" comment. + assert( node ); + itemElement = node->ToElement(); + assert( itemElement ); + itemElement->SetAttribute( "priority", 2 ); + + // Change the distance to "doing bills" from + // "none" to "here". It's the next sibling element. + itemElement = itemElement->NextSiblingElement(); + assert( itemElement ); + itemElement->SetAttribute( "distance", "here" ); + + // Remove the "Look for Evil Dinosaurs!" item. + // It is 1 more sibling away. We ask the parent to remove + // a particular child. + itemElement = itemElement->NextSiblingElement(); + todoElement->RemoveChild( itemElement ); + + itemElement = 0; + + // -------------------------------------------------------- + // What follows is an example of created elements and text + // nodes and adding them to the document. + // -------------------------------------------------------- + + // Add some meetings. + TiXmlElement item( "Item" ); + item.SetAttribute( "priority", "1" ); + item.SetAttribute( "distance", "far" ); + + TiXmlText text( "Talk to:" ); + + TiXmlElement meeting1( "Meeting" ); + meeting1.SetAttribute( "where", "School" ); + + TiXmlElement meeting2( "Meeting" ); + meeting2.SetAttribute( "where", "Lunch" ); + + TiXmlElement attendee1( "Attendee" ); + attendee1.SetAttribute( "name", "Marple" ); + attendee1.SetAttribute( "position", "teacher" ); + + TiXmlElement attendee2( "Attendee" ); + attendee2.SetAttribute( "name", "Voel" ); + attendee2.SetAttribute( "position", "counselor" ); + + // Assemble the nodes we've created: + meeting1.InsertEndChild( attendee1 ); + meeting1.InsertEndChild( attendee2 ); + + item.InsertEndChild( text ); + item.InsertEndChild( meeting1 ); + item.InsertEndChild( meeting2 ); + + // And add the node to the existing list after the first child. + node = todoElement->FirstChild( "Item" ); + assert( node ); + itemElement = node->ToElement(); + assert( itemElement ); + + todoElement->InsertAfterChild( itemElement, item ); + + printf( "\n** Demo doc processed: ** \n\n" ); + doc.Print( stdout ); + + +#ifdef TIXML_USE_STL + printf( "** Demo doc processed to stream: ** \n\n" ); + cout << doc << endl << endl; +#endif + + // -------------------------------------------------------- + // Different tests...do we have what we expect? + // -------------------------------------------------------- - ////////////////////////////////////////////////////// - // GetText(); - { - const char* str = "<foo>This is text</foo>"; - TiXmlDocument doc; - doc.Parse( str ); - const TiXmlElement* element = doc.RootElement(); - - XmlTest( "GetText() normal use.", "This is text", element->GetText() ); - - str = "<foo><b>This is text</b></foo>"; - doc.Clear(); - doc.Parse( str ); - element = doc.RootElement(); - - XmlTest( "GetText() contained element.", element->GetText() == 0, true ); - - str = "<foo>This is <b>text</b></foo>"; - doc.Clear(); - TiXmlBase::SetCondenseWhiteSpace( false ); - doc.Parse( str ); - TiXmlBase::SetCondenseWhiteSpace( true ); - element = doc.RootElement(); - - XmlTest( "GetText() partial.", "This is ", element->GetText() ); - } - - - ////////////////////////////////////////////////////// - // CDATA - { - const char* str = "<xmlElement>" - "<![CDATA[" - "I am > the rules!\n" - "...since I make symbolic puns" - "]]>" - "</xmlElement>"; - TiXmlDocument doc; - doc.Parse( str ); - doc.Print(); - - XmlTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true ); - - #ifdef TIXML_USE_STL - //cout << doc << '\n'; - - doc.Clear(); - - istringstream parse0( str ); - parse0 >> doc; - //cout << doc << '\n'; - - XmlTest( "CDATA stream.", doc.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true ); - #endif - - TiXmlDocument doc1 = doc; - //doc.Print(); - - XmlTest( "CDATA copy.", doc1.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true ); - } - { - // [ 1482728 ] Wrong wide char parsing - char buf[256]; - buf[255] = 0; - for( int i=0; i<255; ++i ) { - buf[i] = (char)((i>=32) ? i : 32); - } - TIXML_STRING str( "<xmlElement><![CDATA[" ); - str += buf; - str += "]]></xmlElement>"; - - TiXmlDocument doc; - doc.Parse( str.c_str() ); - - TiXmlPrinter printer; - printer.SetStreamPrinting(); - doc.Accept( &printer ); - - XmlTest( "CDATA with all bytes #1.", str.c_str(), printer.CStr(), true ); - - #ifdef TIXML_USE_STL - doc.Clear(); - istringstream iss( printer.Str() ); - iss >> doc; - std::string out; - out << doc; - XmlTest( "CDATA with all bytes #2.", out.c_str(), printer.CStr(), true ); - #endif - } - { - // [ 1480107 ] Bug-fix for STL-streaming of CDATA that contains tags - // CDATA streaming had a couple of bugs, that this tests for. - const char* str = "<xmlElement>" - "<![CDATA[" - "<b>I am > the rules!</b>\n" - "...since I make symbolic puns" - "]]>" - "</xmlElement>"; - TiXmlDocument doc; - doc.Parse( str ); - doc.Print(); - - XmlTest( "CDATA parse. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), - "<b>I am > the rules!</b>\n...since I make symbolic puns", - true ); - - #ifdef TIXML_USE_STL - - doc.Clear(); - - istringstream parse0( str ); - parse0 >> doc; - - XmlTest( "CDATA stream. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), - "<b>I am > the rules!</b>\n...since I make symbolic puns", - true ); - #endif - - TiXmlDocument doc1 = doc; - //doc.Print(); - - XmlTest( "CDATA copy. [ 1480107 ]", doc1.FirstChildElement()->FirstChild()->Value(), - "<b>I am > the rules!</b>\n...since I make symbolic puns", - true ); - } - ////////////////////////////////////////////////////// - // Visit() - - - - ////////////////////////////////////////////////////// - printf( "\n** Fuzzing... **\n" ); - - const int FUZZ_ITERATION = 300; - - // The only goal is not to crash on bad input. - int len = (int) strlen( demoStart ); - for( int i=0; i<FUZZ_ITERATION; ++i ) - { - char* demoCopy = new char[ len+1 ]; - strcpy( demoCopy, demoStart ); - - demoCopy[ i%len ] = (char)((i+1)*3); - demoCopy[ (i*7)%len ] = '>'; - demoCopy[ (i*11)%len ] = '<'; - - TiXmlDocument xml; - xml.Parse( demoCopy ); - - delete [] demoCopy; - } - printf( "** Fuzzing Complete. **\n" ); - - ////////////////////////////////////////////////////// - printf ("\n** Bug regression tests **\n"); - - // InsertBeforeChild and InsertAfterChild causes crash. - { - TiXmlElement parent( "Parent" ); - TiXmlElement childText0( "childText0" ); - TiXmlElement childText1( "childText1" ); - TiXmlNode* childNode0 = parent.InsertEndChild( childText0 ); - TiXmlNode* childNode1 = parent.InsertBeforeChild( childNode0, childText1 ); - - XmlTest( "Test InsertBeforeChild on empty node.", ( childNode1 == parent.FirstChild() ), true ); - } - - { - // InsertBeforeChild and InsertAfterChild causes crash. - TiXmlElement parent( "Parent" ); - TiXmlElement childText0( "childText0" ); - TiXmlElement childText1( "childText1" ); - TiXmlNode* childNode0 = parent.InsertEndChild( childText0 ); - TiXmlNode* childNode1 = parent.InsertAfterChild( childNode0, childText1 ); - - XmlTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent.LastChild() ), true ); - } - - // Reports of missing constructors, irregular string problems. - { - // Missing constructor implementation. No test -- just compiles. - TiXmlText text( "Missing" ); - - #ifdef TIXML_USE_STL - // Missing implementation: - TiXmlDocument doc; - string name = "missing"; - doc.LoadFile( name ); - - TiXmlText textSTL( name ); - #else - // verifying some basic string functions: - TiXmlString a; - TiXmlString b( "Hello" ); - TiXmlString c( "ooga" ); - - c = " World!"; - a = b; - a += c; - a = a; - - XmlTest( "Basic TiXmlString test. ", "Hello World!", a.c_str() ); - #endif - } - - // Long filenames crashing STL version - { - TiXmlDocument doc( "midsummerNightsDreamWithAVeryLongFilenameToConfuseTheStringHandlingRoutines.xml" ); - bool loadOkay = doc.LoadFile(); - loadOkay = true; // get rid of compiler warning. - // Won't pass on non-dev systems. Just a "no crash" check. - //XmlTest( "Long filename. ", true, loadOkay ); - } - - { - // Entities not being written correctly. - // From Lynn Allen - - const char* passages = - "<?xml version=\"1.0\" standalone=\"no\" ?>" - "<passages count=\"006\" formatversion=\"20020620\">" - "<psg context=\"Line 5 has "quotation marks" and 'apostrophe marks'." - " It also has <, >, and &, as well as a fake copyright ©.\"> </psg>" - "</passages>"; - - TiXmlDocument doc( "passages.xml" ); - doc.Parse( passages ); - TiXmlElement* psg = doc.RootElement()->FirstChildElement(); - const char* context = psg->Attribute( "context" ); - const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9."; - - XmlTest( "Entity transformation: read. ", expected, context, true ); - - FILE* textfile = fopen( "textfile.txt", "w" ); - if ( textfile ) - { - psg->Print( textfile, 0 ); - fclose( textfile ); - } - textfile = fopen( "textfile.txt", "r" ); - assert( textfile ); - if ( textfile ) - { - char buf[ 1024 ]; - fgets( buf, 1024, textfile ); - XmlTest( "Entity transformation: write. ", - "<psg context=\'Line 5 has "quotation marks" and 'apostrophe marks'." - " It also has <, >, and &, as well as a fake copyright \xC2\xA9.' />", - buf, - true ); - } - fclose( textfile ); - } + int count = 0; + TiXmlElement* element; + + ////////////////////////////////////////////////////// + +#ifdef TIXML_USE_STL + cout << "** Basic structure. **\n"; + ostringstream outputStream( ostringstream::out ); + outputStream << doc; + XmlTest( "Output stream correct.", string( demoEnd ).c_str(), + outputStream.str().c_str(), true ); +#endif + + node = doc.RootElement(); + assert( node ); + XmlTest( "Root element exists.", true, ( node != 0 && node->ToElement() ) ); + XmlTest ( "Root element value is 'ToDo'.", "ToDo", node->Value()); + + node = node->FirstChild(); + XmlTest( "First child exists & is a comment.", true, ( node != 0 && node->ToComment() ) ); + node = node->NextSibling(); + XmlTest( "Sibling element exists & is an element.", true, ( node != 0 && node->ToElement() ) ); + XmlTest ( "Value is 'Item'.", "Item", node->Value() ); + + node = node->FirstChild(); + XmlTest ( "First child exists.", true, ( node != 0 && node->ToText() ) ); + XmlTest ( "Value is 'Go to the'.", "Go to the", node->Value() ); + + + ////////////////////////////////////////////////////// + printf ("\n** Iterators. **\n"); + + // Walk all the top level nodes of the document. + count = 0; + for( node = doc.FirstChild(); + node; + node = node->NextSibling() ) + { + count++; + } + XmlTest( "Top level nodes, using First / Next.", 3, count ); + + count = 0; + for( node = doc.LastChild(); + node; + node = node->PreviousSibling() ) + { + count++; + } + XmlTest( "Top level nodes, using Last / Previous.", 3, count ); + + // Walk all the top level nodes of the document, + // using a different syntax. + count = 0; + for( node = doc.IterateChildren( 0 ); + node; + node = doc.IterateChildren( node ) ) + { + count++; + } + XmlTest( "Top level nodes, using IterateChildren.", 3, count ); + + // Walk all the elements in a node. + count = 0; + for( element = todoElement->FirstChildElement(); + element; + element = element->NextSiblingElement() ) + { + count++; + } + XmlTest( "Children of the 'ToDo' element, using First / Next.", + 3, count ); + + // Walk all the elements in a node by value. + count = 0; + for( node = todoElement->FirstChild( "Item" ); + node; + node = node->NextSibling( "Item" ) ) + { + count++; + } + XmlTest( "'Item' children of the 'ToDo' element, using First/Next.", 3, count ); + + count = 0; + for( node = todoElement->LastChild( "Item" ); + node; + node = node->PreviousSibling( "Item" ) ) + { + count++; + } + XmlTest( "'Item' children of the 'ToDo' element, using Last/Previous.", 3, count ); + +#ifdef TIXML_USE_STL + { + cout << "\n** Parsing. **\n"; + istringstream parse0( "<Element0 attribute0='foo0' attribute1= noquotes attribute2 = '>' />" ); + TiXmlElement element0( "default" ); + parse0 >> element0; + + XmlTest ( "Element parsed, value is 'Element0'.", "Element0", element0.Value() ); + XmlTest ( "Reads attribute 'attribute0=\"foo0\"'.", "foo0", element0.Attribute( "attribute0" )); + XmlTest ( "Reads incorrectly formatted 'attribute1=noquotes'.", "noquotes", element0.Attribute( "attribute1" ) ); + XmlTest ( "Read attribute with entity value '>'.", ">", element0.Attribute( "attribute2" ) ); + } +#endif + + { + const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n" + "<passages count=\"006\" formatversion=\"20020620\">\n" + " <wrong error>\n" + "</passages>"; + + TiXmlDocument docTest; + docTest.Parse( error ); + XmlTest( "Error row", docTest.ErrorRow(), 3 ); + XmlTest( "Error column", docTest.ErrorCol(), 17 ); + //printf( "error=%d id='%s' row %d col%d\n", (int) doc.Error(), doc.ErrorDesc(), doc.ErrorRow()+1, doc.ErrorCol() + 1 ); + + } + +#ifdef TIXML_USE_STL + { + ////////////////////////////////////////////////////// + cout << "\n** Streaming. **\n"; + + // Round trip check: stream in, then stream back out to verify. The stream + // out has already been checked, above. We use the output + + istringstream inputStringStream( outputStream.str() ); + TiXmlDocument document0; + + inputStringStream >> document0; + + ostringstream outputStream0( ostringstream::out ); + outputStream0 << document0; + + XmlTest( "Stream round trip correct.", string( demoEnd ).c_str(), + outputStream0.str().c_str(), true ); + + std::string str; + str << document0; + + XmlTest( "String printing correct.", string( demoEnd ).c_str(), + str.c_str(), true ); + } +#endif + } + + { + const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />"; + + TiXmlDocument doc; + doc.Parse( str ); + + TiXmlElement* ele = doc.FirstChildElement(); + + int iVal, result; + double dVal; + + result = ele->QueryDoubleAttribute( "attr0", &dVal ); + XmlTest( "Query attribute: int as double", result, TIXML_SUCCESS ); + XmlTest( "Query attribute: int as double", (int)dVal, 1 ); + result = ele->QueryDoubleAttribute( "attr1", &dVal ); + XmlTest( "Query attribute: double as double", (int)dVal, 2 ); + result = ele->QueryIntAttribute( "attr1", &iVal ); + XmlTest( "Query attribute: double as int", result, TIXML_SUCCESS ); + XmlTest( "Query attribute: double as int", iVal, 2 ); + result = ele->QueryIntAttribute( "attr2", &iVal ); + XmlTest( "Query attribute: not a number", result, TIXML_WRONG_TYPE ); + result = ele->QueryIntAttribute( "bar", &iVal ); + XmlTest( "Query attribute: does not exist", result, TIXML_NO_ATTRIBUTE ); + } { - FILE* textfile = fopen( "test5.xml", "w" ); - if ( textfile ) - { + const char* str = "<doc/>"; + + TiXmlDocument doc; + doc.Parse( str ); + + TiXmlElement* ele = doc.FirstChildElement(); + + int iVal; + double dVal; + + ele->SetAttribute( "str", "strValue" ); + ele->SetAttribute( "int", 1 ); + ele->SetDoubleAttribute( "double", -1.0 ); + + const char* cStr = ele->Attribute( "str" ); + ele->QueryIntAttribute( "int", &iVal ); + ele->QueryDoubleAttribute( "double", &dVal ); + + XmlTest( "Attribute round trip. c-string.", "strValue", cStr ); + XmlTest( "Attribute round trip. int.", 1, iVal ); + XmlTest( "Attribute round trip. double.", -1, (int)dVal ); + } + + { + const char* str = "\t<?xml version=\"1.0\" standalone=\"no\" ?>\t<room doors='2'>\n" + "</room>"; + + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Parse( str ); + + TiXmlHandle docHandle( &doc ); + TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" ); + + assert( docHandle.Node() ); + assert( roomHandle.Element() ); + + TiXmlElement* room = roomHandle.Element(); + assert( room ); + TiXmlAttribute* doors = room->FirstAttribute(); + assert( doors ); + + XmlTest( "Location tracking: Tab 8: room row", room->Row(), 1 ); + XmlTest( "Location tracking: Tab 8: room col", room->Column(), 49 ); + XmlTest( "Location tracking: Tab 8: doors row", doors->Row(), 1 ); + XmlTest( "Location tracking: Tab 8: doors col", doors->Column(), 55 ); + } + + { + const char* str = "\t<?xml version=\"1.0\" standalone=\"no\" ?>\t<room doors='2'>\n" + " <!-- Silly example -->\n" + " <door wall='north'>A great door!</door>\n" + "\t<door wall='east'/>" + "</room>"; + + TiXmlDocument doc; + doc.Parse( str ); + + TiXmlHandle docHandle( &doc ); + TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" ); + TiXmlHandle commentHandle = docHandle.FirstChildElement( "room" ).FirstChild(); + TiXmlHandle textHandle = docHandle.FirstChildElement( "room" ).ChildElement( "door", 0 ).FirstChild(); + TiXmlHandle door0Handle = docHandle.FirstChildElement( "room" ).ChildElement( 0 ); + TiXmlHandle door1Handle = docHandle.FirstChildElement( "room" ).ChildElement( 1 ); + + assert( docHandle.Node() ); + assert( roomHandle.Element() ); + assert( commentHandle.Node() ); + assert( textHandle.Text() ); + assert( door0Handle.Element() ); + assert( door1Handle.Element() ); + + TiXmlDeclaration* declaration = doc.FirstChild()->ToDeclaration(); + assert( declaration ); + TiXmlElement* room = roomHandle.Element(); + assert( room ); + TiXmlAttribute* doors = room->FirstAttribute(); + assert( doors ); + TiXmlText* text = textHandle.Text(); + TiXmlComment* comment = commentHandle.Node()->ToComment(); + assert( comment ); + TiXmlElement* door0 = door0Handle.Element(); + TiXmlElement* door1 = door1Handle.Element(); + + XmlTest( "Location tracking: Declaration row", declaration->Row(), 1 ); + XmlTest( "Location tracking: Declaration col", declaration->Column(), 5 ); + XmlTest( "Location tracking: room row", room->Row(), 1 ); + XmlTest( "Location tracking: room col", room->Column(), 45 ); + XmlTest( "Location tracking: doors row", doors->Row(), 1 ); + XmlTest( "Location tracking: doors col", doors->Column(), 51 ); + XmlTest( "Location tracking: Comment row", comment->Row(), 2 ); + XmlTest( "Location tracking: Comment col", comment->Column(), 3 ); + XmlTest( "Location tracking: text row", text->Row(), 3 ); + XmlTest( "Location tracking: text col", text->Column(), 24 ); + XmlTest( "Location tracking: door0 row", door0->Row(), 3 ); + XmlTest( "Location tracking: door0 col", door0->Column(), 5 ); + XmlTest( "Location tracking: door1 row", door1->Row(), 4 ); + XmlTest( "Location tracking: door1 col", door1->Column(), 5 ); + } + + + // -------------------------------------------------------- + // UTF-8 testing. It is important to test: + // 1. Making sure name, value, and text read correctly + // 2. Row, Col functionality + // 3. Correct output + // -------------------------------------------------------- + printf ("\n** UTF-8 **\n"); + { + TiXmlDocument doc( "utf8test.xml" ); + doc.LoadFile(); + if ( doc.Error() && doc.ErrorId() == TiXmlBase::TIXML_ERROR_OPENING_FILE ) + { + printf( "WARNING: File 'utf8test.xml' not found.\n" + "(Are you running the test from the wrong directory?)\n" + "Could not test UTF-8 functionality.\n" ); + } + else + { + TiXmlHandle docH( &doc ); + // Get the attribute "value" from the "Russian" element and check it. + TiXmlElement* element = docH.FirstChildElement( "document" ).FirstChildElement( "Russian" ).Element(); + const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU, + 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 + }; + + XmlTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ), true ); + XmlTest( "UTF-8: Russian value row.", 4, element->Row() ); + XmlTest( "UTF-8: Russian value column.", 5, element->Column() ); + + const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U, + 0xd1U, 0x81U, 0xd1U, 0x81U, + 0xd0U, 0xbaU, 0xd0U, 0xb8U, + 0xd0U, 0xb9U, 0 + }; + const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>"; + + TiXmlText* text = docH.FirstChildElement( "document" ).FirstChildElement( (const char*) russianElementName ).Child( 0 ).Text(); + XmlTest( "UTF-8: Browsing russian element name.", + russianText, + text->Value(), + true ); + XmlTest( "UTF-8: Russian element name row.", 7, text->Row() ); + XmlTest( "UTF-8: Russian element name column.", 47, text->Column() ); + + TiXmlDeclaration* dec = docH.Child( 0 ).Node()->ToDeclaration(); + XmlTest( "UTF-8: Declaration column.", 1, dec->Column() ); + XmlTest( "UTF-8: Document column.", 1, doc.Column() ); + + // Now try for a round trip. + doc.SaveFile( "utf8testout.xml" ); + + // Check the round trip. + char savedBuf[256]; + char verifyBuf[256]; + int okay = 1; + + FILE* saved = fopen( "utf8testout.xml", "r" ); + FILE* verify = fopen( "utf8testverify.xml", "r" ); + if ( saved && verify ) + { + while ( fgets( verifyBuf, 256, verify ) ) + { + fgets( savedBuf, 256, saved ); + if ( strcmp( verifyBuf, savedBuf ) ) + { + okay = 0; + break; + } + } + fclose( saved ); + fclose( verify ); + } + XmlTest( "UTF-8: Verified multi-language round trip.", 1, okay ); + + // On most Western machines, this is an element that contains + // the word "resume" with the correct accents, in a latin encoding. + // It will be something else completely on non-wester machines, + // which is why TinyXml is switching to UTF-8. + const char latin[] = "<element>r\x82sum\x82</element>"; + + TiXmlDocument latinDoc; + latinDoc.Parse( latin, 0, TIXML_ENCODING_LEGACY ); + + text = latinDoc.FirstChildElement()->FirstChild()->ToText(); + XmlTest( "Legacy encoding: Verify text element.", "r\x82sum\x82", text->Value() ); + } + } + + ////////////////////// + // Copy and assignment + ////////////////////// + printf ("\n** Copy and Assignment **\n"); + { + TiXmlElement element( "foo" ); + element.Parse( "<element name='value' />", 0, TIXML_ENCODING_UNKNOWN ); + + TiXmlElement elementCopy( element ); + TiXmlElement elementAssign( "foo" ); + elementAssign.Parse( "<incorrect foo='bar'/>", 0, TIXML_ENCODING_UNKNOWN ); + elementAssign = element; + + XmlTest( "Copy/Assign: element copy #1.", "element", elementCopy.Value() ); + XmlTest( "Copy/Assign: element copy #2.", "value", elementCopy.Attribute( "name" ) ); + XmlTest( "Copy/Assign: element assign #1.", "element", elementAssign.Value() ); + XmlTest( "Copy/Assign: element assign #2.", "value", elementAssign.Attribute( "name" ) ); + XmlTest( "Copy/Assign: element assign #3.", true, ( 0 == elementAssign.Attribute( "foo" )) ); + + TiXmlComment comment; + comment.Parse( "<!--comment-->", 0, TIXML_ENCODING_UNKNOWN ); + TiXmlComment commentCopy( comment ); + TiXmlComment commentAssign; + commentAssign = commentCopy; + XmlTest( "Copy/Assign: comment copy.", "comment", commentCopy.Value() ); + XmlTest( "Copy/Assign: comment assign.", "comment", commentAssign.Value() ); + + TiXmlUnknown unknown; + unknown.Parse( "<[unknown]>", 0, TIXML_ENCODING_UNKNOWN ); + TiXmlUnknown unknownCopy( unknown ); + TiXmlUnknown unknownAssign; + unknownAssign.Parse( "incorrect", 0, TIXML_ENCODING_UNKNOWN ); + unknownAssign = unknownCopy; + XmlTest( "Copy/Assign: unknown copy.", "[unknown]", unknownCopy.Value() ); + XmlTest( "Copy/Assign: unknown assign.", "[unknown]", unknownAssign.Value() ); + + TiXmlText text( "TextNode" ); + TiXmlText textCopy( text ); + TiXmlText textAssign( "incorrect" ); + textAssign = text; + XmlTest( "Copy/Assign: text copy.", "TextNode", textCopy.Value() ); + XmlTest( "Copy/Assign: text assign.", "TextNode", textAssign.Value() ); + + TiXmlDeclaration dec; + dec.Parse( "<?xml version='1.0' encoding='UTF-8'?>", 0, TIXML_ENCODING_UNKNOWN ); + TiXmlDeclaration decCopy( dec ); + TiXmlDeclaration decAssign; + decAssign = dec; + + XmlTest( "Copy/Assign: declaration copy.", "UTF-8", decCopy.Encoding() ); + XmlTest( "Copy/Assign: text assign.", "UTF-8", decAssign.Encoding() ); + + TiXmlDocument doc; + elementCopy.InsertEndChild( textCopy ); + doc.InsertEndChild( decAssign ); + doc.InsertEndChild( elementCopy ); + doc.InsertEndChild( unknownAssign ); + + TiXmlDocument docCopy( doc ); + TiXmlDocument docAssign; + docAssign = docCopy; + +#ifdef TIXML_USE_STL + std::string original, copy, assign; + original << doc; + copy << docCopy; + assign << docAssign; + XmlTest( "Copy/Assign: document copy.", original.c_str(), copy.c_str(), true ); + XmlTest( "Copy/Assign: document assign.", original.c_str(), assign.c_str(), true ); + +#endif + } + + ////////////////////////////////////////////////////// +#ifdef TIXML_USE_STL + printf ("\n** Parsing, no Condense Whitespace **\n"); + TiXmlBase::SetCondenseWhiteSpace( false ); + { + istringstream parse1( "<start>This is \ntext</start>" ); + TiXmlElement text1( "text" ); + parse1 >> text1; + + XmlTest ( "Condense white space OFF.", "This is \ntext", + text1.FirstChild()->Value(), + true ); + } + TiXmlBase::SetCondenseWhiteSpace( true ); +#endif + + ////////////////////////////////////////////////////// + // GetText(); + { + const char* str = "<foo>This is text</foo>"; + TiXmlDocument doc; + doc.Parse( str ); + const TiXmlElement* element = doc.RootElement(); + + XmlTest( "GetText() normal use.", "This is text", element->GetText() ); + + str = "<foo><b>This is text</b></foo>"; + doc.Clear(); + doc.Parse( str ); + element = doc.RootElement(); + + XmlTest( "GetText() contained element.", element->GetText() == 0, true ); + + str = "<foo>This is <b>text</b></foo>"; + doc.Clear(); + TiXmlBase::SetCondenseWhiteSpace( false ); + doc.Parse( str ); + TiXmlBase::SetCondenseWhiteSpace( true ); + element = doc.RootElement(); + + XmlTest( "GetText() partial.", "This is ", element->GetText() ); + } + + + ////////////////////////////////////////////////////// + // CDATA + { + const char* str = "<xmlElement>" + "<![CDATA[" + "I am > the rules!\n" + "...since I make symbolic puns" + "]]>" + "</xmlElement>"; + TiXmlDocument doc; + doc.Parse( str ); + doc.Print(); + + XmlTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(), + "I am > the rules!\n...since I make symbolic puns", + true ); + +#ifdef TIXML_USE_STL + //cout << doc << '\n'; + + doc.Clear(); + + istringstream parse0( str ); + parse0 >> doc; + //cout << doc << '\n'; + + XmlTest( "CDATA stream.", doc.FirstChildElement()->FirstChild()->Value(), + "I am > the rules!\n...since I make symbolic puns", + true ); +#endif + + TiXmlDocument doc1 = doc; + //doc.Print(); + + XmlTest( "CDATA copy.", doc1.FirstChildElement()->FirstChild()->Value(), + "I am > the rules!\n...since I make symbolic puns", + true ); + } + { + // [ 1482728 ] Wrong wide char parsing + char buf[256]; + buf[255] = 0; + for( int i=0; i<255; ++i ) + { + buf[i] = (char)((i>=32) ? i : 32); + } + TIXML_STRING str( "<xmlElement><![CDATA[" ); + str += buf; + str += "]]></xmlElement>"; + + TiXmlDocument doc; + doc.Parse( str.c_str() ); + + TiXmlPrinter printer; + printer.SetStreamPrinting(); + doc.Accept( &printer ); + + XmlTest( "CDATA with all bytes #1.", str.c_str(), printer.CStr(), true ); + +#ifdef TIXML_USE_STL + doc.Clear(); + istringstream iss( printer.Str() ); + iss >> doc; + std::string out; + out << doc; + XmlTest( "CDATA with all bytes #2.", out.c_str(), printer.CStr(), true ); +#endif + } + { + // [ 1480107 ] Bug-fix for STL-streaming of CDATA that contains tags + // CDATA streaming had a couple of bugs, that this tests for. + const char* str = "<xmlElement>" + "<![CDATA[" + "<b>I am > the rules!</b>\n" + "...since I make symbolic puns" + "]]>" + "</xmlElement>"; + TiXmlDocument doc; + doc.Parse( str ); + doc.Print(); + + XmlTest( "CDATA parse. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), + "<b>I am > the rules!</b>\n...since I make symbolic puns", + true ); + +#ifdef TIXML_USE_STL + + doc.Clear(); + + istringstream parse0( str ); + parse0 >> doc; + + XmlTest( "CDATA stream. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), + "<b>I am > the rules!</b>\n...since I make symbolic puns", + true ); +#endif + + TiXmlDocument doc1 = doc; + //doc.Print(); + + XmlTest( "CDATA copy. [ 1480107 ]", doc1.FirstChildElement()->FirstChild()->Value(), + "<b>I am > the rules!</b>\n...since I make symbolic puns", + true ); + } + ////////////////////////////////////////////////////// + // Visit() + + + + ////////////////////////////////////////////////////// + printf( "\n** Fuzzing... **\n" ); + + const int FUZZ_ITERATION = 300; + + // The only goal is not to crash on bad input. + int len = (int) strlen( demoStart ); + for( int i=0; i<FUZZ_ITERATION; ++i ) + { + char* demoCopy = new char[ len+1 ]; + strcpy( demoCopy, demoStart ); + + demoCopy[ i%len ] = (char)((i+1)*3); + demoCopy[ (i*7)%len ] = '>'; + demoCopy[ (i*11)%len ] = '<'; + + TiXmlDocument xml; + xml.Parse( demoCopy ); + + delete [] demoCopy; + } + printf( "** Fuzzing Complete. **\n" ); + + ////////////////////////////////////////////////////// + printf ("\n** Bug regression tests **\n"); + + // InsertBeforeChild and InsertAfterChild causes crash. + { + TiXmlElement parent( "Parent" ); + TiXmlElement childText0( "childText0" ); + TiXmlElement childText1( "childText1" ); + TiXmlNode* childNode0 = parent.InsertEndChild( childText0 ); + TiXmlNode* childNode1 = parent.InsertBeforeChild( childNode0, childText1 ); + + XmlTest( "Test InsertBeforeChild on empty node.", ( childNode1 == parent.FirstChild() ), true ); + } + + { + // InsertBeforeChild and InsertAfterChild causes crash. + TiXmlElement parent( "Parent" ); + TiXmlElement childText0( "childText0" ); + TiXmlElement childText1( "childText1" ); + TiXmlNode* childNode0 = parent.InsertEndChild( childText0 ); + TiXmlNode* childNode1 = parent.InsertAfterChild( childNode0, childText1 ); + + XmlTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent.LastChild() ), true ); + } + + // Reports of missing constructors, irregular string problems. + { + // Missing constructor implementation. No test -- just compiles. + TiXmlText text( "Missing" ); + +#ifdef TIXML_USE_STL + // Missing implementation: + TiXmlDocument doc; + string name = "missing"; + doc.LoadFile( name ); + + TiXmlText textSTL( name ); +#else + // verifying some basic string functions: + TiXmlString a; + TiXmlString b( "Hello" ); + TiXmlString c( "ooga" ); + + c = " World!"; + a = b; + a += c; + a = a; + + XmlTest( "Basic TiXmlString test. ", "Hello World!", a.c_str() ); +#endif + } + + // Long filenames crashing STL version + { + TiXmlDocument doc( "midsummerNightsDreamWithAVeryLongFilenameToConfuseTheStringHandlingRoutines.xml" ); + bool loadOkay = doc.LoadFile(); + loadOkay = true; // get rid of compiler warning. + // Won't pass on non-dev systems. Just a "no crash" check. + //XmlTest( "Long filename. ", true, loadOkay ); + } + + { + // Entities not being written correctly. + // From Lynn Allen + + const char* passages = + "<?xml version=\"1.0\" standalone=\"no\" ?>" + "<passages count=\"006\" formatversion=\"20020620\">" + "<psg context=\"Line 5 has "quotation marks" and 'apostrophe marks'." + " It also has <, >, and &, as well as a fake copyright ©.\"> </psg>" + "</passages>"; + + TiXmlDocument doc( "passages.xml" ); + doc.Parse( passages ); + TiXmlElement* psg = doc.RootElement()->FirstChildElement(); + const char* context = psg->Attribute( "context" ); + const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9."; + + XmlTest( "Entity transformation: read. ", expected, context, true ); + + FILE* textfile = fopen( "textfile.txt", "w" ); + if ( textfile ) + { + psg->Print( textfile, 0 ); + fclose( textfile ); + } + textfile = fopen( "textfile.txt", "r" ); + assert( textfile ); + if ( textfile ) + { + char buf[ 1024 ]; + fgets( buf, 1024, textfile ); + XmlTest( "Entity transformation: write. ", + "<psg context=\'Line 5 has "quotation marks" and 'apostrophe marks'." + " It also has <, >, and &, as well as a fake copyright \xC2\xA9.' />", + buf, + true ); + } + fclose( textfile ); + } + + { + FILE* textfile = fopen( "test5.xml", "w" ); + if ( textfile ) + { fputs("<?xml version='1.0'?><a.elem xmi.version='2.0'/>", textfile); fclose(textfile); - TiXmlDocument doc; + TiXmlDocument doc; doc.LoadFile( "test5.xml" ); XmlTest( "dot in element attributes and names", doc.Error(), 0); - } + } } - { - FILE* textfile = fopen( "test6.xml", "w" ); - if ( textfile ) - { + { + FILE* textfile = fopen( "test6.xml", "w" ); + if ( textfile ) + { fputs("<element><Name>1.1 Start easy ignore fin thickness
</Name></element>", textfile ); fclose(textfile); @@ -990,375 +994,376 @@ int main() bool result = doc.LoadFile( "test6.xml" ); XmlTest( "Entity with one digit.", result, true ); - TiXmlText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText(); - XmlTest( "Entity with one digit.", - text->Value(), "1.1 Start easy ignore fin thickness\n" ); - } + TiXmlText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText(); + XmlTest( "Entity with one digit.", + text->Value(), "1.1 Start easy ignore fin thickness\n" ); + } } - { - // DOCTYPE not preserved (950171) - // - const char* doctype = - "<?xml version=\"1.0\" ?>" - "<!DOCTYPE PLAY SYSTEM 'play.dtd'>" - "<!ELEMENT title (#PCDATA)>" - "<!ELEMENT books (title,authors)>" - "<element />"; - - TiXmlDocument doc; - doc.Parse( doctype ); - doc.SaveFile( "test7.xml" ); - doc.Clear(); - doc.LoadFile( "test7.xml" ); - - TiXmlHandle docH( &doc ); - TiXmlUnknown* unknown = docH.Child( 1 ).Unknown(); - XmlTest( "Correct value of unknown.", "!DOCTYPE PLAY SYSTEM 'play.dtd'", unknown->Value() ); - #ifdef TIXML_USE_STL - TiXmlNode* node = docH.Child( 2 ).Node(); - std::string str; - str << (*node); - XmlTest( "Correct streaming of unknown.", "<!ELEMENT title (#PCDATA)>", str.c_str() ); - #endif - } - - { - // [ 791411 ] Formatting bug - // Comments do not stream out correctly. - const char* doctype = - "<!-- Somewhat<evil> -->"; - TiXmlDocument doc; - doc.Parse( doctype ); - - TiXmlHandle docH( &doc ); - TiXmlComment* comment = docH.Child( 0 ).Node()->ToComment(); - - XmlTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() ); - #ifdef TIXML_USE_STL - std::string str; - str << (*comment); - XmlTest( "Comment streaming.", "<!-- Somewhat<evil> -->", str.c_str() ); - #endif - } - - { - // [ 870502 ] White space issues - TiXmlDocument doc; - TiXmlText* text; - TiXmlHandle docH( &doc ); - - const char* doctype0 = "<element> This has leading and trailing space </element>"; - const char* doctype1 = "<element>This has internal space</element>"; - const char* doctype2 = "<element> This has leading, trailing, and internal space </element>"; - - TiXmlBase::SetCondenseWhiteSpace( false ); - doc.Clear(); - doc.Parse( doctype0 ); - text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); - XmlTest( "White space kept.", " This has leading and trailing space ", text->Value() ); - - doc.Clear(); - doc.Parse( doctype1 ); - text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); - XmlTest( "White space kept.", "This has internal space", text->Value() ); - - doc.Clear(); - doc.Parse( doctype2 ); - text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); - XmlTest( "White space kept.", " This has leading, trailing, and internal space ", text->Value() ); - - TiXmlBase::SetCondenseWhiteSpace( true ); - doc.Clear(); - doc.Parse( doctype0 ); - text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); - XmlTest( "White space condensed.", "This has leading and trailing space", text->Value() ); - - doc.Clear(); - doc.Parse( doctype1 ); - text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); - XmlTest( "White space condensed.", "This has internal space", text->Value() ); - - doc.Clear(); - doc.Parse( doctype2 ); - text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); - XmlTest( "White space condensed.", "This has leading, trailing, and internal space", text->Value() ); - } - - { - // Double attributes - const char* doctype = "<element attr='red' attr='blue' />"; - - TiXmlDocument doc; - doc.Parse( doctype ); - - XmlTest( "Parsing repeated attributes.", true, doc.Error() ); // is an error to tinyxml (didn't use to be, but caused issues) - //XmlTest( "Parsing repeated attributes.", "blue", doc.FirstChildElement( "element" )->Attribute( "attr" ) ); - } - - { - // Embedded null in stream. - const char* doctype = "<element att\0r='red' attr='blue' />"; - - TiXmlDocument doc; - doc.Parse( doctype ); - XmlTest( "Embedded null throws error.", true, doc.Error() ); - - #ifdef TIXML_USE_STL - istringstream strm( doctype ); - doc.Clear(); - doc.ClearError(); - strm >> doc; - XmlTest( "Embedded null throws error.", true, doc.Error() ); - #endif - } + { + // DOCTYPE not preserved (950171) + // + const char* doctype = + "<?xml version=\"1.0\" ?>" + "<!DOCTYPE PLAY SYSTEM 'play.dtd'>" + "<!ELEMENT title (#PCDATA)>" + "<!ELEMENT books (title,authors)>" + "<element />"; + + TiXmlDocument doc; + doc.Parse( doctype ); + doc.SaveFile( "test7.xml" ); + doc.Clear(); + doc.LoadFile( "test7.xml" ); + + TiXmlHandle docH( &doc ); + TiXmlUnknown* unknown = docH.Child( 1 ).Unknown(); + XmlTest( "Correct value of unknown.", "!DOCTYPE PLAY SYSTEM 'play.dtd'", unknown->Value() ); +#ifdef TIXML_USE_STL + TiXmlNode* node = docH.Child( 2 ).Node(); + std::string str; + str << (*node); + XmlTest( "Correct streaming of unknown.", "<!ELEMENT title (#PCDATA)>", str.c_str() ); +#endif + } { - // Legacy mode test. (This test may only pass on a western system) - const char* str = - "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" - "<ä>" - "CöntäntßäöüÄÖÜ" - "</ä>"; + // [ 791411 ] Formatting bug + // Comments do not stream out correctly. + const char* doctype = + "<!-- Somewhat<evil> -->"; + TiXmlDocument doc; + doc.Parse( doctype ); - TiXmlDocument doc; - doc.Parse( str ); - - TiXmlHandle docHandle( &doc ); - TiXmlHandle aHandle = docHandle.FirstChildElement( "ä" ); - TiXmlHandle tHandle = aHandle.Child( 0 ); - assert( aHandle.Element() ); - assert( tHandle.Text() ); - XmlTest( "ISO-8859-1 Parsing.", "CöntäntßäöüÄÖÜ", tHandle.Text()->Value() ); + TiXmlHandle docH( &doc ); + TiXmlComment* comment = docH.Child( 0 ).Node()->ToComment(); + + XmlTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() ); +#ifdef TIXML_USE_STL + std::string str; + str << (*comment); + XmlTest( "Comment streaming.", "<!-- Somewhat<evil> -->", str.c_str() ); +#endif + } + + { + // [ 870502 ] White space issues + TiXmlDocument doc; + TiXmlText* text; + TiXmlHandle docH( &doc ); + + const char* doctype0 = "<element> This has leading and trailing space </element>"; + const char* doctype1 = "<element>This has internal space</element>"; + const char* doctype2 = "<element> This has leading, trailing, and internal space </element>"; + + TiXmlBase::SetCondenseWhiteSpace( false ); + doc.Clear(); + doc.Parse( doctype0 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space kept.", " This has leading and trailing space ", text->Value() ); + + doc.Clear(); + doc.Parse( doctype1 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space kept.", "This has internal space", text->Value() ); + + doc.Clear(); + doc.Parse( doctype2 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space kept.", " This has leading, trailing, and internal space ", text->Value() ); + + TiXmlBase::SetCondenseWhiteSpace( true ); + doc.Clear(); + doc.Parse( doctype0 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space condensed.", "This has leading and trailing space", text->Value() ); + + doc.Clear(); + doc.Parse( doctype1 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space condensed.", "This has internal space", text->Value() ); + + doc.Clear(); + doc.Parse( doctype2 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space condensed.", "This has leading, trailing, and internal space", text->Value() ); + } + + { + // Double attributes + const char* doctype = "<element attr='red' attr='blue' />"; + + TiXmlDocument doc; + doc.Parse( doctype ); + + XmlTest( "Parsing repeated attributes.", true, doc.Error() ); // is an error to tinyxml (didn't use to be, but caused issues) + //XmlTest( "Parsing repeated attributes.", "blue", doc.FirstChildElement( "element" )->Attribute( "attr" ) ); + } + + { + // Embedded null in stream. + const char* doctype = "<element att\0r='red' attr='blue' />"; + + TiXmlDocument doc; + doc.Parse( doctype ); + XmlTest( "Embedded null throws error.", true, doc.Error() ); + +#ifdef TIXML_USE_STL + istringstream strm( doctype ); + doc.Clear(); + doc.ClearError(); + strm >> doc; + XmlTest( "Embedded null throws error.", true, doc.Error() ); +#endif + } + + { + // Legacy mode test. (This test may only pass on a western system) + const char* str = + "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + "<ä>" + "CöntäntßäöüÄÖÜ" + "</ä>"; + + TiXmlDocument doc; + doc.Parse( str ); + + TiXmlHandle docHandle( &doc ); + TiXmlHandle aHandle = docHandle.FirstChildElement( "ä" ); + TiXmlHandle tHandle = aHandle.Child( 0 ); + assert( aHandle.Element() ); + assert( tHandle.Text() ); + XmlTest( "ISO-8859-1 Parsing.", "CöntäntßäöüÄÖÜ", tHandle.Text()->Value() ); + } + + { + // Empty documents should return TIXML_ERROR_PARSING_EMPTY, bug 1070717 + const char* str = " "; + TiXmlDocument doc; + doc.Parse( str ); + XmlTest( "Empty document error TIXML_ERROR_DOCUMENT_EMPTY", TiXmlBase::TIXML_ERROR_DOCUMENT_EMPTY, doc.ErrorId() ); + } +#ifndef TIXML_USE_STL + { + // String equality. [ 1006409 ] string operator==/!= no worky in all cases + TiXmlString temp; + XmlTest( "Empty tinyxml string compare equal", ( temp == "" ), true ); + + TiXmlString foo; + TiXmlString bar( "" ); + XmlTest( "Empty tinyxml string compare equal", ( foo == bar ), true ); + } + +#endif + { + // Bug [ 1195696 ] from marlonism + TiXmlBase::SetCondenseWhiteSpace(false); + TiXmlDocument xml; + xml.Parse("<text><break/>This hangs</text>"); + XmlTest( "Test safe error return.", xml.Error(), false ); + } + + { + // Bug [ 1243992 ] - another infinite loop + TiXmlDocument doc; + doc.SetCondenseWhiteSpace(false); + doc.Parse("<p><pb></pb>test</p>"); + } + { + // Low entities + TiXmlDocument xml; + xml.Parse( "<test></test>" ); + const char result[] = { 0x0e, 0 }; + XmlTest( "Low entities.", xml.FirstChildElement()->GetText(), result ); + xml.Print(); + } + { + // Bug [ 1451649 ] Attribute values with trailing quotes not handled correctly + TiXmlDocument xml; + xml.Parse( "<foo attribute=bar\" />" ); + XmlTest( "Throw error with bad end quotes.", xml.Error(), true ); + } +#ifdef TIXML_USE_STL + { + // Bug [ 1449463 ] Consider generic query + TiXmlDocument xml; + xml.Parse( "<foo bar='3' barStr='a string'/>" ); + + TiXmlElement* ele = xml.FirstChildElement(); + double d; + int i; + float f; + bool b; + std::string str; + + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &d ), TIXML_SUCCESS ); + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &i ), TIXML_SUCCESS ); + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &f ), TIXML_SUCCESS ); + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &b ), TIXML_WRONG_TYPE ); + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "nobar", &b ), TIXML_NO_ATTRIBUTE ); + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "barStr", &str ), TIXML_SUCCESS ); + + XmlTest( "QueryValueAttribute", (d==3.0), true ); + XmlTest( "QueryValueAttribute", (i==3), true ); + XmlTest( "QueryValueAttribute", (f==3.0f), true ); + XmlTest( "QueryValueAttribute", (str==std::string( "a string" )), true ); + } +#endif + +#ifdef TIXML_USE_STL + { + // [ 1505267 ] redundant malloc in TiXmlElement::Attribute + TiXmlDocument xml; + xml.Parse( "<foo bar='3' />" ); + TiXmlElement* ele = xml.FirstChildElement(); + double d; + int i; + + std::string bar = "bar"; + + const std::string* atrrib = ele->Attribute( bar ); + ele->Attribute( bar, &d ); + ele->Attribute( bar, &i ); + + XmlTest( "Attribute", atrrib->empty(), false ); + XmlTest( "Attribute", (d==3.0), true ); + XmlTest( "Attribute", (i==3), true ); + } +#endif + + { + // [ 1356059 ] Allow TiXMLDocument to only be at the top level + TiXmlDocument xml, xml2; + xml.InsertEndChild( xml2 ); + XmlTest( "Document only at top level.", xml.Error(), true ); + XmlTest( "Document only at top level.", xml.ErrorId(), TiXmlBase::TIXML_ERROR_DOCUMENT_TOP_ONLY ); + } + + { + // [ 1663758 ] Failure to report error on bad XML + TiXmlDocument xml; + xml.Parse("<x>"); + XmlTest("Missing end tag at end of input", xml.Error(), true); + xml.Parse("<x> "); + XmlTest("Missing end tag with trailing whitespace", xml.Error(), true); + } + + { + // [ 1635701 ] fail to parse files with a tag separated into two lines + // I'm not sure this is a bug. Marked 'pending' for feedback. + TiXmlDocument xml; + xml.Parse( "<title><p>text</p\n><title>" ); + //xml.Print(); + //XmlTest( "Tag split by newline", xml.Error(), false ); + } + +#ifdef TIXML_USE_STL + { + // [ 1475201 ] TinyXML parses entities in comments + TiXmlDocument xml; + istringstream parse1( "<!-- declarations for <head> & <body> -->" + "<!-- far & away -->" ); + parse1 >> xml; + + TiXmlNode* e0 = xml.FirstChild(); + TiXmlNode* e1 = e0->NextSibling(); + TiXmlComment* c0 = e0->ToComment(); + TiXmlComment* c1 = e1->ToComment(); + + XmlTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true ); + XmlTest( "Comments ignore entities.", " far & away ", c1->Value(), true ); + } +#endif + + { + // [ 1475201 ] TinyXML parses entities in comments + TiXmlDocument xml; + xml.Parse("<!-- declarations for <head> & <body> -->" + "<!-- far & away -->" ); + + TiXmlNode* e0 = xml.FirstChild(); + TiXmlNode* e1 = e0->NextSibling(); + TiXmlComment* c0 = e0->ToComment(); + TiXmlComment* c1 = e1->ToComment(); + + XmlTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true ); + XmlTest( "Comments ignore entities.", " far & away ", c1->Value(), true ); + } + + { + TiXmlDocument xml; + xml.Parse( "<Parent>" + "<child1 att=''/>" + "<!-- With this comment, child2 will not be parsed! -->" + "<child2 att=''/>" + "</Parent>" ); + int count = 0; + + TiXmlNode* ele = 0; + while ( (ele = xml.FirstChildElement( "Parent" )->IterateChildren( ele ) ) != 0 ) + { + ++count; + } + XmlTest( "Comments iterate correctly.", 3, count ); + } + + { + // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well. + unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl"; + buf[60] = 239; + buf[61] = 0; + + TiXmlDocument doc; + doc.Parse( (const char*)buf); + } + + + { + // bug 1827248 Error while parsing a little bit malformed file + // Actually not malformed - should work. + TiXmlDocument xml; + xml.Parse( "<attributelist> </attributelist >" ); + XmlTest( "Handle end tag whitespace", false, xml.Error() ); + } + + { + // 1709904 - can not repro the crash + { + TiXmlDocument xml; + xml.Parse( "<tag>/</tag>" ); + XmlTest( "Odd XML parsing.", xml.FirstChild()->Value(), "tag" ); + } + /* Could not repro. { + TiXmlDocument xml; + xml.LoadFile( "EQUI_Inventory.xml" ); + //XmlTest( "Odd XML parsing.", xml.FirstChildElement()->Value(), "XML" ); + TiXmlPrinter printer; + xml.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + }*/ } - { - // Empty documents should return TIXML_ERROR_PARSING_EMPTY, bug 1070717 - const char* str = " "; - TiXmlDocument doc; - doc.Parse( str ); - XmlTest( "Empty document error TIXML_ERROR_DOCUMENT_EMPTY", TiXmlBase::TIXML_ERROR_DOCUMENT_EMPTY, doc.ErrorId() ); - } - #ifndef TIXML_USE_STL - { - // String equality. [ 1006409 ] string operator==/!= no worky in all cases - TiXmlString temp; - XmlTest( "Empty tinyxml string compare equal", ( temp == "" ), true ); - - TiXmlString foo; - TiXmlString bar( "" ); - XmlTest( "Empty tinyxml string compare equal", ( foo == bar ), true ); - } - - #endif - { - // Bug [ 1195696 ] from marlonism - TiXmlBase::SetCondenseWhiteSpace(false); - TiXmlDocument xml; - xml.Parse("<text><break/>This hangs</text>"); - XmlTest( "Test safe error return.", xml.Error(), false ); - } - - { - // Bug [ 1243992 ] - another infinite loop - TiXmlDocument doc; - doc.SetCondenseWhiteSpace(false); - doc.Parse("<p><pb></pb>test</p>"); - } - { - // Low entities - TiXmlDocument xml; - xml.Parse( "<test></test>" ); - const char result[] = { 0x0e, 0 }; - XmlTest( "Low entities.", xml.FirstChildElement()->GetText(), result ); - xml.Print(); - } - { - // Bug [ 1451649 ] Attribute values with trailing quotes not handled correctly - TiXmlDocument xml; - xml.Parse( "<foo attribute=bar\" />" ); - XmlTest( "Throw error with bad end quotes.", xml.Error(), true ); - } - #ifdef TIXML_USE_STL - { - // Bug [ 1449463 ] Consider generic query - TiXmlDocument xml; - xml.Parse( "<foo bar='3' barStr='a string'/>" ); - - TiXmlElement* ele = xml.FirstChildElement(); - double d; - int i; - float f; - bool b; - std::string str; - - XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &d ), TIXML_SUCCESS ); - XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &i ), TIXML_SUCCESS ); - XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &f ), TIXML_SUCCESS ); - XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &b ), TIXML_WRONG_TYPE ); - XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "nobar", &b ), TIXML_NO_ATTRIBUTE ); - XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "barStr", &str ), TIXML_SUCCESS ); - - XmlTest( "QueryValueAttribute", (d==3.0), true ); - XmlTest( "QueryValueAttribute", (i==3), true ); - XmlTest( "QueryValueAttribute", (f==3.0f), true ); - XmlTest( "QueryValueAttribute", (str==std::string( "a string" )), true ); - } - #endif - - #ifdef TIXML_USE_STL - { - // [ 1505267 ] redundant malloc in TiXmlElement::Attribute - TiXmlDocument xml; - xml.Parse( "<foo bar='3' />" ); - TiXmlElement* ele = xml.FirstChildElement(); - double d; - int i; - - std::string bar = "bar"; - - const std::string* atrrib = ele->Attribute( bar ); - ele->Attribute( bar, &d ); - ele->Attribute( bar, &i ); - - XmlTest( "Attribute", atrrib->empty(), false ); - XmlTest( "Attribute", (d==3.0), true ); - XmlTest( "Attribute", (i==3), true ); - } - #endif - - { - // [ 1356059 ] Allow TiXMLDocument to only be at the top level - TiXmlDocument xml, xml2; - xml.InsertEndChild( xml2 ); - XmlTest( "Document only at top level.", xml.Error(), true ); - XmlTest( "Document only at top level.", xml.ErrorId(), TiXmlBase::TIXML_ERROR_DOCUMENT_TOP_ONLY ); - } - - { - // [ 1663758 ] Failure to report error on bad XML - TiXmlDocument xml; - xml.Parse("<x>"); - XmlTest("Missing end tag at end of input", xml.Error(), true); - xml.Parse("<x> "); - XmlTest("Missing end tag with trailing whitespace", xml.Error(), true); - } - - { - // [ 1635701 ] fail to parse files with a tag separated into two lines - // I'm not sure this is a bug. Marked 'pending' for feedback. - TiXmlDocument xml; - xml.Parse( "<title><p>text</p\n><title>" ); - //xml.Print(); - //XmlTest( "Tag split by newline", xml.Error(), false ); - } - - #ifdef TIXML_USE_STL - { - // [ 1475201 ] TinyXML parses entities in comments - TiXmlDocument xml; - istringstream parse1( "<!-- declarations for <head> & <body> -->" - "<!-- far & away -->" ); - parse1 >> xml; - - TiXmlNode* e0 = xml.FirstChild(); - TiXmlNode* e1 = e0->NextSibling(); - TiXmlComment* c0 = e0->ToComment(); - TiXmlComment* c1 = e1->ToComment(); - - XmlTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true ); - XmlTest( "Comments ignore entities.", " far & away ", c1->Value(), true ); - } - #endif - - { - // [ 1475201 ] TinyXML parses entities in comments - TiXmlDocument xml; - xml.Parse("<!-- declarations for <head> & <body> -->" - "<!-- far & away -->" ); - - TiXmlNode* e0 = xml.FirstChild(); - TiXmlNode* e1 = e0->NextSibling(); - TiXmlComment* c0 = e0->ToComment(); - TiXmlComment* c1 = e1->ToComment(); - - XmlTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true ); - XmlTest( "Comments ignore entities.", " far & away ", c1->Value(), true ); - } - - { - TiXmlDocument xml; - xml.Parse( "<Parent>" - "<child1 att=''/>" - "<!-- With this comment, child2 will not be parsed! -->" - "<child2 att=''/>" - "</Parent>" ); - int count = 0; - - TiXmlNode* ele = 0; - while ( (ele = xml.FirstChildElement( "Parent" )->IterateChildren( ele ) ) != 0 ) { - ++count; - } - XmlTest( "Comments iterate correctly.", 3, count ); - } - - { - // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well. - unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl"; - buf[60] = 239; - buf[61] = 0; - - TiXmlDocument doc; - doc.Parse( (const char*)buf); - } - - - { - // bug 1827248 Error while parsing a little bit malformed file - // Actually not malformed - should work. - TiXmlDocument xml; - xml.Parse( "<attributelist> </attributelist >" ); - XmlTest( "Handle end tag whitespace", false, xml.Error() ); - } - - { - // 1709904 - can not repro the crash - { - TiXmlDocument xml; - xml.Parse( "<tag>/</tag>" ); - XmlTest( "Odd XML parsing.", xml.FirstChild()->Value(), "tag" ); - } - /* Could not repro. { - TiXmlDocument xml; - xml.LoadFile( "EQUI_Inventory.xml" ); - //XmlTest( "Odd XML parsing.", xml.FirstChildElement()->Value(), "XML" ); - TiXmlPrinter printer; - xml.Accept( &printer ); - fprintf( stdout, "%s", printer.CStr() ); - }*/ - } - - /* 1417717 experiment - { - TiXmlDocument xml; - xml.Parse("<text>Dan & Tracie</text>"); - xml.Print(stdout); - } - { - TiXmlDocument xml; - xml.Parse("<text>Dan &foo; Tracie</text>"); - xml.Print(stdout); - } - */ - #if defined( WIN32 ) && defined( TUNE ) - _CrtMemCheckpoint( &endMemState ); - //_CrtMemDumpStatistics( &endMemState ); - - _CrtMemState diffMemState; - _CrtMemDifference( &diffMemState, &startMemState, &endMemState ); - _CrtMemDumpStatistics( &diffMemState ); - #endif - - printf ("\nPass %d, Fail %d\n", gPass, gFail); - return gFail; + /* 1417717 experiment + { + TiXmlDocument xml; + xml.Parse("<text>Dan & Tracie</text>"); + xml.Print(stdout); + } + { + TiXmlDocument xml; + xml.Parse("<text>Dan &foo; Tracie</text>"); + xml.Print(stdout); + } + */ +#if defined( WIN32 ) && defined( TUNE ) + _CrtMemCheckpoint( &endMemState ); + //_CrtMemDumpStatistics( &endMemState ); + + _CrtMemState diffMemState; + _CrtMemDifference( &diffMemState, &startMemState, &endMemState ); + _CrtMemDumpStatistics( &diffMemState ); +#endif + + printf ("\nPass %d, Fail %d\n", gPass, gFail); + return gFail; } |