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