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