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