xref: /plan9-contrib/sys/src/cmd/gs/src/stream.h (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /* Copyright (C) 1989, 2000 Aladdin Enterprises.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: stream.h,v 1.11 2002/06/16 05:00:54 lpd Exp $ */
187dd7cddfSDavid du Colombier /* Definitions for Ghostscript stream package */
197dd7cddfSDavid du Colombier /* Requires stdio.h */
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier #ifndef stream_INCLUDED
227dd7cddfSDavid du Colombier #  define stream_INCLUDED
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier #include "scommon.h"
257dd7cddfSDavid du Colombier #include "srdline.h"
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier /* See scommon.h for documentation on the design of streams. */
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier /* ------ Stream structure definition ------ */
307dd7cddfSDavid du Colombier 
317dd7cddfSDavid du Colombier /*
327dd7cddfSDavid du Colombier  * We expose the stream structure definition to clients so that
337dd7cddfSDavid du Colombier  * they can get reasonable performance out of the basic operations.
347dd7cddfSDavid du Colombier  */
357dd7cddfSDavid du Colombier 
367dd7cddfSDavid du Colombier /* Define the "virtual" stream procedures. */
377dd7cddfSDavid du Colombier 
387dd7cddfSDavid du Colombier typedef struct {
397dd7cddfSDavid du Colombier 
407dd7cddfSDavid du Colombier     /* Store # available for reading. */
417dd7cddfSDavid du Colombier     /* Return 0 if OK, ERRC if error or not implemented. */
427dd7cddfSDavid du Colombier #define stream_proc_available(proc)\
43*593dc095SDavid du Colombier   int proc(stream *, long *)
447dd7cddfSDavid du Colombier     stream_proc_available((*available));
457dd7cddfSDavid du Colombier 
467dd7cddfSDavid du Colombier     /* Set position. */
477dd7cddfSDavid du Colombier     /* Return 0 if OK, ERRC if error or not implemented. */
487dd7cddfSDavid du Colombier #define stream_proc_seek(proc)\
49*593dc095SDavid du Colombier   int proc(stream *, long)
507dd7cddfSDavid du Colombier     stream_proc_seek((*seek));
517dd7cddfSDavid du Colombier 
527dd7cddfSDavid du Colombier     /* Clear buffer and, if relevant, unblock channel. */
537dd7cddfSDavid du Colombier     /* Cannot cause an error. */
547dd7cddfSDavid du Colombier #define stream_proc_reset(proc)\
55*593dc095SDavid du Colombier   void proc(stream *)
567dd7cddfSDavid du Colombier     stream_proc_reset((*reset));
577dd7cddfSDavid du Colombier 
587dd7cddfSDavid du Colombier     /* Flush buffered data to output, or drain input. */
597dd7cddfSDavid du Colombier     /* Return 0 if OK, ERRC if error. */
607dd7cddfSDavid du Colombier #define stream_proc_flush(proc)\
61*593dc095SDavid du Colombier   int proc(stream *)
627dd7cddfSDavid du Colombier     stream_proc_flush((*flush));
637dd7cddfSDavid du Colombier 
647dd7cddfSDavid du Colombier     /* Flush data (if writing) & close stream. */
657dd7cddfSDavid du Colombier     /* Return 0 if OK, ERRC if error. */
667dd7cddfSDavid du Colombier #define stream_proc_close(proc)\
67*593dc095SDavid du Colombier   int proc(stream *)
687dd7cddfSDavid du Colombier     stream_proc_close((*close));
697dd7cddfSDavid du Colombier 
707dd7cddfSDavid du Colombier     /* Process a buffer, updating the cursor pointers. */
717dd7cddfSDavid du Colombier     /* See strimpl.h for details. */
727dd7cddfSDavid du Colombier     stream_proc_process((*process));
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier     /* Switch the stream to read or write mode. */
757dd7cddfSDavid du Colombier     /* false = read, true = write. */
767dd7cddfSDavid du Colombier     /* If the procedure is 0, switching is not allowed. */
777dd7cddfSDavid du Colombier #define stream_proc_switch_mode(proc)\
78*593dc095SDavid du Colombier   int proc(stream *, bool)
797dd7cddfSDavid du Colombier     stream_proc_switch_mode((*switch_mode));
807dd7cddfSDavid du Colombier 
817dd7cddfSDavid du Colombier } stream_procs;
827dd7cddfSDavid du Colombier 
837dd7cddfSDavid du Colombier /* ------ The actual stream structure ------ */
847dd7cddfSDavid du Colombier 
857dd7cddfSDavid du Colombier struct stream_s {
867dd7cddfSDavid du Colombier     /*
877dd7cddfSDavid du Colombier      * To allow the stream itself to serve as the "state"
887dd7cddfSDavid du Colombier      * of a couple of heavily used types, we start its
897dd7cddfSDavid du Colombier      * definition with the common stream state.
907dd7cddfSDavid du Colombier      */
917dd7cddfSDavid du Colombier     stream_state_common;
927dd7cddfSDavid du Colombier     /*
937dd7cddfSDavid du Colombier      * The following invariants apply at all times for read streams:
947dd7cddfSDavid du Colombier      *
957dd7cddfSDavid du Colombier      *    s->cbuf - 1 <= s->srptr <= s->srlimit.
967dd7cddfSDavid du Colombier      *
977dd7cddfSDavid du Colombier      *    The amount of data in the buffer is s->srlimit + 1 - s->cbuf.
987dd7cddfSDavid du Colombier      *
997dd7cddfSDavid du Colombier      *    s->position represents the stream position as of the beginning
1007dd7cddfSDavid du Colombier      *      of the buffer, so the current position is s->position +
1017dd7cddfSDavid du Colombier      *      (s->srptr + 1 - s->cbuf).
1027dd7cddfSDavid du Colombier      *
1037dd7cddfSDavid du Colombier      * Analogous invariants apply for write streams:
1047dd7cddfSDavid du Colombier      *
1057dd7cddfSDavid du Colombier      *    s->cbuf - 1 <= s->swptr <= s->swlimit.
1067dd7cddfSDavid du Colombier      *
1077dd7cddfSDavid du Colombier      *    The amount of data in the buffer is s->swptr + 1 - s->cbuf.
1087dd7cddfSDavid du Colombier      *
1097dd7cddfSDavid du Colombier      *    s->position represents the stream position as of the beginning
1107dd7cddfSDavid du Colombier      *      of the buffer, so the current position is s->position +
1117dd7cddfSDavid du Colombier      *      (s->swptr + 1 - s->cbuf).
1127dd7cddfSDavid du Colombier      */
1137dd7cddfSDavid du Colombier     stream_cursor cursor;	/* cursor for reading/writing data */
1147dd7cddfSDavid du Colombier     byte *cbuf;			/* base of buffer */
1157dd7cddfSDavid du Colombier     uint bsize;			/* size of buffer, 0 if closed */
1167dd7cddfSDavid du Colombier     uint cbsize;		/* size of buffer */
1177dd7cddfSDavid du Colombier     /*
1187dd7cddfSDavid du Colombier      * end_status indicates what should happen when the client
1197dd7cddfSDavid du Colombier      * reaches the end of the buffer:
1207dd7cddfSDavid du Colombier      *      0 in the normal case;
1217dd7cddfSDavid du Colombier      *      EOFC if a read stream has reached EOD or a write
1227dd7cddfSDavid du Colombier      *        stream has written the EOD marker;
1237dd7cddfSDavid du Colombier      *      ERRC if an error terminated the last read or write
1247dd7cddfSDavid du Colombier      *        operation from or to the underlying data source
1257dd7cddfSDavid du Colombier      *        or sink;
1267dd7cddfSDavid du Colombier      *      INTC if the last transfer was interrupted (NOT
1277dd7cddfSDavid du Colombier      *        USED YET);
1287dd7cddfSDavid du Colombier      *      CALLC if a callout is required.
1297dd7cddfSDavid du Colombier      */
1307dd7cddfSDavid du Colombier     short end_status;		/* status at end of buffer (when */
1317dd7cddfSDavid du Colombier 				/* reading) or now (when writing) */
1327dd7cddfSDavid du Colombier     byte foreign;		/* true if buffer is outside heap */
1337dd7cddfSDavid du Colombier     byte modes;			/* access modes allowed for this stream */
1347dd7cddfSDavid du Colombier #define s_mode_read 1
1357dd7cddfSDavid du Colombier #define s_mode_write 2
1367dd7cddfSDavid du Colombier #define s_mode_seek 4
1377dd7cddfSDavid du Colombier #define s_mode_append 8		/* (s_mode_write also set) */
1387dd7cddfSDavid du Colombier #define s_is_valid(s) ((s)->modes != 0)
1397dd7cddfSDavid du Colombier #define s_is_reading(s) (((s)->modes & s_mode_read) != 0)
1407dd7cddfSDavid du Colombier #define s_is_writing(s) (((s)->modes & s_mode_write) != 0)
1417dd7cddfSDavid du Colombier #define s_can_seek(s) (((s)->modes & s_mode_seek) != 0)
1427dd7cddfSDavid du Colombier     gs_string cbuf_string;	/* cbuf/cbsize if cbuf is a string, */
1437dd7cddfSDavid du Colombier 				/* 0/? if not */
1447dd7cddfSDavid du Colombier     long position;		/* file position of beginning of */
1457dd7cddfSDavid du Colombier 				/* buffer */
1467dd7cddfSDavid du Colombier     stream_procs procs;
1477dd7cddfSDavid du Colombier     stream *strm;		/* the underlying stream, non-zero */
1487dd7cddfSDavid du Colombier 				/* iff this is a filter stream */
1497dd7cddfSDavid du Colombier     int is_temp;		/* if >0, this is a temporary */
1507dd7cddfSDavid du Colombier 				/* stream and should be freed */
1517dd7cddfSDavid du Colombier 				/* when its source/sink is closed; */
1527dd7cddfSDavid du Colombier 				/* if >1, the buffer is also */
1537dd7cddfSDavid du Colombier 				/* temporary */
1547dd7cddfSDavid du Colombier     int inline_temp;		/* temporary for inline access */
1557dd7cddfSDavid du Colombier 				/* (see spgetc_inline below) */
1567dd7cddfSDavid du Colombier     stream_state *state;	/* state of process */
1577dd7cddfSDavid du Colombier     /*
1587dd7cddfSDavid du Colombier      * The following are for the use of the interpreter.
1597dd7cddfSDavid du Colombier      * See files.h for more information on read_id and write_id,
1607dd7cddfSDavid du Colombier      * zfile.c for more information on prev and next,
1617dd7cddfSDavid du Colombier      * zfilter.c for more information on close_strm.
1627dd7cddfSDavid du Colombier      */
1637dd7cddfSDavid du Colombier     ushort read_id;		/* "unique" serial # for detecting */
1647dd7cddfSDavid du Colombier 				/* references to closed streams */
1657dd7cddfSDavid du Colombier 				/* and for validating read access */
1667dd7cddfSDavid du Colombier     ushort write_id;		/* ditto to validate write access */
1677dd7cddfSDavid du Colombier     stream *prev, *next;	/* keep track of all files */
1687dd7cddfSDavid du Colombier     bool close_strm;		/* CloseSource/CloseTarget */
1697dd7cddfSDavid du Colombier     bool close_at_eod;		/*(default is true, only false if "reusable")*/
170*593dc095SDavid du Colombier     int (*save_close)(stream *);	/* save original close proc */
1717dd7cddfSDavid du Colombier     /*
1727dd7cddfSDavid du Colombier      * In order to avoid allocating a separate stream_state for
1737dd7cddfSDavid du Colombier      * file streams, which are the most heavily used stream type,
1747dd7cddfSDavid du Colombier      * we put their state here.
1757dd7cddfSDavid du Colombier      */
1767dd7cddfSDavid du Colombier     FILE *file;			/* file handle for C library */
1773ff48bf5SDavid du Colombier     gs_const_string file_name;	/* file name (optional) -- clients must */
1783ff48bf5SDavid du Colombier 				/* access only through procedures */
1797dd7cddfSDavid du Colombier     uint file_modes;		/* access modes for the file, */
1807dd7cddfSDavid du Colombier 				/* may be a superset of modes */
1813ff48bf5SDavid du Colombier     /* Clients must only set the following through sread_subfile. */
1823ff48bf5SDavid du Colombier     long file_offset;		/* starting point in file (reading) */
1833ff48bf5SDavid du Colombier     long file_limit;		/* ending point in file (reading) */
1847dd7cddfSDavid du Colombier };
1857dd7cddfSDavid du Colombier 
1867dd7cddfSDavid du Colombier /* The descriptor is only public for subclassing. */
1877dd7cddfSDavid du Colombier extern_st(st_stream);
1887dd7cddfSDavid du Colombier #define public_st_stream()	/* in stream.c */\
1897dd7cddfSDavid du Colombier   gs_public_st_composite_final(st_stream, stream, "stream",\
1907dd7cddfSDavid du Colombier     stream_enum_ptrs, stream_reloc_ptrs, stream_finalize)
1913ff48bf5SDavid du Colombier #define STREAM_NUM_PTRS 6
1927dd7cddfSDavid du Colombier 
1937dd7cddfSDavid du Colombier /* Initialize the checking IDs of a stream. */
1947dd7cddfSDavid du Colombier #define s_init_ids(s) ((s)->read_id = (s)->write_id = 1)
1957dd7cddfSDavid du Colombier #define s_init_read_id(s) ((s)->read_id = 1, (s)->write_id = 0)
1967dd7cddfSDavid du Colombier #define s_init_write_id(s) ((s)->read_id = 0, (s)->write_id = 1)
1977dd7cddfSDavid du Colombier #define s_init_no_id(s) ((s)->read_id = (s)->write_id = 0)
1987dd7cddfSDavid du Colombier 
1997dd7cddfSDavid du Colombier /* ------ Stream functions ------ */
2007dd7cddfSDavid du Colombier 
2017dd7cddfSDavid du Colombier #define srptr cursor.r.ptr
2027dd7cddfSDavid du Colombier #define srlimit cursor.r.limit
2037dd7cddfSDavid du Colombier #define swptr cursor.w.ptr
2047dd7cddfSDavid du Colombier #define swlimit cursor.w.limit
2057dd7cddfSDavid du Colombier 
2067dd7cddfSDavid du Colombier /* Some of these are macros -- beware. */
2077dd7cddfSDavid du Colombier /* Note that unlike the C stream library, */
2087dd7cddfSDavid du Colombier /* ALL stream procedures take the stream as the first argument. */
2097dd7cddfSDavid du Colombier #define sendrp(s) ((s)->srptr >= (s)->srlimit)	/* NOT FOR CLIENTS */
2107dd7cddfSDavid du Colombier #define sendwp(s) ((s)->swptr >= (s)->swlimit)	/* NOT FOR CLIENTS */
2117dd7cddfSDavid du Colombier 
2127dd7cddfSDavid du Colombier /*
2137dd7cddfSDavid du Colombier  * Following are valid for all streams.
2147dd7cddfSDavid du Colombier  */
2157dd7cddfSDavid du Colombier /* flush is NOT a no-op for read streams -- it discards data until EOF. */
2167dd7cddfSDavid du Colombier /* close is NOT a no-op for non-file streams -- */
2177dd7cddfSDavid du Colombier /* it actively disables them. */
2187dd7cddfSDavid du Colombier /* The close routine must do a flush if needed. */
2197dd7cddfSDavid du Colombier #define sseekable(s) s_can_seek(s)
220*593dc095SDavid du Colombier int savailable(stream *, long *);
2217dd7cddfSDavid du Colombier 
2227dd7cddfSDavid du Colombier #define sreset(s) (*(s)->procs.reset)(s)
2237dd7cddfSDavid du Colombier #define sflush(s) (*(s)->procs.flush)(s)
224*593dc095SDavid du Colombier int sclose(stream *);
225*593dc095SDavid du Colombier int sswitch(stream *, bool);
2267dd7cddfSDavid du Colombier 
2277dd7cddfSDavid du Colombier /*
2287dd7cddfSDavid du Colombier  * Following are only valid for read streams.
2297dd7cddfSDavid du Colombier  */
230*593dc095SDavid du Colombier int spgetcc(stream *, bool);	/* bool indicates close at EOD */
2317dd7cddfSDavid du Colombier #define spgetc(s) spgetcc(s, true)	/* a procedure equivalent of sgetc */
2327dd7cddfSDavid du Colombier /*
2337dd7cddfSDavid du Colombier  * Note that sgetc must call spgetc one byte early, because filter must read
2347dd7cddfSDavid du Colombier  * ahead to detect EOD.
2357dd7cddfSDavid du Colombier  *
2367dd7cddfSDavid du Colombier  * In the definition of sgetc, the first alternative should read
2377dd7cddfSDavid du Colombier  *      (int)(*++((s)->srptr))
2387dd7cddfSDavid du Colombier  * but the Borland compiler generates truly atrocious code for this.
2397dd7cddfSDavid du Colombier  * The SCO ODT compiler requires the first, pointless cast to int.
2407dd7cddfSDavid du Colombier  */
2417dd7cddfSDavid du Colombier #define sgetc(s)\
2427dd7cddfSDavid du Colombier   ((int)((s)->srlimit - (s)->srptr > 1 ? (++((s)->srptr), (int)*(s)->srptr) : spgetc(s)))
243*593dc095SDavid du Colombier int sgets(stream *, byte *, uint, uint *);
244*593dc095SDavid du Colombier int sungetc(stream *, byte);	/* ERRC on error, 0 if OK */
2457dd7cddfSDavid du Colombier 
2467dd7cddfSDavid du Colombier #define sputback(s) ((s)->srptr--)	/* can only do this once! */
2477dd7cddfSDavid du Colombier #define seofp(s) (sendrp(s) && (s)->end_status == EOFC)
2487dd7cddfSDavid du Colombier #define serrorp(s) (sendrp(s) && (s)->end_status == ERRC)
249*593dc095SDavid du Colombier int spskip(stream *, long, long *);
2507dd7cddfSDavid du Colombier 
2517dd7cddfSDavid du Colombier #define sskip(s,nskip,pskipped) spskip(s, (long)(nskip), pskipped)
2527dd7cddfSDavid du Colombier /*
2537dd7cddfSDavid du Colombier  * Attempt to refill the buffer of a read stream.
2547dd7cddfSDavid du Colombier  * Only call this if the end_status is not EOFC,
2557dd7cddfSDavid du Colombier  * and if the buffer is (nearly) empty.
2567dd7cddfSDavid du Colombier  */
257*593dc095SDavid du Colombier int s_process_read_buf(stream *);
2587dd7cddfSDavid du Colombier 
2597dd7cddfSDavid du Colombier /*
2607dd7cddfSDavid du Colombier  * Following are only valid for write streams.
2617dd7cddfSDavid du Colombier  */
262*593dc095SDavid du Colombier int spputc(stream *, byte);	/* a procedure equivalent of sputc */
2637dd7cddfSDavid du Colombier 
2647dd7cddfSDavid du Colombier /*
2657dd7cddfSDavid du Colombier  * The first alternative should read
2667dd7cddfSDavid du Colombier  *      ((int)(*++((s)->swptr)=(c)))
2677dd7cddfSDavid du Colombier  * but the Borland compiler generates truly atrocious code for this.
2687dd7cddfSDavid du Colombier  */
2697dd7cddfSDavid du Colombier #define sputc(s,c)\
2707dd7cddfSDavid du Colombier   (!sendwp(s) ? (++((s)->swptr), *(s)->swptr=(c), 0) : spputc((s),(c)))
271*593dc095SDavid du Colombier int sputs(stream *, const byte *, uint, uint *);
2727dd7cddfSDavid du Colombier 
2737dd7cddfSDavid du Colombier /*
2747dd7cddfSDavid du Colombier  * Attempt to empty the buffer of a write stream.
2757dd7cddfSDavid du Colombier  * Only call this if the end_status is not EOFC.
2767dd7cddfSDavid du Colombier  */
277*593dc095SDavid du Colombier int s_process_write_buf(stream *, bool);
2787dd7cddfSDavid du Colombier 
2797dd7cddfSDavid du Colombier /* Following are only valid for positionable streams. */
280*593dc095SDavid du Colombier long stell(stream *);
281*593dc095SDavid du Colombier int spseek(stream *, long);
2827dd7cddfSDavid du Colombier 
2837dd7cddfSDavid du Colombier #define sseek(s,pos) spseek(s, (long)(pos))
2847dd7cddfSDavid du Colombier 
2857dd7cddfSDavid du Colombier /* Following are for high-performance reading clients. */
2867dd7cddfSDavid du Colombier /* bufptr points to the next item. */
2877dd7cddfSDavid du Colombier #define sbufptr(s) ((s)->srptr + 1)
2887dd7cddfSDavid du Colombier #define sbufavailable(s) ((s)->srlimit - (s)->srptr)
2897dd7cddfSDavid du Colombier #define sbufskip(s, n) ((s)->srptr += (n), 0)
2907dd7cddfSDavid du Colombier /*
2917dd7cddfSDavid du Colombier  * Define the minimum amount of data that must be left in an input buffer
2927dd7cddfSDavid du Colombier  * after a read operation to handle filter read-ahead, either 0 or 1
2937dd7cddfSDavid du Colombier  * byte(s).
2947dd7cddfSDavid du Colombier  */
2957dd7cddfSDavid du Colombier #define max_min_left 1
2963ff48bf5SDavid du Colombier /*
2973ff48bf5SDavid du Colombier  * The stream.state min_left value is the minimum amount of data that must
2983ff48bf5SDavid du Colombier  * be left in an input buffer after a read operation to handle filter
2993ff48bf5SDavid du Colombier  * read-ahead. Once filters reach EOD, return 0 since read-ahead is
3003ff48bf5SDavid du Colombier  * no longer relevant.
3013ff48bf5SDavid du Colombier  */
3023ff48bf5SDavid du Colombier #define sbuf_min_left(s) \
3033ff48bf5SDavid du Colombier       ((s->end_status == EOFC || s->end_status == ERRC ? 0 : s->state->min_left))
3047dd7cddfSDavid du Colombier 
3057dd7cddfSDavid du Colombier /* The following are for very high-performance clients of read streams, */
3067dd7cddfSDavid du Colombier /* who unpack the stream state into local variables. */
3077dd7cddfSDavid du Colombier /* Note that any non-inline operations must do a s_end_inline before, */
3087dd7cddfSDavid du Colombier /* and a s_begin_inline after. */
3097dd7cddfSDavid du Colombier #define s_declare_inline(s, cp, ep)\
3107dd7cddfSDavid du Colombier   register const byte *cp;\
3117dd7cddfSDavid du Colombier   const byte *ep
3127dd7cddfSDavid du Colombier #define s_begin_inline(s, cp, ep)\
3137dd7cddfSDavid du Colombier   cp = (s)->srptr, ep = (s)->srlimit
3147dd7cddfSDavid du Colombier #define s_end_inline(s, cp, ep)\
3157dd7cddfSDavid du Colombier   (s)->srptr = cp
3167dd7cddfSDavid du Colombier #define sbufavailable_inline(s, cp, ep)\
3177dd7cddfSDavid du Colombier   (ep - cp)
3187dd7cddfSDavid du Colombier #define sendbufp_inline(s, cp, ep)\
3197dd7cddfSDavid du Colombier   (cp >= ep)
3207dd7cddfSDavid du Colombier /* The (int) is needed to pacify the SCO ODT compiler. */
3217dd7cddfSDavid du Colombier #define sgetc_inline(s, cp, ep)\
3227dd7cddfSDavid du Colombier   ((int)(sendbufp_inline(s, cp, ep) ? spgetc_inline(s, cp, ep) : *++cp))
3237dd7cddfSDavid du Colombier #define spgetc_inline(s, cp, ep)\
3247dd7cddfSDavid du Colombier   (s_end_inline(s, cp, ep), (s)->inline_temp = spgetc(s),\
3257dd7cddfSDavid du Colombier    s_begin_inline(s, cp, ep), (s)->inline_temp)
3267dd7cddfSDavid du Colombier #define sputback_inline(s, cp, ep)\
3277dd7cddfSDavid du Colombier   --cp
3287dd7cddfSDavid du Colombier 
3297dd7cddfSDavid du Colombier /* Allocate a stream or a stream state. */
330*593dc095SDavid du Colombier stream *s_alloc(gs_memory_t *, client_name_t);
331*593dc095SDavid du Colombier stream_state *s_alloc_state(gs_memory_t *, gs_memory_type_ptr_t, client_name_t);
3327dd7cddfSDavid du Colombier /*
3337dd7cddfSDavid du Colombier  * Initialize a separately allocated stream or stream state, as if allocated
3347dd7cddfSDavid du Colombier  * by s_alloc[_state].
3357dd7cddfSDavid du Colombier  */
336*593dc095SDavid du Colombier void s_init(stream *, gs_memory_t *);
337*593dc095SDavid du Colombier void s_init_state(stream_state *, const stream_template *, gs_memory_t *);
3387dd7cddfSDavid du Colombier 
3397dd7cddfSDavid du Colombier /* Create a stream on a string or a file. */
340*593dc095SDavid du Colombier void sread_string(stream *, const byte *, uint),
341*593dc095SDavid du Colombier     sread_string_reusable(stream *, const byte *, uint),
342*593dc095SDavid du Colombier     swrite_string(stream *, byte *, uint);
343*593dc095SDavid du Colombier void sread_file(stream *, FILE *, byte *, uint),
344*593dc095SDavid du Colombier     swrite_file(stream *, FILE *, byte *, uint),
345*593dc095SDavid du Colombier     sappend_file(stream *, FILE *, byte *, uint);
3467dd7cddfSDavid du Colombier 
3473ff48bf5SDavid du Colombier /* Confine reading to a subfile.  This is primarily for reusable streams. */
348*593dc095SDavid du Colombier int sread_subfile(stream *s, long start, long length);
3493ff48bf5SDavid du Colombier 
3503ff48bf5SDavid du Colombier /* Set the file name of a stream, copying the name. */
3513ff48bf5SDavid du Colombier /* Return <0 if the copy could not be allocated. */
352*593dc095SDavid du Colombier int ssetfilename(stream *, const byte *, uint);
3533ff48bf5SDavid du Colombier 
3543ff48bf5SDavid du Colombier /* Return the file name of a stream, if any. */
3553ff48bf5SDavid du Colombier /* There is a guaranteed 0 byte after the string. */
356*593dc095SDavid du Colombier int sfilename(stream *, gs_const_string *);
3573ff48bf5SDavid du Colombier 
3587dd7cddfSDavid du Colombier /* Create a stream that tracks the position, */
3597dd7cddfSDavid du Colombier /* for calculating how much space to allocate when actually writing. */
360*593dc095SDavid du Colombier void swrite_position_only(stream *);
3617dd7cddfSDavid du Colombier 
3627dd7cddfSDavid du Colombier /* Standard stream initialization */
363*593dc095SDavid du Colombier void s_std_init(stream *, byte *, uint, const stream_procs *, int /*mode */ );
3647dd7cddfSDavid du Colombier 
3657dd7cddfSDavid du Colombier /* Standard stream finalization */
366*593dc095SDavid du Colombier void s_disable(stream *);
3677dd7cddfSDavid du Colombier 
3687dd7cddfSDavid du Colombier /* Generic stream procedures exported for templates */
369*593dc095SDavid du Colombier int s_std_null(stream *);
370*593dc095SDavid du Colombier void s_std_read_reset(stream *), s_std_write_reset(stream *);
371*593dc095SDavid du Colombier int s_std_read_flush(stream *), s_std_write_flush(stream *), s_std_noavailable(stream *, long *),
372*593dc095SDavid du Colombier      s_std_noseek(stream *, long), s_std_close(stream *), s_std_switch_mode(stream *, bool);
3737dd7cddfSDavid du Colombier 
3747dd7cddfSDavid du Colombier /* Generic procedures for filters. */
375*593dc095SDavid du Colombier int s_filter_write_flush(stream *), s_filter_close(stream *);
3767dd7cddfSDavid du Colombier 
3777dd7cddfSDavid du Colombier /* Generic procedure structures for filters. */
3787dd7cddfSDavid du Colombier extern const stream_procs s_filter_read_procs, s_filter_write_procs;
3797dd7cddfSDavid du Colombier 
3807dd7cddfSDavid du Colombier /*
3813ff48bf5SDavid du Colombier  * Add a filter to an output pipeline.  The client must have allocated the
3823ff48bf5SDavid du Colombier  * stream state, if any, using the given allocator.  For s_init_filter, the
3837dd7cddfSDavid du Colombier  * client must have called s_init and s_init_state.
3843ff48bf5SDavid du Colombier  *
3853ff48bf5SDavid du Colombier  * Note that if additional buffering is needed, s_add_filter may add
3863ff48bf5SDavid du Colombier  * an additional filter to provide it.
3877dd7cddfSDavid du Colombier  */
388*593dc095SDavid du Colombier int s_init_filter(stream *fs, stream_state *fss, byte *buf, uint bsize,
389*593dc095SDavid du Colombier 		  stream *target);
390*593dc095SDavid du Colombier stream *s_add_filter(stream **ps, const stream_template *template,
391*593dc095SDavid du Colombier 		     stream_state *ss, gs_memory_t *mem);
3927dd7cddfSDavid du Colombier 
3937dd7cddfSDavid du Colombier /*
3947dd7cddfSDavid du Colombier  * Close the filters in a pipeline, up to a given target stream, freeing
3957dd7cddfSDavid du Colombier  * their buffers and state structures.
3967dd7cddfSDavid du Colombier  */
397*593dc095SDavid du Colombier int s_close_filters(stream **ps, stream *target);
3987dd7cddfSDavid du Colombier 
3993ff48bf5SDavid du Colombier /* Define templates for the NullEncode/Decode filters. */
4003ff48bf5SDavid du Colombier /* They have no state. */
4013ff48bf5SDavid du Colombier extern const stream_template s_NullE_template;
4023ff48bf5SDavid du Colombier extern const stream_template s_NullD_template;
4033ff48bf5SDavid du Colombier 
4047dd7cddfSDavid du Colombier #endif /* stream_INCLUDED */
405