1 /* Copyright (C) 2001-2019 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,
8    modified or distributed except as expressly authorized under the terms
9    of the license contained in the file LICENSE in this distribution.
10 
11    Refer to licensing information at http://www.artifex.com or contact
12    Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13    CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 
17 /* Definitions for Ghostscript stream package */
18 /* Requires stdio.h */
19 
20 #ifndef stream_INCLUDED
21 #  define stream_INCLUDED
22 
23 #include "scommon.h"
24 #include "gxiodev.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 *, gs_offset_t *)
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 *, gs_offset_t)
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->cursor.r.ptr <= s->cursor.r.limit.
96      *
97      *    The amount of data in the buffer is s->cursor.r.limit + 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->cursor.r.ptr + 1 - s->cbuf).
102      *
103      * Analogous invariants apply for write streams:
104      *
105      *    s->cbuf - 1 <= s->cursor.w.ptr <= s->cursor.w.limit.
106      *
107      *    The amount of data in the buffer is s->cursor.w.ptr + 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->cursor.w.ptr + 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     gs_offset_t 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     gp_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     gs_offset_t file_offset;		/* starting point in file (reading) */
183     gs_offset_t 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 #define S_FILE_LIMIT_MAX (sizeof(gs_offset_t) > 4 ? max_int64_t : max_long)
194 
195 /* Initialize the checking IDs of a stream. */
196 #define s_init_ids(s) ((s)->read_id = (s)->write_id = 1)
197 #define s_init_read_id(s) ((s)->read_id = 1, (s)->write_id = 0)
198 #define s_init_write_id(s) ((s)->read_id = 0, (s)->write_id = 1)
199 #define s_init_no_id(s) ((s)->read_id = (s)->write_id = 0)
200 
201 /* ------ Stream functions ------ */
202 
203 /* Some of these are macros -- beware. */
204 /* Note that unlike the C stream library, */
205 /* ALL stream procedures take the stream as the first argument. */
206 #define sendrp(s) ((s)->cursor.r.ptr >= (s)->cursor.r.limit)	/* NOT FOR CLIENTS */
207 #define sendwp(s) ((s)->cursor.w.ptr >= (s)->cursor.w.limit)	/* NOT FOR CLIENTS */
208 
209 /*
210  * Following are valid for all streams.
211  */
212 /* flush is NOT a no-op for read streams -- it discards data until EOF. */
213 /* close is NOT a no-op for non-file streams -- */
214 /* it actively disables them. */
215 /* The close routine must do a flush if needed. */
216 #define sseekable(s) s_can_seek(s)
217 int savailable(stream *, gs_offset_t *);
218 
219 #define sreset(s) (*(s)->procs.reset)(s)
220 #define sflush(s) (*(s)->procs.flush)(s)
221 int sclose(stream *);
222 int sswitch(stream *, bool);
223 
224 /*
225  * Following are only valid for read streams.
226  */
227 int spgetcc(stream *, bool);	/* bool indicates close at EOD */
228 #define spgetc(s) spgetcc(s, true)	/* a procedure equivalent of sgetc */
229 /*
230  * Note that sgetc must call spgetc one byte early, because filter must read
231  * ahead to detect EOD.
232  *
233  * In the definition of sgetc, the first alternative should read
234  *      (int)(*++((s)->cursor.r.ptr))
235  * but the Borland compiler generates truly atrocious code for this.
236  * The SCO ODT compiler requires the first, pointless cast to int.
237  */
238 #define sgetc(s)\
239   ((int)((s)->cursor.r.limit - (s)->cursor.r.ptr > 1 ? (++((s)->cursor.r.ptr), (int)*(s)->cursor.r.ptr) : spgetc(s)))
240 int sgets(stream *, byte *, uint, uint *);
241 int sungetc(stream *, byte);	/* ERRC on error, 0 if OK */
242 
243 #define sputback(s) ((s)->cursor.r.ptr--)	/* can only do this once! */
244 #define seofp(s) (sendrp(s) && (s)->end_status == EOFC)
245 #define serrorp(s) (sendrp(s) && (s)->end_status == ERRC)
246 int spskip(stream *, gs_offset_t, gs_offset_t *);
247 
248 #define sskip(s,nskip,pskipped) spskip(s, (long)(nskip), pskipped)
249 /*
250  * Attempt to refill the buffer of a read stream.
251  * Only call this if the end_status is not EOFC,
252  * and if the buffer is (nearly) empty.
253  */
254 int s_process_read_buf(stream *);
255 
256 /*
257  * Following are only valid for write streams.
258  */
259 int spputc(stream *, byte);	/* a procedure equivalent of sputc */
260 
261 /*
262  * The first alternative should read
263  *      ((int)(*++((s)->cursor.w.ptr)=(c)))
264  * but the Borland compiler generates truly atrocious code for this.
265  */
266 #define sputc(s,c)\
267   (!sendwp(s) ? (++((s)->cursor.w.ptr), *(s)->cursor.w.ptr=(c), 0) : spputc((s),(c)))
268 int sputs(stream *, const byte *, uint, uint *);
269 
270 /*
271  * Attempt to empty the buffer of a write stream.
272  * Only call this if the end_status is not EOFC.
273  */
274 int s_process_write_buf(stream *, bool);
275 
276 /* Following are only valid for positionable streams. */
277 gs_offset_t stell(stream *);
278 int spseek(stream *, gs_offset_t);
279 
280 #define sseek(s,pos) spseek(s, (gs_offset_t)(pos))
281 
282 /* Following are for high-performance reading clients. */
283 /* bufptr points to the next item. */
284 #define sbufptr(s) ((s)->cursor.r.ptr + 1)
285 #define sbufavailable(s) ((s)->cursor.r.limit - (s)->cursor.r.ptr)
286 #define sbufskip(s, n) ((s)->cursor.r.ptr += (n), 0)
287 /*
288  * Define the minimum amount of data that must be left in an input buffer
289  * after a read operation to handle filter read-ahead, either 0 or 1
290  * byte(s).
291  */
292 #define max_min_left 1
293 /*
294  * The stream.state min_left value is the minimum amount of data that must
295  * be left in an input buffer after a read operation to handle filter
296  * read-ahead. Once filters reach EOD, return 0 since read-ahead is
297  * no longer relevant.
298  */
299 #define sbuf_min_left(s) \
300       ((s->end_status == EOFC || s->end_status == ERRC ? 0 : s->state->min_left))
301 
302 /* The following are for very high-performance clients of read streams, */
303 /* who unpack the stream state into local variables. */
304 /* Note that any non-inline operations must do a s_end_inline before, */
305 /* and a s_begin_inline after. */
306 #define s_declare_inline(s, cp, ep)\
307   register const byte *cp;\
308   const byte *ep
309 #define s_begin_inline(s, cp, ep)\
310   cp = (s)->cursor.r.ptr, ep = (s)->cursor.r.limit
311 #define s_end_inline(s, cp, ep)\
312   (s)->cursor.r.ptr = cp
313 #define sbufavailable_inline(s, cp, ep)\
314   (ep - cp)
315 #define sendbufp_inline(s, cp, ep)\
316   (cp >= ep)
317 /* The (int) is needed to pacify the SCO ODT compiler. */
318 #define sgetc_inline(s, cp, ep)\
319   ((int)(sendbufp_inline(s, cp, ep) ? spgetc_inline(s, cp, ep) : *++cp))
320 #define spgetc_inline(s, cp, ep)\
321   (s_end_inline(s, cp, ep), (s)->inline_temp = spgetc(s),\
322    s_begin_inline(s, cp, ep), (s)->inline_temp)
323 #define sputback_inline(s, cp, ep)\
324   --cp
325 
326 /* Allocate a stream or a stream state. */
327 stream *s_alloc(gs_memory_t *, client_name_t);
328 stream_state *s_alloc_state(gs_memory_t *, gs_memory_type_ptr_t, client_name_t);
329 /*
330  * Initialize a separately allocated stream or stream state, as if allocated
331  * by s_alloc[_state].
332  */
333 void s_init(stream *, gs_memory_t *);
334 void s_init_state(stream_state *, const stream_template *, gs_memory_t *);
335 
336 /* create a stream for a file object */
337 int file_prepare_stream(const char *, uint, const char *,
338                  uint, stream **, char[4], gs_memory_t *);
339 
340 /* Set up a file stream on a gp_file.  */
341 int file_init_stream(stream *, gp_file *, const char *, byte *, uint);
342 
343 /* Open a file stream, optionally on a gp_file. */
344 int file_open_stream(const char *, uint, const char *,
345                  uint, stream **, gx_io_device *,
346                  iodev_proc_fopen_t, gs_memory_t *);
347 
348 /* Allocate and return a file stream. */
349 stream * file_alloc_stream(gs_memory_t *, client_name_t);
350 
351 /*
352  * Macros for checking file validity.
353  * NOTE: in order to work around a bug in the Borland 5.0 compiler,
354  * you must use file_is_invalid rather than !file_is_valid.
355  */
356 #define file_is_valid(svar,op)\
357   (svar = fptr(op), (svar->read_id | svar->write_id) == r_size(op))
358 #define file_is_invalid(svar,op)\
359   (svar = fptr(op), (svar->read_id | svar->write_id) != r_size(op))
360 #define check_file(svar,op)\
361   BEGIN\
362     check_type(*(op), t_file);\
363     if ( file_is_invalid(svar, op) ) return_error(gs_error_ioerror);\
364   END
365 
366 /* Close a file stream. */
367 int file_close_file(stream *);
368 
369 int file_close_finish(stream *);
370 
371 /* Disable further access on the stream by mangling the id's */
372 int file_close_disable(stream *);
373 
374 /* Create a stream on a string or a file. */
375 void sread_string(stream *, const byte *, uint),
376     sread_string_reusable(stream *, const byte *, uint),
377     swrite_string(stream *, byte *, uint);
378 void sread_file(stream *, gp_file *, byte *, uint),
379     swrite_file(stream *, gp_file *, byte *, uint);
380 int  sappend_file(stream *, gp_file *, byte *, uint);
381 
382 /* Confine reading to a subfile.  This is primarily for reusable streams. */
383 int sread_subfile(stream *s, gs_offset_t start, gs_offset_t length);
384 
385 /* Set the file name of a stream, copying the name. */
386 /* Return <0 if the copy could not be allocated. */
387 int ssetfilename(stream *, const byte *, uint);
388 
389 /* Return the file name of a stream, if any. */
390 /* There is a guaranteed 0 byte after the string. */
391 int sfilename(stream *, gs_const_string *);
392 
393 /* Create a stream that tracks the position, */
394 /* for calculating how much space to allocate when actually writing. */
395 void swrite_position_only(stream *);
396 
397 /* Standard stream initialization */
398 void s_std_init(stream *, byte *, uint, const stream_procs *, int /*mode */ );
399 
400 /* Standard stream finalization */
401 void s_disable(stream *);
402 
403 /* Generic stream procedures exported for templates */
404 int s_std_null(stream *);
405 void s_std_read_reset(stream *), s_std_write_reset(stream *);
406 int s_std_read_flush(stream *), s_std_write_flush(stream *), s_std_noavailable(stream *, gs_offset_t *),
407      s_std_noseek(stream *, gs_offset_t), s_std_close(stream *), s_std_switch_mode(stream *, bool);
408 
409 /* Generic procedures for filters. */
410 int s_filter_write_flush(stream *), s_filter_close(stream *);
411 
412 /* Generic procedure structures for filters. */
413 extern const stream_procs s_filter_read_procs, s_filter_write_procs;
414 
415 /*
416  * Add a filter to an output pipeline.  The client must have allocated the
417  * stream state, if any, using the given allocator.  For s_init_filter, the
418  * client must have called s_init and s_init_state.
419  *
420  * Note that if additional buffering is needed, s_add_filter may add
421  * an additional filter to provide it.
422  */
423 int s_init_filter(stream *fs, stream_state *fss, byte *buf, uint bsize,
424                   stream *target);
425 stream *s_add_filter(stream **ps, const stream_template *template,
426                      stream_state *ss, gs_memory_t *mem);
427 
428 /*
429  * Close the filters in a pipeline, up to a given target stream, freeing
430  * their buffers and state structures.
431  */
432 int s_close_filters(stream **ps, stream *target);
433 
434 /* Define templates for the NullEncode/Decode filters. */
435 /* They have no state. */
436 extern const stream_template s_NullE_template;
437 extern const stream_template s_NullD_template;
438 
439         /* for ziodev.c */
440 int file_close_finish(stream *);
441 int file_close_disable(stream *);
442 
443 #endif /* stream_INCLUDED */
444