1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: sa85d.c 8250 2007-09-25 13:31:24Z giles $ */
15
/* ASCII85Decode filter */
21
/* ------ ASCII85Decode ------ */
23
private_st_A85D_state();
25
/* Initialize the state */
27
s_A85D_init(stream_state * st)
29
stream_A85D_state *const ss = (stream_A85D_state *) st;
31
return s_A85D_init_inline(ss);
34
/* Process a buffer */
35
static int a85d_finish(int, ulong, stream_cursor_write *);
37
s_A85D_process(stream_state * st, stream_cursor_read * pr,
38
stream_cursor_write * pw, bool last)
40
stream_A85D_state *const ss = (stream_A85D_state *) st;
41
register const byte *p = pr->ptr;
42
register byte *q = pw->ptr;
43
/* stop processing early unless the target is empty (last == true) */
44
/* to make sure we consume the EOD marker correctly. The EOD marker */
45
/* might be as many as 6 characters after the last valid data char */
46
/* D <cr> <lf> '~' <cr> <lf> '>' where 'D' is a data character. */
47
const byte *rlimit = pr->limit - (last ? 0 : 7); /* max EOD len + 1 */
48
const byte *r = max(p, rlimit);
49
byte *wlimit = pw->limit;
51
ulong word = ss->word;
54
/* scan to make sure that an EOD isn't fully contained in the */
55
/* last part of the buffer (between rlimit and pr->limit). */
56
while (r < pr->limit) {
60
/* we have both characters of a complete EOD. */
61
rlimit = pr->limit; /* go ahead and process everything */
62
r = rlimit; /* break out of the while loops */
68
uint ccode = ch - '!';
70
if (ccode < 85) { /* catches ch < '!' as well */
73
* We've completed a 32-bit group. Make sure we have
74
* room for it in the output.
81
/* Check for overflow condition, throw ioerror if so */
82
if (word >= 0x03030303 && ccode > 0) {
86
word = word * 85 + ccode;
87
q[1] = (byte) (word >> 24);
88
q[2] = (byte) (word >> 16);
89
q[3] = (byte) ((uint) word >> 8);
95
word = word * 85 + ccode;
98
} else if (ch == 'z' && ccount == 0) {
104
q[1] = q[2] = q[3] = q[4] = 0,
106
} else if (scan_char_decoder[ch] == ctype_space)
108
else if (ch == '~') {
111
rlimit = pr->limit; /* Here we use the real "limit" */
112
/* Handle odd bytes. */
120
if ((int)(wlimit - q) < ccount - 1) {
126
/* According to PLRM 3rd, if the A85 filter encounters '~',
127
* the next character must be '>'.
128
* And any other characters should raise an ioerror.
129
* But Adobe Acrobat allows CR/LF between ~ and >.
130
* So we allow CR/LF between them. */
131
while ((p[i] == 13 || p[i] == 10) && (p+i <= rlimit))
138
p--; /* we'll see the '~' after filling the buffer */
142
p += i; /* advance to the '>' */
144
status = a85d_finish(ccount, word, pw);
147
} else { /* syntax error or exception */
153
if (status == 0 && last) {
154
if ((int)(wlimit - q) < ccount - 1)
157
status = a85d_finish(ccount, word, pw);
164
/* Handle the end of input data. */
166
a85d_finish(int ccount, ulong word, stream_cursor_write * pw)
168
/* Assume there is enough room in the output buffer! */
175
case 1: /* syntax error */
178
case 2: /* 1 odd byte */
179
word = word * (85L * 85 * 85) + 85L * 85 * 85 - 1L;
181
case 3: /* 2 odd bytes */
182
word = word * (85L * 85) + 85L * 85L - 1L;
184
case 4: /* 3 odd bytes */
185
word = word * 85L + 84L;
186
q[3] = (byte) (word >> 8);
187
o2: q[2] = (byte) (word >> 16);
188
o1: q[1] = (byte) (word >> 24);
195
/* Stream template */
196
const stream_template s_A85D_template = {
197
&st_A85D_state, s_A85D_init, s_A85D_process, 2, 4