view stitch/pullable.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
/*
    pullable.c
    ==========

    sources who's native operation is receive pull commands.

*/

#include "stitch.h"
#include "source.h"

#ifndef  lint
static char *sccs_id = "@(#)pullable.c	1.3 John Holdsworth (MRC-APU) 6/6/91" ;
#endif

#if 0
#define DEBUG 1
#endif

/*
    fill a users buffer from a process that returns it's own buffer

*/

static Pointer fillFromPullable( source, bytes, buffer )
struct _pullable_source *source ;
ByteCount *bytes ;
Pointer buffer ;
{
    Pointer input = source->parent.pull( source, bytes ) ;

    CopyArray( (char *) input, (char *) buffer, *bytes ) ;

    return ( buffer ) ;
}

Source setPullableSource( source, puller, name )
struct _pullable_source *source ;
Pointer (*puller)() ;
char *name ;
{
    return ( SetSource( source, puller, fillFromPullable, nonRoller, name ) ) ;
}

Pointer deletePullableSource( source )
struct _pullable_source *source ;
{
    return ( DeleteSource( source ) ) ;
}

/*
    simple slave source as example of derived source

*/

typedef struct { struct _pullable_source parent ; Source master ; } *SlaveSource ;

static Pointer slavePull( source, bytes )
SlaveSource source ;
ByteCount *bytes ;
{
    register int last = *bytes == 0 ;

    if( !last )
	return ( _SPTR( source->master )->returned ) ;
    else
	return ( DeletePullableSource( source ) ) ;
}

Source newSlaveSource( master )
Source master ;
{
    DeclareNew( SlaveSource, source ) ;

    source->master = master ;

    return ( SetPullableSource( source, slavePull, "pullable.c slave" ) ) ;
}

/*
    the simplest Source is one direct from memory

*/

typedef struct {
 struct _pullable_source parent ;
 Pointer next ;
 } *StaticSource ;

static Pointer staticPull( source, bytes )
StaticSource source ;
ByteCount *bytes ;
{
    register int last = *bytes == 0 ;
    register Pointer this = source->next ;

    if( !last ) {

	source->next += abs( *bytes ) ;

	return ( this ) ;
    }
    else
	return ( DeletePullableSource( source ) ) ;
}

Source newStaticSource( pointer )
Pointer pointer ;
{
    DeclareNew( StaticSource, source ) ;

    source->next = pointer ;

    return ( SetPullableSource( source, staticPull, "pullable.c static" ) ) ;
}

typedef struct {
 struct _pullable_source parent ;
 Source input ; Pointer buffer ; ByteCount retained ;
} *RetainingSource ;

static Pointer retaining_callback( source, bytes )
RetainingSource source ;
ByteCount *bytes ;
{
    register int last = *bytes == 0 ;
    Pointer buffer = RollSome( source->input, bytes, source->retained ) ;

    if( !last )
	return ( buffer ) ;
    else
	return ( DeletePullableSource( source ) ) ;
}

Source newRetainingSource( input, retained )
Source input ;
ByteCount retained ;
{
    DeclareNew( RetainingSource, source ) ;

    source->retained = retained ;

    source->input = NewRollableSource( input ) ;

    return ( SetPullableSource( source, retaining_callback, "pullable.c retaining" ) ) ;
}

typedef struct {
 struct _pullable_source parent ;
 Source input ; ByteCount delay ;
 } *DelayingSource  ;

static Pointer delay_callback( source, bytes )
DelayingSource source ;
ByteCount *bytes ;
{
    register int last = *bytes == 0 ;
    Pointer delayed = PullSome( source->input, bytes ) - source->delay ;

    if( !last )
	return ( delayed ) ;
    else
	return ( DeletePullableSource( source ) ) ;
}

Source newDelayingSource( input, delay )
Source input ;
ByteCount delay ;
{
    DeclareNew( DelayingSource, source ) ;

    source->input = NewRetainingSource( input, delay ) ;

    source->delay = delay ;

    return ( SetPullableSource( source, delay_callback, "pullable.c delaying" ) ) ;
}

typedef struct {
 struct _pullable_source parent ;
 Source input ; Pointer buffer, position, end ; ByteCount segment ;
} *BlockingSource ;

static Pointer block_callback( source, bytes )
BlockingSource source ;
ByteCount *bytes ;
{
    register int last = *bytes == 0 ;
    ByteCount segment = source->segment ;

    if( source->position == source->end || last ) {

	if( segment < *bytes || last )
	    segment = *bytes ;

	source->buffer = PullSome( source->input, &segment ) ;
#if DEBUG
printf( "pulled block at %x from %s\n", source->buffer, SourceName( source->input ) ) ;
#endif
	source->end  = source->buffer + segment ;

	source->position = source->buffer ;
    }

    if( *bytes > source->end - source->position )
	*bytes = source->end - source->position ;

    source->position += *bytes ;

    if( !last )
	return ( source->position - *bytes ) ;
    else
	return ( DeletePullableSource( source ) ) ;
}

Source newBlockingSource( input, segment )
Source input ;
ByteCount segment ;
{
    DeclareNew( BlockingSource, source ) ;

    source->input = input ;

    source->position = source->end = (Pointer) 0 ;

    source->segment = segment ;

    return ( SetPullableSource( source, block_callback, "pullable.c blocking" ) ) ;
}