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

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.
        !             6: **     @(#) $Id: Date Author State $
        !             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;
        !           168:        }
        !           169:        me->net = net;
        !           170:        return me;
        !           171:     }
        !           172:     return NULL;
        !           173: }

Webmaster