merging handles to the master

This commit is contained in:
Lee Thomason (grinliz) 2012-04-07 20:56:38 -07:00
commit 8712757389
4 changed files with 165 additions and 5 deletions

2
dox
View File

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

View File

@ -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: Examples are in the "related pages" tab of the HTML docs.
http://grinninglizard.com/tinyxml2docs/pages.html
<h2> What it does. </h2> <h2> What it does. </h2>

View File

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

View File

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