Annotation of sbbs/smblib/lzh.c, revision 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.