view 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 source
/*
    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 ) ) ;
}