diff --git a/src/libxml/utility.h b/src/libxml/utility.h index d4f887e5..09f749ac 100644 --- a/src/libxml/utility.h +++ b/src/libxml/utility.h @@ -48,6 +48,27 @@ namespace xml namespace impl { +// Helper for holding libxml objects with guaranteed freeing +template +class xml_scoped_ptr +{ +public: + explicit xml_scoped_ptr(TPtr ptr) : ptr_(ptr) {} + + ~xml_scoped_ptr() + { + if (ptr_) + FreeFunc(ptr_); + } + + TPtr operator->() const { return ptr_; } + TPtr get() const { return ptr_; } + operator TPtr() const { return ptr_; } + +private: + TPtr ptr_; +}; + // exception safe wrapper around xmlChar*s that are returned from some // of the libxml functions that the user must free. class xmlchar_helper diff --git a/src/libxml/xpath.cxx b/src/libxml/xpath.cxx index 7f10a3dc..c60e87b1 100644 --- a/src/libxml/xpath.cxx +++ b/src/libxml/xpath.cxx @@ -69,8 +69,6 @@ class nodeset_next_functor : public impl::iter_advance_functor for ( size_t i = 0; i < length-1; i++ ) m_next[table[i]] = table[i+1]; - - xmlXPathFreeObject(pathobj); } virtual xmlNodePtr operator()(xmlNodePtr node) const @@ -104,20 +102,16 @@ struct xpath_context_impl template NodesView evaluate(const std::string& expr, node& n) { - // TODO: use auto ptr for this - xmlXPathObjectPtr nsptr = + xml_scoped_ptr nsptr( xmlXPathNodeEval(reinterpret_cast(n.get_node_data()), - ctxt_); xml_string(expr), + ctxt_)); if ( !nsptr ) return NodesView(); if ( xmlXPathNodeSetIsEmpty(nsptr->nodesetval) ) - { - xmlXPathFreeObject(nsptr); return NodesView(); - } return NodesView(nsptr->nodesetval->nodeTab[0], new nodeset_next_functor(nsptr));