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