Annotation of pgp/src/lzh.c, revision 1.1

1.1     ! root        1: /*--------------------------------------------------------------------------*/
        !             2: /*  lzh.c - file compression subroutines for lzss + Huffman encoding        */
        !             3: /*                                                                          */
        !             4: /*  Source code history:                                                    */
        !             5: /*                                                                          */
        !             6: /*      The original lzhuf.c source was written by Haruyasu Yoshizaki on    */
        !             7: /*      11/20/1988 with some minor changes 4/6/1989.  Comments were         */
        !             8: /*      translated by Haruhiko Okumura on 4/7/1989.                         */
        !             9: /*                                                                          */
        !            10: /*      The original lzss compression was written by Haruhiko Okumura,      */
        !            11: /*      12-2-404 Green Heights, 580 Nagasawa, Yokosuka 239, Japan.  The     */
        !            12: /*      Adaptive Huffman algorithm was added by Yoshizaki to increase       */
        !            13: /*      speed and compression and developed it into the LHarc archiver.     */
        !            14: /*                                                                          */
        !            15: /*      Modifications were made by Allan Hoeltje P.O. Box 18045 Boulder,    */
        !            16: /*      Colorado, USA 80308-8045, during the month of June 1989.  These     */
        !            17: /*      modifications include: More comments; better file error handling;   */
        !            18: /*      run-length encoding input and output to increase the compression    */
        !            19: /*      ratio.  Note: the run length encoding gives you about 2 to 5 per    */
        !            20: /*      cent better compression but more importantly it speeds up the       */
        !            21: /*      compression process on text files by about 60 per cent.             */
        !            22: /*                                                                          */
        !            23: /*      Additional modifications made on February 17, 1991 to make the      */
        !            24: /*      routines more usable as subroutines for a parent application.       */
        !            25: /*      The two routines, lzhEncode and lzhDecode are the main entry        */
        !            26: /*      points.  Everything else is static.                                 */
        !            27: /*                                                                          */
        !            28: /*      It is my understanding that the lzHuff algorithm and source code    */
        !            29: /*      is in the public domain and it's use is free and unrestricted.      */
        !            30: /*--------------------------------------------------------------------------*/
        !            31: 
        !            32: #include <stdio.h>
        !            33: #include <stdlib.h>
        !            34: #include <string.h>
        !            35: #include <ctype.h>
        !            36: #include "rsalib.h"
        !            37: #include "rsaio.h"
        !            38: 
        !            39: /*
        !            40: **     Convert to or from external byte order.
        !            41: **     Note that hilo_swap does nothing if this is a LSB-first CPU.
        !            42: */
        !            43: 
        !            44: #define convert2(x,lx) hilo_swap( (byteptr)&(x), (lx) )
        !            45: #define convert(x)             convert2( (x), sizeof(x) )
        !            46: 
        !            47: 
        !            48: #define EXIT_FAILURE   1
        !            49: #define EXIT_SUCCESS   0
        !            50: typedef unsigned char uchar;
        !            51: 
        !            52: static FILE    *inFile;                        /*  clear text input    */
        !            53: static FILE    *outFile;                       /*  compressed output   */
        !            54: 
        !            55: static unsigned long int   codesize    = 0;
        !            56: static unsigned long int   inCount     = 0;
        !            57: static unsigned long int   outCount    = 0;
        !            58: 
        !            59: void Error( char *message )
        !            60:     {
        !            61:     printf( "\n%s\n", message );
        !            62:     exit( EXIT_FAILURE );
        !            63:     }
        !            64: 
        !            65: /*--------------------------------------------------------------------------*/
        !            66: /*  Run length encoded getc and putc routines.                              */
        !            67: /*--------------------------------------------------------------------------*/
        !            68: 
        !            69: /*             getCHR
        !            70:                This does a simple getc and count.
        !            71: */
        !            72: static int getCHR( FILE *f )
        !            73:     {
        !            74:     int c;
        !            75:     if ((c = getc( f )) != EOF)
        !            76:         inCount++;
        !            77:     return( c );
        !            78:     }
        !            79: 
        !            80: 
        !            81: /*             putCHR
        !            82:                This does a simple putc and count with a write error check.
        !            83: */
        !            84: void putCHR( int c, FILE *f )
        !            85:     {
        !            86:     if (putc( c, f ) == EOF)
        !            87:         {
        !            88:         Error( "lzh putCHR: can't write output file!" );
        !            89:         }
        !            90:     outCount++;
        !            91:     }
        !            92: 
        !            93: 
        !            94: #define NOHIST   0                      /* don't consider previous input    */
        !            95: #define INREP    1                      /* sending a repeated value         */
        !            96: #define SENTCHAR 1                      /* lastchar set, no lookahead yet   */
        !            97: #define SENDNEWC 2                      /* run over, send new char next     */
        !            98: #define SENDCNT  3                      /* newchar set, send count next     */
        !            99: #define DLE      0x90                   /* repeat sequence marker           */
        !           100: 
        !           101: static unsigned char state = NOHIST;    /* current packing state            */
        !           102: 
        !           103: /*--------------------------------------------------------------------------*/
        !           104: /*  getRLC                                                                  */
        !           105: /*      Non-repeat compression - text is read from file "f" and passed      */
        !           106: /*      through normally except that a run of more than two characters is   */
        !           107: /*      encoded as: <char> <DLE> <count>.  Special case: a count of zero    */
        !           108: /*      indicates that the DLE is really a DLE, not a repeat marker.        */
        !           109: /*--------------------------------------------------------------------------*/
        !           110: 
        !           111: static int
        !           112: getRLC( FILE *f )
        !           113:     {
        !           114:     static int lastc;                   /* value returned on last call   */
        !           115:     static int repcnt;                  /* repetition counter    */
        !           116:     static int c;                       /* latest value seen     */
        !           117:     static char *badstate = "lzh getRLC: Bad packing state!";
        !           118: 
        !           119:     switch (state)                      /* depends on our state  */
        !           120:         {
        !           121:         case NOHIST:                    /* no relevant history   */
        !           122:             state = SENTCHAR;
        !           123:             return (lastc = getCHR(f));   /* remember the value next time */
        !           124:             break;
        !           125:         case SENTCHAR:                  /* char was sent. look ahead    */
        !           126:             switch (lastc)              /* action depends on char       */
        !           127:                 {
        !           128:                 case DLE:                 /* if we sent a real DLE */
        !           129:                     state = NOHIST;       /* then start over again */
        !           130:                     return (0);           /* but note that the DLE was real */
        !           131:                     break;
        !           132:                 case EOF:                 /* EOF is always a special case */
        !           133:                     return (EOF);
        !           134:                     break;
        !           135:                 default:                  /* else test for a repeat */
        !           136:                     for (repcnt = 1 ;
        !           137:                         ((c = getCHR(f)) == lastc) && (repcnt < 255) ;
        !           138:                         repcnt++);           /* find end of run */
        !           139: 
        !           140:                     switch(repcnt)           /* action depends on run size */
        !           141:                         {
        !           142:                         case 1:                 /* not a repeat */
        !           143:                             return (lastc = c); /* but remember value next time */
        !           144:                             break;
        !           145:                         case 2:                 /* a repeat, but too short */
        !           146:                             state = SENDNEWC;   /* send the second one next time */
        !           147:                             return (lastc);
        !           148:                             break;
        !           149:                         default:                /* a run - compress it */
        !           150:                             state = SENDCNT;    /* send repeat count next time */
        !           151:                             return (DLE);       /* send repeat marker this time */
        !           152:                             break;
        !           153:                         }
        !           154:                 }
        !           155:             case SENDNEWC:                   /* send second char of short run */
        !           156:                 state = SENTCHAR;
        !           157:                 return (lastc = c);
        !           158:                 break;
        !           159:             case SENDCNT:                    /* sent DLE, now send count */
        !           160:                 state = SENDNEWC;
        !           161:                 return (repcnt);
        !           162:                 break;
        !           163:             default:
        !           164:                 {
        !           165:                 Error( badstate );
        !           166:                 }
        !           167:         }
        !           168:     }
        !           169: 
        !           170: 
        !           171: /*--------------------------------------------------------------------------*/
        !           172: /*  putRLC                                                                  */
        !           173: /*      This routine is used to decode non-repeat compression bytes and     */
        !           174: /*      write them to file "t".  Bytes are passed one at a time in coded    */
        !           175: /*      format, and are written out uncoded.  The data is stored normally,  */
        !           176: /*      except that runs of more than two characters are represented as:    */
        !           177: /*                                                                          */
        !           178: /*                          <char> <DLE> <count>                            */
        !           179: /*      with a special case that a count of zero indicates a DLE as data,   */
        !           180: /*      not as a repeat marker.                                             */
        !           181: /*--------------------------------------------------------------------------*/
        !           182: 
        !           183: static int
        !           184: putRLC( int c, FILE *t )
        !           185:     {
        !           186:     static int lastc;                   /* last character seen */
        !           187:     static char *badstate = "lzh putRLC: Bad unpacking state!";
        !           188: 
        !           189:     switch (state)                      /* action depends on our state  */
        !           190:         {
        !           191:         case NOHIST:                        /* no previous history      */
        !           192:             if (c == DLE)                   /* if starting a series     */
        !           193:                 state = INREP;              /* then remember it next time */
        !           194:             else
        !           195:                 putCHR( (lastc = c), t );     /* else nothing unusual     */
        !           196:             break;
        !           197:         case INREP:                         /* in a repeat              */
        !           198:             if (c)                          /* if count is nonzero      */
        !           199:                 while(--c)                  /* then repeatedly ...      */
        !           200:                     putCHR( lastc, t );       /* ... output the byte      */
        !           201:             else
        !           202:                 putCHR( DLE, t );             /* else output DLE as data  */
        !           203:             state = NOHIST;                 /* back to no history       */
        !           204:             break;
        !           205:         default:
        !           206:             {
        !           207:             Error( badstate );
        !           208:             }
        !           209:         }
        !           210:     return(0);
        !           211:     }
        !           212: 
        !           213: 
        !           214: /*--------------------------------------------------------------------------*/
        !           215: /*                             LZSS Compression                             */
        !           216: /*--------------------------------------------------------------------------*/
        !           217: 
        !           218: #define buffSize    2048        /* size of ring buffer   */
        !           219: #define lookSize    60          /* lookahead buffer size */
        !           220: #define THRESHOLD   2           /* if matchLen is greater than Threshold    */
        !           221:                                 /* then code string into position & length  */
        !           222: #define treeRoot    buffSize    /* index for root of binary search tree     */
        !           223: 
        !           224:     /*
        !           225:         ring buffer with extra bytes to facilitate string comparison of
        !           226:         longest match.  This is set by the InsertNode() procedure.
        !           227:     */
        !           228: 
        !           229: static unsigned char   textBuf[ buffSize + lookSize - 1 ];
        !           230: static int             matchPos, matchLen;
        !           231: static int             lson[ buffSize + 1   ];
        !           232: static int             rson[ buffSize + 257 ];
        !           233: static int             dad [ buffSize + 1   ];
        !           234: 
        !           235: 
        !           236: /*--------------------------------------------------------------------------*/
        !           237: /*  InitTree                                                                */
        !           238: /*      Initialize the LZSS trees.                                          */
        !           239: /*--------------------------------------------------------------------------*/
        !           240: 
        !           241: static void InitTree( void )
        !           242:     {
        !           243:     register int  i;
        !           244: 
        !           245:     /*
        !           246:        For i = 0 to buffSize, rson[i] and lson[i] will be the right and
        !           247:        left children of node i.  These nodes need not be initialized.  Also,
        !           248:        dad[i] is the parent of node i.  These are initialized to "treeRoot"
        !           249:        which means 'not used.'
        !           250: 
        !           251:        For i = buffSize+1 to buffSize+256, rson[i] is the root of the tree
        !           252:        for strings that begin with character i.  These are initialized
        !           253:        to "treeRoot".  Note there are 256 trees.
        !           254:     */
        !           255: 
        !           256:     for (i = buffSize + 1 ; i <= (buffSize + 256) ; i++)
        !           257:         rson[i] = treeRoot;            /* root */
        !           258:     for (i = 0 ; i < buffSize ; i++)
        !           259:         dad[i] = treeRoot;             /* node */
        !           260:     }
        !           261: 
        !           262: 
        !           263: /*--------------------------------------------------------------------------*/
        !           264: /*  InsertNode                                                              */
        !           265: /*      Inserts string of length lookSize, textBuf[r..r+lookSize-1], into   */
        !           266: /*  one of the trees (textBuf[r]'th tree) and returns the longest-match     */
        !           267: /*  position and length via the global variables matchPos and matchLen.     */
        !           268: /*  If matchLen = lookSize, then remove the old node in favor of the new    */
        !           269: /*  one, because the old one will be deleted sooner.  Note r plays double   */
        !           270: /*  role, as tree node and position in buffer.                              */
        !           271: /*--------------------------------------------------------------------------*/
        !           272: 
        !           273: static void InsertNode(int r)
        !           274:     {
        !           275:     int             i, p, cmp;
        !           276:     unsigned char   *key;
        !           277:     unsigned        c;
        !           278: 
        !           279:     cmp = 1;
        !           280:     key = &textBuf[r];
        !           281:     p = buffSize + 1 + key[0];
        !           282:     rson[r] = lson[r] = treeRoot;
        !           283:     matchLen = 0;
        !           284:     for ( ; ; )
        !           285:         {
        !           286:         if (cmp >= 0)
        !           287:             {
        !           288:             if (rson[p] != treeRoot)
        !           289:                 p = rson[p];
        !           290:             else
        !           291:                 {
        !           292:                 rson[p] = r;
        !           293:                 dad [r] = p;
        !           294:                 return;
        !           295:                 }
        !           296:             }
        !           297:         else
        !           298:             {
        !           299:             if (lson[p] != treeRoot)
        !           300:                 p = lson[p];
        !           301:             else
        !           302:                 {
        !           303:                 lson[p] = r;
        !           304:                 dad [r] = p;
        !           305:                 return;
        !           306:                 }
        !           307:             }
        !           308:         for (i = 1; i < lookSize; i++)
        !           309:             if ((cmp = key[i] - textBuf[p + i]) != 0)
        !           310:                 break;
        !           311:         if (i > THRESHOLD)
        !           312:             {
        !           313:             if (i > matchLen)
        !           314:                 {
        !           315:                 matchPos = ((r - p) & (buffSize - 1)) - 1;
        !           316:                 if ((matchLen = i) >= lookSize)
        !           317:                     break;
        !           318:                 }
        !           319:             if (i == matchLen)
        !           320:                 {
        !           321:                 if ((c = ((r - p) & (buffSize - 1)) - 1) < matchPos)
        !           322:                     {
        !           323:                     matchPos = c;
        !           324:                     }
        !           325:                 }
        !           326:             }
        !           327:         }
        !           328:     dad[r]  = dad[p];
        !           329:     lson[r] = lson[p];
        !           330:     rson[r] = rson[p];
        !           331:     dad[lson[p]] = r;
        !           332:     dad[rson[p]] = r;
        !           333:     if (rson[dad[p]] == p)
        !           334:         rson[dad[p]] = r;
        !           335:     else
        !           336:         lson[dad[p]] = r;
        !           337:     dad[p] = treeRoot;  /* remove p */
        !           338:     }
        !           339: 
        !           340: 
        !           341: /*--------------------------------------------------------------------------*/
        !           342: /*  DeleteNode                                                              */
        !           343: /*      Delete node p from the tree.                                        */
        !           344: /*--------------------------------------------------------------------------*/
        !           345: 
        !           346: static void DeleteNode( register int p )
        !           347:     {
        !           348:     register int  q;
        !           349: 
        !           350:     if (dad[p] == treeRoot)
        !           351:         return;            /* not registered */
        !           352:     if (rson[p] == treeRoot)
        !           353:         q = lson[p];
        !           354:     else
        !           355:     if (lson[p] == treeRoot)
        !           356:         q = rson[p];
        !           357:     else
        !           358:         {
        !           359:         q = lson[p];
        !           360:         if (rson[q] != treeRoot)
        !           361:             {
        !           362:             do  {
        !           363:                 q = rson[q];
        !           364:                 }
        !           365:             while (rson[q] != treeRoot);
        !           366: 
        !           367:             rson[dad[q]] = lson[q];
        !           368:             dad[lson[q]] = dad[q];
        !           369:             lson[q] = lson[p];
        !           370:             dad[lson[p]] = q;
        !           371:             }
        !           372:         rson[q] = rson[p];
        !           373:         dad[rson[p]] = q;
        !           374:         }
        !           375:     dad[q] = dad[p];
        !           376: 
        !           377:     if (rson[dad[p]] == p)
        !           378:         rson[dad[p]] = q;
        !           379:     else
        !           380:         lson[dad[p]] = q;
        !           381:     dad[p] = treeRoot;
        !           382:     }
        !           383: 
        !           384: /*--------------------------------------------------------------------------*/
        !           385: /*                              Huffman Coding                              */
        !           386: /*--------------------------------------------------------------------------*/
        !           387: 
        !           388:                     /* kinds of characters (character code = 0..N_CHAR-1)   */
        !           389: #define N_CHAR      (256 - THRESHOLD + lookSize)
        !           390: #define tableSize   (N_CHAR * 2 - 1)    /* size of table        */
        !           391: #define rootSize    (tableSize - 1)     /* position of root     */
        !           392: #define MAX_FREQ    0x8000              /* update the tree when the root    */
        !           393:                                         /* frequency comes to this value.   */
        !           394: 
        !           395: /*--------------------------------------------------------------------------*/
        !           396: /*  Tables for encoding the upper 6 bits of position                        */
        !           397: /*--------------------------------------------------------------------------*/
        !           398: 
        !           399: static uchar p_len[64] =
        !           400:     {
        !           401:     0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
        !           402:     0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
        !           403:     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        !           404:     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        !           405:     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        !           406:     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        !           407:     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
        !           408:     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
        !           409:     };
        !           410: 
        !           411: static uchar p_code[64] =
        !           412:     {
        !           413:     0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
        !           414:     0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
        !           415:     0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
        !           416:     0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
        !           417:     0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
        !           418:     0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
        !           419:     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
        !           420:     0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
        !           421:     };
        !           422: 
        !           423: /*--------------------------------------------------------------------------*/
        !           424: /*  Tables for decoding the upper 6 bits of position                        */
        !           425: /*--------------------------------------------------------------------------*/
        !           426: 
        !           427: static uchar d_code[256] =
        !           428:     {
        !           429:     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           430:     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           431:     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           432:     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        !           433:     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        !           434:     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        !           435:     0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
        !           436:     0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
        !           437:     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        !           438:     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        !           439:     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
        !           440:     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        !           441:     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        !           442:     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        !           443:     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
        !           444:     0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
        !           445:     0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
        !           446:     0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
        !           447:     0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
        !           448:     0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
        !           449:     0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
        !           450:     0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
        !           451:     0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
        !           452:     0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
        !           453:     0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
        !           454:     0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
        !           455:     0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
        !           456:     0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
        !           457:     0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
        !           458:     0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
        !           459:     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
        !           460:     0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
        !           461:     };
        !           462: 
        !           463: static uchar d_len[256] =
        !           464:     {
        !           465:     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        !           466:     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        !           467:     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        !           468:     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        !           469:     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
        !           470:     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
        !           471:     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
        !           472:     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
        !           473:     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
        !           474:     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
        !           475:     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        !           476:     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        !           477:     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        !           478:     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        !           479:     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        !           480:     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        !           481:     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        !           482:     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        !           483:     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        !           484:     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        !           485:     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        !           486:     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        !           487:     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        !           488:     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        !           489:     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        !           490:     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        !           491:     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        !           492:     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        !           493:     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        !           494:     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        !           495:     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
        !           496:     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
        !           497:     };
        !           498: 
        !           499: static unsigned freq[tableSize + 1];    /* frequency table */
        !           500: 
        !           501: static int     prnt[ tableSize + N_CHAR ];
        !           502:             /* pointers to parent nodes, except for the elements    */
        !           503:             /* [tableSize..tableSize + N_CHAR - 1] which are used   */
        !           504:             /* to get the positions of leaves corresponding to the  */
        !           505:             /* codes.                                               */
        !           506: 
        !           507: static int     son[ tableSize ];   /* pointers to child nodes (son[], son[] + 1) */
        !           508: 
        !           509: static unsigned    getbuf = 0;
        !           510: static uchar       getlen = 0;
        !           511: 
        !           512: 
        !           513: /*--------------------------------------------------------------------------*/
        !           514: /*  GetBit                                                                  */
        !           515: /*      Get one bit.                                                        */
        !           516: /*--------------------------------------------------------------------------*/
        !           517: 
        !           518: static int GetBit( void )
        !           519:     {
        !           520:     int i;
        !           521: 
        !           522:     while (getlen <= 8)
        !           523:         {
        !           524:         if ((i = getc( inFile )) < 0)
        !           525:             i = 0;
        !           526:         getbuf |= i << (8 - getlen);
        !           527:         getlen += 8;
        !           528:         }
        !           529:     i = getbuf;
        !           530:     getbuf <<= 1;
        !           531:     getlen--;
        !           532:     return (i < 0);
        !           533:     }
        !           534: 
        !           535: 
        !           536: /*--------------------------------------------------------------------------*/
        !           537: /*  GetByte                                                                 */
        !           538: /*      Get one byte.                                                       */
        !           539: /*--------------------------------------------------------------------------*/
        !           540: 
        !           541: static int GetByte( void )
        !           542:     {
        !           543:     unsigned i;
        !           544: 
        !           545:     while (getlen <= 8)
        !           546:         {
        !           547:         if ((i = getc( inFile )) < 0)
        !           548:             i = 0;
        !           549:         getbuf |= i << (8 - getlen);
        !           550:         getlen += 8;
        !           551:         }
        !           552:     i = getbuf;
        !           553:     getbuf <<= 8;
        !           554:     getlen -= 8;
        !           555:     return i >> 8;
        !           556:     }
        !           557: 
        !           558: 
        !           559: /*--------------------------------------------------------------------------*/
        !           560: /*  Putcode                                                                 */
        !           561: /*      Write c bits of code.                                               */
        !           562: /*--------------------------------------------------------------------------*/
        !           563: 
        !           564: static unsigned    putbuf = 0;
        !           565: static uchar       putlen = 0;
        !           566: 
        !           567: static void Putcode(int l, unsigned c)
        !           568:     {
        !           569:        static char     *werr = "lzh Putcode: can't write output file!";
        !           570: 
        !           571:     putbuf |= (c >> putlen);
        !           572:     if ((putlen += l) >= 8)
        !           573:         {
        !           574:         if (putc( putbuf >> 8, outFile ) == EOF)
        !           575:             {
        !           576:             Error( werr );
        !           577:             }
        !           578:         if ((putlen -= 8) >= 8)
        !           579:             {
        !           580:             if (putc( putbuf, outFile ) == EOF)
        !           581:                 {
        !           582:                 Error( werr );
        !           583:                 }
        !           584:             codesize += 2;
        !           585:             putlen   -= 8;
        !           586:             putbuf    = c << (l - putlen);
        !           587:             }
        !           588:         else
        !           589:             {
        !           590:             putbuf <<= 8;
        !           591:             codesize++;
        !           592:             }
        !           593:         }
        !           594:     }
        !           595: 
        !           596: 
        !           597: /*--------------------------------------------------------------------------*/
        !           598: /*  StartHuff                                                               */
        !           599: /*      initialize the Huffman trees.                                       */
        !           600: /*--------------------------------------------------------------------------*/
        !           601: 
        !           602: static void StartHuff( void )
        !           603:     {
        !           604:     register int i, j;
        !           605: 
        !           606:     for (i = 0; i < N_CHAR; i++)
        !           607:         {
        !           608:         freq[i] = 1;
        !           609:         son[i]  = i + tableSize;
        !           610:         prnt[i + tableSize] = i;
        !           611:         }
        !           612:     i = 0;
        !           613:     j = N_CHAR;
        !           614: 
        !           615:     while (j <= rootSize)
        !           616:         {
        !           617:         freq[j] = freq[i] + freq[i + 1];
        !           618:         son[j]  = i;
        !           619:         prnt[i] = prnt[i + 1] = j;
        !           620:         i += 2;
        !           621:         j++;
        !           622:         }
        !           623:     freq[tableSize] = 0xffff;
        !           624:     prnt[rootSize] = 0;
        !           625:     }
        !           626: 
        !           627: 
        !           628: /*--------------------------------------------------------------------------*/
        !           629: /*  reconst                                                                 */
        !           630: /*      Reconstruction of tree.                                             */
        !           631: /*--------------------------------------------------------------------------*/
        !           632: 
        !           633: static void reconst( void )
        !           634:     {
        !           635:     register int    i, j, k;
        !           636:     unsigned int    f, l;
        !           637: 
        !           638:     /* Collect leaf nodes in the first half of the table and replace the    */
        !           639:     /* freq by (freq + 1) / 2.                                              */
        !           640: 
        !           641:     j = 0;
        !           642:     for (i = 0; i < tableSize; i++)
        !           643:         {
        !           644:         if (son[i] >= tableSize)
        !           645:             {
        !           646:             freq[j] = (freq[i] + 1) / 2;
        !           647:             son[j]  = son[i];
        !           648:             j++;
        !           649:             }
        !           650:         }
        !           651: 
        !           652:     /* begin constructing tree by connecting sons */
        !           653: 
        !           654:     for (i = 0, j = N_CHAR; j < tableSize; i += 2, j++)
        !           655:         {
        !           656:         k = i + 1;
        !           657:         f = freq[j] = freq[i] + freq[k];
        !           658: 
        !           659:         for (k = j - 1; f < freq[k]; k--);
        !           660: 
        !           661:         k++;
        !           662:         l = (j - k) * 2;
        !           663:         memmove( &freq[k + 1], &freq[k], l );
        !           664:         freq[k] = f;
        !           665:         memmove( &son[k + 1], &son[k], l );
        !           666:         son[k] = i;
        !           667:         }
        !           668: 
        !           669:     /* connect prnt */
        !           670: 
        !           671:     for (i = 0; i < tableSize; i++)
        !           672:         if ((k = son[i]) >= tableSize)
        !           673:             prnt[k] = i;
        !           674:         else
        !           675:             prnt[k] = prnt[k + 1] = i;
        !           676:     }
        !           677: 
        !           678: 
        !           679: /*--------------------------------------------------------------------------*/
        !           680: /*  update                                                                  */
        !           681: /*      Increment frequency of given code by one, and update tree.          */
        !           682: /*--------------------------------------------------------------------------*/
        !           683: 
        !           684: static void update(int c)
        !           685:     {
        !           686:     int i, j, k, l;
        !           687: 
        !           688:     if (freq[rootSize] == MAX_FREQ)
        !           689:         reconst();
        !           690: 
        !           691:     c = prnt[c + tableSize];
        !           692:     do  {
        !           693:         k = ++freq[c];
        !           694: 
        !           695:         /* if the order is disturbed, exchange nodes */
        !           696:         if (k > freq[l = c + 1])
        !           697:             {
        !           698:             while (k > freq[++l]);
        !           699:             l--;
        !           700:             freq[c] = freq[l];
        !           701:             freq[l] = k;
        !           702: 
        !           703:             i = son[c];
        !           704:             prnt[i] = l;
        !           705:             if (i < tableSize)
        !           706:                 prnt[i + 1] = l;
        !           707: 
        !           708:             j = son[l];
        !           709:             son[l] = i;
        !           710: 
        !           711:             prnt[j] = c;
        !           712:             if (j < tableSize)
        !           713:                 prnt[j + 1] = c;
        !           714:             son[c] = j;
        !           715: 
        !           716:             c = l;
        !           717:             }
        !           718:         }
        !           719:     while ((c = prnt[c]) != 0);    /* repeat up to root */
        !           720:     }
        !           721: 
        !           722: 
        !           723: /*--------------------------------------------------------------------------*/
        !           724: /*  EncodeChar                                                              */
        !           725: /*--------------------------------------------------------------------------*/
        !           726: 
        !           727: static void EncodeChar(unsigned c)
        !           728:     {
        !           729:     unsigned i;
        !           730:     int j, k;
        !           731: 
        !           732:     i = j = 0;
        !           733:     k = prnt[c + tableSize];
        !           734: 
        !           735:     /* travel from leaf to root */
        !           736:     do {
        !           737:         i >>= 1;
        !           738: 
        !           739:         /* if node's address is odd-numbered, choose bigger brother node */
        !           740:         if (k & 1) i += 0x8000;
        !           741: 
        !           742:         j++;
        !           743:         }
        !           744:     while ((k = prnt[k]) != rootSize);
        !           745: 
        !           746:     Putcode(j, i);
        !           747:     update(c);
        !           748:     }
        !           749: 
        !           750: 
        !           751: /*--------------------------------------------------------------------------*/
        !           752: /*  EncodePosition                                                          */
        !           753: /*--------------------------------------------------------------------------*/
        !           754: 
        !           755: static void EncodePosition(unsigned c)
        !           756:     {
        !           757:     unsigned i;
        !           758: 
        !           759:     /* output upper 6 bits by table lookup */
        !           760: 
        !           761:     i = c >> 6;
        !           762:     Putcode( p_len[i], (unsigned)p_code[i] << 8 );
        !           763: 
        !           764:     /* output lower 6 bits verbatim */
        !           765:     Putcode( 6, (c & 0x3f) << 10 );
        !           766:     }
        !           767: 
        !           768: 
        !           769: /*--------------------------------------------------------------------------*/
        !           770: /*  EncodeEnd                                                               */
        !           771: /*--------------------------------------------------------------------------*/
        !           772: 
        !           773: static void EncodeEnd( void )
        !           774:     {
        !           775:        static char     *werr = "lzh EncodeEnd: can't write output file!";
        !           776: 
        !           777:     if (putlen)
        !           778:         {
        !           779:         if (putc(putbuf >> 8, outFile) == EOF)
        !           780:             Error( werr );
        !           781:         codesize++;
        !           782:         }
        !           783:     }
        !           784: 
        !           785: 
        !           786: /*--------------------------------------------------------------------------*/
        !           787: /*  DecodeChar                                                              */
        !           788: /*--------------------------------------------------------------------------*/
        !           789: 
        !           790: static int DecodeChar( void )
        !           791:     {
        !           792:     register unsigned c;
        !           793: 
        !           794:     /* Travel from root to leaf choosing the smaller child node (son[]) if  */
        !           795:     /* the read bit is 0, the bigger (son[]+1} if 1.                        */
        !           796: 
        !           797:     c = son[rootSize];
        !           798:     while (c < tableSize)
        !           799:         {
        !           800:         c += GetBit();
        !           801:         c  = son[c];
        !           802:         }
        !           803:     c -= tableSize;
        !           804:     update(c);
        !           805:     return c;
        !           806:     }
        !           807: 
        !           808: 
        !           809: /*--------------------------------------------------------------------------*/
        !           810: /*  DecodePosition                                                          */
        !           811: /*--------------------------------------------------------------------------*/
        !           812: 
        !           813: static int DecodePosition( void )
        !           814:     {
        !           815:     register unsigned i, j, c;
        !           816: 
        !           817:     /* recover upper 6 bits from table */
        !           818:     i = GetByte();
        !           819:     c = (unsigned)d_code[i] << 6;
        !           820:     j = d_len[i];
        !           821: 
        !           822:     /* read lower 6 bits verbatim */
        !           823:     j -= 2;
        !           824:     while (j--)
        !           825:         i = (i << 1) + GetBit();
        !           826:     return (c | (i & 0x3f));
        !           827:     }
        !           828: 
        !           829: 
        !           830: /*             lzhEncode
        !           831:                Compress the input file and write to the output file.
        !           832:                Return the ratio of output to input size.
        !           833: */
        !           834: int lzhEncode( FILE *in, FILE *out )
        !           835:     {
        !           836:     int  i, c, len, r, s, last_matchLen;
        !           837:     unsigned long int   textsize, beginByte;
        !           838:        static char *werr = "lzhEncode: can't write output file!";
        !           839: 
        !           840:        inFile  = in;                   /*      set the global file pointers */
        !           841:        outFile = out;
        !           842: 
        !           843:     /* Skip to the end of file and get the byte length.  Write the length
        !           844:        as the first word in the compressed output file.
        !           845:        */
        !           846:     beginByte = ftell( inFile );       /* just in case we were prepositioned */
        !           847:     fseek( inFile, 0L, SEEK_END );
        !           848:     textsize = ftell( inFile ) - beginByte;
        !           849:     fseek( inFile, beginByte, SEEK_SET );      /* go back to the beginning of the file */
        !           850: 
        !           851:     if (textsize == 0)
        !           852:         return( -1 );          /* empty files are easy - signal an error */
        !           853: 
        !           854:        convert( textsize );    /* convert to little endian if necessary */
        !           855: 
        !           856:     if (fwrite( &textsize, sizeof textsize, 1, outFile ) < 1)
        !           857:         Error( werr );
        !           858: 
        !           859:     StartHuff();            /*  init the Huffman trees  */
        !           860:     InitTree();             /*  init the LZSS trees     */
        !           861:     inCount = 0;            /*  init the input character count  */
        !           862:     s = 0;
        !           863:     r = buffSize - lookSize;
        !           864:     for (i = 0; i < r; i++)
        !           865:         textBuf[i] = ' ';
        !           866: 
        !           867:     /*  fill the look ahead buffer  */
        !           868: 
        !           869:     for (len = 0; (len < lookSize) && ((c = getRLC( inFile )) != EOF); len++)
        !           870:         textBuf[r + len] = c;
        !           871:     for (i = 1; i <= lookSize; i++)
        !           872:         InsertNode( r - i );
        !           873:     InsertNode( r );
        !           874:     do  {
        !           875:         if (matchLen > len)
        !           876:             matchLen = len;
        !           877:         if (matchLen <= THRESHOLD)
        !           878:             {
        !           879:             matchLen = 1;
        !           880:             EncodeChar( textBuf[r] );
        !           881:             }
        !           882:         else
        !           883:             {
        !           884:             EncodeChar( 255 - THRESHOLD + matchLen );
        !           885:             EncodePosition( matchPos );
        !           886:             }
        !           887:         last_matchLen = matchLen;
        !           888:         for (i = 0; (i < last_matchLen) && ((c = getRLC( inFile )) != EOF); i++)
        !           889:             {
        !           890:             DeleteNode( s );
        !           891:             textBuf[s] = c;
        !           892:             if (s < lookSize - 1)
        !           893:                 textBuf[s + buffSize] = c;
        !           894:             s = (s + 1) & (buffSize - 1);
        !           895:             r = (r + 1) & (buffSize - 1);
        !           896:             InsertNode( r );
        !           897:             }
        !           898: 
        !           899:         while (i++ < last_matchLen)
        !           900:             {
        !           901:             DeleteNode( s );
        !           902:             s = (s + 1) & (buffSize - 1);
        !           903:             r = (r + 1) & (buffSize - 1);
        !           904:             if (--len)
        !           905:                 InsertNode( r );
        !           906:             }
        !           907:         }
        !           908:     while (len > 0);
        !           909: 
        !           910:     EncodeEnd();
        !           911: 
        !           912:        return( (int)((codesize * 10) / inCount ));
        !           913:     }
        !           914: 
        !           915: 
        !           916: /*--------------------------------------------------------------------------*/
        !           917: /*  lzhDecode                                                               */
        !           918: /*--------------------------------------------------------------------------*/
        !           919: 
        !           920: void lzhDecode( FILE *in, FILE *out )
        !           921:     {
        !           922:     int  i, j, k, r, c;
        !           923:     unsigned long int   textsize;
        !           924:        static char *werr = "lzhDecode: can't write output file!";
        !           925: 
        !           926:        inFile  = in;   /* set the global file pointers */
        !           927:        outFile = out;
        !           928: 
        !           929:        /* get the size of the input file in the first word */
        !           930: 
        !           931:     if (fread( &textsize, sizeof textsize, 1, inFile ) < 1)
        !           932:         Error( "lzhDecode: Can't read the input file" );
        !           933: 
        !           934:        convert( textsize );    /* convert to little endian if necessary */
        !           935:     if (textsize == 0)
        !           936:         return;             /*  nothing to decode, empty file   */
        !           937: 
        !           938:     StartHuff();
        !           939:     for (i = 0; i < (buffSize - lookSize); i++)
        !           940:         textBuf[i] = ' ';
        !           941:     r = buffSize - lookSize;
        !           942: 
        !           943:     outCount = 0;           /*  init the output character count */
        !           944:     while (outCount < textsize )
        !           945:         {
        !           946:         c = DecodeChar();
        !           947:         if (c < 256)
        !           948:             {
        !           949:             if (putRLC( c, outFile ) == EOF)
        !           950:                 Error( werr );
        !           951: 
        !           952:             textBuf[r++] = c;
        !           953:             r &= (buffSize - 1);
        !           954:             }
        !           955:         else
        !           956:             {
        !           957:             i = (r - DecodePosition() - 1) & (buffSize - 1);
        !           958:             j = c - 255 + THRESHOLD;
        !           959:             for (k = 0; k < j; k++)
        !           960:                 {
        !           961:                 c = textBuf[(i + k) & (buffSize - 1)];
        !           962:                 if (putRLC( c, outFile ) == EOF)
        !           963:                     Error( werr );
        !           964:                 textBuf[r++] = c;
        !           965:                 r &= (buffSize - 1);
        !           966:                 }
        !           967:             }
        !           968:         }
        !           969:     }
        !           970: 
        !           971: /* ----        end of lzh.c */
        !           972: 

unix.superglobalmegacorp.com

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