Annotation of libwww/Library/src/HTBufWrt.c, revision 2.2

2.1       frystyk     1: /*
                      2: **     BUFFERED TRANSPORT WRITER STREAM
                      3: **
                      4: **     (c) COPYRIGHT MIT 1995.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
2.2     ! eric        6: **     @(#) $Id: HTBufWrt.c,v 2.1 1996/04/14 01:22:58 frystyk Exp $
2.1       frystyk     7: **
                      8: **     A buffered output stream. This stream lets you write characters to a
                      9: **     stream without causing a write every time.  The data is first written
                     10: **     into a buffer. Data is written to the actual stream only when the
                     11: **     buffer is full, or when the stream is flushed.
                     12: */
                     13: 
                     14: /* Library include files */
                     15: #include "sysdep.h"
                     16: #include "WWWUtil.h"
                     17: #include "WWWCore.h"
                     18: #include "HTNetMan.h"
                     19: #include "HTWriter.h"
                     20: #include "HTBufWrt.h"                                   /* Implemented here */
                     21: 
                     22: struct _HTStream {
                     23:     const HTStreamClass *      isa;
                     24:     /* ... */
                     25: };
                     26: 
                     27: struct _HTOutputStream {
                     28:     const HTOutputStreamClass *        isa;
                     29:     HTOutputStream *           target;          /* Target for outgoing data */
                     30:     HTChannel *                        ch;
                     31:     HTNet *                    net;
                     32:     int                                size;                         /* Buffer size */
                     33:     char *                     block;
                     34:     char *                     read;                  /* Position in 'data' */
                     35:     char *                     data;                              /* buffer */
                     36: };
                     37: 
                     38: #define PUTBLOCK(b,l) (*me->target->isa->put_block)(me->target,(b),(l))
                     39: 
                     40: /* ------------------------------------------------------------------------- */
                     41: 
                     42: PRIVATE int HTBufferWriter_flush (HTOutputStream * me)
                     43: {
                     44:     int status = HT_OK;
                     45:     if (me->read > me->data) {
                     46:        if ((status = PUTBLOCK(me->data, me->read - me->data))==HT_WOULD_BLOCK)
                     47:            return HT_WOULD_BLOCK;
                     48:        me->read = me->data;
                     49:        me->block = NULL;
                     50:     }
                     51:     return status;
                     52: }
                     53: 
                     54: PRIVATE int HTBufferWriter_free (HTOutputStream * me)
                     55: {
                     56:     return HTBufferWriter_flush(me);
                     57: }
                     58: 
                     59: PRIVATE int HTBufferWriter_abort (HTOutputStream * me, HTList * e)
                     60: {
                     61:     if (me->target) (*me->target->isa->abort)(me->target, e);
                     62:     if (PROT_TRACE) HTTrace("Buffer...... ABORTING...\n");
                     63:     return HT_ERROR;
                     64: }
                     65: 
                     66: PRIVATE int HTBufferWriter_write (HTOutputStream *me, const char *buf, int len)
                     67: {
                     68:     int available = me->data + me->size - me->read;
                     69:     int status;
                     70: 
                     71:     /* Still room in buffer */
                     72:     if (len <= available) {
                     73:        memcpy(me->read, buf, len);
                     74:        me->read += len;
                     75:        return HT_OK;
                     76:     }
                     77: 
                     78:     /* If already data in buffer then fill it and flush */
                     79:     if (me->read > me->data) {
                     80:        memcpy(me->read, buf, available);
                     81:        me->block = (char *) buf+available;
                     82:     }
                     83:     if ((status = PUTBLOCK(me->data, me->size)) != HT_OK) return status;
                     84: 
                     85:     /* If more data then write n times buffer size */
                     86:     if (!me->block)
                     87:        me->block = (char *) buf;
                     88:     else
                     89:        len -= (me->block - buf);
                     90:     {
                     91:        int bb = len - len%me->size;
                     92:        if ((status = PUTBLOCK(me->block, bb)) != HT_OK) return status;
                     93:        me->block += bb;
                     94:        len -= bb;
                     95:     }
                     96: 
                     97:     /* If data is not aligned then save the rest in our buffer */
                     98:     if (len > 0) {
                     99:        memcpy(me->data, me->block, len);
                    100:        me->read = me->data + len;
                    101:     } else
                    102:        me->read = me->data;
                    103:     me->block = NULL;
                    104:     return HT_OK;
                    105: }
                    106: 
                    107: /*     Character handling
                    108: **     ------------------
                    109: */
                    110: PRIVATE int HTBufferWriter_put_character (HTOutputStream * me, char c)
                    111: {
                    112:     return HTBufferWriter_write(me, &c, 1);
                    113: }
                    114: 
                    115: /*     String handling
                    116: **     ---------------
                    117: **
                    118: **     Strings must be smaller than this buffer size.
                    119: */
                    120: PRIVATE int HTBufferWriter_put_string (HTOutputStream * me, const char * s)
                    121: {
                    122:     return HTBufferWriter_write(me, s, (int) strlen(s));
                    123: }
                    124: /*
                    125: **     The difference between the close and the free method is that we don't
                    126: **     close the connection in the free method - we only call the free method
                    127: **     of the target stream. That way, we can keep the output stream as long 
                    128: **     as the channel itself.
                    129: */
                    130: PRIVATE int HTBufferWriter_close (HTOutputStream * me)
                    131: {
                    132:     if (me) {
                    133:        HTBufferWriter_flush(me);
                    134:        if (me->target) (*me->target->isa->close)(me->target);
                    135:        HT_FREE(me->data);
                    136:        HT_FREE(me);
                    137:     }
                    138:     return HT_OK;
                    139: }
                    140: 
                    141: PRIVATE const HTOutputStreamClass HTBufferWriter =
                    142: {              
                    143:     "SocketWriter",
                    144:     HTBufferWriter_flush,
                    145:     HTBufferWriter_free,
                    146:     HTBufferWriter_abort,
                    147:     HTBufferWriter_put_character,
                    148:     HTBufferWriter_put_string,
                    149:     HTBufferWriter_write,
                    150:     HTBufferWriter_close
                    151: }; 
                    152: 
                    153: PUBLIC HTOutputStream * HTBufferWriter_new (HTNet * net, HTChannel * ch,
                    154:                                            void * param, int bufsize)
                    155: {
                    156:     if (net && ch) {
                    157:        HTOutputStream * me = HTChannel_output(ch);
                    158:        if (me == NULL) {
                    159:            if (bufsize <= 0) bufsize = OUTPUT_BUFFER_SIZE;
                    160:            if ((me = (HTOutputStream *) HT_CALLOC(1, sizeof(HTOutputStream))) == NULL ||
                    161:                (me->data = (char *) HT_MALLOC(bufsize)) == NULL)
                    162:                HT_OUTOFMEM("HTBufferWriter_new");
                    163:            me->isa = &HTBufferWriter;
                    164:            me->read = me->data;
                    165:            me->size = bufsize;
                    166:            me->target = HTWriter_new(net, ch, param, 0);
                    167:            me->ch = ch;
2.2     ! eric      168:        } else
        !           169:            HTWriter_set(me->target, net, ch, param, 0);
2.1       frystyk   170:        me->net = net;
                    171:        return me;
                    172:     }
                    173:     return NULL;
                    174: }

Webmaster