Boost logo

Boost :

From: Hamish Mackenzie (hamish_at_[hidden])
Date: 2003-06-12 18:14:46


On Thu, 2003-06-12 at 22:12, Stefan Seefeld wrote:
> I'm wrapping libxml2. The structs provided by libxml2 all carry a
> '_private' member, precisely because it's a good way for extensions
> such as language wrapping.
> libxml2 itself calls callbacks whenever it allocates instances of these
> structs, and I allocate my C++ wrappers in these callbacks, and let the
> _private member point to it.
> 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++.

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.

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

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_;
};

> > Here are some suggestions...
> >
> > 1) parse_file could be
> >
> > class parse_file
> > {
> > public:
> > parse_file( const std::string & ) : {}
> > ...
> > };
>
> 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.

> > 2) How about parse_string (based on xmlParseMemory)?
>
> hmm, while that would be possible, I think it's more C++'ish to
> provide document extraction from a std::streambuf, which could be
> a string_buf or any other buffer implementation. (Note that I wouldn't
> use std::iostreams as that would suggest that formatted extraction is
> possible, which would only work on ascii, not on unicode content.

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.

How about this for reading an input stream...

xml::dom::document doc( parse_stream( std::cin.rdbuf() ) );

and if you want to write to to the parser (for instance if the data is
coming from a series of asynchronous read operations).

class document
{
public:
  std::streambuf & parser();
};

xml::dom::document doc;
doc.parser().write( buffer, buffer_size );

> > 4) How about something like
> >
> > class basic_document
> > {
> > public:
> > ...
> >
> > typedef node_iterator iterator;
> > typedef const_node_iterator const_iterator;
> >
> > iterator begin()
> > { return iterator( ptr_->children ); }
> > const_iterator begin() const
> > { return const_iterator( ptr_->children ); }
> > iterator end() { return iterator(); }
> > const_iterator end() const { return const_iterator(); }
> >
> > iterator root()
> > { return iterator( xmlDocGetRootElement( ptr_ ) ); }
> > const_iterator root() const
> > { return const_iterator( xmlDocGetRootElement( ptr_ ) ); }
> > };
>
> I don't understand: are you suggesting an iterator that traverses
> the whole tree (as opposed the children of a single node) ?

No just the children. If figure node.begin() and node.end() be fore
iteration over the child nodes.

-- 
Hamish Mackenzie <hamish_at_[hidden]>



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