2 |
- |
1 |
/* Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved.
|
|
|
2 |
|
|
|
3 |
This software is provided AS-IS with no warranty, either express or
|
|
|
4 |
implied.
|
|
|
5 |
|
|
|
6 |
This software is distributed under license and may not be copied,
|
|
|
7 |
modified or distributed except as expressly authorized under the terms
|
|
|
8 |
of the license contained in the file LICENSE in this distribution.
|
|
|
9 |
|
|
|
10 |
For more information about licensing, please refer to
|
|
|
11 |
http://www.ghostscript.com/licensing/. For information on
|
|
|
12 |
commercial licensing, go to http://www.artifex.com/licensing/ or
|
|
|
13 |
contact Artifex Software, Inc., 101 Lucas Valley Road #110,
|
|
|
14 |
San Rafael, CA 94903, U.S.A., +1(415)492-9861.
|
|
|
15 |
*/
|
|
|
16 |
|
|
|
17 |
/* $Id: stream.h,v 1.11 2002/06/16 05:00:54 lpd Exp $ */
|
|
|
18 |
/* Definitions for Ghostscript stream package */
|
|
|
19 |
/* Requires stdio.h */
|
|
|
20 |
|
|
|
21 |
#ifndef stream_INCLUDED
|
|
|
22 |
# define stream_INCLUDED
|
|
|
23 |
|
|
|
24 |
#include "scommon.h"
|
|
|
25 |
#include "srdline.h"
|
|
|
26 |
|
|
|
27 |
/* See scommon.h for documentation on the design of streams. */
|
|
|
28 |
|
|
|
29 |
/* ------ Stream structure definition ------ */
|
|
|
30 |
|
|
|
31 |
/*
|
|
|
32 |
* We expose the stream structure definition to clients so that
|
|
|
33 |
* they can get reasonable performance out of the basic operations.
|
|
|
34 |
*/
|
|
|
35 |
|
|
|
36 |
/* Define the "virtual" stream procedures. */
|
|
|
37 |
|
|
|
38 |
typedef struct {
|
|
|
39 |
|
|
|
40 |
/* Store # available for reading. */
|
|
|
41 |
/* Return 0 if OK, ERRC if error or not implemented. */
|
|
|
42 |
#define stream_proc_available(proc)\
|
|
|
43 |
int proc(stream *, long *)
|
|
|
44 |
stream_proc_available((*available));
|
|
|
45 |
|
|
|
46 |
/* Set position. */
|
|
|
47 |
/* Return 0 if OK, ERRC if error or not implemented. */
|
|
|
48 |
#define stream_proc_seek(proc)\
|
|
|
49 |
int proc(stream *, long)
|
|
|
50 |
stream_proc_seek((*seek));
|
|
|
51 |
|
|
|
52 |
/* Clear buffer and, if relevant, unblock channel. */
|
|
|
53 |
/* Cannot cause an error. */
|
|
|
54 |
#define stream_proc_reset(proc)\
|
|
|
55 |
void proc(stream *)
|
|
|
56 |
stream_proc_reset((*reset));
|
|
|
57 |
|
|
|
58 |
/* Flush buffered data to output, or drain input. */
|
|
|
59 |
/* Return 0 if OK, ERRC if error. */
|
|
|
60 |
#define stream_proc_flush(proc)\
|
|
|
61 |
int proc(stream *)
|
|
|
62 |
stream_proc_flush((*flush));
|
|
|
63 |
|
|
|
64 |
/* Flush data (if writing) & close stream. */
|
|
|
65 |
/* Return 0 if OK, ERRC if error. */
|
|
|
66 |
#define stream_proc_close(proc)\
|
|
|
67 |
int proc(stream *)
|
|
|
68 |
stream_proc_close((*close));
|
|
|
69 |
|
|
|
70 |
/* Process a buffer, updating the cursor pointers. */
|
|
|
71 |
/* See strimpl.h for details. */
|
|
|
72 |
stream_proc_process((*process));
|
|
|
73 |
|
|
|
74 |
/* Switch the stream to read or write mode. */
|
|
|
75 |
/* false = read, true = write. */
|
|
|
76 |
/* If the procedure is 0, switching is not allowed. */
|
|
|
77 |
#define stream_proc_switch_mode(proc)\
|
|
|
78 |
int proc(stream *, bool)
|
|
|
79 |
stream_proc_switch_mode((*switch_mode));
|
|
|
80 |
|
|
|
81 |
} stream_procs;
|
|
|
82 |
|
|
|
83 |
/* ------ The actual stream structure ------ */
|
|
|
84 |
|
|
|
85 |
struct stream_s {
|
|
|
86 |
/*
|
|
|
87 |
* To allow the stream itself to serve as the "state"
|
|
|
88 |
* of a couple of heavily used types, we start its
|
|
|
89 |
* definition with the common stream state.
|
|
|
90 |
*/
|
|
|
91 |
stream_state_common;
|
|
|
92 |
/*
|
|
|
93 |
* The following invariants apply at all times for read streams:
|
|
|
94 |
*
|
|
|
95 |
* s->cbuf - 1 <= s->srptr <= s->srlimit.
|
|
|
96 |
*
|
|
|
97 |
* The amount of data in the buffer is s->srlimit + 1 - s->cbuf.
|
|
|
98 |
*
|
|
|
99 |
* s->position represents the stream position as of the beginning
|
|
|
100 |
* of the buffer, so the current position is s->position +
|
|
|
101 |
* (s->srptr + 1 - s->cbuf).
|
|
|
102 |
*
|
|
|
103 |
* Analogous invariants apply for write streams:
|
|
|
104 |
*
|
|
|
105 |
* s->cbuf - 1 <= s->swptr <= s->swlimit.
|
|
|
106 |
*
|
|
|
107 |
* The amount of data in the buffer is s->swptr + 1 - s->cbuf.
|
|
|
108 |
*
|
|
|
109 |
* s->position represents the stream position as of the beginning
|
|
|
110 |
* of the buffer, so the current position is s->position +
|
|
|
111 |
* (s->swptr + 1 - s->cbuf).
|
|
|
112 |
*/
|
|
|
113 |
stream_cursor cursor; /* cursor for reading/writing data */
|
|
|
114 |
byte *cbuf; /* base of buffer */
|
|
|
115 |
uint bsize; /* size of buffer, 0 if closed */
|
|
|
116 |
uint cbsize; /* size of buffer */
|
|
|
117 |
/*
|
|
|
118 |
* end_status indicates what should happen when the client
|
|
|
119 |
* reaches the end of the buffer:
|
|
|
120 |
* 0 in the normal case;
|
|
|
121 |
* EOFC if a read stream has reached EOD or a write
|
|
|
122 |
* stream has written the EOD marker;
|
|
|
123 |
* ERRC if an error terminated the last read or write
|
|
|
124 |
* operation from or to the underlying data source
|
|
|
125 |
* or sink;
|
|
|
126 |
* INTC if the last transfer was interrupted (NOT
|
|
|
127 |
* USED YET);
|
|
|
128 |
* CALLC if a callout is required.
|
|
|
129 |
*/
|
|
|
130 |
short end_status; /* status at end of buffer (when */
|
|
|
131 |
/* reading) or now (when writing) */
|
|
|
132 |
byte foreign; /* true if buffer is outside heap */
|
|
|
133 |
byte modes; /* access modes allowed for this stream */
|
|
|
134 |
#define s_mode_read 1
|
|
|
135 |
#define s_mode_write 2
|
|
|
136 |
#define s_mode_seek 4
|
|
|
137 |
#define s_mode_append 8 /* (s_mode_write also set) */
|
|
|
138 |
#define s_is_valid(s) ((s)->modes != 0)
|
|
|
139 |
#define s_is_reading(s) (((s)->modes & s_mode_read) != 0)
|
|
|
140 |
#define s_is_writing(s) (((s)->modes & s_mode_write) != 0)
|
|
|
141 |
#define s_can_seek(s) (((s)->modes & s_mode_seek) != 0)
|
|
|
142 |
gs_string cbuf_string; /* cbuf/cbsize if cbuf is a string, */
|
|
|
143 |
/* 0/? if not */
|
|
|
144 |
long position; /* file position of beginning of */
|
|
|
145 |
/* buffer */
|
|
|
146 |
stream_procs procs;
|
|
|
147 |
stream *strm; /* the underlying stream, non-zero */
|
|
|
148 |
/* iff this is a filter stream */
|
|
|
149 |
int is_temp; /* if >0, this is a temporary */
|
|
|
150 |
/* stream and should be freed */
|
|
|
151 |
/* when its source/sink is closed; */
|
|
|
152 |
/* if >1, the buffer is also */
|
|
|
153 |
/* temporary */
|
|
|
154 |
int inline_temp; /* temporary for inline access */
|
|
|
155 |
/* (see spgetc_inline below) */
|
|
|
156 |
stream_state *state; /* state of process */
|
|
|
157 |
/*
|
|
|
158 |
* The following are for the use of the interpreter.
|
|
|
159 |
* See files.h for more information on read_id and write_id,
|
|
|
160 |
* zfile.c for more information on prev and next,
|
|
|
161 |
* zfilter.c for more information on close_strm.
|
|
|
162 |
*/
|
|
|
163 |
ushort read_id; /* "unique" serial # for detecting */
|
|
|
164 |
/* references to closed streams */
|
|
|
165 |
/* and for validating read access */
|
|
|
166 |
ushort write_id; /* ditto to validate write access */
|
|
|
167 |
stream *prev, *next; /* keep track of all files */
|
|
|
168 |
bool close_strm; /* CloseSource/CloseTarget */
|
|
|
169 |
bool close_at_eod; /*(default is true, only false if "reusable")*/
|
|
|
170 |
int (*save_close)(stream *); /* save original close proc */
|
|
|
171 |
/*
|
|
|
172 |
* In order to avoid allocating a separate stream_state for
|
|
|
173 |
* file streams, which are the most heavily used stream type,
|
|
|
174 |
* we put their state here.
|
|
|
175 |
*/
|
|
|
176 |
FILE *file; /* file handle for C library */
|
|
|
177 |
gs_const_string file_name; /* file name (optional) -- clients must */
|
|
|
178 |
/* access only through procedures */
|
|
|
179 |
uint file_modes; /* access modes for the file, */
|
|
|
180 |
/* may be a superset of modes */
|
|
|
181 |
/* Clients must only set the following through sread_subfile. */
|
|
|
182 |
long file_offset; /* starting point in file (reading) */
|
|
|
183 |
long file_limit; /* ending point in file (reading) */
|
|
|
184 |
};
|
|
|
185 |
|
|
|
186 |
/* The descriptor is only public for subclassing. */
|
|
|
187 |
extern_st(st_stream);
|
|
|
188 |
#define public_st_stream() /* in stream.c */\
|
|
|
189 |
gs_public_st_composite_final(st_stream, stream, "stream",\
|
|
|
190 |
stream_enum_ptrs, stream_reloc_ptrs, stream_finalize)
|
|
|
191 |
#define STREAM_NUM_PTRS 6
|
|
|
192 |
|
|
|
193 |
/* Initialize the checking IDs of a stream. */
|
|
|
194 |
#define s_init_ids(s) ((s)->read_id = (s)->write_id = 1)
|
|
|
195 |
#define s_init_read_id(s) ((s)->read_id = 1, (s)->write_id = 0)
|
|
|
196 |
#define s_init_write_id(s) ((s)->read_id = 0, (s)->write_id = 1)
|
|
|
197 |
#define s_init_no_id(s) ((s)->read_id = (s)->write_id = 0)
|
|
|
198 |
|
|
|
199 |
/* ------ Stream functions ------ */
|
|
|
200 |
|
|
|
201 |
#define srptr cursor.r.ptr
|
|
|
202 |
#define srlimit cursor.r.limit
|
|
|
203 |
#define swptr cursor.w.ptr
|
|
|
204 |
#define swlimit cursor.w.limit
|
|
|
205 |
|
|
|
206 |
/* Some of these are macros -- beware. */
|
|
|
207 |
/* Note that unlike the C stream library, */
|
|
|
208 |
/* ALL stream procedures take the stream as the first argument. */
|
|
|
209 |
#define sendrp(s) ((s)->srptr >= (s)->srlimit) /* NOT FOR CLIENTS */
|
|
|
210 |
#define sendwp(s) ((s)->swptr >= (s)->swlimit) /* NOT FOR CLIENTS */
|
|
|
211 |
|
|
|
212 |
/*
|
|
|
213 |
* Following are valid for all streams.
|
|
|
214 |
*/
|
|
|
215 |
/* flush is NOT a no-op for read streams -- it discards data until EOF. */
|
|
|
216 |
/* close is NOT a no-op for non-file streams -- */
|
|
|
217 |
/* it actively disables them. */
|
|
|
218 |
/* The close routine must do a flush if needed. */
|
|
|
219 |
#define sseekable(s) s_can_seek(s)
|
|
|
220 |
int savailable(stream *, long *);
|
|
|
221 |
|
|
|
222 |
#define sreset(s) (*(s)->procs.reset)(s)
|
|
|
223 |
#define sflush(s) (*(s)->procs.flush)(s)
|
|
|
224 |
int sclose(stream *);
|
|
|
225 |
int sswitch(stream *, bool);
|
|
|
226 |
|
|
|
227 |
/*
|
|
|
228 |
* Following are only valid for read streams.
|
|
|
229 |
*/
|
|
|
230 |
int spgetcc(stream *, bool); /* bool indicates close at EOD */
|
|
|
231 |
#define spgetc(s) spgetcc(s, true) /* a procedure equivalent of sgetc */
|
|
|
232 |
/*
|
|
|
233 |
* Note that sgetc must call spgetc one byte early, because filter must read
|
|
|
234 |
* ahead to detect EOD.
|
|
|
235 |
*
|
|
|
236 |
* In the definition of sgetc, the first alternative should read
|
|
|
237 |
* (int)(*++((s)->srptr))
|
|
|
238 |
* but the Borland compiler generates truly atrocious code for this.
|
|
|
239 |
* The SCO ODT compiler requires the first, pointless cast to int.
|
|
|
240 |
*/
|
|
|
241 |
#define sgetc(s)\
|
|
|
242 |
((int)((s)->srlimit - (s)->srptr > 1 ? (++((s)->srptr), (int)*(s)->srptr) : spgetc(s)))
|
|
|
243 |
int sgets(stream *, byte *, uint, uint *);
|
|
|
244 |
int sungetc(stream *, byte); /* ERRC on error, 0 if OK */
|
|
|
245 |
|
|
|
246 |
#define sputback(s) ((s)->srptr--) /* can only do this once! */
|
|
|
247 |
#define seofp(s) (sendrp(s) && (s)->end_status == EOFC)
|
|
|
248 |
#define serrorp(s) (sendrp(s) && (s)->end_status == ERRC)
|
|
|
249 |
int spskip(stream *, long, long *);
|
|
|
250 |
|
|
|
251 |
#define sskip(s,nskip,pskipped) spskip(s, (long)(nskip), pskipped)
|
|
|
252 |
/*
|
|
|
253 |
* Attempt to refill the buffer of a read stream.
|
|
|
254 |
* Only call this if the end_status is not EOFC,
|
|
|
255 |
* and if the buffer is (nearly) empty.
|
|
|
256 |
*/
|
|
|
257 |
int s_process_read_buf(stream *);
|
|
|
258 |
|
|
|
259 |
/*
|
|
|
260 |
* Following are only valid for write streams.
|
|
|
261 |
*/
|
|
|
262 |
int spputc(stream *, byte); /* a procedure equivalent of sputc */
|
|
|
263 |
|
|
|
264 |
/*
|
|
|
265 |
* The first alternative should read
|
|
|
266 |
* ((int)(*++((s)->swptr)=(c)))
|
|
|
267 |
* but the Borland compiler generates truly atrocious code for this.
|
|
|
268 |
*/
|
|
|
269 |
#define sputc(s,c)\
|
|
|
270 |
(!sendwp(s) ? (++((s)->swptr), *(s)->swptr=(c), 0) : spputc((s),(c)))
|
|
|
271 |
int sputs(stream *, const byte *, uint, uint *);
|
|
|
272 |
|
|
|
273 |
/*
|
|
|
274 |
* Attempt to empty the buffer of a write stream.
|
|
|
275 |
* Only call this if the end_status is not EOFC.
|
|
|
276 |
*/
|
|
|
277 |
int s_process_write_buf(stream *, bool);
|
|
|
278 |
|
|
|
279 |
/* Following are only valid for positionable streams. */
|
|
|
280 |
long stell(stream *);
|
|
|
281 |
int spseek(stream *, long);
|
|
|
282 |
|
|
|
283 |
#define sseek(s,pos) spseek(s, (long)(pos))
|
|
|
284 |
|
|
|
285 |
/* Following are for high-performance reading clients. */
|
|
|
286 |
/* bufptr points to the next item. */
|
|
|
287 |
#define sbufptr(s) ((s)->srptr + 1)
|
|
|
288 |
#define sbufavailable(s) ((s)->srlimit - (s)->srptr)
|
|
|
289 |
#define sbufskip(s, n) ((s)->srptr += (n), 0)
|
|
|
290 |
/*
|
|
|
291 |
* Define the minimum amount of data that must be left in an input buffer
|
|
|
292 |
* after a read operation to handle filter read-ahead, either 0 or 1
|
|
|
293 |
* byte(s).
|
|
|
294 |
*/
|
|
|
295 |
#define max_min_left 1
|
|
|
296 |
/*
|
|
|
297 |
* The stream.state min_left value is the minimum amount of data that must
|
|
|
298 |
* be left in an input buffer after a read operation to handle filter
|
|
|
299 |
* read-ahead. Once filters reach EOD, return 0 since read-ahead is
|
|
|
300 |
* no longer relevant.
|
|
|
301 |
*/
|
|
|
302 |
#define sbuf_min_left(s) \
|
|
|
303 |
((s->end_status == EOFC || s->end_status == ERRC ? 0 : s->state->min_left))
|
|
|
304 |
|
|
|
305 |
/* The following are for very high-performance clients of read streams, */
|
|
|
306 |
/* who unpack the stream state into local variables. */
|
|
|
307 |
/* Note that any non-inline operations must do a s_end_inline before, */
|
|
|
308 |
/* and a s_begin_inline after. */
|
|
|
309 |
#define s_declare_inline(s, cp, ep)\
|
|
|
310 |
register const byte *cp;\
|
|
|
311 |
const byte *ep
|
|
|
312 |
#define s_begin_inline(s, cp, ep)\
|
|
|
313 |
cp = (s)->srptr, ep = (s)->srlimit
|
|
|
314 |
#define s_end_inline(s, cp, ep)\
|
|
|
315 |
(s)->srptr = cp
|
|
|
316 |
#define sbufavailable_inline(s, cp, ep)\
|
|
|
317 |
(ep - cp)
|
|
|
318 |
#define sendbufp_inline(s, cp, ep)\
|
|
|
319 |
(cp >= ep)
|
|
|
320 |
/* The (int) is needed to pacify the SCO ODT compiler. */
|
|
|
321 |
#define sgetc_inline(s, cp, ep)\
|
|
|
322 |
((int)(sendbufp_inline(s, cp, ep) ? spgetc_inline(s, cp, ep) : *++cp))
|
|
|
323 |
#define spgetc_inline(s, cp, ep)\
|
|
|
324 |
(s_end_inline(s, cp, ep), (s)->inline_temp = spgetc(s),\
|
|
|
325 |
s_begin_inline(s, cp, ep), (s)->inline_temp)
|
|
|
326 |
#define sputback_inline(s, cp, ep)\
|
|
|
327 |
--cp
|
|
|
328 |
|
|
|
329 |
/* Allocate a stream or a stream state. */
|
|
|
330 |
stream *s_alloc(gs_memory_t *, client_name_t);
|
|
|
331 |
stream_state *s_alloc_state(gs_memory_t *, gs_memory_type_ptr_t, client_name_t);
|
|
|
332 |
/*
|
|
|
333 |
* Initialize a separately allocated stream or stream state, as if allocated
|
|
|
334 |
* by s_alloc[_state].
|
|
|
335 |
*/
|
|
|
336 |
void s_init(stream *, gs_memory_t *);
|
|
|
337 |
void s_init_state(stream_state *, const stream_template *, gs_memory_t *);
|
|
|
338 |
|
|
|
339 |
/* Create a stream on a string or a file. */
|
|
|
340 |
void sread_string(stream *, const byte *, uint),
|
|
|
341 |
sread_string_reusable(stream *, const byte *, uint),
|
|
|
342 |
swrite_string(stream *, byte *, uint);
|
|
|
343 |
void sread_file(stream *, FILE *, byte *, uint),
|
|
|
344 |
swrite_file(stream *, FILE *, byte *, uint),
|
|
|
345 |
sappend_file(stream *, FILE *, byte *, uint);
|
|
|
346 |
|
|
|
347 |
/* Confine reading to a subfile. This is primarily for reusable streams. */
|
|
|
348 |
int sread_subfile(stream *s, long start, long length);
|
|
|
349 |
|
|
|
350 |
/* Set the file name of a stream, copying the name. */
|
|
|
351 |
/* Return <0 if the copy could not be allocated. */
|
|
|
352 |
int ssetfilename(stream *, const byte *, uint);
|
|
|
353 |
|
|
|
354 |
/* Return the file name of a stream, if any. */
|
|
|
355 |
/* There is a guaranteed 0 byte after the string. */
|
|
|
356 |
int sfilename(stream *, gs_const_string *);
|
|
|
357 |
|
|
|
358 |
/* Create a stream that tracks the position, */
|
|
|
359 |
/* for calculating how much space to allocate when actually writing. */
|
|
|
360 |
void swrite_position_only(stream *);
|
|
|
361 |
|
|
|
362 |
/* Standard stream initialization */
|
|
|
363 |
void s_std_init(stream *, byte *, uint, const stream_procs *, int /*mode */ );
|
|
|
364 |
|
|
|
365 |
/* Standard stream finalization */
|
|
|
366 |
void s_disable(stream *);
|
|
|
367 |
|
|
|
368 |
/* Generic stream procedures exported for templates */
|
|
|
369 |
int s_std_null(stream *);
|
|
|
370 |
void s_std_read_reset(stream *), s_std_write_reset(stream *);
|
|
|
371 |
int s_std_read_flush(stream *), s_std_write_flush(stream *), s_std_noavailable(stream *, long *),
|
|
|
372 |
s_std_noseek(stream *, long), s_std_close(stream *), s_std_switch_mode(stream *, bool);
|
|
|
373 |
|
|
|
374 |
/* Generic procedures for filters. */
|
|
|
375 |
int s_filter_write_flush(stream *), s_filter_close(stream *);
|
|
|
376 |
|
|
|
377 |
/* Generic procedure structures for filters. */
|
|
|
378 |
extern const stream_procs s_filter_read_procs, s_filter_write_procs;
|
|
|
379 |
|
|
|
380 |
/*
|
|
|
381 |
* Add a filter to an output pipeline. The client must have allocated the
|
|
|
382 |
* stream state, if any, using the given allocator. For s_init_filter, the
|
|
|
383 |
* client must have called s_init and s_init_state.
|
|
|
384 |
*
|
|
|
385 |
* Note that if additional buffering is needed, s_add_filter may add
|
|
|
386 |
* an additional filter to provide it.
|
|
|
387 |
*/
|
|
|
388 |
int s_init_filter(stream *fs, stream_state *fss, byte *buf, uint bsize,
|
|
|
389 |
stream *target);
|
|
|
390 |
stream *s_add_filter(stream **ps, const stream_template *template,
|
|
|
391 |
stream_state *ss, gs_memory_t *mem);
|
|
|
392 |
|
|
|
393 |
/*
|
|
|
394 |
* Close the filters in a pipeline, up to a given target stream, freeing
|
|
|
395 |
* their buffers and state structures.
|
|
|
396 |
*/
|
|
|
397 |
int s_close_filters(stream **ps, stream *target);
|
|
|
398 |
|
|
|
399 |
/* Define templates for the NullEncode/Decode filters. */
|
|
|
400 |
/* They have no state. */
|
|
|
401 |
extern const stream_template s_NullE_template;
|
|
|
402 |
extern const stream_template s_NullD_template;
|
|
|
403 |
|
|
|
404 |
#endif /* stream_INCLUDED */
|