Annotation of libwww/Library/src/HTTee.c, revision 2.17
2.5 frystyk 1: /* HTee.c
2: ** TEE CLASS STREAM DEFINITION
3: **
2.9 frystyk 4: ** (c) COPYRIGHT MIT 1995.
2.5 frystyk 5: ** Please first read the full copyright statement in the file COPYRIGH.
2.17 ! frystyk 6: ** @(#) $Id: HTTee.c,v 2.16 1996/04/12 17:49:25 frystyk Exp $
2.1 timbl 7: **
8: ** The Tee class just writes to two streams. Easy.
9: ** See also the Black Hole stream which is even easier.
2.3 duns 10: **
11: ** HISTORY:
12: ** 8 Jul 94 FM Insulate free() from _free structure element.
13: **
2.1 timbl 14: */
15:
2.7 frystyk 16: /* Library include files */
2.15 frystyk 17: #include "sysdep.h"
2.7 frystyk 18: #include "HTUtils.h"
2.13 frystyk 19: #include "HTArray.h"
2.1 timbl 20: #include "HTTee.h"
21:
22: /* Stream Object
23: ** ------------
24: */
25:
26: struct _HTStream {
2.15 frystyk 27: const HTStreamClass * isa;
2.13 frystyk 28: HTStream * s1;
29: HTStream * s2;
30: HTComparer * resolver;
2.1 timbl 31: };
32:
2.13 frystyk 33: /*
34: ** Algorithm produced by H&kon
35: */
2.15 frystyk 36: PRIVATE int default_resolver (const void *a, const void *b)
2.13 frystyk 37: {
38: if (*(int *) a < 0)
39: return *(int *) a;
40: if (*(int *) b < 0)
41: return *(int *) b;
42: if (*(int *) a == 0)
43: return *(int *) b;
44: return *(int *) a;
45: }
2.1 timbl 46:
2.11 frystyk 47: PRIVATE int HTTee_put_character (HTStream * me, char c)
2.1 timbl 48: {
2.8 frystyk 49: int ret1 = (*me->s1->isa->put_character)(me->s1, c);
50: int ret2 = (*me->s2->isa->put_character)(me->s2, c);
2.13 frystyk 51: return me->resolver(&ret1, &ret2);
2.1 timbl 52: }
2.8 frystyk 53:
2.15 frystyk 54: PRIVATE int HTTee_put_string (HTStream * me, const char* s)
2.1 timbl 55: {
2.8 frystyk 56: int ret1 = (*me->s1->isa->put_string)(me->s1, s);
57: int ret2 = (*me->s2->isa->put_string)(me->s2, s);
2.13 frystyk 58: return me->resolver(&ret1, &ret2);
2.1 timbl 59: }
2.8 frystyk 60:
2.15 frystyk 61: PRIVATE int HTTee_write (HTStream * me, const char* s, int l)
2.1 timbl 62: {
2.8 frystyk 63: int ret1 = (*me->s1->isa->put_block)(me->s1, s, l);
64: int ret2 = (*me->s2->isa->put_block)(me->s2, s, l);
2.13 frystyk 65: return me->resolver(&ret1, &ret2);
2.1 timbl 66: }
2.8 frystyk 67:
2.11 frystyk 68: PRIVATE int HTTee_flush (HTStream * me)
2.8 frystyk 69: {
70: int ret1 = (*me->s1->isa->flush)(me->s1);
71: int ret2 = (*me->s2->isa->flush)(me->s2);
2.13 frystyk 72: return me->resolver(&ret1, &ret2);
2.8 frystyk 73: }
74:
2.17 ! frystyk 75: /*
! 76: ** BUGS: We do not handle WOULD_BLOCK here. This is tricky as we don't
! 77: ** know which one actually blocked.
! 78: */
2.11 frystyk 79: PRIVATE int HTTee_free (HTStream * me)
2.1 timbl 80: {
2.8 frystyk 81: int ret1 = (*me->s1->isa->_free)(me->s1);
82: int ret2 = (*me->s2->isa->_free)(me->s2);
2.16 frystyk 83: int ret = me->resolver(&ret1, &ret2);
2.14 frystyk 84: HT_FREE(me);
2.16 frystyk 85: return ret;
2.1 timbl 86: }
2.8 frystyk 87:
2.11 frystyk 88: PRIVATE int HTTee_abort (HTStream * me, HTList * e)
2.1 timbl 89: {
90: (*me->s1->isa->abort)(me->s1, e);
91: (*me->s2->isa->abort)(me->s2, e);
2.14 frystyk 92: HT_FREE(me);
2.8 frystyk 93: return HT_ERROR;
2.1 timbl 94: }
95:
96:
97: /* Tee stream
98: ** ----------
99: */
2.15 frystyk 100: PRIVATE const HTStreamClass HTTeeClass =
2.1 timbl 101: {
102: "Tee",
2.8 frystyk 103: HTTee_flush,
2.1 timbl 104: HTTee_free,
105: HTTee_abort,
106: HTTee_put_character, HTTee_put_string,
107: HTTee_write
108: };
109:
110:
2.13 frystyk 111: /* Tee Stream creation
112: ** -------------------
113: ** You can create a T stream using this method. Each stream returns a
114: ** return value and in order to resolve conflicts in the return code
115: ** you can specify a resolver callback function. Each time any of the
116: ** data methods are called the resolver function is then called with
117: ** the return codes from the two streams. The return code of the T stream
118: ** itself will be the result of the resolver function. If you pass NULL
119: ** as the resolver routine then a default resolver is used.
2.1 timbl 120: */
2.13 frystyk 121: PUBLIC HTStream * HTTee(HTStream * s1, HTStream * s2, HTComparer * resolver)
2.1 timbl 122: {
2.14 frystyk 123: HTStream * me;
124: if ((me = (HTStream *) HT_CALLOC(1, sizeof(*me))) == NULL)
125: HT_OUTOFMEM("HTTee");
2.1 timbl 126: me->isa = &HTTeeClass;
127: me->s1 = s1;
128: me->s2 = s2;
2.13 frystyk 129: me->resolver = resolver ? resolver : default_resolver;
2.1 timbl 130: return me;
131: }
132:
133:
Webmaster