Explorar el Código

merging handles to the master

Lee Thomason (grinliz) hace 14 años
padre
commit
8712757389
Se han modificado 4 ficheros con 165 adiciones y 5 borrados
  1. 1 1
      dox
  2. 1 2
      readme.txt
  3. 135 2
      tinyxml2.h
  4. 28 0
      xmltest.cpp

+ 1 - 1
dox

@@ -32,7 +32,7 @@ PROJECT_NAME           = "TinyXML-2"
 # This could be handy for archiving the generated documentation or
 # This could be handy for archiving the generated documentation or
 # if some version control system is used.
 # if some version control system is used.
 
 
-PROJECT_NUMBER = 0.9.3
+PROJECT_NUMBER = 0.9.4
 
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer
 # for a project that appears at the top of each page and should give viewer

+ 1 - 2
readme.txt

@@ -11,8 +11,7 @@ github.com/leethomason/tinyxml2
 The online HTML version of these docs:
 The online HTML version of these docs:
 http://grinninglizard.com/tinyxml2docs/index.html
 http://grinninglizard.com/tinyxml2docs/index.html
 
 
-Where examples are in the "related pages" tab:
-http://grinninglizard.com/tinyxml2docs/pages.html
+Examples are in the "related pages" tab of the HTML docs.
 
 
 <h2> What it does. </h2>
 <h2> What it does. </h2>
 	
 	

+ 135 - 2
tinyxml2.h

@@ -97,7 +97,7 @@ distribution.
 
 
 static const int TIXML2_MAJOR_VERSION = 0;
 static const int TIXML2_MAJOR_VERSION = 0;
 static const int TIXML2_MINOR_VERSION = 9;
 static const int TIXML2_MINOR_VERSION = 9;
-static const int TIXML2_PATCH_VERSION = 3;
+static const int TIXML2_PATCH_VERSION = 4;
 
 
 namespace tinyxml2
 namespace tinyxml2
 {
 {
@@ -407,7 +407,7 @@ public:
 	XML Document Object Model (DOM), except XMLAttributes.
 	XML Document Object Model (DOM), except XMLAttributes.
 	Nodes have siblings, a parent, and children which can
 	Nodes have siblings, a parent, and children which can
 	be navigated. A node is always in a XMLDocument.
 	be navigated. A node is always in a XMLDocument.
-	The type of a TiXmlNode can be queried, and it can 
+	The type of a XMLNode can be queried, and it can 
 	be cast to its more defined type.
 	be cast to its more defined type.
 
 
 	An XMLDocument allocates memory for all its Nodes.
 	An XMLDocument allocates memory for all its Nodes.
@@ -1132,6 +1132,139 @@ private:
 };
 };
 
 
 
 
