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

2.1       frystyk     1: /*
                      2: **     BUFFERED MUX OUTPUT STREAM
                      3: **
                      4: **     (c) COPYRIGHT MIT 1995.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
2.2     ! frystyk     6: **     @(#) $Id: HTMuxTx.c,v 2.1 1996/12/01 00:26:41 frystyk Exp $
2.1       frystyk     7: **
                      8: **     A buffered output MUX stream.
                      9: **
                     10: ** Authors
                     11: **     HFN     Henrik Frystyk Nielsen <frystyk@w3.org>
                     12: **
                     13: ** History:
                     14: **     Oct 96  Written
                     15: */
                     16: 
                     17: /* Library include files */
2.2     ! frystyk    18: #include "wwwsys.h"
2.1       frystyk    19: #include "WWWUtil.h"
                     20: #include "WWWCore.h"
                     21: #include "WWWTrans.h"
                     22: #include "HTMuxHeader.h"
                     23: #include "HTMuxCh.h"
                     24: #include "HTMuxTx.h"                                    /* Implemented here */
                     25: 
                     26: struct _HTOutputStream {
                     27:     const HTOutputStreamClass *        isa;
                     28:     HTOutputStream *           target;          /* Target for outgoing data */
                     29:     HTChannel *                        ch;
                     30:     int                                size;                         /* Buffer size */
                     31:     int                                bb;
                     32:     char *                     block;
                     33:     char *                     read;                  /* Position in 'data' */
                     34:     char *                     data;                              /* buffer */
                     35: };
                     36: 
                     37: #define PUTBLOCK(b,l) (*me->target->isa->put_block)(me->target,(b),(l))
                     38: 
                     39: /* ------------------------------------------------------------------------- */
                     40: 
                     41: PRIVATE int HTMuxBuffer_write (HTOutputStream *me, const char *buf, int len)
                     42: {
                     43:     int status;
                     44: 
                     45:     if (me->bb > 0) {
                     46:        len -= (me->block - buf);
                     47:        if ((status = PUTBLOCK(me->block, me->bb)) != HT_OK) return status;
                     48:        me->block += me->bb;
                     49:        len -= me->bb;
                     50:        me->bb = 0;
                     51:     } else {
                     52:        int available = me->data + me->size - me->read;
                     53: 
                     54:        /* Still room in buffer */
                     55:        if (len <= available) {
                     56:            memcpy(me->read, buf, len);
                     57:            me->read += len;
                     58:            return HT_OK;
                     59:        }
                     60: 
                     61:        /* If already data in buffer then fill it and flush */
                     62:        if (me->read > me->data) {
                     63:            memcpy(me->read, buf, available);
                     64:            me->block = (char *) buf+available;
                     65:            if ((status = PUTBLOCK(me->data, me->size))!=HT_OK) return status;
                     66:        }
                     67: 
                     68:        /* If more data then write n times buffer size */
                     69:        if (!me->block)
                     70:            me->block = (char *) buf;
                     71:        else {
                     72:            len -= (me->block - buf);
                     73:        }
                     74:        me->bb = len - len%me->size;
                     75:        if ((status = PUTBLOCK(me->block, me->bb)) != HT_OK) return status;
                     76:        me->block += me->bb;
                     77:        len -= me->bb;
                     78:        me->bb = 0;
                     79:     }
                     80: 
                     81:     /* If data is not aligned then save the rest in our buffer */
                     82:     if (len > 0) {
                     83:        memcpy(me->data, me->block, len);
                     84:        me->read = me->data + len;
                     85:     } else
                     86:        me->read = me->data;
                     87:     me->block = NULL;
                     88:     return HT_OK;
                     89: }
                     90: 
                     91: PRIVATE int HTMuxBuffer_put_character (HTOutputStream * me, char c)
                     92: {
                     93:     return HTMuxBuffer_write(me, &c, 1);
                     94: }
                     95: 
                     96: PRIVATE int HTMuxBuffer_put_string (HTOutputStream * me, const char * s)
                     97: {
                     98:     return HTMuxBuffer_write(me, s, (int) strlen(s));
                     99: }
                    100: 
                    101: PRIVATE int HTMuxBuffer_flush (HTOutputStream * me)
                    102: {
                    103:     int status = HT_OK;
                    104:     if (me->read > me->data) {
                    105:        if ((status = PUTBLOCK(me->data, me->read - me->data))==HT_WOULD_BLOCK)
                    106:            return HT_WOULD_BLOCK;
                    107:        me->read = me->data;
                    108:        me->block = NULL;
                    109:     }
                    110:     return status;
                    111: }
                    112: 
                    113: PRIVATE int HTMuxBuffer_free (HTOutputStream * me)
                    114: {
                    115: #if 0
                    116:     return HTMuxBuffer_flush(me);
                    117: #else
                    118:     return HT_OK;
                    119: #endif
                    120: }
                    121: 
                    122: PRIVATE int HTMuxBuffer_abort (HTOutputStream * me, HTList * e)
                    123: {
                    124:     if (me->target) (*me->target->isa->abort)(me->target, e);
                    125:     if (PROT_TRACE) HTTrace("MUX Tx...... ABORTING...\n");
                    126:     return HT_ERROR;
                    127: }
                    128: 
                    129: /*
                    130: **     The difference between the close and the free method is that we don't
                    131: **     close the connection in the free method - we only call the free method
                    132: **     of the target stream. That way, we can keep the output stream as long 
                    133: **     as the channel itself.
                    134: */
                    135: PRIVATE int HTMuxBuffer_close (HTOutputStream * me)
                    136: {
                    137:     if (me) {
                    138:        HTMuxBuffer_flush(me);
                    139:        if (me->target) (*me->target->isa->close)(me->target);
                    140:        HT_FREE(me->data);
                    141:        HT_FREE(me);
                    142:     }
                    143:     return HT_OK;
                    144: }
                    145: 
                    146: PRIVATE const HTOutputStreamClass HTMuxBuffer =
                    147: {              
                    148:     "MuxBuffer",
                    149:     HTMuxBuffer_flush,
                    150:     HTMuxBuffer_free,
                    151:     HTMuxBuffer_abort,
                    152:     HTMuxBuffer_put_character,
                    153:     HTMuxBuffer_put_string,
                    154:     HTMuxBuffer_write,
                    155:     HTMuxBuffer_close
                    156: }; 
                    157: 
                    158: PUBLIC HTOutputStream * HTMuxBuffer_new (HTHost * host, HTChannel * ch,
                    159:                                         void * param, int bufsize)
                    160: {
                    161:     if (host && ch) {
                    162:        HTOutputStream * me = HTChannel_output(ch);
                    163:        if (me == NULL) {
                    164:            if (bufsize <= 0) bufsize = MUX_BUFFER_SIZE;
                    165:            if ((me = (HTOutputStream *) HT_CALLOC(1, sizeof(HTOutputStream))) == NULL ||
                    166:                (me->data = (char *) HT_MALLOC(bufsize)) == NULL)
                    167:                HT_OUTOFMEM("HTMuxBuffer_new");
                    168:            me->isa = &HTMuxBuffer;
                    169:            me->target = HTWriter_new(host, ch, param, 0);
                    170:            me->ch = ch;
                    171:            me->size = bufsize;
                    172:            me->read = me->data;
                    173:        }
                    174:        return me;
                    175:     }
                    176:     return NULL;
                    177: }

Webmaster