home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Amiga / Workbench / Archivers / PPCxDMSWOS.lha / source.lha / src / u_deep.c < prev    next >
C/C++ Source or Header  |  1998-02-17  |  4KB  |  209 lines

  1.  
  2. /*
  3.  *     xDMS  v1.0  -  Portable DMS archive unpacker  -  Public Domain
  4.  *     Written by     Andre R. de la Rocha  <adlroc@usa.net>
  5.  *
  6.  *     Lempel-Ziv-DynamicHuffman decompression functions used in Deep
  7.  *     mode.
  8.  *     Most routines ripped from LZHUF written by  Haruyasu Yoshizaki
  9.  *
  10.  */
  11.  
  12. #include <string.h>
  13.  
  14. #include "cdata.h"
  15. #include "tables.h"
  16. #include "u_deep.h"
  17. #include "getbits.h"
  18.  
  19.  
  20. static USHORT deep_text_loc;
  21.  
  22.  
  23.  
  24. INLINE USHORT DecodeChar(void);
  25. INLINE USHORT DecodePosition(void);
  26. INLINE void update(USHORT c);
  27. static void reconst(void);
  28.  
  29.  
  30.  
  31. #define DBITMASK 0x3fff   /*  uses 16Kb dictionary  */
  32.  
  33. #define F       60  /* lookahead buffer size */
  34. #define THRESHOLD   2
  35. #define N_CHAR      (256 - THRESHOLD + F)   /* kinds of characters (character code = 0..N_CHAR-1) */
  36. #define T       (N_CHAR * 2 - 1)    /* size of table */
  37. #define R       (T - 1)         /* position of root */
  38. #define MAX_FREQ    0x8000      /* updates tree when the */
  39.  
  40.  
  41. USHORT freq[T + 1]; /* frequency table */
  42.  
  43. USHORT prnt[T + N_CHAR]; /* pointers to parent nodes, except for the */
  44.                 /* elements [T..T + N_CHAR - 1] which are used to get */
  45.                 /* the positions of leaves corresponding to the codes. */
  46.  
  47. USHORT son[T];   /* pointers to child nodes (son[], son[] + 1) */
  48.  
  49.  
  50.  
  51. void Init_DEEP(void){
  52.     USHORT i, j;
  53.  
  54.     for (i = 0; i < N_CHAR; i++) {
  55.         freq[i] = 1;
  56.         son[i] = (USHORT)(i + T);
  57.         prnt[i + T] = i;
  58.     }
  59.     i = 0; j = N_CHAR;
  60.     while (j <= R) {
  61.         freq[j] = (USHORT) (freq[i] + freq[i + 1]);
  62.         son[j] = i;
  63.         prnt[i] = prnt[i + 1] = j;
  64.         i += 2; j++;
  65.     }
  66.     freq[T] = 0xffff;
  67.     prnt[R] = 0;
  68.  
  69.     deep_text_loc = 0x3fc4;
  70.     memset(text,0,0x3fc8);
  71. }
  72.  
  73.  
  74.  
  75. USHORT Unpack_DEEP(UCHAR *in, UCHAR *out, UCHAR flags, USHORT origsize){
  76.     USHORT i, j, c;
  77.     UCHAR *outend;
  78.  
  79.     initbitbuf(in);
  80.  
  81.     outend = out+origsize;
  82.     while (out < outend) {
  83.         c = DecodeChar();
  84.         if (c < 256) {
  85.             *out++ = text[deep_text_loc++ & DBITMASK] = (UCHAR)c;
  86.         } else {
  87.             j = (USHORT) (c - 255 + THRESHOLD);
  88.             i = (USHORT) (deep_text_loc - DecodePosition() - 1);
  89.             while (j--) *out++ = text[deep_text_loc++ & DBITMASK] = text[i++ & DBITMASK];
  90.         }
  91.     }
  92.  
  93.     deep_text_loc = (USHORT)((deep_text_loc+60) & DBITMASK);
  94.  
  95.     if (!(flags & 1)) Init_DEEP();
  96.  
  97.     return 0;
  98. }
  99.  
  100.  
  101.  
  102. INLINE USHORT DecodeChar(void){
  103.     USHORT c;
  104.  
  105.     c = son[R];
  106.  
  107.     /* travel from root to leaf, */
  108.     /* choosing the smaller child node (son[]) if the read bit is 0, */
  109.     /* the bigger (son[]+1} if 1 */
  110.     while (c < T) {
  111.         c = son[c + GETBITS(1)];
  112.         DROPBITS(1);
  113.     }
  114.     c -= T;
  115.     update(c);
  116.     return c;
  117. }
  118.  
  119.  
  120.  
  121. INLINE USHORT DecodePosition(void){
  122.     USHORT i, j, c;
  123.  
  124.     i = GETBITS(8);  DROPBITS(8);
  125.     c = (USHORT) (d_code[i] << 8);
  126.     j = d_len[i];
  127.     i = (USHORT) (((i << j) | GETBITS(j)) & 0xff);  DROPBITS(j);
  128.  
  129.     return (USHORT) (c | i) ;
  130. }
  131.  
  132.  
  133.  
  134. /* reconstruction of tree */
  135.  
  136. static void reconst(void){
  137.     USHORT i, j, k, f, l;
  138.  
  139.     /* collect leaf nodes in the first half of the table */
  140.     /* and replace the freq by (freq + 1) / 2. */
  141.     j = 0;
  142.     for (i = 0; i < T; i++) {
  143.         if (son[i] >= T) {
  144.             freq[j] = (USHORT) ((freq[i] + 1) / 2);
  145.             son[j] = son[i];
  146.             j++;
  147.         }
  148.     }
  149.     /* begin constructing tree by connecting sons */
  150.     for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
  151.         k = (USHORT) (i + 1);
  152.         f = freq[j] = (USHORT) (freq[i] + freq[k]);
  153.         for (k = (USHORT)(j - 1); f < freq[k]; k--);
  154.         k++;
  155.         l = (USHORT)((j - k) * 2);
  156.         memmove(&freq[k + 1], &freq[k], (size_t)l);
  157.         freq[k] = f;
  158.         memmove(&son[k + 1], &son[k], (size_t)l);
  159.         son[k] = i;
  160.     }
  161.     /* connect prnt */
  162.     for (i = 0; i < T; i++) {
  163.         if ((k = son[i]) >= T) {
  164.             prnt[k] = i;
  165.         } else {
  166.             prnt[k] = prnt[k + 1] = i;
  167.         }
  168.     }
  169. }
  170.  
  171.  
  172.  
  173. /* increment frequency of given code by one, and update tree */
  174.  
  175. INLINE void update(USHORT c){
  176.     USHORT i, j, k, l;
  177.  
  178.     if (freq[R] == MAX_FREQ) {
  179.         reconst();
  180.     }
  181.     c = prnt[c + T];
  182.     do {
  183.         k = ++freq[c];
  184.  
  185.         /* if the order is disturbed, exchange nodes */
  186.         if (k > freq[l = (USHORT)(c + 1)]) {
  187.             while (k > freq[++l]);
  188.             l--;
  189.             freq[c] = freq[l];
  190.             freq[l] = k;
  191.  
  192.             i = son[c];
  193.             prnt[i] = l;
  194.             if (i < T) prnt[i + 1] = l;
  195.  
  196.             j = son[l];
  197.             son[l] = i;
  198.  
  199.             prnt[j] = c;
  200.             if (j < T) prnt[j + 1] = c;
  201.             son[c] = j;
  202.  
  203.             c = l;
  204.         }
  205.     } while ((c = prnt[c]) != 0); /* repeat up to root */
  206. }
  207.  
  208.  
  209.