+/**
+	A XMLHandle is a class that wraps a node pointer with null checks; this is
+	an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
+	DOM structure. It is a separate utility class.
+
+	Take an example:
+	@verbatim
+	<Document>
+		<Element attributeA = "valueA">
+			<Child attributeB = "value1" />
+			<Child attributeB = "value2" />
+		</Element>
+	<Document>
+	@endverbatim
+
+	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
+	XMLElement* root = document.FirstChildElement( "Document" );
+	if ( root )
+	{
+		XMLElement* element = root->FirstChildElement( "Element" );
+		if ( element )
+		{
+			XMLElement* child = element->FirstChildElement( "Child" );
+			if ( child )
+			{
+				XMLElement* child2 = child->NextSiblingElement( "Child" );
+				if ( child2 )
+				{
+					// Finally do something useful.
+	@endverbatim
+
+	And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
+	of such code. A XMLHandle checks for null pointers so it is perfectly safe 
+	and correct to use:
+
+	@verbatim
+	XMLHandle docHandle( &document );
+	XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
+	if ( child2 )
+	{
+		// do something useful
+	@endverbatim
+
+	Which is MUCH more concise and useful.
+
+	It is also safe to copy handles - internally they are nothing more than node pointers.
+	@verbatim
+	XMLHandle handleCopy = handle;
+	@endverbatim
+
+	See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
+*/
+class XMLHandle
+{
+public:
+	/// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
+	XMLHandle( XMLNode* _node )												{ node = _node; }
+	/// Create a handle from a node.
+	XMLHandle( XMLNode& _node )												{ node = &_node; }
+	/// Copy constructor
+	XMLHandle( const XMLHandle& ref )										{ node = ref.node; }
+	/// Assignment
+	XMLHandle operator=( const XMLHandle& ref )								{ node = ref.node; return *this; }
+
+	/// Get the first child of this handle.
+	XMLHandle FirstChild() 													{ return XMLHandle( node ? node->FirstChild() : 0 ); }
+	/// Get the first child element of this handle.
+	XMLHandle FirstChildElement( const char* value=0 )						{ return XMLHandle( node ? node->FirstChildElement( value ) : 0 ); }
+	/// Get the last child of this handle.
+	XMLHandle LastChild()													{ return XMLHandle( node ? node->LastChild() : 0 ); }
+	/// Get the last child element of this handle.
+	XMLHandle LastChildElement( const char* _value=0 )						{ return XMLHandle( node ? node->LastChildElement( _value ) : 0 ); }
+	/// Get the previous sibling of this handle.
+	XMLHandle PreviousSibling()												{ return XMLHandle( node ? node->PreviousSibling() : 0 ); }
+	/// Get the previous sibling element of this handle.
+	XMLHandle PreviousSiblingElement( const char* _value=0 )				{ return XMLHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
+	/// Get the next sibling of this handle.
+	XMLHandle NextSibling()													{ return XMLHandle( node ? node->NextSibling() : 0 ); }		
+	/// Get the next sibling element of this handle.
+	XMLHandle NextSiblingElement( const char* _value=0 )					{ return XMLHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
+
+	/// Safe cast to XMLNode. This can return null.
+	XMLNode* ToNode()							{ return node; } 
+	/// Safe cast to XMLElement. This can return null.
+	XMLElement* ToElement() 					{ return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
+	/// Safe cast to XMLText. This can return null.
+	XMLText* ToText() 							{ return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
+	/// Safe cast to XMLUnknown. This can return null.
+	XMLUnknown* ToUnknown() 					{ return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
+	/// Safe cast to XMLDeclaration. This can return null.
+	XMLDeclaration* ToDeclaration() 			{ return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
+
+private:
+	XMLNode* node;
+};
+
+
+/**
+	A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
+	same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
+*/
+class XMLConstHandle
+{
+public:
+	XMLConstHandle( const XMLNode* _node )											{ node = _node; }
+	XMLConstHandle( const XMLNode& _node )											{ node = &_node; }
+	XMLConstHandle( const XMLConstHandle& ref )										{ node = ref.node; }
+
+	XMLConstHandle operator=( const XMLConstHandle& ref )							{ node = ref.node; return *this; }
+
+	const XMLConstHandle FirstChild() const											{ return XMLConstHandle( node ? node->FirstChild() : 0 ); }
+	const XMLConstHandle FirstChildElement( const char* value=0 ) const				{ return XMLConstHandle( node ? node->FirstChildElement( value ) : 0 ); }
+	const XMLConstHandle LastChild()	const										{ return XMLConstHandle( node ? node->LastChild() : 0 ); }
+	const XMLConstHandle LastChildElement( const char* _value=0 ) const				{ return XMLConstHandle( node ? node->LastChildElement( _value ) : 0 ); }
+	const XMLConstHandle PreviousSibling() const									{ return XMLConstHandle( node ? node->PreviousSibling() : 0 ); }
+	const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const		{ return XMLConstHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
+	const XMLConstHandle NextSibling() const										{ return XMLConstHandle( node ? node->NextSibling() : 0 ); }
+	const XMLConstHandle NextSiblingElement( const char* _value=0 ) const			{ return XMLConstHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
+
+
+	const XMLNode* ToNode() const				{ return node; } 
+	const XMLElement* ToElement() const			{ return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
+	const XMLText* ToText() const				{ return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
+	const XMLUnknown* ToUnknown() const			{ return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
+	const XMLDeclaration* ToDeclaration() const	{ return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
+
+private:
+	const XMLNode* node;
+};
+
 
 
 /**
 /**
 	Printing functionality. The XMLPrinter gives you more
 	Printing functionality. The XMLPrinter gives you more

+ 28 - 0
xmltest.cpp

@@ -761,6 +761,34 @@ int main( int /*argc*/, const char ** /*argv*/ )
 		XMLTest( "Error in snprinf handling.", true, doc.Error() );
 		XMLTest( "Error in snprinf handling.", true, doc.Error() );
 	}
 	}
 
 
+	// -------- Handles ------------
+	{
+		static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
+		XMLDocument doc;
+		doc.Parse( xml );
+
+		XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
+		XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
+
+		XMLHandle docH( doc );
+		ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
+		XMLTest( "Handle, dne, mutable", 0, (int)ele );
+	}
+	
+	{
+		static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
+		XMLDocument doc;
+		doc.Parse( xml );
+		XMLConstHandle docH( doc );
+
+		const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
+		XMLTest( "Handle, success, const", ele->Value(), "sub" );
+
+		ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
+		XMLTest( "Handle, dne, const", 0, (int)ele );
+	}
+
+	
 	// ----------- Performance tracking --------------
 	// ----------- Performance tracking --------------
 	{
 	{
 #if defined( _MSC_VER )
 #if defined( _MSC_VER )