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