added attribute handling. StrPair can now new/delete memory.
diff --git a/tinyxml2.cpp b/tinyxml2.cpp
index 2241fd2..22cf5cb 100644
--- a/tinyxml2.cpp
+++ b/tinyxml2.cpp
@@ -37,6 +37,85 @@
 };

 

 

+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 @@
 			}

 			*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<pool.Size(); ++i ) {

-			if ( pool[i] != 0 ) {

-				store.Push( pool[i] );

-			}

-		}

-		int newSize = pool.Size() * 2;

-		pool.PopArr( pool.Size() );

-

-		const char** mem = pool.PushArr( newSize );

-		memset( (void*)mem, 0, sizeof(char)*newSize );

-

-		while ( !store.Empty() ) {

-			Intern( store.Pop() );

-		}

-	}

-

-}

-*/

 

 

 // --------- XMLUtil ----------- //

 

-char* StrPair::ParseText( char* p, const char* endTag, int strFlags )

-{

-	TIXMLASSERT( endTag && *endTag );

-

-	char* start = p;

-	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;

-}

-

-

 char* XMLDocument::Identify( char* p, XMLNode** node ) 

 {

 	XMLNode* returnNode = 0;

@@ -290,6 +293,15 @@
 }

 

 

+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 @@
 

 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 @@
 	}

 	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 @@
 }

 

 

+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 @@
 	};

 

 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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;