Boost logo

Boost :

From: Stefan Seefeld (seefeld_at_[hidden])
Date: 2003-06-13 08:11:08


Hamish Mackenzie wrote:

>>That way I'v got a pointer from the C struct to the C++ wrapper
>>(_private), as well as a pointer from the C++ wrapper to the C struct
>>(my_impl).
>
>
> Would a thin proxy object not be a better way to go? More in keeping
> with the "you don't pay for what you don't use" philosophy of C++.

Hmm, I see your point. Well, that would be possible, but that way you
are unable to make nodes polymorphic. Neither with respect to the basic
node types (Element, Attribute, Text, CData, etc.) nor later when
implementing real DOM support on top of it.

> I have attached the wrappers I have written. They do not cover much of
> libxml2 (just what I needed at the time). Feel free to borrow as much
> or as little from it as you like.

yeah, looks interesting, and even more thin than my wrapper. However,
the thinner the wrapper gets the greater is indeed the danger of having
the whole design tied to a particular implementation, as William pointed
out earlier. I don't think that this is a problem with my wrapper lib,
but with your implementation you get dangerously close...:-)

> If you look in node_iterator.h you can see that it uses a proxy
> containing just a pointer to the libxml2 node.

indeed.

> Looking up this node's parent node is thus simply
>
>>static_cast<Node *>(this->my_impl->parent->_private);
>
>
> If there was a parent lookup in node_proxy it would be
>
> class node_proxy
> {
> public:
> node_proxy parent() { return node_proxy( node_->parent ); }
> ...
> private:
> xmlNodePtr node_;
> };

yes, and you could even make that an 'element_proxy' as you know that
parent nodes are always elements. However, with a flat set of (libxml2)
nodes that wouldn't work any more, so runtime polymorphism would be
lost. Well, may be there is no need for it either. I have to think over
that...

>>making 'parse_file' a class suggests it is carrying some data/state.
>>What would that be ? I'm thinking of 'parse_file' as a stateless
>>factory, i.e. a function returning a newly created document.
>
>
> Sorry I should have included the ... bit
>
> class parse_file
> {
> public:
> parse_file( const std::string & f ) : file_name_ {}
> private:
> const std::string & file_name_;
>
> template< ... >
> friend class ::boost::xml::dom::document;
> };
>
> Put that together with the constructor...
>
> template<...>
> class basic_document
> {
> public:
> basic_document( const parse_file & f )
> {
> // does what parse_file function does now
> }
> };
>
> And you can write code that goes
>
> xml::dom::document doc( xml::dom::parse_file( "a.xml" ) );
>
> No auto_ptr needed. It's not in my wrappers as I only thought of it
> while I was reading through yours.

well, but you could also make it such that

xml::dom::document doc = xml::dom::parse_file("a.xml");

works with parse_file being a function. That would mean the document is
copied, but then following your philosophy xml::dom::document could be
a proxy, too, so copying could be cheap...

I really don't like the idea of 'parse_file' being an object (whichs
state being a potentially already parsed document). It's unintuive.

> parse_stream would indeed be even better. As I recall there are
> functions in libxml2 that allow you to write to the parser as well.

erm, that's even more confusing, I think. A parser should remain
just a parser, i.e. something that extracts tokens from an input stream.

Best regards,
                Stefan


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk