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) 1999 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: sa85d.c,v 1.9 2003/04/24 19:42:13 ray Exp $ */
18
/* ASCII85Decode filter */
19
#include "std.h"
20
#include "strimpl.h"
21
#include "sa85d.h"
22
#include "scanchar.h"
23
 
24
/* ------ ASCII85Decode ------ */
25
 
26
private_st_A85D_state();
27
 
28
/* Initialize the state */
29
private int
30
s_A85D_init(stream_state * st)
31
{
32
    stream_A85D_state *const ss = (stream_A85D_state *) st;
33
 
34
    return s_A85D_init_inline(ss);
35
}
36
 
37
/* Process a buffer */
38
private int a85d_finish(int, ulong, stream_cursor_write *);
39
private int
40
s_A85D_process(stream_state * st, stream_cursor_read * pr,
41
	       stream_cursor_write * pw, bool last)
42
{
43
    stream_A85D_state *const ss = (stream_A85D_state *) st;
44
    register const byte *p = pr->ptr;
45
    register byte *q = pw->ptr;
46
    const byte *rlimit = pr->limit;
47
    byte *wlimit = pw->limit;
48
    int ccount = ss->odd;
49
    ulong word = ss->word;
50
    int status = 0;
51
 
52
    while (p < rlimit) {
53
	int ch = *++p;
54
	uint ccode = ch - '!';
55
 
56
	if (ccode < 85) {	/* catches ch < '!' as well */
57
	    if (ccount == 4) {
58
		/*
59
		 * We've completed a 32-bit group.  Make sure we have
60
		 * room for it in the output.
61
		 */
62
		if (wlimit - q < 4) {
63
		    p--;
64
		    status = 1;
65
		    break;
66
		}
67
		/* Check for overflow condition, throw ioerror if so */
68
		if (word >= 0x03030303 && ccode > 0) {
69
		    status = ERRC;
70
	            break;
71
	        }
72
		word = word * 85 + ccode;
73
		q[1] = (byte) (word >> 24);
74
		q[2] = (byte) (word >> 16);
75
		q[3] = (byte) ((uint) word >> 8);
76
		q[4] = (byte) word;
77
		q += 4;
78
		word = 0;
79
		ccount = 0;
80
	    } else {
81
		word = word * 85 + ccode;
82
		++ccount;
83
	    }
84
	} else if (ch == 'z' && ccount == 0) {
85
	    if (wlimit - q < 4) {
86
		p--;
87
		status = 1;
88
		break;
89
	    }
90
	    q[1] = q[2] = q[3] = q[4] = 0,
91
		q += 4;
92
	} else if (scan_char_decoder[ch] == ctype_space)
93
	    DO_NOTHING;
94
	else if (ch == '~') {
95
	    int i = 1;
96
 
97
	    /* Handle odd bytes. */
98
	    if (p == rlimit) {
99
		if (last)
100
		    status = ERRC;
101
		else
102
		    p--;
103
		break;
104
	    }
105
	    if ((int)(wlimit - q) < ccount - 1) {
106
		status = 1;
107
		p--;
108
		break;
109
	    }
110
 
111
	    /* According to PLRM 3rd, if the A85 filter encounters '~',
112
	     * the next character must be '>'.
113
	     * And any other characters should raise an ioerror.
114
	     * But Adobe Acrobat allows CR/LF between ~ and >.
115
	     * So we allow CR/LF between them. */
116
	    while ((p[i] == 13 || p[i] == 10) && (p+i <= rlimit)) 
117
		i++;
118
	    if (p[i] != '>') {
119
		if (p+i == rlimit) {
120
		    if (last)
121
			status = ERRC;
122
		    else
123
			p--;	/* we'll see the '~' after filling the buffer */
124
		}
125
		break;
126
	    }
127
	    p += i;		/* advance to the '>' */
128
	    pw->ptr = q;
129
	    status = a85d_finish(ccount, word, pw);
130
	    q = pw->ptr;
131
	    break;
132
	} else {		/* syntax error or exception */
133
	    status = ERRC;
134
	    break;
135
	}
136
    }
137
    pw->ptr = q;
138
    if (status == 0 && last) {
139
	if ((int)(wlimit - q) < ccount - 1)
140
	    status = 1;
141
	else
142
	    status = a85d_finish(ccount, word, pw);
143
    }
144
    pr->ptr = p;
145
    ss->odd = ccount;
146
    ss->word = word;
147
    return status;
148
}
149
/* Handle the end of input data. */
150
private int
151
a85d_finish(int ccount, ulong word, stream_cursor_write * pw)
152
{
153
    /* Assume there is enough room in the output buffer! */
154
    byte *q = pw->ptr;
155
    int status = EOFC;
156
 
157
    switch (ccount) {
158
	case 0:
159
	    break;
160
	case 1:		/* syntax error */
161
	    status = ERRC;
162
	    break;
163
	case 2:		/* 1 odd byte */
164
	    word = word * (85L * 85 * 85) + 85L * 85 * 85 - 1L;
165
	    goto o1;
166
	case 3:		/* 2 odd bytes */
167
	    word = word * (85L * 85) + 85L * 85L - 1L;
168
	    goto o2;
169
	case 4:		/* 3 odd bytes */
170
	    word = word * 85L + 84L;
171
	    q[3] = (byte) (word >> 8);
172
o2:	    q[2] = (byte) (word >> 16);
173
o1:	    q[1] = (byte) (word >> 24);
174
	    q += ccount - 1;
175
	    pw->ptr = q;
176
    }
177
    return status;
178
}
179
 
180
/* Stream template */
181
const stream_template s_A85D_template = {
182
    &st_A85D_state, s_A85D_init, s_A85D_process, 2, 4
183
};