diff --git a/tinyxml2.cpp b/tinyxml2.cpp index 2241fd2..22cf5cb 100644 --- a/tinyxml2.cpp +++ b/tinyxml2.cpp @@ -37,6 +37,85 @@ static const Entity entities[NUM_ENTITIES] = }; +StrPair::~StrPair() +{ + Reset(); +} + + +void StrPair::Reset() +{ + if ( flags & NEEDS_DELETE ) { + delete [] start; + } + flags = 0; + start = 0; + end = 0; +} + + +void StrPair::SetStr( const char* str, int flags ) +{ + Reset(); + size_t len = strlen( str ); + start = new char[ len+1 ]; + strncpy( start, str, len ); + end = start + len; + this->flags = flags | NEEDS_DELETE; +} + + +char* StrPair::ParseText( char* p, const char* endTag, int strFlags ) +{ + TIXMLASSERT( endTag && *endTag ); + + char* start = p; // fixme: hides a member + char endChar = *endTag; + int length = strlen( endTag ); + + // Inner loop of text parsing. + while ( *p ) { + if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) { + Set( start, p, strFlags ); + return p + length; + } + ++p; + } + return p; +} + + +char* StrPair::ParseName( char* p ) +{ + char* start = p; + + start = p; + if ( !start || !(*start) ) { + return 0; + } + + if ( !XMLUtil::IsAlpha( *p ) ) { + return 0; + } + + while( *p && ( + XMLUtil::IsAlphaNum( (unsigned char) *p ) + || *p == '_' + || *p == '-' + || *p == '.' + || *p == ':' )) + { + ++p; + } + + if ( p > start ) { + Set( start, p, 0 ); + return p; + } + return 0; +} + + const char* StrPair::GetStr() { if ( flags & NEEDS_FLUSH ) { @@ -96,91 +175,15 @@ const char* StrPair::GetStr() } *q = 0; } - flags = 0; + flags = (flags & NEEDS_DELETE); } return start; } -/* -const char* StringPool::Intern( const char* str ) -{ - // Treat the array as a linear, inplace hash table. - // Nothing can get deleted, so that's handy. - if ( size > pool.Size()*3/4 ) { - DynArray< const char*, 20 > store; - for( int i=0; i start ) { - Set( start, p, 0 ); - return p; - } - return 0; -} - - char* XMLDocument::Identify( char* p, XMLNode** node ) { XMLNode* returnNode = 0; @@ -290,6 +293,15 @@ XMLNode::~XMLNode() } +void XMLNode::SetValue( const char* str, bool staticMem ) +{ + if ( staticMem ) + value.SetInternedStr( str ); + else + value.SetStr( str ); +} + + void XMLNode::ClearChildren() { while( firstChild ) { @@ -557,16 +569,16 @@ char* XMLAttribute::ParseDeep( char* p ) int XMLAttribute::QueryIntAttribute( int* value ) const { - if ( TIXML_SSCANF( Value(), "%d", value ) == 1 ) - return ATTRIBUTE_SUCCESS; + if ( TIXML_SSCANF( Value(), "%d", value ) == 1 ) + return ATTRIBUTE_SUCCESS; return WRONG_ATTRIBUTE_TYPE; } int XMLAttribute::QueryUnsignedAttribute( unsigned int* value ) const { - if ( TIXML_SSCANF( Value(), "%u", value ) == 1 ) - return ATTRIBUTE_SUCCESS; + if ( TIXML_SSCANF( Value(), "%u", value ) == 1 ) + return ATTRIBUTE_SUCCESS; return WRONG_ATTRIBUTE_TYPE; } @@ -582,43 +594,71 @@ int XMLAttribute::QueryBoolAttribute( bool* value ) const } else if ( ival == 0 || XMLUtil::StringEqual( Value(), "false" ) ) { *value = false; - return ATTRIBUTE_SUCCESS; - } + return ATTRIBUTE_SUCCESS; + } return WRONG_ATTRIBUTE_TYPE; } int XMLAttribute::QueryDoubleAttribute( double* value ) const { - if ( TIXML_SSCANF( Value(), "%lf", value ) == 1 ) - return ATTRIBUTE_SUCCESS; + if ( TIXML_SSCANF( Value(), "%lf", value ) == 1 ) + return ATTRIBUTE_SUCCESS; return WRONG_ATTRIBUTE_TYPE; } int XMLAttribute::QueryFloatAttribute( float* value ) const { - if ( TIXML_SSCANF( Value(), "%f", value ) == 1 ) - return ATTRIBUTE_SUCCESS; + if ( TIXML_SSCANF( Value(), "%f", value ) == 1 ) + return ATTRIBUTE_SUCCESS; return WRONG_ATTRIBUTE_TYPE; } void XMLAttribute::SetAttribute( const char* v ) { - value.SetInternedStr( v ); + value.SetStr( v ); } -/* void XMLAttribute::SetAttribute( int v ) { char buf[BUF_SIZE]; - TIXML_SNPRINTF( buf, BUF_SIZE-1, "%d" ); - - value.SetInternedStr( v ); + TIXML_SNPRINTF( buf, BUF_SIZE-1, "%d", v ); + value.SetStr( buf ); } -*/ + + +void XMLAttribute::SetAttribute( unsigned v ) +{ + char buf[BUF_SIZE]; + TIXML_SNPRINTF( buf, BUF_SIZE-1, "%u", v ); + value.SetStr( buf ); +} + + +void XMLAttribute::SetAttribute( bool v ) +{ + char buf[BUF_SIZE]; + TIXML_SNPRINTF( buf, BUF_SIZE-1, "%d", v ? 1 : 0 ); + value.SetStr( buf ); +} + +void XMLAttribute::SetAttribute( double v ) +{ + char buf[BUF_SIZE]; + TIXML_SNPRINTF( buf, BUF_SIZE-1, "%f", v ); + value.SetStr( buf ); +} + +void XMLAttribute::SetAttribute( float v ) +{ + char buf[BUF_SIZE]; + TIXML_SNPRINTF( buf, BUF_SIZE-1, "%f", v ); + value.SetStr( buf ); +} + // --------- XMLElement ---------- // XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), @@ -640,6 +680,39 @@ XMLElement::~XMLElement() } +XMLAttribute* XMLElement::FindAttribute( const char* name ) +{ + XMLAttribute* a = 0; + for( a=rootAttribute; a; a = a->next ) { + if ( XMLUtil::StringEqual( a->Name(), name ) ) + return a; + } + return 0; +} + + +const XMLAttribute* XMLElement::FindAttribute( const char* name ) const +{ + XMLAttribute* a = 0; + for( a=rootAttribute; a; a = a->next ) { + if ( XMLUtil::StringEqual( a->Name(), name ) ) + return a; + } + return 0; +} + + +XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name ) +{ + XMLAttribute* attrib = FindAttribute( name ); + if ( !attrib ) { + attrib = new (document->attributePool.Alloc() ) XMLAttribute( this ); + attrib->memPool = &document->attributePool; + } + return attrib; +} + + char* XMLElement::ParseAttributes( char* p, bool* closedElement ) { const char* start = p; diff --git a/tinyxml2.h b/tinyxml2.h index 0cf859b..67e6d2d 100644 --- a/tinyxml2.h +++ b/tinyxml2.h @@ -49,29 +49,29 @@ #endif -// Deprecated library function hell. Compilers want to use the -// new safe versions. This probably doesn't fully address the problem, -// but it gets closer. There are too many compilers for me to fully -// test. If you get compilation troubles, undefine TIXML_SAFE - -#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 +// Deprecated library function hell. Compilers want to use the +// new safe versions. This probably doesn't fully address the problem, +// but it gets closer. There are too many compilers for me to fully +// test. If you get compilation troubles, undefine TIXML_SAFE + +#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 namespace tinyxml2 @@ -101,20 +101,28 @@ public: }; StrPair() : flags( 0 ), start( 0 ), end( 0 ) {} + ~StrPair(); + void Set( char* start, char* end, int flags ) { + Reset(); this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH; } const char* GetStr(); bool Empty() const { return start == end; } - void SetInternedStr( const char* str ) { this->start = (char*) str; this->end = 0; this->flags = 0; } + void SetInternedStr( const char* str ) { Reset(); this->start = (char*) str; } + void SetStr( const char* str, int flags=0 ); + char* ParseText( char* in, const char* endTag, int strFlags ); char* ParseName( char* in ); private: + void Reset(); + enum { - NEEDS_FLUSH = 0x100 + NEEDS_FLUSH = 0x100, + NEEDS_DELETE = 0x200 }; // After parsing, if *end != 0, it can be set to zero. @@ -363,7 +371,7 @@ public: virtual const XMLUnknown* ToUnknown() const { return 0; } const char* Value() const { return value.GetStr(); } - void SetValue( const char* val ) { value.SetInternedStr( val ); } + void SetValue( const char* val, bool staticMem=false ); const XMLNode* Parent() const { return parent; } XMLNode* Parent() { return parent; } @@ -548,16 +556,14 @@ public: int QueryFloatAttribute( float* value ) const; void SetAttribute( const char* value ); - - // NOTE: other sets aren't supported...need to deal with memory model? - /* void SetAttribute( int value ); void SetAttribute( unsigned value ); void SetAttribute( bool value ); void SetAttribute( double value ); - */ + void SetAttribute( float value ); private: + enum { BUF_SIZE = 200 }; XMLAttribute( XMLElement* element ) : next( 0 ) {} virtual ~XMLAttribute() {} XMLAttribute( const XMLAttribute& ); // not supported @@ -578,29 +584,30 @@ class XMLElement : public XMLNode friend class XMLDocument; public: const char* Name() const { return Value(); } - void SetName( const char* str ) { SetValue( str ); } + void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); } virtual XMLElement* ToElement() { return this; } virtual const XMLElement* ToElement() const { return this; } virtual bool Accept( XMLVisitor* visitor ) const; - const char* Attribute( const char* name ) const; + const char* Attribute( const char* name ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return 0; return a->Value(); } - int QueryIntAttribute( const char* name, int* value ) const; - int QueryUnsignedAttribute( const char* name, unsigned int* value ) const; - int QueryBoolAttribute( const char* name, bool* value ) const; - int QueryDoubleAttribute( const char* name, double* _value ) const; - int QueryFloatAttribute( const char* name, float* _value ) const; + int QueryIntAttribute( const char* name, int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryIntAttribute( value ); } + int QueryUnsignedAttribute( const char* name, unsigned int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryUnsignedAttribute( value ); } + int QueryBoolAttribute( const char* name, bool* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryBoolAttribute( value ); } + int QueryDoubleAttribute( const char* name, double* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryDoubleAttribute( value ); } + int QueryFloatAttribute( const char* name, float* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryFloatAttribute( value ); } - void SetAttribute( const char* name, const char* value ); - void SetAttribute( const char* name, int value ); - void SetAttribute( const char* name, unsigned value ); - void SetAttribute( const char* name, bool value ); - void SetAttribute( const char* name, double value ); + void SetAttribute( const char* name, const char* value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); } + void SetAttribute( const char* name, int value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); } + void SetAttribute( const char* name, unsigned value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); } + void SetAttribute( const char* name, bool value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); } + void SetAttribute( const char* name, double value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); } void RemoveAttribute( const char* name ); const XMLAttribute* FirstAttribute() const { return rootAttribute; } + const XMLAttribute* FindAttribute( const char* name ) const; const char* GetText() const; @@ -614,6 +621,8 @@ private: XMLElement( const XMLElement& ); // not supported void operator=( const XMLElement& ); // not supported + XMLAttribute* FindAttribute( const char* name ); + XMLAttribute* FindOrCreateAttribute( const char* name ); char* ParseAttributes( char* p, bool *closedElement ); bool closing;