Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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