~ubuntu-branches/ubuntu/oneiric/ghostscript/oneiric

« back to all changes in this revision

Viewing changes to psi/zfrsd.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2011-07-15 16:49:55 UTC
  • mfrom: (1.1.23 upstream)
  • Revision ID: james.westby@ubuntu.com-20110715164955-uga6qibao6kez05c
Tags: 9.04~dfsg~20110715-0ubuntu1
* New upstream release
   - GIT snapshot from Jult, 12 2011.
* debian/patches/020110406~a54df2d.patch,
  debian/patches/020110408~0791cc8.patch,
  debian/patches/020110408~507cbee.patch,
  debian/patches/020110411~4509a49.patch,
  debian/patches/020110412~78bb9a6.patch,
  debian/patches/020110418~a05ab8a.patch,
  debian/patches/020110420~20b6c78.patch,
  debian/patches/020110420~4ddefa2.patch: Removed upstream patches.
* debian/rules: Generate ABI version number (variable "abi") correctly,
  cutting off repackaging and pre-release parts.
* debian/rules: Added ./lcms2/ directory to DEB_UPSTREAM_REPACKAGE_EXCLUDES.
* debian/copyright: Added lcms2/* to the list of excluded files.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
2
2
   All Rights Reserved.
3
 
  
 
3
 
4
4
   This software is provided AS-IS with no warranty, either express or
5
5
   implied.
6
6
 
11
11
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12
12
*/
13
13
 
14
 
/* $Id: zfrsd.c 11731 2010-09-20 01:26:14Z alexcher $ */
 
14
/* $Id$ */
15
15
/* ReusableStreamDecode filter support */
16
16
#include "memory_.h"
17
17
#include "ghost.h"
54
54
 
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;
62
 
        }
 
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;
 
62
        }
63
63
    } else
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
68
 
        ) {
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
 
68
        ) {
 
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);
76
76
    } else
77
 
        pDecodeParms = 0;
 
77
        pDecodeParms = 0;
78
78
    for (i = 0; i < r_size(pFilter); ++i) {
79
 
        ref f, fname, dp;
 
79
        ref f, fname, dp;
80
80
 
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)
87
 
            )
88
 
            return_error(e_rangecheck);
89
 
        if (pDecodeParms) {
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);
93
 
        }
 
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)
 
87
            )
 
88
            return_error(e_rangecheck);
 
89
        if (pDecodeParms) {
 
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);
 
93
        }
94
94
    }
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 */
97
 
        return code;
 
97
        return code;
98
98
    if ((code = dict_bool_param(op, "AsyncRead", false, &AsyncRead)) < 0
99
 
        )
100
 
        return code;
 
99
        )
 
100
        return code;
101
101
    push(1);
102
102
    op[-1] = *pFilter;
103
103
    if (pDecodeParms)
104
 
        *op = *pDecodeParms;
 
104
        *op = *pDecodeParms;
105
105
    else
106
 
        make_null(op);
 
106
        make_null(op);
107
107
    return 0;
108
108
}
109
109
 
120
120
 * ordinary file or string streams.
121
121
 */
122
122
static int make_rfs(i_ctx_t *i_ctx_p, os_ptr op, stream *fs,
123
 
                     long offset, long length);
 
123
                     long offset, long length);
124
124
 
125
125
static int make_aos(i_ctx_t *i_ctx_p, os_ptr op,
126
126
                    int blk_sz, int blk_sz_last, unsigned int file_sz);
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);
141
141
 
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);
147
147
 
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;
156
156
        ref *blk_ref;
157
157
        ulong filelen = 0;
158
158
 
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++) {
173
173
        }
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);
177
177
        } else {
178
178
           code = make_aos(i_ctx_p, source_op, blk_sz, r_size(&blk_ref[blk_cnt - 1]), filelen);
179
179
        }
180
180
    } else {
181
 
        long offset = 0;
182
 
        stream *source;
183
 
        stream *s;
 
181
        long offset = 0;
 
182
        stream *source;
 
183
        stream *s;
184
184
 
185
 
        check_read_file(i_ctx_p, source, source_op);
186
 
        s = source;
 
185
        check_read_file(i_ctx_p, source, source_op);
 
186
        s = source;
187
187
rs:
188
 
        if (s->cbuf_string.data != 0) { /* string stream */
189
 
            long pos = stell(s);
190
 
            long avail = sbufavailable(s) + pos;
191
 
 
192
 
            offset += pos;
193
 
            code = make_rss(i_ctx_p, source_op, s->cbuf_string.data,
194
 
                            s->cbuf_string.size,
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;
205
 
 
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);
211
 
 
212
 
                if (left < length)
213
 
                    length = left;
214
 
            }
215
 
            s = s->strm;
216
 
            goto rs;
217
 
        }
218
 
        else                    /* some other kind of stream */
219
 
            return_error(e_rangecheck);
220
 
        if (close_source) {
221
 
            stream *rs = fptr(source_op);
222
 
 
223
 
            rs->strm = source;  /* only for close_source */
224
 
            rs->close_strm = true;
225
 
        }
 
188
        if (s->cbuf_string.data != 0) { /* string stream */
 
189
            long pos = stell(s);
 
190
            long avail = sbufavailable(s) + pos;
 
191
 
 
192
            offset += pos;
 
193
            code = make_rss(i_ctx_p, source_op, s->cbuf_string.data,
 
194
                            s->cbuf_string.size,
 
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;
 
205
 
 
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);
 
211
 
 
212
                if (left < length)
 
213
                    length = left;
 
214
            }
 
