OSDN Git Service

huf.c was refined.
authorKoji Arai <jca02266@gmail.com>
Wed, 18 Jun 2008 15:34:17 +0000 (00:34 +0900)
committerKoji Arai <jca02266@gmail.com>
Wed, 18 Jun 2008 15:34:17 +0000 (00:34 +0900)
ar.h
huf.c

diff --git a/ar.h b/ar.h
index be6740e..ac1472d 100644 (file)
--- a/ar.h
+++ b/ar.h
@@ -37,6 +37,10 @@ struct lzh_ostream {
     /* huf.c */
     unsigned char *buf;
     unsigned int bufsiz;
+
+    /* huf.c:output() */
+    unsigned int output_pos, output_mask;
+    unsigned int cpos;
 };
 
 struct lzh_header {
diff --git a/huf.c b/huf.c
index 0147e89..14c13e6 100644 (file)
--- a/huf.c
+++ b/huf.c
 #define NPT NP
 #endif
 
-static uchar c_len[NC], pt_len[NPT];
-static ushort c_freq[2 * NC - 1], c_table[4096], c_code[NC],
-    p_freq[2 * NP - 1], pt_table[256], pt_code[NPT], t_freq[2 * NT - 1];
-
 static int np;
 static int pbit;
 
+/* encoding/decoding */
+static uchar c_len[NC], pt_len[NPT];
+
+/* encoding */
+static ushort c_freq[2 * NC - 1], c_code[NC];
+static ushort p_freq[2 * NP - 1], pt_code[NPT];
+static ushort t_freq[2 * NT - 1];
+
+/*
+    size        frequency       bitlength       Huffman coding
+   -----------------------------------------------------------
+     NC         c_freq          c_len           c_code
+     NT         t_freq          pt_len          pt_code
+     np         p_freq          pt_len          pt_code
+ */
+
+/* decoding */
+static ushort c_table[4096], pt_table[256];
+
 static void
 init_parameter(struct lha_method *m)
 {
@@ -208,36 +223,54 @@ send_block(struct lzh_ostream *wp)
         p_freq[i] = 0;
 }
 
-static uint output_pos, output_mask;
+/*
+  call with output(wp, c, 0)
+         or output(wp, len, off)
 
+
+  block
+
+output_mask    128   64    32                16    8     4     2     1
+        +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+buf     |  32 | c1  | c2  | len |    off    |  c3 |  c4 |  c5 |  c6 |  c7 |
+        +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+        cpos                                                             /
+                                                                        /
+                                                               output_pos
+
+*/
 void
 output(struct lzh_ostream *wp, uint c, uint p)
 {
-    static uint cpos;
-
-    if ((output_mask >>= 1) == 0) {
-        output_mask = 1U << (CHAR_BIT - 1);
-        if (output_pos >= wp->bufsiz - 3 * CHAR_BIT) {
+    if ((wp->output_mask >>= 1) == 0) {
+        wp->output_mask = 1U << (CHAR_BIT - 1);
+        if (wp->output_pos >= wp->bufsiz - 3 * CHAR_BIT) {
             send_block(wp);
             if (wp->unpackable)
                 return;
-            output_pos = 0;
+            wp->output_pos = 0;
         }
-        cpos = output_pos++;
-        wp->buf[cpos] = 0;
+        wp->cpos = wp->output_pos++;
+        wp->buf[wp->cpos] = 0;
     }
-    wp->buf[output_pos++] = (uchar) c;
+    wp->buf[wp->output_pos++] = (uchar) c;
     c_freq[c]++;
+
     if (c >= (1U << CHAR_BIT)) {
-        wp->buf[cpos] |= output_mask;
-        wp->buf[output_pos++] = (uchar) (p >> CHAR_BIT);
-        wp->buf[output_pos++] = (uchar) p;
-        c = 0;
-        while (p) {
-            p >>= 1;
-            c++;
+        /* c is length, p is offset */
+        wp->buf[wp->cpos] |= wp->output_mask;
+        wp->buf[wp->output_pos++] = (uchar) (p >> CHAR_BIT);
+        wp->buf[wp->output_pos++] = (uchar) p;
+
+        {
+            /* count frequency of p's bit length */
+            int n = 0;          /* max of n is np-1 */
+            while (p) {
+                p >>= 1;
+                n++;
+            }
+            p_freq[n]++;
         }
-        p_freq[c]++;
     }
 }
 
@@ -247,6 +280,7 @@ huf_encode_start(struct lzh_ostream *wp, struct lha_method *m)
     int i;
 
     init_parameter(m);
+    wp->output_pos = wp->output_mask = wp->cpos = 0;
 
     if (wp->buf == 0) {
         wp->bufsiz = 16 * 1024U;
@@ -261,7 +295,7 @@ huf_encode_start(struct lzh_ostream *wp, struct lha_method *m)
         c_freq[i] = 0;
     for (i = 0; i < np; i++)
         p_freq[i] = 0;
-    output_pos = output_mask = 0;
+
     init_putbits(wp);
 }