Annotation of sbbs/smblib/lzh.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.