tomwalters@0
|
1 /*
|
tomwalters@0
|
2 pullable.c
|
tomwalters@0
|
3 ==========
|
tomwalters@0
|
4
|
tomwalters@0
|
5 sources who's native operation is receive pull commands.
|
tomwalters@0
|
6
|
tomwalters@0
|
7 */
|
tomwalters@0
|
8
|
tomwalters@0
|
9 #include "stitch.h"
|
tomwalters@0
|
10 #include "source.h"
|
tomwalters@0
|
11
|
tomwalters@0
|
12 #ifndef lint
|
tomwalters@0
|
13 static char *sccs_id = "@(#)pullable.c 1.3 John Holdsworth (MRC-APU) 6/6/91" ;
|
tomwalters@0
|
14 #endif
|
tomwalters@0
|
15
|
tomwalters@0
|
16 #if 0
|
tomwalters@0
|
17 #define DEBUG 1
|
tomwalters@0
|
18 #endif
|
tomwalters@0
|
19
|
tomwalters@0
|
20 /*
|
tomwalters@0
|
21 fill a users buffer from a process that returns it's own buffer
|
tomwalters@0
|
22
|
tomwalters@0
|
23 */
|
tomwalters@0
|
24
|
tomwalters@0
|
25 static Pointer fillFromPullable( source, bytes, buffer )
|
tomwalters@0
|
26 struct _pullable_source *source ;
|
tomwalters@0
|
27 ByteCount *bytes ;
|
tomwalters@0
|
28 Pointer buffer ;
|
tomwalters@0
|
29 {
|
tomwalters@0
|
30 Pointer input = source->parent.pull( source, bytes ) ;
|
tomwalters@0
|
31
|
tomwalters@0
|
32 CopyArray( (char *) input, (char *) buffer, *bytes ) ;
|
tomwalters@0
|
33
|
tomwalters@0
|
34 return ( buffer ) ;
|
tomwalters@0
|
35 }
|
tomwalters@0
|
36
|
tomwalters@0
|
37 Source setPullableSource( source, puller, name )
|
tomwalters@0
|
38 struct _pullable_source *source ;
|
tomwalters@0
|
39 Pointer (*puller)() ;
|
tomwalters@0
|
40 char *name ;
|
tomwalters@0
|
41 {
|
tomwalters@0
|
42 return ( SetSource( source, puller, fillFromPullable, nonRoller, name ) ) ;
|
tomwalters@0
|
43 }
|
tomwalters@0
|
44
|
tomwalters@0
|
45 Pointer deletePullableSource( source )
|
tomwalters@0
|
46 struct _pullable_source *source ;
|
tomwalters@0
|
47 {
|
tomwalters@0
|
48 return ( DeleteSource( source ) ) ;
|
tomwalters@0
|
49 }
|
tomwalters@0
|
50
|
tomwalters@0
|
51 /*
|
tomwalters@0
|
52 simple slave source as example of derived source
|
tomwalters@0
|
53
|
tomwalters@0
|
54 */
|
tomwalters@0
|
55
|
tomwalters@0
|
56 typedef struct { struct _pullable_source parent ; Source master ; } *SlaveSource ;
|
tomwalters@0
|
57
|
tomwalters@0
|
58 static Pointer slavePull( source, bytes )
|
tomwalters@0
|
59 SlaveSource source ;
|
tomwalters@0
|
60 ByteCount *bytes ;
|
tomwalters@0
|
61 {
|
tomwalters@0
|
62 register int last = *bytes == 0 ;
|
tomwalters@0
|
63
|
tomwalters@0
|
64 if( !last )
|
tomwalters@0
|
65 return ( _SPTR( source->master )->returned ) ;
|
tomwalters@0
|
66 else
|
tomwalters@0
|
67 return ( DeletePullableSource( source ) ) ;
|
tomwalters@0
|
68 }
|
tomwalters@0
|
69
|
tomwalters@0
|
70 Source newSlaveSource( master )
|
tomwalters@0
|
71 Source master ;
|
tomwalters@0
|
72 {
|
tomwalters@0
|
73 DeclareNew( SlaveSource, source ) ;
|
tomwalters@0
|
74
|
tomwalters@0
|
75 source->master = master ;
|
tomwalters@0
|
76
|
tomwalters@0
|
77 return ( SetPullableSource( source, slavePull, "pullable.c slave" ) ) ;
|
tomwalters@0
|
78 }
|
tomwalters@0
|
79
|
tomwalters@0
|
80 /*
|
tomwalters@0
|
81 the simplest Source is one direct from memory
|
tomwalters@0
|
82
|
tomwalters@0
|
83 */
|
tomwalters@0
|
84
|
tomwalters@0
|
85 typedef struct {
|
tomwalters@0
|
86 struct _pullable_source parent ;
|
tomwalters@0
|
87 Pointer next ;
|
tomwalters@0
|
88 } *StaticSource ;
|
tomwalters@0
|
89
|
tomwalters@0
|
90 static Pointer staticPull( source, bytes )
|
tomwalters@0
|
91 StaticSource source ;
|
tomwalters@0
|
92 ByteCount *bytes ;
|
tomwalters@0
|
93 {
|
tomwalters@0
|
94 register int last = *bytes == 0 ;
|
tomwalters@0
|
95 register Pointer this = source->next ;
|
tomwalters@0
|
96
|
tomwalters@0
|
97 if( !last ) {
|
tomwalters@0
|
98
|
tomwalters@0
|
99 source->next += abs( *bytes ) ;
|
tomwalters@0
|
100
|
tomwalters@0
|
101 return ( this ) ;
|
tomwalters@0
|
102 }
|
tomwalters@0
|
103 else
|
tomwalters@0
|
104 return ( DeletePullableSource( source ) ) ;
|
tomwalters@0
|
105 }
|
tomwalters@0
|
106
|
tomwalters@0
|
107 Source newStaticSource( pointer )
|
tomwalters@0
|
108 Pointer pointer ;
|
tomwalters@0
|
109 {
|
tomwalters@0
|
110 DeclareNew( StaticSource, source ) ;
|
tomwalters@0
|
111
|
tomwalters@0
|
112 source->next = pointer ;
|
tomwalters@0
|
113
|
tomwalters@0
|
114 return ( SetPullableSource( source, staticPull, "pullable.c static" ) ) ;
|
tomwalters@0
|
115 }
|
tomwalters@0
|
116
|
tomwalters@0
|
117 typedef struct {
|
tomwalters@0
|
118 struct _pullable_source parent ;
|
tomwalters@0
|
119 Source input ; Pointer buffer ; ByteCount retained ;
|
tomwalters@0
|
120 } *RetainingSource ;
|
tomwalters@0
|
121
|
tomwalters@0
|
122 static Pointer retaining_callback( source, bytes )
|
tomwalters@0
|
123 RetainingSource source ;
|
tomwalters@0
|
124 ByteCount *bytes ;
|
tomwalters@0
|
125 {
|
tomwalters@0
|
126 register int last = *bytes == 0 ;
|
tomwalters@0
|
127 Pointer buffer = RollSome( source->input, bytes, source->retained ) ;
|
tomwalters@0
|
128
|
tomwalters@0
|
129 if( !last )
|
tomwalters@0
|
130 return ( buffer ) ;
|
tomwalters@0
|
131 else
|
tomwalters@0
|
132 return ( DeletePullableSource( source ) ) ;
|
tomwalters@0
|
133 }
|
tomwalters@0
|
134
|
tomwalters@0
|
135 Source newRetainingSource( input, retained )
|
tomwalters@0
|
136 Source input ;
|
tomwalters@0
|
137 ByteCount retained ;
|
tomwalters@0
|
138 {
|
tomwalters@0
|
139 DeclareNew( RetainingSource, source ) ;
|
tomwalters@0
|
140
|
tomwalters@0
|
141 source->retained = retained ;
|
tomwalters@0
|
142
|
tomwalters@0
|
143 source->input = NewRollableSource( input ) ;
|
tomwalters@0
|
144
|
tomwalters@0
|
145 return ( SetPullableSource( source, retaining_callback, "pullable.c retaining" ) ) ;
|
tomwalters@0
|
146 }
|
tomwalters@0
|
147
|
tomwalters@0
|
148 typedef struct {
|
tomwalters@0
|
149 struct _pullable_source parent ;
|
tomwalters@0
|
150 Source input ; ByteCount delay ;
|
tomwalters@0
|
151 } *DelayingSource ;
|
tomwalters@0
|
152
|
tomwalters@0
|
153 static Pointer delay_callback( source, bytes )
|
tomwalters@0
|
154 DelayingSource source ;
|
tomwalters@0
|
155 ByteCount *bytes ;
|
tomwalters@0
|
156 {
|
tomwalters@0
|
157 register int last = *bytes == 0 ;
|
tomwalters@0
|
158 Pointer delayed = PullSome( source->input, bytes ) - source->delay ;
|
tomwalters@0
|
159
|
tomwalters@0
|
160 if( !last )
|
tomwalters@0
|
161 return ( delayed ) ;
|
tomwalters@0
|
162 else
|
tomwalters@0
|
163 return ( DeletePullableSource( source ) ) ;
|
tomwalters@0
|
164 }
|
tomwalters@0
|
165
|
tomwalters@0
|
166 Source newDelayingSource( input, delay )
|
tomwalters@0
|
167 Source input ;
|
tomwalters@0
|
168 ByteCount delay ;
|
tomwalters@0
|
169 {
|
tomwalters@0
|
170 DeclareNew( DelayingSource, source ) ;
|
tomwalters@0
|
171
|
tomwalters@0
|
172 source->input = NewRetainingSource( input, delay ) ;
|
tomwalters@0
|
173
|
tomwalters@0
|
174 source->delay = delay ;
|
tomwalters@0
|
175
|
tomwalters@0
|
176 return ( SetPullableSource( source, delay_callback, "pullable.c delaying" ) ) ;
|
tomwalters@0
|
177 }
|
tomwalters@0
|
178
|
tomwalters@0
|
179 typedef struct {
|
tomwalters@0
|
180 struct _pullable_source parent ;
|
tomwalters@0
|
181 Source input ; Pointer buffer, position, end ; ByteCount segment ;
|
tomwalters@0
|
182 } *BlockingSource ;
|
tomwalters@0
|
183
|
tomwalters@0
|
184 static Pointer block_callback( source, bytes )
|
tomwalters@0
|
185 BlockingSource source ;
|
tomwalters@0
|
186 ByteCount *bytes ;
|
tomwalters@0
|
187 {
|
tomwalters@0
|
188 register int last = *bytes == 0 ;
|
tomwalters@0
|
189 ByteCount segment = source->segment ;
|
tomwalters@0
|
190
|
tomwalters@0
|
191 if( source->position == source->end || last ) {
|
tomwalters@0
|
192
|
tomwalters@0
|
193 if( segment < *bytes || last )
|
tomwalters@0
|
194 segment = *bytes ;
|
tomwalters@0
|
195
|
tomwalters@0
|
196 source->buffer = PullSome( source->input, &segment ) ;
|
tomwalters@0
|
197 #if DEBUG
|
tomwalters@0
|
198 printf( "pulled block at %x from %s\n", source->buffer, SourceName( source->input ) ) ;
|
tomwalters@0
|
199 #endif
|
tomwalters@0
|
200 source->end = source->buffer + segment ;
|
tomwalters@0
|
201
|
tomwalters@0
|
202 source->position = source->buffer ;
|
tomwalters@0
|
203 }
|
tomwalters@0
|
204
|
tomwalters@0
|
205 if( *bytes > source->end - source->position )
|
tomwalters@0
|
206 *bytes = source->end - source->position ;
|
tomwalters@0
|
207
|
tomwalters@0
|
208 source->position += *bytes ;
|
tomwalters@0
|
209
|
tomwalters@0
|
210 if( !last )
|
tomwalters@0
|
211 return ( source->position - *bytes ) ;
|
tomwalters@0
|
212 else
|
tomwalters@0
|
213 return ( DeletePullableSource( source ) ) ;
|
tomwalters@0
|
214 }
|
tomwalters@0
|
215
|
tomwalters@0
|
216 Source newBlockingSource( input, segment )
|
tomwalters@0
|
217 Source input ;
|
tomwalters@0
|
218 ByteCount segment ;
|
tomwalters@0
|
219 {
|
tomwalters@0
|
220 DeclareNew( BlockingSource, source ) ;
|
tomwalters@0
|
221
|
tomwalters@0
|
222 source->input = input ;
|
tomwalters@0
|
223
|
tomwalters@0
|
224 source->position = source->end = (Pointer) 0 ;
|
tomwalters@0
|
225
|
tomwalters@0
|
226 source->segment = segment ;
|
tomwalters@0
|
227
|
tomwalters@0
|
228 return ( SetPullableSource( source, block_callback, "pullable.c blocking" ) ) ;
|
tomwalters@0
|
229 }
|
tomwalters@0
|
230
|