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