Răsfoiți Sursa

added attribute handling. StrPair can now new/delete memory.

Lee Thomason 14 ani în urmă
părinte
comite
1a1d4a72dd
2 a modificat fișierele cu 216 adăugiri și 134 ștergeri
  1. 165 92
      tinyxml2.cpp
  2. 51 42
      tinyxml2.h

+ 165 - 92
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<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 @@ 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" );
+	TIXML_SNPRINTF( buf, BUF_SIZE-1, "%d", v );	
+	value.SetStr( buf );
+}
+
 
-	value.SetInternedStr( v );
+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;

+ 51 - 42
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;