summaryrefslogtreecommitdiff
blob: d8bdda8cce80c2bca279268eeee6201d25e93bc2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/* Copyright (C) 2001-2021 Artifex Software, Inc.
   All Rights Reserved.

   This software is provided AS-IS with no warranty, either express or
   implied.

   This software is distributed under license and may not be copied,
   modified or distributed except as expressly authorized under the terms
   of the license contained in the file LICENSE in this distribution.

   Refer to licensing information at http://www.artifex.com or contact
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
   CA 94945, U.S.A., +1(415)492-9861, for further information.
*/


/* Definitions common to stream clients and implementors */

#ifndef scommon_INCLUDED
#  define scommon_INCLUDED

#include "gsmemory.h"
#include "gstypes.h"		/* for gs_string */
#include "gsstype.h"		/* for extern_st */
#include "stdint_.h"         /* for int64_t */

/*
 * There are three major structures involved in the stream package.
 *
 * A stream is an "object" that owns a buffer, which it uses to implement
 * byte-oriented sequential access in a standard way, and a set of
 * procedures that handle things like buffer refilling.  See stream.h
 * for more information about streams.
 */
typedef struct stream_s stream;

/* We really want our offset type to be 64 bit for large file support
 * but this allows a particular port to specficy a prefered data type
 */
#ifdef GS_OFFSET_T
typedef GS_OFFSET_T gs_offset_t;
#else
typedef int64_t gs_offset_t;
#endif

/*
 * A stream_state records the state specific to a given variety of stream.
 * The buffer processing function of a stream maintains this state.
 */
typedef struct stream_state_s stream_state;

/*
 * A stream_template provides the information needed to create a stream.
 * The client must fill in any needed setup parameters in the appropriate
 * variety of stream_state, and then call the initialization function
 * provided by the template.  See strimpl.h for more information about
 * stream_templates.
 */
typedef struct stream_template_s stream_template;

/*
 * The stream package works with bytes, not chars.
 * This is to ensure unsigned representation on all systems.
 * A stream currently can only be read or written, not both.
 * Note also that the read procedure returns an int, not a char or a byte;
 * we use negative values to indicate exceptional conditions.
 * (We cast these values to int explicitly, because some compilers
 * don't do this if the other arm of a conditional is a byte.)
 *
 * Note that when a stream reaches an exceptional condition, that condition
 * remains set until the client does something explicit to reset it.
 * (There should be a 'sclearerr' procedure to do that, but there isn't.)
 * In particular, if a read stream encounters an exceptional condition,
 * it delivers the data it has in its buffer, and then all subsequent
 * calls to read data (sgetc, sgets, etc.) will return the exceptional
 * condition without reading any more actual data.
 */
/* End of data */
#define EOFC ((int)(-1))
/* Error */
#define ERRC ((int)(-2))
/* Interrupt */
#define INTC ((int)(-3))
/****** INTC IS NOT USED YET ******/
/* Callout */
#define CALLC ((int)(-4))
#define max_stream_exception 4
/* The following hack is needed for initializing scan_char_array in iscan.c. */
#define stream_exception_repeat(x) x, x, x, x

/*
 * Define cursors for reading from or writing into a buffer.
 * We lay them out this way so that we can alias
 * the write pointer and the read limit.
 */
typedef struct stream_cursor_read_s {
    const byte *ptr;
    const byte *limit;
    byte *_skip;
} stream_cursor_read;
typedef struct stream_cursor_write_s {
    const byte *_skip;
    byte *ptr;
    byte *limit;
} stream_cursor_write;
typedef union stream_cursor_s {
    stream_cursor_read r;
    stream_cursor_write w;
} stream_cursor;

/* The following two inline functions are here to keep the nasty
 * cursor initialisation (that ptr is initialised to one byte
 * /before/ the beginning of the buffer) in the one place,
 * rather than everywhere that uses short lived streams.
 * This allows localized disabling of the "array bounds" compiler
 * warning for this one specific case.
 */
static inline void
stream_cursor_read_init(stream_cursor_read *r, const byte *buf, size_t length)
{
#ifdef __GNUC__
#  pragma GCC diagnostic push
#  pragma GCC diagnostic ignored "-Warray-bounds"
#endif
    /* starting pos for pointer is always one position back */
    r->ptr = buf - 1;
    r->limit = r->ptr + length;
#ifdef __GNUC__
#  pragma GCC diagnostic pop
#endif
}

static inline void
stream_cursor_write_init(stream_cursor_write *w, const byte *buf, size_t length)
{
#ifdef __GNUC__
#  pragma GCC diagnostic push
#  pragma GCC diagnostic ignored "-Warray-bounds"
#endif
    /* starting pos for pointer is always one position back */
    w->ptr = (byte *)buf - 1;
    w->limit = (byte *)w->ptr + length;
#ifdef __GNUC__
#  pragma GCC diagnostic pop
#endif
}

/*
 * Define the prototype for the procedures known to both the generic
 * stream code and the stream implementations.
 */

/* Initialize the stream state (after the client parameters are set). */
#define stream_proc_init(proc)\
  int proc(stream_state *)

/* Process a buffer.  See strimpl.h for details. */
#define stream_proc_process(proc)\
  int proc(stream_state *, stream_cursor_read *,\
    stream_cursor_write *, bool)

/* Release the stream state when closing. */
#define stream_proc_release(proc)\
  void proc(stream_state *)

/* Initialize the client parameters to default values. */
#define stream_proc_set_defaults(proc)\
  void proc(stream_state *)

/* Reinitialize any internal stream state.  Note that this does not */
/* affect buffered data.  We declare this as returning an int so that */
/* it can be the same as the init procedure; however, reinit cannot fail. */
#define stream_proc_reinit(proc)\
  int proc(stream_state *)

/* Report an error.  Note that this procedure is stored in the state, */
/* not in the main stream structure. */
#define stream_proc_report_error(proc)\
  int proc(stream_state *, const char *)
stream_proc_report_error(s_no_report_error);

/*
 * Some types of streams have the ability to read their parameters from
 * a parameter list, and to write all (or only the non-default)
 * parameters to a parameter list.  Since these are not virtual
 * procedures for the stream (they operate on stream_state structures
 * even if no actual stream has been created), we name them differently.
 */
#define stream_state_proc_get_params(proc, state_type)\
  int proc(gs_param_list *plist, const state_type *ss, bool all)
#define stream_state_proc_put_params(proc, state_type)\
  int proc(gs_param_list *plist, state_type *ss)

/*
 * Define a generic stream state.  If a processing procedure has no
 * state of its own, it can use stream_state; otherwise, it must
 * create a "subclass".  There is a hack in stream.h to allow the stream
 * itself to serve as the "state" of a couple of heavily used stream types.
 *
 * In order to simplify the structure descriptors for concrete streams,
 * we require that the generic stream state not contain any pointers
 * to garbage-collectable storage.
 */
#define STREAM_MAX_ERROR_STRING 79
#define stream_state_common\
        const stream_template *templat;\
        gs_memory_t *memory;\
        stream_proc_report_error((*report_error));\
        int min_left; /* required bytes for lookahead */ \
        char error_string[STREAM_MAX_ERROR_STRING + 1]
struct stream_state_s {
    stream_state_common;
};

extern_st(st_stream_state);
#define public_st_stream_state() /* in stream.c */\
  gs_public_st_simple(st_stream_state, stream_state, "stream_state")

#endif /* scommon_INCLUDED */