comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:5242703e91d3
1 /*
2 fillable.c
3 ==========
4
5 Sources whose native mode of operation is the fill entry point.
6 They may be pulled in which case a buffer is allocated.
7
8 */
9
10 #include "stitch.h"
11 #include "source.h"
12
13 #ifndef lint
14 static char *sccs_id = "@(#)fillable.c 1.2 John Holdsworth (MRC-APU) 11/8/90" ;
15 #endif
16
17 #if 0
18 #define DEBUG 1
19 #endif
20
21 Source SharingSource( source1, source2 )
22 struct _fillable_source *source1, *source2 ;
23 {
24 DeleteBuffer( source1->buffer ) ;
25
26 source1->buffer = SharedBuffer( source2->buffer ) ;
27
28 return ( (Source) source1 ) ;
29 }
30
31 /* converter of pull command to fill commands */
32
33 static Pointer pullFromFillable( source, bytes )
34 struct _fillable_source *source ;
35 ByteCount *bytes ;
36 {
37 #if DEBUG
38 printf( "buffering pulling from passive \"%s\", %d bytes\n", SourceName( source ), *bytes ) ;
39 #endif
40 #if 00
41 if( source->bsize < *bytes ) {
42
43 if( source->bsize != 0 )
44 Delete( source->buffer ) ;
45
46 source->buffer = Allocate( *bytes, "fillable.c for source buffer" ) ;
47
48 source->bsize = *bytes ;
49 }
50 #endif
51 return ( source->parent.fill( source, bytes, SizedBufferPointer( SourceBuffer( source ), *bytes ) ) ) ;
52 }
53
54 /* constructor for all pullable sources */
55
56 Source setFillableSource( source, filler, name )
57 struct _fillable_source *source ;
58 Pointer (*filler)() ;
59 char *name ;
60 {
61 source->buffer = NewBuffer( "pulling" ) ;
62
63 return ( SetSource( source, pullFromFillable, filler, nonRoller, name ) ) ;
64 }
65
66 Pointer deleteFillableSource( source )
67 struct _fillable_source *source ;
68 {
69 DeleteBuffer( source->buffer ) ;
70
71 return ( DeleteSource( source ) ) ;
72 }
73
74
75 /* derived fillable source */
76
77 typedef struct {
78 struct _fillable_source parent ;
79 Pointer data, end, ptr ;
80 } *RepeatingSource ;
81
82 static Pointer repeating_callback( source, bytes, buffer )
83 RepeatingSource source ;
84 ByteCount *bytes ;
85 Pointer buffer ;
86 {
87 register int last = *bytes == 0 ;
88 register Pointer bptr = buffer ;
89 register Pointer bend = buffer + *bytes ;
90 register ByteCount segment ;
91
92 if( !last ) {
93
94 while( bptr < bend ) {
95
96 segment = source->end - source->ptr ;
97 if( segment > bend - bptr )
98 segment = bend - bptr ;
99
100 CopyArray( (char *) source->ptr, (char *) bptr, segment ) ;
101
102 source->ptr += segment ;
103 bptr += segment ;
104
105 if( source->ptr == source->end )
106 source->ptr = source->data ;
107 }
108
109 return ( buffer ) ;
110 }
111 else
112 return ( DeleteFillableSource( source ) ) ;
113 }
114
115 Source newRepeatingSource( data, segment )
116 Pointer data ;
117 ByteCount segment ;
118 {
119 DeclareNew( RepeatingSource, source ) ;
120
121 source->data = data ;
122 source->end = data + segment ;
123
124 source->ptr = source->data ;
125
126 return ( SetFillableSource( source, repeating_callback, "fillable.c repeating" ) ) ;
127 }
128
129 typedef struct {
130 struct _fillable_source parent ;
131 Source input ; ByteCount segment ;
132 } *SegmentingSource ;
133
134 static Pointer segmenting_callback( source, bytes, buffer )
135 SegmentingSource source ;
136 ByteCount *bytes ;
137 Pointer buffer ;
138 {
139 register int last = *bytes == 0 ;
140 Pointer bptr = buffer ;
141 ByteCount segment ;
142
143 do {
144
145 segment = source->segment ;
146
147 if( segment > buffer + *bytes - bptr )
148 segment = buffer + *bytes - bptr ;
149
150 (void) FillSome( source->input, &segment, bptr ) ;
151
152 bptr += segment ;
153
154 } while ( bptr < buffer + *bytes ) ;
155
156 if( !last )
157 return ( buffer ) ;
158 else
159 return ( DeleteFillableSource( source ) ) ;
160 }
161
162 Source newSegmentingSource( input, segment )
163 Source input ;
164 ByteCount segment ;
165 {
166 DeclareNew( SegmentingSource, source ) ;
167
168 source->input = input ;
169
170 source->segment = segment ;
171
172 return ( SetFillableSource( source, segmenting_callback, "segmenting" ) ) ;
173 }
174
175
176
177 /* higher level methods to sources */
178
179
180 typedef struct _callback_source {
181 struct _fillable_source parent ;
182 Pointer state ;
183 void (*callback)(), (*close)() ;
184 } *CallbackSource ;
185
186 Source setCallbackSource( source, filler, state, callback, close, name )
187 CallbackSource source ;
188 Pointer (*filler)() ;
189 Pointer state ;
190 void (*callback)(), (*close)() ;
191 char *name ;
192 {
193 source->state = state ;
194 source->callback = callback ;
195 source->close = close ;
196
197 return ( SetFillableSource( source, filler, name ) ) ;
198 }
199
200 Source newCallbackSource( filler, state, callback, close, name )
201 Pointer (*filler)() ;
202 Pointer state ;
203 void (*callback)(), (*close)() ;
204 char *name ;
205 {
206 return ( setCallbackSource( New( CallbackSource ), filler, state, callback, close, name ) ) ;
207 }
208
209 static Pointer externalFiller( source, bytes, buffer )
210 CallbackSource source ;
211 ByteCount *bytes ;
212 Pointer buffer ;
213 {
214 register int last = *bytes == 0 ;
215
216 source->callback( source->state, bytes, buffer, buffer+*bytes ) ;
217
218 if( !last )
219 return ( buffer ) ;
220 else {
221 if( source->close != (void ( * )()) 0 )
222 source->close( source->state ) ;
223
224 return ( DeleteFillableSource( source ) ) ;
225 }
226 }
227
228 Source newExternalSource( state, callback, close, name )
229 Pointer state ;
230 void (*callback)(), (*close)() ;
231 char *name ;
232 {
233 return ( newCallbackSource( externalFiller, state, callback, close, name ) ) ;
234 }
235
236 typedef struct _through_source {
237 struct _callback_source parent ;
238 Source input ;
239 } *ThroughSource ;
240
241 static Source setThroughSource( source, filler, state, callback, close, input, name )
242 ThroughSource source ;
243 Pointer (*filler)() ;
244 Pointer state ;
245 void (*callback)(), (*close)() ;
246 Source input ;
247 char *name ;
248 {
249 source->input = input ;
250
251 return ( setCallbackSource( (CallbackSource) source, filler, state, callback, close, name ) ) ;
252 }
253
254 Source newThroughSource( filler, state, callback, close, input, name )
255 Pointer (*filler)(), state ;
256 void (*callback)(), (*close)() ;
257 Source input ;
258 char *name ;
259 {
260 return ( setThroughSource( New( ThroughSource ), filler, state, callback, close, input, name ) ) ;
261 }
262
263
264 static Pointer processingFiller( source, bytes, buffer )
265 ThroughSource source ;
266 ByteCount *bytes ;
267 Pointer buffer ;
268 {
269 register int last = *bytes == 0 ;
270
271 source->parent.callback( source->parent.state, bytes, buffer, buffer+*bytes, PullSome( source->input, bytes ) ) ;
272
273 if( !last )
274 return ( buffer ) ;
275 else {
276 if( source->parent.close != (void ( * )()) 0 )
277 source->parent.close( source->parent.state ) ;
278
279 return ( DeleteFillableSource( &source->parent ) ) ;
280 }
281 }
282
283 Source newProcessingSource( state, callback, close, input, name )
284 Pointer state ;
285 void (*callback)(), (*close)() ;
286 Source input ;
287 char *name ;
288 {
289 return ( newThroughSource( processingFiller, state, callback, close, input, name ) ) ;
290 }
291
292 Source newSimpleProcessingSource( callback, input, name )
293 void (*callback)() ;
294 Source input ;
295 char *name ;
296 {
297 return ( NewProcessingSource( (Pointer) 0, callback, (void ( * )()) 0, input, name ) ) ;
298 }
299
300 typedef struct {
301 struct _fillable_source parent ;
302 Pointer *states ;
303 int (*callback)() ;
304 void (*close)() ;
305 int channels ;
306 Source input ;
307 } *MultiplexedSource ;
308
309 static Pointer multiplexed_callback( source, bytes, buffer )
310 MultiplexedSource source ;
311 ByteCount *bytes ;
312 Pointer buffer ;
313 {
314 register int last = *bytes == 0 ;
315 Pointer iptr = PullSome( source->input, bytes ) ;
316 Pointer optr = buffer ;
317 Pointer end = buffer + *bytes ;
318 ByteCount data_size ;
319 int channel ;
320
321 for( channel=0 ; channel<source->channels ; channel++ ) {
322 data_size = source->callback( source->states[channel], optr, end, iptr, source->channels ) ;
323 iptr += data_size ;
324 optr += data_size ;
325 }
326
327 if( !last )
328 return ( buffer ) ;
329 else {
330 if( source->close != (void ( * )()) 0 )
331 for( channel=0 ; channel<source->channels ; channel++ )
332 source->close( source->states[channel] ) ;
333
334 Delete( source->states ) ;
335
336 return ( DeleteFillableSource( source ) ) ;
337 }
338 }
339
340 Source newMultiplexedSource( states, callback, close, channels, input, name )
341 Pointer *states ;
342 int (*callback)() ;
343 void (*close)() ;
344 int channels ;
345 Source input ;
346 char *name ;
347 {
348 DeclareNew( MultiplexedSource, source ) ;
349
350 source->states = states ;
351 source->callback = callback ;
352 source->close = close ;
353 source->channels = channels ;
354
355 source->input = input ;
356
357 return ( SetFillableSource( source, multiplexed_callback, name ) ) ;
358 }
359
360 typedef struct _merging_source {
361 struct _callback_source parent ; Source *inputs ;
362 } *MergingSource ;
363
364 static Pointer mergingFiller( source, bytes, buffer )
365 MergingSource source ;
366 ByteCount *bytes ;
367 Pointer buffer ;
368 {
369 register int last = *bytes == 0 ;
370 Pointer input1, input2 ;
371 int n ;
372
373 input1 = PullSome( source->inputs[0], bytes ) ;
374
375 for( n=1 ; _SPTR( source->inputs[n] ) != (struct _source *) 0 ; n++ ) {
376
377 input2 = PullSome( source->inputs[n], bytes ) ;
378
379 source->parent.callback( source->parent.state, bytes, buffer, buffer+*bytes, input1, input2 ) ;
380
381 input1 = buffer ;
382 }
383
384 if( !last )
385 return ( buffer ) ;
386 else {
387 Delete( source->inputs ) ;
388
389 return ( DeleteFillableSource( &source->parent ) ) ;
390 }
391 }
392
393 Source newMergingSource( state, callback, close, inputs, name )
394 Pointer state ;
395 void (*callback)(), (*close)() ;
396 Source *inputs ;
397 char *name ;
398 {
399 DeclareNew( MergingSource, source ) ;
400
401 source->inputs = inputs ;
402
403 return ( setCallbackSource( (CallbackSource) source, mergingFiller, state, callback, close, name ) ) ;
404 }
405