|
|
1.1 root 1: /* lzh.c */
2:
3: /* Synchronet LZH compression library */
4:
5: /* $Id: lzh.c,v 1.3 2000/10/26 02:53:26 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Rob Swindell's conversion of 1988 LZH (LHarc) encoding functions *
12: * Based on Japanese version 29-NOV-1988 *
13: * LZSS coded by Haruhiko Okumura *
14: * Adaptive Huffman Coding coded by Haruyasu Yoshizaki *
15: * *
16: * Anonymous FTP access to the most recent released source is available at *
17: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
18: * *
19: * Anonymous CVS access to the development source and modification history *
20: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
21: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
22: * (just hit return, no password is necessary) *
23: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
24: * *
25: * For Synchronet coding style and modification guidelines, see *
26: * http://www.synchro.net/source.html *
27: * *
28: * You are encouraged to submit any modifications (preferably in Unix diff *
29: * format) via e-mail to [email protected] *
30: * *
31: * Note: If this box doesn't appear square, then you need to fix your tabs. *
32: ****************************************************************************/
33:
34: #include <stdio.h>
35: #include <stdlib.h>
36: #include <string.h>
37: #include <ctype.h>
38: #include <malloc.h>
39: #include "lzh.h"
40:
41: /****************************************************************************/
42: /* Memory allocation macros for various compilers and environments */
43: /* MALLOC is used for allocations of 64k or less */
44: /* FREE is used to free buffers allocated with MALLOC */
45: /* LMALLOC is used for allocations of possibly larger than 64k */
46: /* LFREE is used to free buffers allocated with LMALLOC */
47: /* REALLOC is used to re-size a previously MALLOCed or LMALLOCed buffer */
48: /****************************************************************************/
49: #if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
50: #if defined(__TURBOC__)
51: #define REALLOC(x,y) farrealloc(x,y)
52: #define LMALLOC(x) farmalloc(x)
53: #define MALLOC(x) farmalloc(x)
54: #define LFREE(x) farfree(x)
55: #define FREE(x) farfree(x)
56: #elif defined(__WATCOMC__)
57: #define REALLOC realloc
58: #define LMALLOC(x) halloc(x,1) /* far heap, but slow */
59: #define MALLOC malloc /* far heap, but 64k max */
60: #define LFREE hfree
61: #define FREE free
62: #else /* Other 16-bit Compiler */
63: #define REALLOC realloc
64: #define LMALLOC malloc
65: #define MALLOC malloc
66: #define LFREE free
67: #define FREE free
68: #endif
69: #else /* 32-bit Compiler or Small Memory Model */
70: #define REALLOC realloc
71: #define LMALLOC malloc
72: #define MALLOC malloc
73: #define LFREE free
74: #define FREE free
75: #endif
76:
77:
78:
79: /* LZSS Parameters */
80:
81: #define LZH_N 4096 /* Size of string buffer */
82: #define LZH_F 60 /* Size of look-ahead buffer */
83: #define LZH_THRESHOLD 2
84: #define LZH_NIL LZH_N /* End of tree's node */
85:
86: #ifdef LZH_DYNAMIC_BUF
87:
88: unsigned char *lzh_text_buf;
89: short int lzh_match_position, lzh_match_length,
90: *lzh_lson, *lzh_rson, *lzh_dad;
91:
92: #else
93:
94: unsigned char lzh_text_buf[LZH_N + LZH_F - 1];
95: short int lzh_match_position, lzh_match_length,
96: lzh_lson[LZH_N + 1], lzh_rson[LZH_N + 257], lzh_dad[LZH_N + 1];
97:
98: #endif
99:
100:
101: void lzh_init_tree(void) /* Initializing tree */
102: {
103: short int i;
104:
105: for (i = LZH_N + 1; i <= LZH_N + 256; i++)
106: lzh_rson[i] = LZH_NIL; /* root */
107: for (i = 0; i < LZH_N; i++)
108: lzh_dad[i] = LZH_NIL; /* node */
109: }
110:
111: /******************************/
112: /* Inserting node to the tree */
113: /* Only used during encoding */
114: /******************************/
115: void lzh_insert_node(short int r)
116: {
117: short int i, p, cmp;
118: unsigned char *key;
119: unsigned c;
120:
121: cmp = 1;
122: key = lzh_text_buf+r;
123: p = LZH_N + 1 + key[0];
124: lzh_rson[r] = lzh_lson[r] = LZH_NIL;
125: lzh_match_length = 0;
126: for ( ; ; ) {
127: if (cmp >= 0) {
128: if (lzh_rson[p] != LZH_NIL)
129: p = lzh_rson[p];
130: else {
131: lzh_rson[p] = r;
132: lzh_dad[r] = p;
133: return;
134: }
135: } else {
136: if (lzh_lson[p] != LZH_NIL)
137: p = lzh_lson[p];
138: else {
139: lzh_lson[p] = r;
140: lzh_dad[r] = p;
141: return;
142: }
143: }
144: for (i = 1; i < LZH_F; i++)
145: if ((cmp = key[i] - lzh_text_buf[p + i]) != 0)
146: break;
147: if (i > LZH_THRESHOLD) {
148: if (i > lzh_match_length) {
149: lzh_match_position = ((r - p) & (LZH_N - 1)) - 1;
150: if ((lzh_match_length = i) >= LZH_F)
151: break;
152: }
153: if (i == lzh_match_length) {
154: if ((c = ((r - p) & (LZH_N - 1)) - 1)
155: < (unsigned)lzh_match_position) {
156: lzh_match_position = c;
157: }
158: }
159: }
160: }
161: lzh_dad[r] = lzh_dad[p];
162: lzh_lson[r] = lzh_lson[p];
163: lzh_rson[r] = lzh_rson[p];
164: lzh_dad[lzh_lson[p]] = r;
165: lzh_dad[lzh_rson[p]] = r;
166: if (lzh_rson[lzh_dad[p]] == p)
167: lzh_rson[lzh_dad[p]] = r;
168: else
169: lzh_lson[lzh_dad[p]] = r;
170: lzh_dad[p] = LZH_NIL; /* remove p */
171: }
172:
173: void lzh_delete_node(short int p) /* Deleting node from the tree */
174: {
175: short int q;
176:
177: if (lzh_dad[p] == LZH_NIL)
178: return; /* unregistered */
179: if (lzh_rson[p] == LZH_NIL)
180: q = lzh_lson[p];
181: else
182: if (lzh_lson[p] == LZH_NIL)
183: q = lzh_rson[p];
184: else {
185: q = lzh_lson[p];
186: if (lzh_rson[q] != LZH_NIL) {
187: do {
188: q = lzh_rson[q];
189: } while (lzh_rson[q] != LZH_NIL);
190: lzh_rson[lzh_dad[q]] = lzh_lson[q];
191: lzh_dad[lzh_lson[q]] = lzh_dad[q];
192: lzh_lson[q] = lzh_lson[p];
193: lzh_dad[lzh_lson[p]] = q;
194: }
195: lzh_rson[q] = lzh_rson[p];
196: lzh_dad[lzh_rson[p]] = q;
197: }
198: lzh_dad[q] = lzh_dad[p];
199: if (lzh_rson[lzh_dad[p]] == p)
200: lzh_rson[lzh_dad[p]] = q;
201: else
202: lzh_lson[lzh_dad[p]] = q;
203: lzh_dad[p] = LZH_NIL;
204: }
205:
206: /* Huffman coding parameters */
207:
208: #define LZH_N_CHAR (256 - LZH_THRESHOLD + LZH_F)
209: /* character code (= 0..LZH_N_CHAR-1) */
210: #define LZH_T (LZH_N_CHAR * 2 - 1) /* Size of table */
211: #define LZH_R (LZH_T - 1) /* root position */
212: #define MAX_FREQ 0x8000
213: /* update when cumulative frequency */
214: /* reaches to this value */
215:
216: /*
217: * Tables for encoding/decoding upper 6 bits of
218: * sliding dictionary pointer
219: */
220: /* encoder table */
221: uchar lzh_p_len[64] = {
222: 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
223: 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
224: 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
225: 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
226: 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
227: 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
228: 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
229: 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
230: };
231:
232: uchar lzh_p_code[64] = {
233: 0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
234: 0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
235: 0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
236: 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
237: 0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
238: 0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
239: 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
240: 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
241: };
242:
243: /* decoder table */
244: uchar lzh_d_code[256] = {
245: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249: 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
250: 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
251: 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
252: 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
253: 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
254: 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
255: 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
256: 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
257: 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
258: 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
259: 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
260: 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
261: 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
262: 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
263: 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
264: 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
265: 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
266: 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
267: 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
268: 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
269: 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
270: 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
271: 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
272: 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
273: 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
274: 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
275: 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
276: 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
277: };
278:
279: uchar lzh_d_len[256] = {
280: 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
281: 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
282: 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
283: 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
284: 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
285: 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
286: 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
287: 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
288: 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
289: 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
290: 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
291: 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
292: 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
293: 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
294: 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
295: 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
296: 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
297: 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
298: 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
299: 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
300: 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
301: 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
302: 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
303: 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
304: 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
305: 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
306: 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
307: 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
308: 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
309: 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
310: 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
311: 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
312: };
313:
314: #ifdef LZH_DYNAMIC_BUF
315:
316: unsigned short *lzh_freq=NULL; /* cumulative freq table */
317:
318: /*
319: * pointing parent nodes.
320: * area [LZH_T..(LZH_T + LZH_N_CHAR - 1)] are pointers for leaves
321: */
322: short int *lzh_prnt=NULL;
323:
324: /* pointing children nodes (son[], son[] + 1)*/
325: short int *lzh_son=NULL;
326:
327: #else /* STATIC */
328:
329: unsigned short lzh_freq[LZH_T + 1]; /* cumulative freq table */
330: short int lzh_prnt[LZH_T + LZH_N_CHAR];
331: short int lzh_son[LZH_T + 1]; /* bug fixed by Digital Dynamics */
332:
333: #endif
334:
335:
336: unsigned short lzh_getbuf = 0; /* Was just "unsigned" fixed 04/12/95 */
337: uchar lzh_getlen = 0;
338:
339: int lzh_getbit(uchar *inbuf, long *incnt, long inlen) /* get one bit */
340: {
341: short int i;
342:
343: while (lzh_getlen <= 8) {
344: if((*incnt)>=inlen)
345: i=0;
346: else
347: i=inbuf[(*incnt)++];
348: lzh_getbuf |= i << (8 - lzh_getlen);
349: lzh_getlen += 8;
350: }
351: i = lzh_getbuf;
352: lzh_getbuf <<= 1;
353: lzh_getlen--;
354: return (i < 0);
355: }
356:
357: short int lzh_getbyte(uchar *inbuf, long *incnt, long inlen) /* get a byte */
358: {
359: unsigned short i;
360:
361: while (lzh_getlen <= 8) {
362: if((*incnt)>=inlen)
363: i=0;
364: else
365: i=inbuf[(*incnt)++];
366: lzh_getbuf |= i << (8 - lzh_getlen);
367: lzh_getlen += 8;
368: }
369: i = lzh_getbuf;
370: lzh_getbuf <<= 8;
371: lzh_getlen -= 8;
372: return i >> 8;
373: }
374:
375: unsigned lzh_putbuf = 0;
376: uchar lzh_putlen = 0;
377:
378: /* output c bits */
379: void lzh_putcode(short int l, unsigned short c, uchar *outbuf, long *outlen)
380: {
381: lzh_putbuf |= c >> lzh_putlen;
382: if ((lzh_putlen += l) >= 8) {
383: outbuf[(*outlen)++]=(lzh_putbuf >> 8);
384: if ((lzh_putlen -= 8) >= 8) {
385: outbuf[(*outlen)++]=lzh_putbuf;
386: lzh_putlen -= 8;
387: lzh_putbuf = c << (l - lzh_putlen);
388: } else {
389: lzh_putbuf <<= 8;
390: }
391: }
392: }
393:
394:
395: /* initialize freq tree */
396:
397: void lzh_start_huff(void)
398: {
399: short int i, j;
400:
401: lzh_getbuf = 0; /* Added by Digital Dynamics for repeating operations */
402: lzh_getlen = 0;
403: lzh_putbuf = 0;
404: lzh_putlen = 0;
405:
406: for (i = 0; i < LZH_N_CHAR; i++) {
407: lzh_freq[i] = 1;
408: lzh_son[i] = i + LZH_T;
409: lzh_prnt[i + LZH_T] = i;
410: }
411: i = 0; j = LZH_N_CHAR;
412: while (j <= LZH_R) {
413: lzh_freq[j] = lzh_freq[i] + lzh_freq[i + 1];
414: lzh_son[j] = i;
415: lzh_prnt[i] = lzh_prnt[i + 1] = j;
416: i += 2; j++;
417: }
418: lzh_freq[LZH_T] = 0xffff;
419: lzh_prnt[LZH_R] = 0;
420: }
421:
422:
423: /* reconstruct freq tree */
424:
425: void lzh_reconst(void)
426: {
427: short int i, j, k;
428: unsigned short f, l;
429:
430: /* halven cumulative freq for leaf nodes */
431: j = 0;
432: for (i = 0; i < LZH_T; i++) {
433: if (lzh_son[i] >= LZH_T) {
434: lzh_freq[j] = (lzh_freq[i] + 1) / 2;
435: lzh_son[j] = lzh_son[i];
436: j++;
437: }
438: }
439: /* make a tree : first, connect children nodes */
440: for (i = 0, j = LZH_N_CHAR; j < LZH_T; i += 2, j++) {
441: k = i + 1;
442: f = lzh_freq[j] = lzh_freq[i] + lzh_freq[k];
443: for (k = j - 1; f < lzh_freq[k]; k--);
444: k++;
445: l = (j - k) * 2;
446:
447: /* movmem() is Turbo-C dependent
448: rewritten to memmove() by Kenji */
449:
450: /* movmem(&lzh_freq[k], &lzh_freq[k + 1], l); */
451: (void)memmove(lzh_freq+k+1,lzh_freq+k, l);
452: lzh_freq[k] = f;
453: /* movmem(&lzh_son[k], &lzh_son[k + 1], l); */
454: (void)memmove(lzh_son+k+1,lzh_son+k, l);
455: lzh_son[k] = i;
456: }
457: /* connect parent nodes */
458: for (i = 0; i < LZH_T; i++) {
459: if ((k = lzh_son[i]) >= LZH_T) {
460: lzh_prnt[k] = i;
461: } else {
462: lzh_prnt[k] = lzh_prnt[k + 1] = i;
463: }
464: }
465: }
466:
467: /* update freq tree */
468:
469: void lzh_update(short int c)
470: {
471: short int i, j, k, l;
472:
473: if (lzh_freq[LZH_R] == MAX_FREQ) {
474: lzh_reconst();
475: }
476: c = lzh_prnt[c + LZH_T];
477: do {
478: k = ++lzh_freq[c];
479:
480: /* swap nodes to keep the tree freq-ordered */
481: if (k > lzh_freq[l = c + 1]) {
482: while (k > lzh_freq[++l]);
483: l--;
484: lzh_freq[c] = lzh_freq[l];
485: lzh_freq[l] = k;
486:
487: i = lzh_son[c];
488: lzh_prnt[i] = l;
489: if (i < LZH_T) lzh_prnt[i + 1] = l;
490:
491: j = lzh_son[l];
492: lzh_son[l] = i;
493:
494: lzh_prnt[j] = c;
495: if (j < LZH_T) lzh_prnt[j + 1] = c;
496: lzh_son[c] = j;
497:
498: c = l;
499: }
500: } while ((c = lzh_prnt[c]) != 0); /* do it until reaching the root */
501: }
502:
503: unsigned short lzh_code, lzh_len;
504:
505: void lzh_encode_char(unsigned short c, uchar *outbuf, long *outlen)
506: {
507: unsigned short i;
508: short int j, k;
509:
510: i = 0;
511: j = 0;
512: k = lzh_prnt[c + LZH_T];
513:
514: /* search connections from leaf node to the root */
515: do {
516: i >>= 1;
517:
518: /*
519: if node's address is odd, output 1
520: else output 0
521: */
522: if (k & 1) i += 0x8000;
523:
524: j++;
525: } while ((k = lzh_prnt[k]) != LZH_R);
526: lzh_putcode(j, i, outbuf, outlen);
527: lzh_code = i;
528: lzh_len = j;
529: lzh_update(c);
530: }
531:
532: void lzh_encode_position(unsigned short c, uchar *outbuf, long *outlen)
533: {
534: unsigned short i;
535:
536: /* output upper 6 bits with encoding */
537: i = c >> 6;
538: lzh_putcode(lzh_p_len[i], (unsigned short)(lzh_p_code[i] << 8), outbuf, outlen);
539:
540: /* output lower 6 bits directly */
541: lzh_putcode(6, (unsigned short)((c & 0x3f) << 10), outbuf, outlen);
542: }
543:
544: void lzh_encode_end(uchar *outbuf, long *outlen)
545: {
546: if (lzh_putlen) {
547: outbuf[(*outlen)++]=(lzh_putbuf >> 8);
548: }
549: }
550:
551: short int lzh_decode_char(uchar *inbuf, long *incnt, long inlen)
552: {
553: unsigned short c;
554:
555: c = lzh_son[LZH_R];
556:
557: /*
558: * start searching tree from the root to leaves.
559: * choose node #(lzh_son[]) if input bit == 0
560: * else choose #(lzh_son[]+1) (input bit == 1)
561: */
562: while (c < LZH_T) {
563: c += lzh_getbit(inbuf,incnt,inlen);
564: c = lzh_son[c];
565: }
566: c -= LZH_T;
567: lzh_update(c);
568: return c;
569: }
570:
571: short int lzh_decode_position(uchar *inbuf, long *incnt, long inlen)
572: {
573: unsigned short i, j, c;
574:
575: /* decode upper 6 bits from given table */
576: i = lzh_getbyte(inbuf,incnt,inlen);
577: c = (unsigned)lzh_d_code[i] << 6;
578: j = lzh_d_len[i];
579:
580: /* input lower 6 bits directly */
581: j -= 2;
582: while (j--) {
583: i = (i << 1) + lzh_getbit(inbuf,incnt,inlen);
584: }
585: return c | i & 0x3f;
586: }
587:
588: /* Compression */
589:
590: /* Encoding/Compressing */
591: /* Returns length of outbuf */
592: long LZHCALL lzh_encode(uchar *inbuf, long inlen, uchar *outbuf)
593: {
594: short int i, c, len, r, s, last_match_length;
595: long incnt,outlen; /* textsize=0; */
596:
597: #ifdef LZH_DYNAMIC_BUF
598:
599: if((lzh_text_buf=(uchar *)MALLOC(LZH_N + LZH_F - 1))==NULL)
600: return(-1);
601: if((lzh_freq=(unsigned short*)MALLOC((LZH_T + 1)*sizeof(unsigned short)))==NULL) {
602: FREE(lzh_text_buf);
603: return(-1); }
604: if((lzh_prnt=(short *)MALLOC((LZH_T + LZH_N_CHAR)*sizeof(short)))==NULL) {
605: FREE(lzh_text_buf);
606: FREE(lzh_freq);
607: return(-1); }
608: if((lzh_son=(short *)MALLOC((LZH_T + 1) * sizeof(short)))==NULL) {
609: FREE(lzh_text_buf);
610: FREE(lzh_prnt);
611: FREE(lzh_freq);
612: return(-1); }
613: if((lzh_lson=(short *)MALLOC((LZH_N + 1)*sizeof(short)))==NULL) {
614: FREE(lzh_text_buf);
615: FREE(lzh_prnt);
616: FREE(lzh_freq);
617: FREE(lzh_son);
618: return(-1); }
619: if((lzh_rson=(short *)MALLOC((LZH_N + 257)*sizeof(short)))==NULL) {
620: FREE(lzh_text_buf);
621: FREE(lzh_prnt);
622: FREE(lzh_freq);
623: FREE(lzh_son);
624: FREE(lzh_lson);
625: return(-1); }
626: if((lzh_dad=(short *)MALLOC((LZH_N + 1)*sizeof(short)))==NULL) {
627: FREE(lzh_text_buf);
628: FREE(lzh_prnt);
629: FREE(lzh_freq);
630: FREE(lzh_son);
631: FREE(lzh_lson);
632: FREE(lzh_rson);
633: return(-1); }
634: #endif
635:
636: incnt=0;
637: memcpy(outbuf,&inlen,sizeof(inlen));
638: outlen=sizeof(inlen);
639: if(!inlen) {
640: #ifdef LZH_DYNAMIC_BUF
641: FREE(lzh_text_buf);
642: FREE(lzh_prnt);
643: FREE(lzh_freq);
644: FREE(lzh_son);
645: FREE(lzh_lson);
646: FREE(lzh_rson);
647: FREE(lzh_dad);
648: #endif
649: return(outlen); }
650: lzh_start_huff();
651: lzh_init_tree();
652: s = 0;
653: r = LZH_N - LZH_F;
654: for (i = s; i < r; i++)
655: lzh_text_buf[i] = ' ';
656: for (len = 0; len < LZH_F && incnt<inlen; len++)
657: lzh_text_buf[r + len] = inbuf[incnt++];
658: /* textsize = len; */
659: for (i = 1; i <= LZH_F; i++)
660: lzh_insert_node((short)(r - i));
661: lzh_insert_node(r);
662: do {
663: if (lzh_match_length > len)
664: lzh_match_length = len;
665: if (lzh_match_length <= LZH_THRESHOLD) {
666: lzh_match_length = 1;
667: lzh_encode_char(lzh_text_buf[r],outbuf,&outlen);
668: } else {
669: lzh_encode_char((unsigned short)(255 - LZH_THRESHOLD + lzh_match_length)
670: ,outbuf,&outlen);
671: lzh_encode_position(lzh_match_position
672: ,outbuf,&outlen);
673: }
674: last_match_length = lzh_match_length;
675: for (i = 0; i < last_match_length && incnt<inlen; i++) {
676: lzh_delete_node(s);
677: c=inbuf[incnt++];
678: lzh_text_buf[s] = (uchar)c;
679: if (s < LZH_F - 1)
680: lzh_text_buf[s + LZH_N] = (uchar)c;
681: s = (s + 1) & (LZH_N - 1);
682: r = (r + 1) & (LZH_N - 1);
683: lzh_insert_node(r);
684: }
685: /***
686: if ((textsize += i) > printcount) {
687: printf("%12ld\r", textsize);
688: printcount += 1024;
689: }
690: ***/
691: while (i++ < last_match_length) {
692: lzh_delete_node(s);
693: s = (s + 1) & (LZH_N - 1);
694: r = (r + 1) & (LZH_N - 1);
695: if (--len) lzh_insert_node(r);
696: }
697: } while (len > 0);
698: lzh_encode_end(outbuf,&outlen);
699: /*
700: printf("input: %ld (%ld) bytes\n", inlen,textsize);
701: printf("output: %ld bytes\n", outlen);
702: printf("output/input: %.3f\n", (double)outlen / inlen);
703: */
704:
705: #ifdef LZH_DYNAMIC_BUF
706: FREE(lzh_text_buf);
707: FREE(lzh_prnt);
708: FREE(lzh_freq);
709: FREE(lzh_son);
710: FREE(lzh_lson);
711: FREE(lzh_rson);
712: FREE(lzh_dad);
713: #endif
714:
715: return(outlen);
716: }
717:
718: /* Decoding/Uncompressing */
719: /* Returns length of outbuf */
720: long LZHCALL lzh_decode(uchar *inbuf, long inlen, uchar *outbuf)
721: {
722: short int i, j, k, r, c;
723: unsigned long int count;
724: long incnt,textsize;
725:
726: #ifdef LZH_DYNAMIC_BUF
727:
728: if((lzh_text_buf=(uchar *)MALLOC((LZH_N + LZH_F - 1)*2))==NULL)
729: return(-1);
730: if((lzh_freq=(unsigned short *)MALLOC((LZH_T + 1)*sizeof(unsigned short)))
731: ==NULL) {
732: FREE(lzh_text_buf);
733: return(-1); }
734: if((lzh_prnt=(short *)MALLOC((LZH_T + LZH_N_CHAR)*sizeof(short)))==NULL) {
735: FREE(lzh_text_buf);
736: FREE(lzh_freq);
737: return(-1); }
738: if((lzh_son=(short *)MALLOC((LZH_T + 1) * sizeof(short)))==NULL) {
739: FREE(lzh_text_buf);
740: FREE(lzh_prnt);
741: FREE(lzh_freq);
742: return(-1); }
743:
744: #endif
745:
746: incnt=0;
747: memcpy(&textsize,inbuf,sizeof(textsize));
748: incnt+=sizeof(textsize);
749: if (textsize == 0) {
750: #ifdef LZH_DYNAMIC_BUF
751: FREE(lzh_text_buf);
752: FREE(lzh_prnt);
753: FREE(lzh_freq);
754: FREE(lzh_son);
755: #endif
756: return(textsize); }
757: lzh_start_huff();
758: for (i = 0; i < LZH_N - LZH_F; i++)
759: *(lzh_text_buf+i) = ' ';
760: r = LZH_N - LZH_F;
761: for (count = 0; count < (unsigned long)textsize; ) {
762: c = lzh_decode_char(inbuf,&incnt,inlen);
763: if (c < 256) {
764: outbuf[count]=(uchar)c;
765: #if 0
766: if(r>(LZH_N + LZH_F - 1) || r<0) {
767: printf("Overflow! (%d)\n",r);
768: getch();
769: exit(-1); }
770: #endif
771: *(lzh_text_buf+r) = (uchar)c;
772: r++;
773: r &= (LZH_N - 1);
774: count++;
775: } else {
776: i = (r - lzh_decode_position(inbuf,&incnt,inlen) - 1)
777: & (LZH_N - 1);
778: j = c - 255 + LZH_THRESHOLD;
779: for (k = 0; k < j && count<(unsigned long)textsize; k++) {
780: c = lzh_text_buf[(i + k) & (LZH_N - 1)];
781: outbuf[count]=(uchar)c;
782: #if 0
783: if(r>(LZH_N + LZH_F - 1) || r<0) {
784: printf("Overflow! (%d)\n",r);
785: exit(-1); }
786: #endif
787: *(lzh_text_buf+r) = (uchar)c;
788: r++;
789: r &= (LZH_N - 1);
790: count++;
791: }
792: }
793: }
794: /***
795: printf("%12ld\n", count);
796: ***/
797:
798: #ifdef LZH_DYNAMIC_BUF
799: FREE(lzh_text_buf);
800: FREE(lzh_prnt);
801: FREE(lzh_freq);
802: FREE(lzh_son);
803: #endif
804:
805: return(count);
806: }
807:
808:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.