Annotation of libwww/Library/src/HTTee.c, revision 2.19

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.19    ! frystyk     6: **     @(#) $Id: HTTee.c,v 2.18 1996/10/07 02:05:31 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.19    ! frystyk    17: #include "wwwsys.h"
2.18      frystyk    18: #include "WWWUtil.h"
2.1       timbl      19: #include "HTTee.h"
                     20: 
                     21: /*             Stream Object
                     22: **             ------------
                     23: */
                     24: 
                     25: struct _HTStream {
2.15      frystyk    26:     const HTStreamClass *      isa;
2.13      frystyk    27:     HTStream *                 s1;
                     28:     HTStream *                 s2;
                     29:     HTComparer *               resolver;
2.1       timbl      30: };
                     31: 
2.13      frystyk    32: /*
                     33: **     Algorithm produced by H&kon
                     34: */
2.15      frystyk    35: PRIVATE int default_resolver (const void *a, const void *b)
2.13      frystyk    36: {
                     37:     if (*(int *) a < 0)
                     38:         return *(int *) a;
                     39:     if (*(int *) b < 0)
                     40:         return *(int *) b;
                     41:     if (*(int *) a == 0)
                     42:         return *(int *) b;
                     43:     return *(int *) a;
                     44: }
2.1       timbl      45: 
2.11      frystyk    46: PRIVATE int HTTee_put_character (HTStream * me, char c)
2.1       timbl      47: {
2.8       frystyk    48:     int ret1 = (*me->s1->isa->put_character)(me->s1, c);
                     49:     int ret2 = (*me->s2->isa->put_character)(me->s2, c);
2.13      frystyk    50:     return me->resolver(&ret1, &ret2);
2.1       timbl      51: }
2.8       frystyk    52: 
2.15      frystyk    53: PRIVATE int HTTee_put_string (HTStream * me, const char* s)
2.1       timbl      54: {
2.8       frystyk    55:     int ret1 = (*me->s1->isa->put_string)(me->s1, s);
                     56:     int ret2 = (*me->s2->isa->put_string)(me->s2, s);
2.13      frystyk    57:     return me->resolver(&ret1, &ret2);
2.1       timbl      58: }
2.8       frystyk    59: 
2.15      frystyk    60: PRIVATE int HTTee_write (HTStream * me, const char* s, int l)
2.1       timbl      61: {
2.8       frystyk    62:     int ret1 = (*me->s1->isa->put_block)(me->s1, s, l);
                     63:     int ret2 = (*me->s2->isa->put_block)(me->s2, s, l);
2.13      frystyk    64:     return me->resolver(&ret1, &ret2);
2.1       timbl      65: }
2.8       frystyk    66: 
2.11      frystyk    67: PRIVATE int HTTee_flush (HTStream * me)
2.8       frystyk    68: {
                     69:     int ret1 = (*me->s1->isa->flush)(me->s1);
                     70:     int ret2 = (*me->s2->isa->flush)(me->s2);
2.13      frystyk    71:     return me->resolver(&ret1, &ret2);
2.8       frystyk    72: }
                     73: 
2.17      frystyk    74: /*
                     75: **     BUGS: We do not handle WOULD_BLOCK here. This is tricky as we don't
                     76: **     know which one actually blocked.
                     77: */
2.11      frystyk    78: PRIVATE int HTTee_free (HTStream * me)
2.1       timbl      79: {
2.18      frystyk    80:     if (me) {
                     81:        int ret1 = me->s1 ? (*me->s1->isa->_free)(me->s1) : HT_OK;
                     82:        int ret2 = me->s2 ? (*me->s2->isa->_free)(me->s2) : HT_OK;
                     83:        int ret = me->resolver(&ret1, &ret2);
                     84:        me->s1 = me->s2 = NULL;
                     85:        HT_FREE(me);
                     86:        return ret;
                     87:     }
                     88:     return HT_OK;
2.1       timbl      89: }
2.8       frystyk    90: 
2.11      frystyk    91: PRIVATE int HTTee_abort (HTStream * me, HTList * e)
2.1       timbl      92: {
2.18      frystyk    93:     if (me) {
                     94:        if (me->s1) (*me->s1->isa->abort)(me->s1, e);
                     95:        if (me->s2) (*me->s2->isa->abort)(me->s2, e);
                     96:        me->s1 = me->s2 = NULL;
                     97:        HT_FREE(me);
                     98:     }
2.8       frystyk    99:     return HT_ERROR;
2.1       timbl     100: }
                    101: 
                    102: 
                    103: /*     Tee stream
                    104: **     ----------
                    105: */
2.15      frystyk   106: PRIVATE const HTStreamClass HTTeeClass =
2.1       timbl     107: {              
                    108:        "Tee",
2.8       frystyk   109:        HTTee_flush,
2.1       timbl     110:        HTTee_free,
                    111:        HTTee_abort,
                    112:        HTTee_put_character,    HTTee_put_string,
                    113:        HTTee_write
                    114: }; 
                    115: 
                    116: 
2.13      frystyk   117: /*     Tee Stream creation
                    118: **     -------------------
                    119: **     You can create a T stream using this method. Each stream returns a
                    120: **     return value and in order to resolve conflicts in the return code
                    121: **     you can specify a resolver callback function. Each time any of the 
                    122: **     data methods are called the resolver function is then called with
                    123: **     the return codes from the two streams. The return code of the T stream
                    124: **     itself will be the result of the resolver function. If you pass NULL
                    125: **     as the resolver routine then a default resolver is used.
2.1       timbl     126: */
2.13      frystyk   127: PUBLIC HTStream * HTTee(HTStream * s1, HTStream * s2, HTComparer * resolver)
2.1       timbl     128: {
2.14      frystyk   129:     HTStream * me;
                    130:     if ((me = (HTStream  *) HT_CALLOC(1, sizeof(*me))) == NULL)
                    131:         HT_OUTOFMEM("HTTee");
2.1       timbl     132:     me->isa = &HTTeeClass;
2.18      frystyk   133:     me->s1 = s1 ? s1 : HTBlackHole();
                    134:     me->s2 = s2 ? s2 : HTBlackHole();
2.13      frystyk   135:     me->resolver = resolver ? resolver : default_resolver;
2.18      frystyk   136:     if (STREAM_TRACE)
                    137:        HTTrace("Tee......... Created stream %p with resolver %p\n",
                    138:                me, me->resolver);
2.1       timbl     139:     return me;
                    140: }
                    141: 
                    142: 

Webmaster