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