Mercurial > hg > aim92
diff stitch/fillable.c @ 0:5242703e91d3 tip
Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author | tomwalters |
---|---|
date | Fri, 20 May 2011 15:19:45 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stitch/fillable.c Fri May 20 15:19:45 2011 +0100 @@ -0,0 +1,405 @@ +/* + fillable.c + ========== + + Sources whose native mode of operation is the fill entry point. + They may be pulled in which case a buffer is allocated. + +*/ + +#include "stitch.h" +#include "source.h" + +#ifndef lint +static char *sccs_id = "@(#)fillable.c 1.2 John Holdsworth (MRC-APU) 11/8/90" ; +#endif + +#if 0 +#define DEBUG 1 +#endif + +Source SharingSource( source1, source2 ) +struct _fillable_source *source1, *source2 ; +{ + DeleteBuffer( source1->buffer ) ; + + source1->buffer = SharedBuffer( source2->buffer ) ; + + return ( (Source) source1 ) ; +} + +/* converter of pull command to fill commands */ + +static Pointer pullFromFillable( source, bytes ) +struct _fillable_source *source ; +ByteCount *bytes ; +{ +#if DEBUG + printf( "buffering pulling from passive \"%s\", %d bytes\n", SourceName( source ), *bytes ) ; +#endif +#if 00 + if( source->bsize < *bytes ) { + + if( source->bsize != 0 ) + Delete( source->buffer ) ; + + source->buffer = Allocate( *bytes, "fillable.c for source buffer" ) ; + + source->bsize = *bytes ; + } +#endif + return ( source->parent.fill( source, bytes, SizedBufferPointer( SourceBuffer( source ), *bytes ) ) ) ; +} + +/* constructor for all pullable sources */ + +Source setFillableSource( source, filler, name ) +struct _fillable_source *source ; +Pointer (*filler)() ; +char *name ; +{ + source->buffer = NewBuffer( "pulling" ) ; + + return ( SetSource( source, pullFromFillable, filler, nonRoller, name ) ) ; +} + +Pointer deleteFillableSource( source ) +struct _fillable_source *source ; +{ + DeleteBuffer( source->buffer ) ; + + return ( DeleteSource( source ) ) ; +} + + +/* derived fillable source */ + +typedef struct { + struct _fillable_source parent ; + Pointer data, end, ptr ; + } *RepeatingSource ; + +static Pointer repeating_callback( source, bytes, buffer ) +RepeatingSource source ; +ByteCount *bytes ; +Pointer buffer ; +{ + register int last = *bytes == 0 ; + register Pointer bptr = buffer ; + register Pointer bend = buffer + *bytes ; + register ByteCount segment ; + + if( !last ) { + + while( bptr < bend ) { + + segment = source->end - source->ptr ; + if( segment > bend - bptr ) + segment = bend - bptr ; + + CopyArray( (char *) source->ptr, (char *) bptr, segment ) ; + + source->ptr += segment ; + bptr += segment ; + + if( source->ptr == source->end ) + source->ptr = source->data ; + } + + return ( buffer ) ; + } + else + return ( DeleteFillableSource( source ) ) ; +} + +Source newRepeatingSource( data, segment ) +Pointer data ; +ByteCount segment ; +{ + DeclareNew( RepeatingSource, source ) ; + + source->data = data ; + source->end = data + segment ; + + source->ptr = source->data ; + + return ( SetFillableSource( source, repeating_callback, "fillable.c repeating" ) ) ; +} + +typedef struct { + struct _fillable_source parent ; + Source input ; ByteCount segment ; + } *SegmentingSource ; + +static Pointer segmenting_callback( source, bytes, buffer ) +SegmentingSource source ; +ByteCount *bytes ; +Pointer buffer ; +{ + register int last = *bytes == 0 ; + Pointer bptr = buffer ; + ByteCount segment ; + + do { + + segment = source->segment ; + + if( segment > buffer + *bytes - bptr ) + segment = buffer + *bytes - bptr ; + + (void) FillSome( source->input, &segment, bptr ) ; + + bptr += segment ; + + } while ( bptr < buffer + *bytes ) ; + + if( !last ) + return ( buffer ) ; + else + return ( DeleteFillableSource( source ) ) ; +} + +Source newSegmentingSource( input, segment ) +Source input ; +ByteCount segment ; +{ + DeclareNew( SegmentingSource, source ) ; + + source->input = input ; + + source->segment = segment ; + + return ( SetFillableSource( source, segmenting_callback, "segmenting" ) ) ; +} + + + +/* higher level methods to sources */ + + +typedef struct _callback_source { + struct _fillable_source parent ; + Pointer state ; + void (*callback)(), (*close)() ; + } *CallbackSource ; + +Source setCallbackSource( source, filler, state, callback, close, name ) +CallbackSource source ; +Pointer (*filler)() ; +Pointer state ; +void (*callback)(), (*close)() ; +char *name ; +{ + source->state = state ; + source->callback = callback ; + source->close = close ; + + return ( SetFillableSource( source, filler, name ) ) ; +} + +Source newCallbackSource( filler, state, callback, close, name ) +Pointer (*filler)() ; +Pointer state ; +void (*callback)(), (*close)() ; +char *name ; +{ + return ( setCallbackSource( New( CallbackSource ), filler, state, callback, close, name ) ) ; +} + +static Pointer externalFiller( source, bytes, buffer ) +CallbackSource source ; +ByteCount *bytes ; +Pointer buffer ; +{ + register int last = *bytes == 0 ; + + source->callback( source->state, bytes, buffer, buffer+*bytes ) ; + + if( !last ) + return ( buffer ) ; + else { + if( source->close != (void ( * )()) 0 ) + source->close( source->state ) ; + + return ( DeleteFillableSource( source ) ) ; + } +} + +Source newExternalSource( state, callback, close, name ) +Pointer state ; +void (*callback)(), (*close)() ; +char *name ; +{ + return ( newCallbackSource( externalFiller, state, callback, close, name ) ) ; +} + +typedef struct _through_source { + struct _callback_source parent ; + Source input ; + } *ThroughSource ; + +static Source setThroughSource( source, filler, state, callback, close, input, name ) +ThroughSource source ; +Pointer (*filler)() ; +Pointer state ; +void (*callback)(), (*close)() ; +Source input ; +char *name ; +{ + source->input = input ; + + return ( setCallbackSource( (CallbackSource) source, filler, state, callback, close, name ) ) ; +} + +Source newThroughSource( filler, state, callback, close, input, name ) +Pointer (*filler)(), state ; +void (*callback)(), (*close)() ; +Source input ; +char *name ; +{ + return ( setThroughSource( New( ThroughSource ), filler, state, callback, close, input, name ) ) ; +} + + +static Pointer processingFiller( source, bytes, buffer ) +ThroughSource source ; +ByteCount *bytes ; +Pointer buffer ; +{ + register int last = *bytes == 0 ; + + source->parent.callback( source->parent.state, bytes, buffer, buffer+*bytes, PullSome( source->input, bytes ) ) ; + + if( !last ) + return ( buffer ) ; + else { + if( source->parent.close != (void ( * )()) 0 ) + source->parent.close( source->parent.state ) ; + + return ( DeleteFillableSource( &source->parent ) ) ; + } +} + +Source newProcessingSource( state, callback, close, input, name ) +Pointer state ; +void (*callback)(), (*close)() ; +Source input ; +char *name ; +{ + return ( newThroughSource( processingFiller, state, callback, close, input, name ) ) ; +} + +Source newSimpleProcessingSource( callback, input, name ) +void (*callback)() ; +Source input ; +char *name ; +{ + return ( NewProcessingSource( (Pointer) 0, callback, (void ( * )()) 0, input, name ) ) ; +} + +typedef struct { + struct _fillable_source parent ; + Pointer *states ; + int (*callback)() ; + void (*close)() ; + int channels ; + Source input ; +} *MultiplexedSource ; + +static Pointer multiplexed_callback( source, bytes, buffer ) +MultiplexedSource source ; +ByteCount *bytes ; +Pointer buffer ; +{ + register int last = *bytes == 0 ; + Pointer iptr = PullSome( source->input, bytes ) ; + Pointer optr = buffer ; + Pointer end = buffer + *bytes ; + ByteCount data_size ; + int channel ; + + for( channel=0 ; channel<source->channels ; channel++ ) { + data_size = source->callback( source->states[channel], optr, end, iptr, source->channels ) ; + iptr += data_size ; + optr += data_size ; + } + + if( !last ) + return ( buffer ) ; + else { + if( source->close != (void ( * )()) 0 ) + for( channel=0 ; channel<source->channels ; channel++ ) + source->close( source->states[channel] ) ; + + Delete( source->states ) ; + + return ( DeleteFillableSource( source ) ) ; + } +} + +Source newMultiplexedSource( states, callback, close, channels, input, name ) +Pointer *states ; +int (*callback)() ; +void (*close)() ; +int channels ; +Source input ; +char *name ; +{ + DeclareNew( MultiplexedSource, source ) ; + + source->states = states ; + source->callback = callback ; + source->close = close ; + source->channels = channels ; + + source->input = input ; + + return ( SetFillableSource( source, multiplexed_callback, name ) ) ; +} + +typedef struct _merging_source { + struct _callback_source parent ; Source *inputs ; + } *MergingSource ; + +static Pointer mergingFiller( source, bytes, buffer ) +MergingSource source ; +ByteCount *bytes ; +Pointer buffer ; +{ + register int last = *bytes == 0 ; + Pointer input1, input2 ; + int n ; + + input1 = PullSome( source->inputs[0], bytes ) ; + + for( n=1 ; _SPTR( source->inputs[n] ) != (struct _source *) 0 ; n++ ) { + + input2 = PullSome( source->inputs[n], bytes ) ; + + source->parent.callback( source->parent.state, bytes, buffer, buffer+*bytes, input1, input2 ) ; + + input1 = buffer ; + } + + if( !last ) + return ( buffer ) ; + else { + Delete( source->inputs ) ; + + return ( DeleteFillableSource( &source->parent ) ) ; + } +} + +Source newMergingSource( state, callback, close, inputs, name ) +Pointer state ; +void (*callback)(), (*close)() ; +Source *inputs ; +char *name ; +{ + DeclareNew( MergingSource, source ) ; + + source->inputs = inputs ; + + return ( setCallbackSource( (CallbackSource) source, mergingFiller, state, callback, close, name ) ) ; +} +