Mercurial > hg > aim92
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 |