Annotation of sbbs/src/smblib/lzh.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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