55
55
make_empty_array(&empty_array, a_readonly);
56
56
if (dict_find_string(op, "Filter", &pFilter) > 0) {
57
if (!r_is_array(pFilter)) {
58
if (!r_has_type(pFilter, t_name))
59
return_error(e_typecheck);
60
make_array(&filter1_array, a_readonly, 1, pFilter);
61
pFilter = &filter1_array;
57
if (!r_is_array(pFilter)) {
58
if (!r_has_type(pFilter, t_name))
59
return_error(e_typecheck);
60
make_array(&filter1_array, a_readonly, 1, pFilter);
61
pFilter = &filter1_array;
64
pFilter = &empty_array;
64
pFilter = &empty_array;
65
65
/* If Filter is undefined, ignore DecodeParms. */
66
66
if (pFilter != &empty_array &&
67
dict_find_string(op, "DecodeParms", &pDecodeParms) > 0
69
if (pFilter == &filter1_array) {
70
make_array(&parms1_array, a_readonly, 1, pDecodeParms);
71
pDecodeParms = &parms1_array;
72
} else if (!r_is_array(pDecodeParms))
73
return_error(e_typecheck);
74
else if (r_size(pFilter) != r_size(pDecodeParms))
75
return_error(e_rangecheck);
67
dict_find_string(op, "DecodeParms", &pDecodeParms) > 0
69
if (pFilter == &filter1_array) {
70
make_array(&parms1_array, a_readonly, 1, pDecodeParms);
71
pDecodeParms = &parms1_array;
72
} else if (!r_is_array(pDecodeParms))
73
return_error(e_typecheck);
74
else if (r_size(pFilter) != r_size(pDecodeParms))
75
return_error(e_rangecheck);
78
78
for (i = 0; i < r_size(pFilter); ++i) {
81
array_get(imemory, pFilter, (long)i, &f);
82
if (!r_has_type(&f, t_name))
83
return_error(e_typecheck);
84
name_string_ref(imemory, &f, &fname);
85
if (r_size(&fname) < 6 ||
86
memcmp(fname.value.bytes + r_size(&fname) - 6, "Decode", 6)
88
return_error(e_rangecheck);
90
array_get(imemory, pDecodeParms, (long)i, &dp);
91
if (!(r_has_type(&dp, t_dictionary) || r_has_type(&dp, t_null)))
92
return_error(e_typecheck);
81
array_get(imemory, pFilter, (long)i, &f);
82
if (!r_has_type(&f, t_name))
83
return_error(e_typecheck);
84
name_string_ref(imemory, &f, &fname);
85
if (r_size(&fname) < 6 ||
86
memcmp(fname.value.bytes + r_size(&fname) - 6, "Decode", 6)
88
return_error(e_rangecheck);
90
array_get(imemory, pDecodeParms, (long)i, &dp);
91
if (!(r_has_type(&dp, t_dictionary) || r_has_type(&dp, t_null)))
92
return_error(e_typecheck);
95
95
code = dict_int_param(op, "Intent", 0, 3, 0, &Intent);
96
96
if (code < 0 && code != e_rangecheck) /* out-of-range int is ok, use 0 */
98
98
if ((code = dict_bool_param(op, "AsyncRead", false, &AsyncRead)) < 0
102
102
op[-1] = *pFilter;
103
103
if (pDecodeParms)
137
137
check_type(*op, t_boolean);
138
138
close_source = op->value.boolval;
139
139
if (r_has_type(source_op, t_string)) {
140
uint size = r_size(source_op);
140
uint size = r_size(source_op);
142
check_read(*source_op);
143
code = make_rss(i_ctx_p, source_op, source_op->value.const_bytes,
144
size, r_space(source_op), 0L, size, false);
142
check_read(*source_op);
143
code = make_rss(i_ctx_p, source_op, source_op->value.const_bytes,
144
size, r_space(source_op), 0L, size, false);
145
145
} else if (r_has_type(source_op, t_astruct)) {
146
uint size = gs_object_size(imemory, source_op->value.pstruct);
146
uint size = gs_object_size(imemory, source_op->value.pstruct);
148
if (gs_object_type(imemory, source_op->value.pstruct) != &st_bytes)
149
return_error(e_rangecheck);
150
check_read(*source_op);
151
code = make_rss(i_ctx_p, source_op,
152
(const byte *)source_op->value.pstruct, size,
153
r_space(source_op), 0L, size, true);
148
if (gs_object_type(imemory, source_op->value.pstruct) != &st_bytes)
149
return_error(e_rangecheck);
150
check_read(*source_op);
151
code = make_rss(i_ctx_p, source_op,
152
(const byte *)source_op->value.pstruct, size,
153
r_space(source_op), 0L, size, true);
154
154
} else if (r_has_type(source_op, t_array)) { /* no packedarrays */
155
int i, blk_cnt, blk_sz;
155
int i, blk_cnt, blk_sz;
157
157
ulong filelen = 0;
159
159
check_read(*source_op);
160
160
blk_cnt = r_size(source_op);
161
blk_ref = source_op->value.refs;
161
blk_ref = source_op->value.refs;
162
162
if (blk_cnt > 0) {
163
163
blk_sz = r_size(blk_ref);
164
164
for (i = 0; i < blk_cnt; i++) {
174
174
if (filelen == 0) {
175
175
code = make_rss(i_ctx_p, source_op, (unsigned char *)"", 0,
176
r_space(source_op), 0, 0, false);
176
r_space(source_op), 0, 0, false);
178
178
code = make_aos(i_ctx_p, source_op, blk_sz, r_size(&blk_ref[blk_cnt - 1]), filelen);
185
check_read_file(i_ctx_p, source, source_op);
185
check_read_file(i_ctx_p, source, source_op);
188
if (s->cbuf_string.data != 0) { /* string stream */
190
long avail = sbufavailable(s) + pos;
193
code = make_rss(i_ctx_p, source_op, s->cbuf_string.data,
195
imemory_space((const gs_ref_memory_t *)s->memory),
196
offset, min(avail, length), false);
197
} else if (s->file != 0) { /* file stream */
198
if (~s->modes & (s_mode_read | s_mode_seek))
199
return_error(e_ioerror);
200
code = make_rfs(i_ctx_p, source_op, s, offset + stell(s), length);
201
} else if (s->state->template == &s_SFD_template) {
202
/* SubFileDecode filter */
203
const stream_SFD_state *const sfd_state =
204
(const stream_SFD_state *)s->state;
206
if (sfd_state->eod.size != 0)
207
return_error(e_rangecheck);
208
offset += sfd_state->skip_count - sbufavailable(s);
209
if (sfd_state->count != 0) {
210
long left = max(sfd_state->count, 0) + sbufavailable(s);
218
else /* some other kind of stream */
219
return_error(e_rangecheck);
221
stream *rs = fptr(source_op);
223
rs->strm = source; /* only for close_source */
224
rs->close_strm = true;
188
if (s->cbuf_string.data != 0) { /* string stream */
190
long avail = sbufavailable(s) + pos;
193
code = make_rss(i_ctx_p, source_op, s->cbuf_string.data,
195
imemory_space((const gs_ref_memory_t *)s->memory),
196
offset, min(avail, length), false);
197
} else if (s->file != 0) { /* file stream */
198
if (~s->modes & (s_mode_read | s_mode_seek))
199
return_error(e_ioerror);
200
code = make_rfs(i_ctx_p, source_op, s, offset + stell(s), length);
201
} else if (s->state->template == &s_SFD_template) {
202
/* SubFileDecode filter */
203
const stream_SFD_state *const sfd_state =
204
(const stream_SFD_state *)s->state;
206
if (sfd_state->eod.size != 0)
207
return_error(e_rangecheck);
208
offset += sfd_state->skip_count - sbufavailable(s);
209
if (sfd_state->count != 0) {
210
long left = max(sfd_state->count, 0) + sbufavailable(s);
218
else /* some other kind of stream */
219
return_error(e_rangecheck);
221
stream *rs = fptr(source_op);
223
rs->strm = source; /* only for close_source */
224
rs->close_strm = true;
232
232
/* Make a reusable string stream. */
234
234
make_rss(i_ctx_t *i_ctx_p, os_ptr op, const byte * data, uint size,
235
uint string_space, long offset, long length, bool is_bytestring)
235
uint string_space, long offset, long length, bool is_bytestring)
237
237
uint save_space = icurrent_space;
264
264
if (sfilename(fs, &fname) < 0)
265
return_error(e_ioerror);
265
return_error(e_ioerror);
266
266
code = gs_parse_file_name(&pname, (const char *)fname.data, fname.size,
270
270
if (pname.len == 0) /* %stdin% etc. won't have a filename */
271
return_error(e_invalidfileaccess); /* can't reopen */
271
return_error(e_invalidfileaccess); /* can't reopen */
272
272
if (pname.iodev == NULL)
273
pname.iodev = iodev_default(imemory);
273
pname.iodev = iodev_default(imemory);
274
274
/* Open the file again, to be independent of the source. */
275
275
ialloc_set_space(idmemory, stream_space);
276
276
code = zopen_file(i_ctx_p, &pname, "r", &s, imemory);
277
277
ialloc_set_space(idmemory, save_space);
280
280
if (sread_subfile(s, offset, length) < 0) {
282
return_error(e_ioerror);
282
return_error(e_ioerror);
284
284
s->close_at_eod = false;
285
285
make_stream_file(op, s, "r");
293
293
static int s_aos_flush(stream *s);
294
294
static int s_aos_close(stream *);
295
295
static int s_aos_process(stream_state *, stream_cursor_read *,
296
stream_cursor_write *, bool);
296
stream_cursor_write *, bool);
298
298
/* Stream state */
299
299
typedef struct aos_state_s {
300
300
stream_state_common;
308
308
/* GC procedures */
310
310
CLEAR_MARKS_PROC(aos_clear_marks)
311
311
{ aos_state_t *const pptr = vptr;
313
313
r_clear_attrs(&pptr->blocks, l_mark);
316
316
ENUM_PTRS_WITH(aos_enum_ptrs, aos_state_t *pptr) return 0;
317
317
ENUM_PTR(0, aos_state_t, s);
328
328
"aos_state", aos_clear_marks, aos_enum_ptrs, aos_reloc_ptrs, 0);
330
330
/* Stream template */
331
static const stream_template s_aos_template = {
331
static const stream_template s_aos_template = {
332
332
&st_aos_state, 0, s_aos_process, 1, 1, 0, 0 };
334
334
/* Stream procs */
335
static const stream_procs s_aos_procs = {
335
static const stream_procs s_aos_procs = {
336
336
s_aos_available, s_aos_seek, s_aos_reset,
337
337
s_aos_flush, s_aos_close, s_aos_process,
338
338
NULL /* no s_aos_switch */