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