tomwalters@0: /* tomwalters@0: pullable.c tomwalters@0: ========== tomwalters@0: tomwalters@0: sources who's native operation is receive pull commands. tomwalters@0: tomwalters@0: */ tomwalters@0: tomwalters@0: #include "stitch.h" tomwalters@0: #include "source.h" tomwalters@0: tomwalters@0: #ifndef lint tomwalters@0: static char *sccs_id = "@(#)pullable.c 1.3 John Holdsworth (MRC-APU) 6/6/91" ; tomwalters@0: #endif tomwalters@0: tomwalters@0: #if 0 tomwalters@0: #define DEBUG 1 tomwalters@0: #endif tomwalters@0: tomwalters@0: /* tomwalters@0: fill a users buffer from a process that returns it's own buffer tomwalters@0: tomwalters@0: */ tomwalters@0: tomwalters@0: static Pointer fillFromPullable( source, bytes, buffer ) tomwalters@0: struct _pullable_source *source ; tomwalters@0: ByteCount *bytes ; tomwalters@0: Pointer buffer ; tomwalters@0: { tomwalters@0: Pointer input = source->parent.pull( source, bytes ) ; tomwalters@0: tomwalters@0: CopyArray( (char *) input, (char *) buffer, *bytes ) ; tomwalters@0: tomwalters@0: return ( buffer ) ; tomwalters@0: } tomwalters@0: tomwalters@0: Source setPullableSource( source, puller, name ) tomwalters@0: struct _pullable_source *source ; tomwalters@0: Pointer (*puller)() ; tomwalters@0: char *name ; tomwalters@0: { tomwalters@0: return ( SetSource( source, puller, fillFromPullable, nonRoller, name ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: Pointer deletePullableSource( source ) tomwalters@0: struct _pullable_source *source ; tomwalters@0: { tomwalters@0: return ( DeleteSource( source ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /* tomwalters@0: simple slave source as example of derived source tomwalters@0: tomwalters@0: */ tomwalters@0: tomwalters@0: typedef struct { struct _pullable_source parent ; Source master ; } *SlaveSource ; tomwalters@0: tomwalters@0: static Pointer slavePull( source, bytes ) tomwalters@0: SlaveSource source ; tomwalters@0: ByteCount *bytes ; tomwalters@0: { tomwalters@0: register int last = *bytes == 0 ; tomwalters@0: tomwalters@0: if( !last ) tomwalters@0: return ( _SPTR( source->master )->returned ) ; tomwalters@0: else tomwalters@0: return ( DeletePullableSource( source ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: Source newSlaveSource( master ) tomwalters@0: Source master ; tomwalters@0: { tomwalters@0: DeclareNew( SlaveSource, source ) ; tomwalters@0: tomwalters@0: source->master = master ; tomwalters@0: tomwalters@0: return ( SetPullableSource( source, slavePull, "pullable.c slave" ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /* tomwalters@0: the simplest Source is one direct from memory tomwalters@0: tomwalters@0: */ tomwalters@0: tomwalters@0: typedef struct { tomwalters@0: struct _pullable_source parent ; tomwalters@0: Pointer next ; tomwalters@0: } *StaticSource ; tomwalters@0: tomwalters@0: static Pointer staticPull( source, bytes ) tomwalters@0: StaticSource source ; tomwalters@0: ByteCount *bytes ; tomwalters@0: { tomwalters@0: register int last = *bytes == 0 ; tomwalters@0: register Pointer this = source->next ; tomwalters@0: tomwalters@0: if( !last ) { tomwalters@0: tomwalters@0: source->next += abs( *bytes ) ; tomwalters@0: tomwalters@0: return ( this ) ; tomwalters@0: } tomwalters@0: else tomwalters@0: return ( DeletePullableSource( source ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: Source newStaticSource( pointer ) tomwalters@0: Pointer pointer ; tomwalters@0: { tomwalters@0: DeclareNew( StaticSource, source ) ; tomwalters@0: tomwalters@0: source->next = pointer ; tomwalters@0: tomwalters@0: return ( SetPullableSource( source, staticPull, "pullable.c static" ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: typedef struct { tomwalters@0: struct _pullable_source parent ; tomwalters@0: Source input ; Pointer buffer ; ByteCount retained ; tomwalters@0: } *RetainingSource ; tomwalters@0: tomwalters@0: static Pointer retaining_callback( source, bytes ) tomwalters@0: RetainingSource source ; tomwalters@0: ByteCount *bytes ; tomwalters@0: { tomwalters@0: register int last = *bytes == 0 ; tomwalters@0: Pointer buffer = RollSome( source->input, bytes, source->retained ) ; tomwalters@0: tomwalters@0: if( !last ) tomwalters@0: return ( buffer ) ; tomwalters@0: else tomwalters@0: return ( DeletePullableSource( source ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: Source newRetainingSource( input, retained ) tomwalters@0: Source input ; tomwalters@0: ByteCount retained ; tomwalters@0: { tomwalters@0: DeclareNew( RetainingSource, source ) ; tomwalters@0: tomwalters@0: source->retained = retained ; tomwalters@0: tomwalters@0: source->input = NewRollableSource( input ) ; tomwalters@0: tomwalters@0: return ( SetPullableSource( source, retaining_callback, "pullable.c retaining" ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: typedef struct { tomwalters@0: struct _pullable_source parent ; tomwalters@0: Source input ; ByteCount delay ; tomwalters@0: } *DelayingSource ; tomwalters@0: tomwalters@0: static Pointer delay_callback( source, bytes ) tomwalters@0: DelayingSource source ; tomwalters@0: ByteCount *bytes ; tomwalters@0: { tomwalters@0: register int last = *bytes == 0 ; tomwalters@0: Pointer delayed = PullSome( source->input, bytes ) - source->delay ; tomwalters@0: tomwalters@0: if( !last ) tomwalters@0: return ( delayed ) ; tomwalters@0: else tomwalters@0: return ( DeletePullableSource( source ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: Source newDelayingSource( input, delay ) tomwalters@0: Source input ; tomwalters@0: ByteCount delay ; tomwalters@0: { tomwalters@0: DeclareNew( DelayingSource, source ) ; tomwalters@0: tomwalters@0: source->input = NewRetainingSource( input, delay ) ; tomwalters@0: tomwalters@0: source->delay = delay ; tomwalters@0: tomwalters@0: return ( SetPullableSource( source, delay_callback, "pullable.c delaying" ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: typedef struct { tomwalters@0: struct _pullable_source parent ; tomwalters@0: Source input ; Pointer buffer, position, end ; ByteCount segment ; tomwalters@0: } *BlockingSource ; tomwalters@0: tomwalters@0: static Pointer block_callback( source, bytes ) tomwalters@0: BlockingSource source ; tomwalters@0: ByteCount *bytes ; tomwalters@0: { tomwalters@0: register int last = *bytes == 0 ; tomwalters@0: ByteCount segment = source->segment ; tomwalters@0: tomwalters@0: if( source->position == source->end || last ) { tomwalters@0: tomwalters@0: if( segment < *bytes || last ) tomwalters@0: segment = *bytes ; tomwalters@0: tomwalters@0: source->buffer = PullSome( source->input, &segment ) ; tomwalters@0: #if DEBUG tomwalters@0: printf( "pulled block at %x from %s\n", source->buffer, SourceName( source->input ) ) ; tomwalters@0: #endif tomwalters@0: source->end = source->buffer + segment ; tomwalters@0: tomwalters@0: source->position = source->buffer ; tomwalters@0: } tomwalters@0: tomwalters@0: if( *bytes > source->end - source->position ) tomwalters@0: *bytes = source->end - source->position ; tomwalters@0: tomwalters@0: source->position += *bytes ; tomwalters@0: tomwalters@0: if( !last ) tomwalters@0: return ( source->position - *bytes ) ; tomwalters@0: else tomwalters@0: return ( DeletePullableSource( source ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: Source newBlockingSource( input, segment ) tomwalters@0: Source input ; tomwalters@0: ByteCount segment ; tomwalters@0: { tomwalters@0: DeclareNew( BlockingSource, source ) ; tomwalters@0: tomwalters@0: source->input = input ; tomwalters@0: tomwalters@0: source->position = source->end = (Pointer) 0 ; tomwalters@0: tomwalters@0: source->segment = segment ; tomwalters@0: tomwalters@0: return ( SetPullableSource( source, block_callback, "pullable.c blocking" ) ) ; tomwalters@0: } tomwalters@0: