[libxml++] Moved create_wrapper() and free_wrappers() to Node.
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libxml++] Moved create_wrapper() and free_wrappers() to Node.
- Date: Sun, 14 Nov 2010 15:44:48 +0000 (UTC)
commit 95243eee9837ab6843a20fa43a6a1ef41d1fcd62
Author: Murray Cumming <murrayc murrayc com>
Date: Sun Nov 14 16:44:36 2010 +0100
Moved create_wrapper() and free_wrappers() to Node.
* libxml++/document.[h|cc]:
* libxml++/nodes/node.[h|cc]: Moved create_wrapper() and free_wrappers()
to here from Document.
free_wrappers(): Never return inside the switch/case, so we check
xmlNode::properties for all struct types, and to avoid making the behaviour
non-obvious.
* libxml++/parsers/textreader.cc:
* libxml++/validators/dtdvalidator.cc:
* libxml++/nodes/element.cc: Adapted.
ChangeLog | 31 ++++++++
libxml++/document.cc | 118 +-----------------------------
libxml++/document.h | 4 -
libxml++/nodes/element.cc | 20 +++---
libxml++/nodes/node.cc | 136 ++++++++++++++++++++++++++++++++---
libxml++/nodes/node.h | 16 ++++
libxml++/parsers/textreader.cc | 6 +-
libxml++/validators/dtdvalidator.cc | 6 +-
8 files changed, 191 insertions(+), 146 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index fb88441..bd1e424 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,34 @@
+2010-11-14 Murray Cumming <murrayc murrayc com>
+
+ Moved create_wrapper() and free_wrappers() to Node.
+
+ * libxml++/document.[h|cc]:
+ * libxml++/nodes/node.[h|cc]: Moved create_wrapper() and free_wrappers()
+ to here from Document.
+ free_wrappers(): Never return inside the switch/case, so we check
+ xmlNode::properties for all struct types, and to avoid making the behaviour
+ non-obvious.
+ * libxml++/parsers/textreader.cc:
+ * libxml++/validators/dtdvalidator.cc:
+ * libxml++/nodes/element.cc: Adapted.
+
+2010-11-08 Alessandro Pignotti <a pignotti sssup it>
+
+ Make libxml++ compatible with separate and multi-threaded libxml2 usage.
+
+ * libxml++/document.[h|cc]: Added create_wrapper() and free_wrappers(),
+ replacing on_libxml_construct() and on_libxml_destruct() .
+ Init(): Do not register these global callbacks with libxml.
+ * libxml++/nodes/element.cc:
+ * libxml++/nodes/node.[h|cc]:
+ * libxml++/parsers/textreader.cc:
+ * libxml++/validators/dtdvalidator.cc: Call these create_wrapper() before
+ ever trying to get a C++ instance from a C instance. Call free_wrappers()
+ in destructors and other places where we want the instance to be destroyed.
+
+ This avoids use of libxml's global function pointers, which are not
+ thread-safe.
+
2010-11-08 Murray Cumming <murrayc murrayc com>
Do not call xmlCleanupParser() because it is brutal.
diff --git a/libxml++/document.cc b/libxml++/document.cc
index 2056d3e..df159fb 100644
--- a/libxml++/document.cc
+++ b/libxml++/document.cc
@@ -11,95 +11,17 @@
#include <libxml++/dtd.h>
#include <libxml++/attribute.h>
#include <libxml++/nodes/element.h>
-#include <libxml++/nodes/entityreference.h>
-#include <libxml++/nodes/textnode.h>
-#include <libxml++/nodes/commentnode.h>
-#include <libxml++/nodes/cdatanode.h>
-#include <libxml++/nodes/processinginstructionnode.h>
#include <libxml++/exceptions/internal_error.h>
#include <libxml++/keepblanks.h>
#include <libxml++/io/ostreamoutputbuffer.h>
#include <libxml/tree.h>
-#include <assert.h>
-
#include <iostream>
namespace xmlpp
{
-void Document::create_wrapper(xmlNode* node)
-{
- if(node->_private)
- {
- //Node already wrapped, skip
- return;
- }
-
- switch (node->type)
- {
- case XML_ELEMENT_NODE:
- {
- node->_private = new xmlpp::Element(node);
- break;
- }
- case XML_ATTRIBUTE_NODE:
- {
- node->_private = new xmlpp::Attribute(node);
- break;
- }
- case XML_TEXT_NODE:
- {
- node->_private = new xmlpp::TextNode(node);
- break;
- }
- case XML_COMMENT_NODE:
- {
- node->_private = new xmlpp::CommentNode(node);
- break;
- }
- case XML_CDATA_SECTION_NODE:
- {
- node->_private = new xmlpp::CdataNode(node);
- break;
- }
- case XML_PI_NODE:
- {
- node->_private = new xmlpp::ProcessingInstructionNode(node);
- break;
- }
- case XML_DTD_NODE:
- {
- node->_private = new xmlpp::Dtd(reinterpret_cast<xmlDtd*>(node));
- break;
- }
- //case XML_ENTITY_NODE:
- //{
- // assert(0 && "Warning: XML_ENTITY_NODE not implemented");
- // //node->_private = new xmlpp::ProcessingInstructionNode(node);
- // break;
- //}
- case XML_ENTITY_REF_NODE:
- {
- node->_private = new xmlpp::EntityReference(node);
- break;
- }
- case XML_DOCUMENT_NODE:
- {
- // do nothing ! in case of documents it's the wrapper that is the owner
- break;
- }
- default:
- {
- // good default for release versions
- node->_private = new xmlpp::Node(node);
- assert(0 && "Warning: new node of unknown type created");
- break;
- }
- }
-}
-
Document::Init::Init()
{
xmlInitParser(); //Not always necessary, but necessary for thread safety.
@@ -135,44 +57,10 @@ Document::Document(xmlDoc* doc)
Document::~Document()
{
- free_wrappers(reinterpret_cast<xmlNode*>(impl_));
+ Node::free_wrappers(reinterpret_cast<xmlNode*>(impl_));
xmlFreeDoc(impl_);
}
-void Document::free_wrappers(xmlNode* node)
-{
- //Walk the children list
- for(xmlNode* child=node->children; child; child=child->next)
- free_wrappers(child);
-
- //Delete the local one
- switch(node->type)
- {
- //Node types that have no properties
- case XML_DTD_NODE:
- delete static_cast<Dtd*>(node->_private);
- node->_private=0;
- return;
- case XML_ATTRIBUTE_NODE:
- case XML_ELEMENT_DECL:
- case XML_ATTRIBUTE_DECL:
- case XML_ENTITY_DECL:
- delete static_cast<Node*>(node->_private);
- node->_private=0;
- return;
- case XML_DOCUMENT_NODE:
- //Do not free now, the ownernship is reversed
- return;
- default:
- delete static_cast<Node*>(node->_private);
- node->_private=0;
- }
-
- //Walk the attributes list
- for(xmlAttr* attr=node->properties; attr; attr=attr->next)
- free_wrappers(reinterpret_cast<xmlNode*>(attr));
-}
-
Glib::ustring Document::get_encoding() const
{
Glib::ustring encoding;
@@ -214,7 +102,7 @@ Element* Document::get_root_node() const
return 0;
else
{
- create_wrapper(root);
+ Node::create_wrapper(root);
return reinterpret_cast<Element*>(root->_private);
}
}
@@ -270,7 +158,7 @@ CommentNode* Document::add_comment(const Glib::ustring& content)
// Use the result, because node can be freed when merging text nodes:
node = xmlAddChild( (xmlNode*)impl_, node);
- create_wrapper(node);
+ Node::create_wrapper(node);
return static_cast<CommentNode*>(node->_private);
}
diff --git a/libxml++/document.h b/libxml++/document.h
index 0ed9e7b..c30068c 100644
--- a/libxml++/document.h
+++ b/libxml++/document.h
@@ -170,10 +170,6 @@ public:
///Access the underlying libxml implementation.
const _xmlDoc* cobj() const;
- ///Construct the right C++ instances for a given element
- static void create_wrapper(_xmlNode* node);
- ///Recursively destroy the created C++ instances
- static void free_wrappers(_xmlNode* attr);
protected:
/** Retrieve an Entity.
* The entity can be from an external subset or internally declared.
diff --git a/libxml++/nodes/element.cc b/libxml++/nodes/element.cc
index e275e71..1b9cf96 100644
--- a/libxml++/nodes/element.cc
+++ b/libxml++/nodes/element.cc
@@ -26,7 +26,7 @@ Element::AttributeList Element::get_attributes()
AttributeList attributes;
for(xmlAttr* attr = cobj()->properties; attr; attr = attr->next)
{
- Document::create_wrapper(reinterpret_cast<xmlNode*>(attr));
+ Node::create_wrapper(reinterpret_cast<xmlNode*>(attr));
attributes.push_back(reinterpret_cast<Attribute*>(attr->_private));
}
@@ -46,7 +46,7 @@ Attribute* Element::get_attribute(const Glib::ustring& name,
xmlAttr* attr = xmlHasProp(const_cast<xmlNode*>(cobj()), (const xmlChar*)name.c_str());
if( attr )
{
- Document::create_wrapper(reinterpret_cast<xmlNode*>(attr));
+ Node::create_wrapper(reinterpret_cast<xmlNode*>(attr));
return reinterpret_cast<Attribute*>(attr->_private);
}
}
@@ -57,7 +57,7 @@ Attribute* Element::get_attribute(const Glib::ustring& name,
(const xmlChar*)ns_uri.c_str());
if( attr )
{
- Document::create_wrapper(reinterpret_cast<xmlNode*>(attr));
+ Node::create_wrapper(reinterpret_cast<xmlNode*>(attr));
return reinterpret_cast<Attribute*>(attr->_private);
}
}
@@ -100,7 +100,7 @@ Attribute* Element::set_attribute(const Glib::ustring& name, const Glib::ustring
if(attr)
{
- Document::create_wrapper(reinterpret_cast<xmlNode*>(attr));
+ Node::create_wrapper(reinterpret_cast<xmlNode*>(attr));
return reinterpret_cast<Attribute*>(attr->_private);
}
else
@@ -125,7 +125,7 @@ const TextNode* Element::get_child_text() const
for(xmlNode* child = cobj()->children; child; child = child->next)
if(child->type == XML_TEXT_NODE)
{
- Document::create_wrapper(child);
+ Node::create_wrapper(child);
return static_cast<TextNode*>(child->_private);
}
@@ -139,7 +139,7 @@ TextNode* Element::get_child_text()
for(xmlNode* child = cobj()->children; child; child = child->next)
if(child->type == XML_TEXT_NODE)
{
- Document::create_wrapper(child);
+ Node::create_wrapper(child);
return static_cast<TextNode*>(child->_private);
}
@@ -164,7 +164,7 @@ TextNode* Element::add_child_text(const Glib::ustring& content)
// Use the result, because node can be freed when merging text nodes:
node = xmlAddChild(cobj(), node);
- Document::create_wrapper(node);
+ Node::create_wrapper(node);
return static_cast<TextNode*>(node->_private);
}
return 0;
@@ -182,7 +182,7 @@ TextNode* Element::add_child_text(xmlpp::Node* previous_sibling, const Glib::ust
// Use the result, because node can be freed when merging text nodes:
node = xmlAddNextSibling(previous_sibling->cobj(), node);
- Document::create_wrapper(node);
+ Node::create_wrapper(node);
return static_cast<TextNode*>(node->_private);
}
return 0;
@@ -200,7 +200,7 @@ TextNode* Element::add_child_text_before(xmlpp::Node* next_sibling, const Glib::
// Use the result, because node can be freed when merging text nodes:
node = xmlAddPrevSibling(next_sibling->cobj(), node);
- Document::create_wrapper(node);
+ Node::create_wrapper(node);
return static_cast<TextNode*>(node->_private);
}
return 0;
@@ -242,7 +242,7 @@ CommentNode* Element::add_child_comment(const Glib::ustring& content)
// Use the result, because node can be freed when merging text nodes:
node = xmlAddChild(cobj(), node);
- Document::create_wrapper(node);
+ Node::create_wrapper(node);
return static_cast<CommentNode*>(node->_private);
}
diff --git a/libxml++/nodes/node.cc b/libxml++/nodes/node.cc
index e9ba6dc..ab22bbf 100644
--- a/libxml++/nodes/node.cc
+++ b/libxml++/nodes/node.cc
@@ -6,6 +6,11 @@
#include <libxml++/nodes/element.h>
#include <libxml++/nodes/node.h>
+#include <libxml++/nodes/entityreference.h>
+#include <libxml++/nodes/textnode.h>
+#include <libxml++/nodes/commentnode.h>
+#include <libxml++/nodes/cdatanode.h>
+#include <libxml++/nodes/processinginstructionnode.h>
#include <libxml++/exceptions/internal_error.h>
#include <libxml++/document.h>
#include <libxml/xpath.h>
@@ -36,7 +41,7 @@ Element* Node::get_parent()
if(!(cobj()->parent && cobj()->parent->type == XML_ELEMENT_NODE))
return 0;
- Document::create_wrapper(cobj()->parent);
+ Node::create_wrapper(cobj()->parent);
return static_cast<Element*>(cobj()->parent->_private);
}
@@ -50,7 +55,7 @@ Node* Node::get_next_sibling()
if(!cobj()->next)
return 0;
- Document::create_wrapper(cobj()->next);
+ Node::create_wrapper(cobj()->next);
return static_cast<Node*>(cobj()->next->_private);
}
@@ -64,7 +69,7 @@ Node* Node::get_previous_sibling()
if(!cobj()->prev)
return 0;
- Document::create_wrapper(cobj()->prev);
+ Node::create_wrapper(cobj()->prev);
return static_cast<Node*>(cobj()->prev->_private);
}
@@ -79,7 +84,7 @@ Node::NodeList Node::get_children(const Glib::ustring& name)
{
if(name.empty() || name == (const char*)child->name)
{
- Document::create_wrapper(child);
+ Node::create_wrapper(child);
children.push_back(reinterpret_cast<Node*>(child->_private));
}
}
@@ -104,7 +109,7 @@ Element* Node::add_child(const Glib::ustring& name,
if(!node)
return 0;
- Document::create_wrapper(node);
+ Node::create_wrapper(node);
return static_cast<Element*>(node->_private);
}
@@ -123,7 +128,7 @@ Element* Node::add_child(xmlpp::Node* previous_sibling,
if(!node)
return 0;
- Document::create_wrapper(node);
+ Node::create_wrapper(node);
return static_cast<Element*>(node->_private);
}
@@ -142,7 +147,7 @@ Element* Node::add_child_before(xmlpp::Node* next_sibling,
if(!node)
return 0;
- Document::create_wrapper(node);
+ Node::create_wrapper(node);
return static_cast<Element*>(node->_private);
}
@@ -182,7 +187,7 @@ void Node::remove_child(Node* node)
{
//TODO: Allow a node to be removed without deleting it, to allow it to be moved?
//This would require a more complex memory management API.
- Document::free_wrappers(node->cobj());
+ Node::free_wrappers(node->cobj());
xmlUnlinkNode(node->cobj());
xmlFreeNode(node->cobj()); //The C++ instance will be deleted in a callback.
}
@@ -204,7 +209,7 @@ Node* Node::import_node(const Node* node, bool recursive)
xmlNode* added_node = xmlAddChild(this->cobj(),imported_node);
if (!added_node)
{
- Document::free_wrappers(imported_node);
+ Node::free_wrappers(imported_node);
xmlFreeNode(imported_node);
#ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
@@ -214,7 +219,7 @@ Node* Node::import_node(const Node* node, bool recursive)
#endif //LIBXMLCPP_EXCEPTIONS_ENABLED
}
- Document::create_wrapper(imported_node);
+ Node::create_wrapper(imported_node);
return static_cast<Node*>(imported_node->_private);
}
@@ -298,7 +303,7 @@ static NodeSet find_impl(xmlXPathContext* ctxt, const Glib::ustring& xpath)
//TODO: Check for other cnode->type values?
- Document::create_wrapper(cnode);
+ Node::create_wrapper(cnode);
Node* cppNode = static_cast<Node*>(cnode->_private);
nodes.push_back(cppNode);
}
@@ -392,5 +397,114 @@ void Node::set_namespace(const Glib::ustring& ns_prefix)
}
}
+void Node::create_wrapper(xmlNode* node)
+{
+ if(node->_private)
+ {
+ //Node already wrapped, skip
+ return;
+ }
+
+ switch (node->type)
+ {
+ case XML_ELEMENT_NODE:
+ {
+ node->_private = new xmlpp::Element(node);
+ break;
+ }
+ case XML_ATTRIBUTE_NODE:
+ {
+ node->_private = new xmlpp::Attribute(node);
+ break;
+ }
+ case XML_TEXT_NODE:
+ {
+ node->_private = new xmlpp::TextNode(node);
+ break;
+ }
+ case XML_COMMENT_NODE:
+ {
+ node->_private = new xmlpp::CommentNode(node);
+ break;
+ }
+ case XML_CDATA_SECTION_NODE:
+ {
+ node->_private = new xmlpp::CdataNode(node);
+ break;
+ }
+ case XML_PI_NODE:
+ {
+ node->_private = new xmlpp::ProcessingInstructionNode(node);
+ break;
+ }
+ case XML_DTD_NODE:
+ {
+ node->_private = new xmlpp::Dtd(reinterpret_cast<xmlDtd*>(node));
+ break;
+ }
+ //case XML_ENTITY_NODE:
+ //{
+ // assert(0 && "Warning: XML_ENTITY_NODE not implemented");
+ // //node->_private = new xmlpp::ProcessingInstructionNode(node);
+ // break;
+ //}
+ case XML_ENTITY_REF_NODE:
+ {
+ node->_private = new xmlpp::EntityReference(node);
+ break;
+ }
+ case XML_DOCUMENT_NODE:
+ {
+ // do nothing. For Documents it's the wrapper that is the owner.
+ break;
+ }
+ default:
+ {
+ // good default for release versions
+ node->_private = new xmlpp::Node(node);
+ std::cerr << G_STRFUNC << "Warning: new node of unknown type created: " << node->type << std::endl;
+ break;
+ }
+ }
+}
+
+void Node::free_wrappers(xmlNode* node)
+{
+ if(!node)
+ return;
+
+ //Walk the children list
+ for(xmlNode* child=node->children; child; child=child->next)
+ free_wrappers(child);
+
+ //Delete the local one
+ switch(node->type)
+ {
+ //Node types that have no properties
+ case XML_DTD_NODE:
+ delete static_cast<Dtd*>(node->_private);
+ node->_private = 0;
+ break;
+ case XML_ATTRIBUTE_NODE:
+ case XML_ELEMENT_DECL:
+ case XML_ATTRIBUTE_DECL:
+ case XML_ENTITY_DECL:
+ delete static_cast<Node*>(node->_private);
+ node->_private = 0;
+ break;
+ case XML_DOCUMENT_NODE:
+ //Do not free now. The Document is usually the one who owns the caller.
+ break;
+ default:
+ delete static_cast<Node*>(node->_private);
+ node->_private = 0;
+ break;
+ }
+
+ //Walk the attributes list
+ for(xmlAttr* attr = node->properties; attr; attr = attr->next)
+ free_wrappers(reinterpret_cast<xmlNode*>(attr));
+}
+
} //namespace xmlpp
diff --git a/libxml++/nodes/node.h b/libxml++/nodes/node.h
index 088da4e..35dd97d 100644
--- a/libxml++/nodes/node.h
+++ b/libxml++/nodes/node.h
@@ -179,6 +179,22 @@ public:
///Access the underlying libxml implementation.
const _xmlNode* cobj() const;
+ /** Construct the correct C++ instance for a given libxml C struct instance.
+ *
+ * This is only for use by the libxml++ implementation.
+ *
+ * @para node A pointer to an xmlNode or a "derived" struct, such as xmlDoc, xmlAttr, etc.
+ */
+ static void create_wrapper(_xmlNode* node);
+
+ /** Delete the C++ instance for a given libxml C struct instance, and also
+ * recursively destroy the C++ instances for any children.
+ *
+ * This is only for use by the libxml++ implementation.
+ * @para node A pointer to an xmlNode or a "derived" struct, such as xmlDoc, xmlAttr, etc.
+ */
+ static void free_wrappers(_xmlNode* attr);
+
protected:
///Create the C instance ready to be added to the parent node.
diff --git a/libxml++/parsers/textreader.cc b/libxml++/parsers/textreader.cc
index 8770771..c196d57 100644
--- a/libxml++/parsers/textreader.cc
+++ b/libxml++/parsers/textreader.cc
@@ -300,7 +300,7 @@ Node* TextReader::get_current_node()
xmlNodePtr node = xmlTextReaderCurrentNode(impl_);
if(node)
{
- Document::create_wrapper(node);
+ Node::create_wrapper(node);
return static_cast<Node*>(node->_private);
}
@@ -313,7 +313,7 @@ const Node* TextReader::get_current_node() const
xmlNodePtr node = xmlTextReaderCurrentNode(impl_);
if(node)
{
- Document::create_wrapper(node);
+ Node::create_wrapper(node);
return static_cast<Node*>(node->_private);
}
@@ -337,7 +337,7 @@ Node* TextReader::expand()
if(node)
if(node)
{
- Document::create_wrapper(node);
+ Node::create_wrapper(node);
return static_cast<Node*>(node->_private);
}
diff --git a/libxml++/validators/dtdvalidator.cc b/libxml++/validators/dtdvalidator.cc
index 9d9420a..5517720 100644
--- a/libxml++/validators/dtdvalidator.cc
+++ b/libxml++/validators/dtdvalidator.cc
@@ -68,7 +68,7 @@ void DtdValidator::parse_subset(const Glib::ustring& external,const Glib::ustrin
#endif //LIBXMLCPP_EXCEPTIONS_ENABLED
}
- Document::create_wrapper(reinterpret_cast<xmlNode*>(dtd));
+ Node::create_wrapper(reinterpret_cast<xmlNode*>(dtd));
dtd_ = static_cast<Dtd*>(dtd->_private);
}
@@ -97,7 +97,7 @@ void DtdValidator::parse_stream(std::istream& in)
#endif //LIBXMLCPP_EXCEPTIONS_ENABLED
}
- Document::create_wrapper(reinterpret_cast<xmlNode*>(dtd));
+ Node::create_wrapper(reinterpret_cast<xmlNode*>(dtd));
dtd_ = static_cast<Dtd*>(dtd->_private);
}
@@ -108,7 +108,7 @@ void DtdValidator::release_underlying()
//Make a local copy as the wrapper is destroyed first
//After free_wrappers is called dtd_ will be invalid (e.g. delete dtd_)
xmlDtd* dtd=dtd_->cobj();
- Document::free_wrappers(reinterpret_cast<xmlNode*>(dtd));
+ Node::free_wrappers(reinterpret_cast<xmlNode*>(dtd));
xmlFreeDtd(dtd);
dtd_ = 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]