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