1 /*
2 * asc85enc.c
3 * Copyright (C) 2000-2003 A.J. van Os; Released under GPL
4 *
5 * Description:
6 * Functions to for ASCII 85 encoding
7 *
8 *====================================================================
9 * This part of the software is based on:
10 * asc85ec.c - ASCII85 and Hex encoding for PostScript Level 2 and PDF
11 * Copyright (C) 1994-99 Thomas Merz (tm@muc.de)
12 *====================================================================
13 * The credit should go to him, but all the bugs are mine.
14 */
15
16 #include <stdio.h>
17 #include "antiword.h"
18
19 static const ULONG aulPower85[5] = {
20 1UL, 85UL, 85UL * 85, 85UL * 85 * 85, 85UL * 85 * 85 * 85,
21 };
22 static int iOutBytes = 0; /* Number of characters in an output line */
23 static char cCharPrev = '\0';
24
25 /*
26 * Two percent characters at the start of a line will cause trouble
27 * with some post-processing software. In order to avoid this, we
28 * simply insert a line break if we encounter two percent characters
29 * at the start of the line. Of course, this rather simplistic
30 * algorithm may lead to a large line count in pathological cases,
31 * but the chance for hitting such a case is very small, and even
32 * so it's only a cosmetic flaw and not a functional restriction.
33 */
34
35 /*
36 * vOutputByte - output one byte
37 */
38 static void
vOutputByte(ULONG ulChar,FILE * pOutFile)39 vOutputByte(ULONG ulChar, FILE *pOutFile)
40 {
41 if (iOutBytes == 1 && cCharPrev == '%' && ulChar == (ULONG)'%') {
42 if (putc('\n', pOutFile) != EOF) {
43 iOutBytes = 0;
44 }
45 }
46 if (putc((int)ulChar, pOutFile) == EOF) {
47 return;
48 }
49 iOutBytes++;
50 if (iOutBytes > 63) {
51 if (putc('\n', pOutFile) != EOF) {
52 iOutBytes = 0;
53 }
54 }
55 cCharPrev = (char)ulChar;
56 } /* end of vOutputByte */
57
58 /*
59 * vASCII85EncodeByte - ASCII 85 encode a byte
60 */
61 void
vASCII85EncodeByte(FILE * pOutFile,int iByte)62 vASCII85EncodeByte(FILE *pOutFile, int iByte)
63 {
64 static ULONG ulBuffer[4] = { 0, 0, 0, 0 };
65 static int iInBuffer = 0;
66 ULONG ulValue, ulTmp;
67 int iIndex;
68
69 fail(pOutFile == NULL);
70 fail(iInBuffer < 0);
71 fail(iInBuffer > 3);
72
73 if (iByte == EOF) {
74 /* End Of File, time to clean up */
75 if (iInBuffer > 0 && iInBuffer < 4) {
76 /* Encode the remaining bytes */
77 ulValue = 0;
78 for (iIndex = iInBuffer - 1; iIndex >= 0; iIndex--) {
79 ulValue |=
80 ulBuffer[iIndex] << (8 * (3 - iIndex));
81 }
82 for (iIndex = 4; iIndex >= 4 - iInBuffer; iIndex--) {
83 ulTmp = ulValue / aulPower85[iIndex];
84 vOutputByte(ulTmp + '!', pOutFile);
85 ulValue -= ulTmp * aulPower85[iIndex];
86 }
87 }
88 /* Add the End Of Data marker */
89 (void)putc('~', pOutFile);
90 (void)putc('>', pOutFile);
91 (void)putc('\n', pOutFile);
92 /* Reset the control variables */
93 iInBuffer = 0;
94 iOutBytes = 0;
95 cCharPrev = '\0';
96 return;
97 }
98
99 ulBuffer[iInBuffer] = (ULONG)iByte & 0xff;
100 iInBuffer++;
101
102 if (iInBuffer >= 4) {
103 ulValue = (ulBuffer[0] << 24) | (ulBuffer[1] << 16) |
104 (ulBuffer[2] << 8) | ulBuffer[3];
105 if (ulValue == 0) {
106 vOutputByte((ULONG)'z', pOutFile); /* Shortcut for 0 */
107 } else {
108 for (iIndex = 4; iIndex >= 0; iIndex--) {
109 ulTmp = ulValue / aulPower85[iIndex];
110 vOutputByte(ulTmp + '!', pOutFile);
111 ulValue -= ulTmp * aulPower85[iIndex];
112 }
113 }
114 /* Reset the buffer */
115 iInBuffer = 0;
116 }
117 } /* end of vASCII85EncodeByte */
118
119 /*
120 * vASCII85EncodeArray - ASCII 85 encode a byte array
121 */
122 void
vASCII85EncodeArray(FILE * pInFile,FILE * pOutFile,size_t tLength)123 vASCII85EncodeArray(FILE *pInFile, FILE *pOutFile, size_t tLength)
124 {
125 size_t tCount;
126 int iByte;
127
128 fail(pInFile == NULL);
129 fail(pOutFile == NULL);
130
131 DBG_DEC(tLength);
132
133 for (tCount = 0; tCount < tLength; tCount++) {
134 iByte = iNextByte(pInFile);
135 if (iByte == EOF) {
136 break;
137 }
138 vASCII85EncodeByte(pOutFile, iByte);
139 }
140 } /* end of vASCII85EncodeArray */
141
142 /*
143 * vASCII85EncodeFile - ASCII 85 encode part of a file
144 */
145 void
vASCII85EncodeFile(FILE * pInFile,FILE * pOutFile,size_t tLength)146 vASCII85EncodeFile(FILE *pInFile, FILE *pOutFile, size_t tLength)
147 {
148 fail(pInFile == NULL);
149 fail(pOutFile == NULL);
150 fail(tLength == 0);
151
152 vASCII85EncodeArray(pInFile, pOutFile, tLength);
153 vASCII85EncodeByte(pOutFile, EOF);
154 } /* end of vASCII85EncodeFile */
155