215
            s = s->strm;
 
216
            goto rs;
 
217
        }
 
218
        else                    /* some other kind of stream */
 
219
            return_error(e_rangecheck);
 
220
        if (close_source) {
 
221
            stream *rs = fptr(source_op);
 
222
 
 
223
            rs->strm = source;  /* only for close_source */
 
224
            rs->close_strm = true;
 
225
        }
226
226
    }
227
227
    if (code >= 0)
228
 
        pop(1);
 
228
        pop(1);
229
229
    return code;
230
230
}
231
231
 
232
232
/* Make a reusable string stream. */
233
233
int
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)
236
236
{
237
237
    uint save_space = icurrent_space;
238
238
    stream *s;
242
242
    s = file_alloc_stream(imemory, "make_rss");
243
243
    ialloc_set_space(idmemory, save_space);
244
244
    if (s == 0)
245
 
        return_error(e_VMerror);
 
245
        return_error(e_VMerror);
246
246
    sread_string_reusable(s, data + offset, max(left, 0));
247
247
    if (is_bytestring)
248
 
        s->cbuf_string.data = 0;        /* byte array, not string */
 
248
        s->cbuf_string.data = 0;        /* byte array, not string */
249
249
    make_stream_file(op, s, "r");
250
250
    return 0;
251
251
}
262
262
    int code;
263
263
 
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,
267
267
                              imemory);
268
268
    if (code < 0)
269
 
        return code;
 
269
        return code;
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);
278
278
    if (code < 0)
279
 
        return code;
 
279
        return code;
280
280
    if (sread_subfile(s, offset, length) < 0) {
281
 
        sclose(s);
282
 
        return_error(e_ioerror);
 
281
        sclose(s);
 
282
        return_error(e_ioerror);
283
283
    }
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);
297
297
 
298
298
/* Stream state */
299
299
typedef struct aos_state_s {
300
300
    stream_state_common;
301
301
    ref   blocks;
302
 
    stream *s;  
 
302
    stream *s;
303
303
    int   blk_sz;
304
304
    int   blk_sz_last;
305
 
    uint  file_sz; 
 
305
    uint  file_sz;
306
306
} aos_state_t;
307
307
 
308
308
/* GC procedures */
309
 
static 
 
309
static
310
310
CLEAR_MARKS_PROC(aos_clear_marks)
311
311
{   aos_state_t *const pptr = vptr;
312
312
 
313
313
    r_clear_attrs(&pptr->blocks, l_mark);
314
314
}
315
 
static 
 
315
static
316
316
ENUM_PTRS_WITH(aos_enum_ptrs, aos_state_t *pptr) return 0;
317
317
ENUM_PTR(0, aos_state_t, s);
318
318
case 1:
328
328
    "aos_state", aos_clear_marks, aos_enum_ptrs, aos_reloc_ptrs, 0);
329
329
 
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 };
333
333
 
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 */
347
347
    const int aos_buf_size = 1024; /* arbitrary */
348
348
    uint save_space = icurrent_space;
349
349
    ialloc_set_space(idmemory, r_space(op));
350
 
    
 
350
 
351
351
    s = s_alloc(imemory, "aos_stream");
352
352
    ss = (aos_state_t *)s_alloc_state(imemory, &st_aos_state, "st_aos_state");
353
353
    buf = gs_alloc_bytes(imemory, aos_buf_size, "aos_stream_buf");
391
391
    long offset = pos - s->position;
392
392
 
393
393
    if (offset >= 0 && offset <= end) {  /* Staying within the same buffer */
394
 
        s->srptr = s->cbuf + offset - 1;
395
 
        return 0;
 
394
        s->srptr = s->cbuf + offset - 1;
 
395
        return 0;
396
396
    }
397
397
    if (pos < 0 || pos > s->file_limit)
398
 
        return ERRC;
 
398
        return ERRC;
399
399
    s->srptr = s->srlimit = s->cbuf - 1;
400
400
    s->end_status = 0;
401
401
    s->position = pos;
407
407
{
408
408
    /* PLRM definition of reset operator is strange. */
409
409
    /* Rewind the file and discard the buffer. */
410
 
    s->position = 0; 
 
410
    s->position = 0;
411
411
    s->srptr = s->srlimit = s->cbuf - 1;
412
412
    s->end_status = 0;
413
413
}
432
432
 
433
433
static int
434
434
s_aos_process(stream_state * st, stream_cursor_read * ignore_pr,
435
 
                      stream_cursor_write * pw, bool last)
 
435
                      stream_cursor_write * pw, bool last)
436
436
{
437
437
    int blk_i, blk_off, blk_cnt, status = 1;
438
438
    uint count;
444
444
 
445
445
    pos += sbufavailable(ss->s);
446
446
    if (pos >= ss->file_sz)
447
 
        return EOFC;
 
447
        return EOFC;
448
448
    blk_i   = pos / ss->blk_sz;
449
449
    blk_off = pos % ss->blk_sz;
450
450
    blk_cnt = r_size(&ss->blocks);
455
455
    if (max_count > count - blk_off) {
456
456
        max_count = count - blk_off;
457
457
        if (blk_i == blk_cnt - 1)
458
 
             status = EOFC;     
 
458
             status = EOFC;
459
459
    }
460
460
    memcpy(pw->ptr+1, data + blk_off, max_count);
461
461
    pw->ptr += max_count;