- From: Martin J. Duerst <duerst@w3.org>
- Date: Thu, 08 Apr 1999 18:07:45 +0900
- To: www-lib@w3.org
Dear libwww programmers/users, I'm studying libwww for various purposes. One thing that makes this difficult to me is that although there are many objects, most of them are written in C and not C++. So I came up with a few ideas. Please tell me whether they make sense or not. One example I'm particularly interested in are streams. Of course, it would be possible to convert everything from C to C++ at once, but that might introduce changes and problems that we don't yet understand. So I had another idea: Introduce a new HTCStream (C stands for class), and make it behave like a HTStream, but be a C++ class. I include the code I have up to now below (not compiled yet, may have a few syntax bugs,...). Here is how it is supposed to work: - If an old stream calls an old stream, it works as always. - If an old stream calls a new stream, it doesn't know that it's a new stream. But it works because the new stream is made to also look like an old stream, with the "isa" field. HTCStream here takes care of all subclasses and forwards calls to the appropriate methods. - If a new stream calls a new stream, it just calls the appropriate method, and will do so even once all old streams are gone. - If a new stream calls an old stream, it does as if it called a new stream. This works because when the object is constructed with an old stream as a target, that old stream is wrapped in a subclass of HTCStream, called HTOldStream, that does the appropriate conversion. Although this may look a bit complicated at the moment, the subclasses derived from HTCStream will be quite a bit easier to write than at the moment. The main problem that isn't addressed here is that it's not really advisable in C++ for an object to delete itself, and that therefore deletion has to be done at the place where the object is constructed. What do you think? Is this a direction that is worth pursuing? Any proposals for improvements? Regards, Martin. // HTCStream.h class HTCStream { private: const HTStreamClass * isa; // this has to be first; we rely on // C and C++ having the same layout! protected: HTCStream * target; HTCStream (HTStream * target); // for old stream targets HTCStream (HTCStream * target); public: virtual int flush() = 0; // is there a default for this? virtual int free() = 0; // is there a default for this? virtual int abort(HTList * e); virtual int put_character(char c); virtual int put_string(const char * s); virtual int put_block(const char * s, int l) = 0; //is there a default for this? } // HTCStream.cpp PRIVATE HTStreamClass HTCStreamClass = { "HTCStreamClass", // we need something better than this in the long run HTCStream_flush, HTCStream_free, HTCStream_abort, HTCStream_put_character, HTCStream_put_string, HTCStream_put_block }; // // Constructors // HTCStream::HTCStream (HTStream * t) // for old streams { isa = &HTCStreamClass; target = HTOldStream(t); } HTCStream::HTCStream (HTCStream * t) // for new streams { isa = &HTCStreamClass; target = t; } // // Old functions for new classes // // we know that we have a CStream, so we cast // PRIVATE int HTCStream_flush (HTStream *me) { ((HTCStream*)me)->flush(); } PRIVATE int HTCStream_free (HTStream *me) { ((HTCStream*)me)->free(); } PRIVATE int HTCStream_abort (HTStream *me, HTList * e) { ((HTCStream*)me)->abort(e); } PRIVATE int HTCStream_put_character (HTStream *me, char c) { ((HTCStream*)me)->put_character(c); } PRIVATE int HTCStream_put_string (HTStream * me, const char * s) { ((HTCStream*)me)->put_string(s); } PRIVATE int HTCStream_put_block (HTStream * me, const char * s, int l) { ((HTCStream*)me)->put_block(s, l); } // // the actual new methods // int HTCStream::abort(HTList * e) { if (target) target->abort(e); // HT_FREE(me); // allocation model changes! Can we do a delete here? return HT_ERROR; } int HTCStream::put_character(char c) { put_block (c, 1); // default implementation } int HTCStream::put_string(const char * s) { put_block (s, (int) strlen(s)); } -------------- // HTOldStream.h class HTOldStream : public HTCStream { private: HTStream * old; // for old stream targets public: HTCStream (HTStream * target); int flush(); int free(); int abort(HTList * e); int put_character(char c); int put_string(const char * s); int put_block(const char * s, int l); } // // Constructors // HTOldStream::HTOldStream (HTStream * t) // for old streams : HTCStream (NULL) { old = t; } // // methods // int HTOldStream::flush() { (*(old->isa->flush))(old->target); } int HTOldStream::free() { (*(old->isa->_free))(old->target); } int HTOldStream::abort(HTList * e) { (*(old->isa->abort))(old->target, e); } int HTOldStream::put_character(char c) { (*(old->isa->put_character))(old->target, c); } int HTOldStream::put_string(const char * s) { (*(old->isa->put_string))(old->target, s); } int HTOldStream::put_block(const char * s, int l); { (*(old->isa->put_block))(old->target, s, l); } #-#-# Martin J. Du"rst, World Wide Web Consortium #-#-# mailto:duerst@w3.org http://www.w3.org
Received on Thursday, 8 April 1999 08:18:44 UTC