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