Slowly moving to C++

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