home *** CD-ROM | disk | FTP | other *** search
/ Phoenix Heaven Sunny 2 / APPARE2.BIN / oh_towns / dic / src / comp.c < prev    next >
Text File  |  1995-06-20  |  4KB  |  194 lines

  1. #include    "defs.h"
  2.  
  3. #define    NIL    (-1)
  4.  
  5. #define    HASH_MAX    (1024)
  6. #define    HASH_MSK    (HASH_MAX - 1)
  7.  
  8. static    short    *node = NULL;
  9. static    ulong    *tab = NULL;
  10.  
  11. static    int    hash(char *p)
  12. {
  13.     int     hs;
  14.  
  15.     hs = *(p++); hs *= 31;
  16.     hs += *(p++); hs *= 31;
  17.     hs += *(p++);
  18.  
  19.     return (hs & HASH_MSK);
  20. }
  21. static    int    encode(char *buf, int len, FILE *fp)
  22. {
  23.     int     i, n, a, b, p;
  24.     int     cnt, pos, wrt;
  25.     char    tmp[8 * 2 + 1];
  26.  
  27.     cnt = 0;
  28.     pos = 1;
  29.     tmp[0] = 0;
  30.     b = 0;
  31.     wrt = 0;
  32.  
  33.     for ( n = 2048 ; n < (2048 + HASH_MAX) ; n++ )
  34.     node[n] = NIL;
  35.  
  36.     while ( b < len ) {
  37.     a = 1;
  38.     if ( (len - b) >= 3 ) {
  39.         for ( i = node[2048 + hash(buf + b)] ; i != NIL ; i = node[i] ) {
  40.         if ( buf[i + a] != buf[b + a] )
  41.             continue;
  42.             for ( n = 0 ; n < 34 && (b + n) < len && 
  43.             buf[i + n] == buf[b + n] ; n++ )
  44.             ;
  45.             if ( n > a ) {
  46.             a = n;
  47.             p = i;
  48.                 if ( n >= 34 || (b + n) >= len )
  49.                 break;
  50.             }
  51.         }
  52.     }
  53.  
  54.     if ( a > 2 ) {
  55.         n = (p << 5) | (a - 3);
  56.         tmp[pos++] = n >> 8;
  57.         tmp[pos++] = n & 0xff;
  58.     } else {
  59.         tmp[0] |= (1 << cnt);
  60.         tmp[pos++] = buf[b];
  61.         a = 1;
  62.     }
  63.  
  64.     if ( a >= 34 || (b + a) >= 2048 ) {
  65.         b += a;
  66.  
  67.     } else {
  68.         while ( a-- > 0 ) {
  69.             n = 2048 + hash(buf + b);
  70.             node[b] = node[n];
  71.             node[n] = b++;
  72.         }
  73.     }
  74.  
  75.     if ( ++cnt >= 8 ) {
  76.         fwrite(tmp, 1, pos, fp);
  77.         wrt += pos;
  78.         cnt = 0;
  79.         pos = 1;
  80.         tmp[0] = 0;
  81.     }
  82.     }
  83.  
  84.     if ( cnt > 0 ) {
  85.     fwrite(tmp, 1, pos, fp);
  86.     wrt += pos;
  87.     }
  88.  
  89.     return wrt;
  90. }
  91. int    compress(int flag, char *file)
  92. {
  93.     int     i, n, blk;
  94.     ulong   top, size, pos, block;
  95.     ulong   skip_size = 0L;
  96.     int     skip_max = 0;
  97.     ulong   skip_sta[16];
  98.     ulong   skip_end[16];
  99.     FILE    *fp;
  100.     uchar   *p;
  101.  
  102.     if ( (node = (short *)malloc(sizeof(short) * (2048 + HASH_MAX))) == NULL ||
  103.          (tab  = (ulong *)malloc(sizeof(ulong) * 256)) == NULL )
  104.     return ERR;
  105.  
  106. #ifdef    MSDOS
  107.     if ( (fp = fopen(file, "wb")) == NULL )
  108. #else
  109.     if ( (fp = fopen(file, "w")) == NULL )
  110. #endif
  111.     return ERR;
  112.  
  113.     if ( now_dic_mode == DIC_DEVICE_MODE ) {
  114.         size = file_end_block - file_start_block + 1;
  115.     } else {
  116.     fseek(dev_fp, 0L, 2);
  117.     size = ftell(dev_fp);
  118.     fseek(dev_fp, 0L, 0);
  119.     size = (size + 2047) / 2048;
  120.     }
  121.  
  122.     if ( flag ) {
  123.     if ( IO_block_read(1) )
  124.         return ERR;
  125.  
  126.     i = (dic_buf[0] << 8) | dic_buf[1];
  127.     for ( n = 1 ; n <= i ; n++ ) {
  128.         p = dic_buf + (n * 16);
  129.         if ( (*p & 0xF0) == 0xD0 || *p == 0xE0 ) {
  130.         if ( skip_max < 16 ) {
  131.             skip_sta[skip_max] = tolong(p + 2);
  132.             block = tolong(p + 6);
  133.             skip_end[skip_max] = skip_sta[skip_max] + block;
  134.             skip_size += block;
  135.             skip_max++;
  136.         }
  137.         }
  138.     }
  139.     }
  140.  
  141.     fwrite("EDIC", 1, 4, fp);
  142.     pos = size * sizeof(long) + 4L;
  143.     fseek(fp, pos, 0);
  144.  
  145.     printf("Dictonary Size %ld - %ld = %ld Byte\n",
  146.     size * 2048L, skip_size * 2048L, (size - skip_size) * 2048);
  147.     printf("compress   0%%\r"); fflush(stdout);
  148.  
  149.     top = 0L;
  150.     blk = 0;
  151.  
  152.     for ( block = 1 ; block <= size ; block++ ) {
  153.     for ( i = 0 ; i < skip_max ; i++ ) {
  154.         if ( block >= skip_sta[i] && block < skip_end[i] )
  155.         break;
  156.     }
  157.  
  158.     if ( i >= skip_max ) {
  159.         if ( IO_block_read(block) )
  160.             return ERR;
  161.         tab[blk++] = pos;
  162.         pos += encode(dic_buf, 2048, fp);
  163.     } else {
  164.         tab[blk++] = 0L;
  165.     }
  166.  
  167.     if ( blk >= 256 ) {
  168.         fseek(fp, top * sizeof(long) + 4L, 0);
  169.         fwrite(tab, sizeof(long), blk, fp);
  170.         fseek(fp, pos, 0);
  171.         top += blk;
  172.         blk = 0;
  173.         printf("compress %3d%%(%3d%%)\r",
  174.         (int)(top * 100 / size), (int)((pos / 20L) / top));
  175.         fflush(stdout);
  176.     }
  177.     }
  178.  
  179.     if ( blk > 0 ) {
  180.     fseek(fp, top * sizeof(long) + 4L, 0);
  181.     fwrite(tab, sizeof(long), blk, fp);
  182.     top += blk;
  183.     }
  184.  
  185.     printf("compress %3d%%(%3d%%)\n",
  186.     (int)(top * 100 / size), (int)((pos / 20L) / top));
  187.  
  188.     fclose(fp);
  189.     free(node);
  190.     free(tab);
  191.  
  192.     return FALSE;
  193. }
  194.