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 ) ) ;
+}
+