|
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