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: sfilter2.c 8250 2007-09-25 13:31:24Z giles $ */
15
/* Simple Level 2 filters */
16
#include "stdio_.h" /* includes std.h */
24
/* ------ ASCII85Encode ------ */
26
private_st_A85E_state();
28
/* Initialize the state */
30
s_A85E_init(stream_state * st)
32
stream_A85E_state *const ss = (stream_A85E_state *) st;
34
return s_A85E_init_inline(ss);
37
/* Process a buffer */
38
#define LINE_LIMIT 79 /* not 80, to satisfy Genoa FTS */
40
s_A85E_process(stream_state * st, stream_cursor_read * pr,
41
stream_cursor_write * pw, bool last)
43
stream_A85E_state *const ss = (stream_A85E_state *) st;
44
register const byte *p = pr->ptr;
45
register byte *q = pw->ptr;
46
byte *qn = q + (LINE_LIMIT - ss->count); /* value of q before next EOL */
47
const byte *rlimit = pr->limit;
48
byte *wlimit = pw->limit;
50
int prev = ss->last_char;
53
if_debug3('w', "[w85]initial ss->count = %d, rcount = %d, wcount = %d\n",
54
ss->count, (int)(rlimit - p), (int)(wlimit - q));
55
for (; (count = rlimit - p) >= 4; p += 4) {
57
((ulong) (((uint) p[1] << 8) + p[2]) << 16) +
58
(((uint) p[3] << 8) + p[4]);
68
if_debug1('w', "[w85]EOL at %d bytes written\n",
78
ulong v4 = word / 85; /* max 85^4 */
79
ulong v3 = v4 / 85; /* max 85^3 */
80
uint v2 = v3 / 85; /* max 85^2 */
81
uint v1 = v2 / 85; /* max 85 */
83
put: if (q + 5 > qn) {
90
if_debug1('w', "[w85]EOL at %d bytes written\n",
98
q[1] = (byte) v1 + '!';
99
q[2] = (byte) (v2 - v1 * 85) + '!';
100
q[3] = (byte) ((uint) v3 - v2 * 85) + '!';
101
q[4] = (byte) ((uint) v4 - (uint) v3 * 85) + '!';
102
q[5] = (byte) ((uint) word - (uint) v4 * 85) + '!';
104
* '%%' or '%!' at the beginning of the line will confuse some
105
* document managers: insert (an) EOL(s) if necessary to prevent
110
if (qn - q == LINE_LIMIT - 1) {
111
/* A line would begin with %%. */
115
"[w85]EOL for %%%% at %d bytes written\n",
119
} else if (prev == '\n' && (q[2] == '%' || q[2] == '!')) {
121
* We may have to insert more than one EOL if
122
* there are more than two %s in a row.
125
(q[2] == '!' ? 1 : /* else q[2] == '%' */
131
q[5] != '%' ? 3 : 4);
133
if (wlimit - q < 5 + extra) {
137
if_debug6('w', "[w]%c%c%c%c%c extra = %d\n",
138
q[1], q[2], q[3], q[4], q[5], extra);
141
q[9] = q[5], q[8] = '\n';
145
e3:q[7] = q[4], q[6] = '\n';
148
q[7] = q[5], q[6] = q[4];
149
e2:q[5] = q[3], q[4] = '\n';
152
q[6] = q[5], q[5] = q[4], q[4] = q[3];
153
e1:q[3] = q[2], q[2] = '\n';
155
if_debug1('w', "[w85]EOL at %d bytes written\n",
156
(int)(q + 2 * extra - pw->ptr));
157
qn = q + 2 * extra + LINE_LIMIT;
160
} else if (q[1] == '!' && prev == '%' &&
161
qn - q == LINE_LIMIT - 1
163
/* A line would begin with %!. */
166
if_debug1('w', "[w85]EOL for %%! at %d bytes written\n",
174
ss->count = LINE_LIMIT - (qn - q);
175
/* Check for final partial word. */
176
if (last && status == 0 && count < 4) {
178
int nchars = (count == 0 ? 2 : count + 3);
180
ulong divisor = 85L * 85 * 85 * 85;
185
word += (uint) p[3] << 8;
187
word += (ulong) p[2] << 16;
189
word += (ulong) p[1] << 24;
190
for(i=0; i <= count; i++) {
191
ulong v = word / divisor; /* actually only a byte */
193
buf[i] = (byte) v + '!';
199
space = count && buf[0] == '%' &&
200
( (prev == '\n' && ( buf[1] == '%' || buf[1] =='!')) ||
201
(prev == '%' && qn - q == LINE_LIMIT - 1)
203
if (wlimit - q < nchars+space)
205
else if (q + nchars+space > qn) {
213
memcpy(q+1, buf, count+1);
221
if_debug3('w', "[w85]final ss->count = %d, %d bytes read, %d written\n",
222
ss->count, (int)(p - pr->ptr), (int)(q - pw->ptr));
231
/* Stream template */
232
const stream_template s_A85E_template = {
233
&st_A85E_state, s_A85E_init, s_A85E_process, 4, 6
236
/* ------ ByteTranslateEncode/Decode ------ */
238
private_st_BT_state();
240
/* Process a buffer. Note that the same code serves for both streams. */
242
s_BT_process(stream_state * st, stream_cursor_read * pr,
243
stream_cursor_write * pw, bool last)
245
stream_BT_state *const ss = (stream_BT_state *) st;
246
const byte *p = pr->ptr;
248
uint rcount = pr->limit - p;
249
uint wcount = pw->limit - q;
253
if (rcount <= wcount)
254
count = rcount, status = 0;
256
count = wcount, status = 1;
258
*++q = ss->table[*++p];
264
/* Stream template */
265
const stream_template s_BTE_template = {
266
&st_BT_state, NULL, s_BT_process, 1, 1
268
const stream_template s_BTD_template = {
269
&st_BT_state, NULL, s_BT_process, 1, 1