summaryrefslogtreecommitdiff
path: root/plugins/vtx/lh5dec.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/vtx/lh5dec.c')
-rw-r--r--plugins/vtx/lh5dec.c304
1 files changed, 304 insertions, 0 deletions
diff --git a/plugins/vtx/lh5dec.c b/plugins/vtx/lh5dec.c
new file mode 100644
index 00000000..1b2456bb
--- /dev/null
+++ b/plugins/vtx/lh5dec.c
@@ -0,0 +1,304 @@
+/* extractiong lh5 module
+ (c) Haruhiko Okumura
+ (m) Roman Scherbakov
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h> /* memmove */
+#include <limits.h>
+
+static unsigned short bitbuf;
+
+#define BITBUFSIZ (CHAR_BIT * sizeof bitbuf)
+
+#define DICBIT 13 /* 12(-lh4-) or 13(-lh5-) */
+#define DICSIZ (1L << DICBIT)
+#define MATCHBIT 8 /* bits for MAXMATCH - THRESHOLD */
+#define MAXMATCH 256 /* formerly F (not more than unsigned char_MAX + 1) */
+#define THRESHOLD 3 /* choose optimal value */
+#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
+#define CBIT 9 /* $\lfloor \log_2 NC \rfloor + 1$ */
+#define CODE_BIT 16 /* codeword length */
+#define NP (DICBIT + 1)
+#define NT (CODE_BIT + 3)
+#define PBIT 4 /* smallest integer such that (1U << PBIT) > NP */
+#define TBIT 5 /* smallest integer such that (1U << TBIT) > NT */
+#if NT > NP
+#define NPT NT
+#else
+#define NPT NP
+#endif
+
+static unsigned long origsize, compsize;
+static const unsigned char *in_buf;
+static unsigned char *out_buf;
+
+static unsigned short subbitbuf;
+static int bitcount;
+
+static unsigned short left[2 * NC - 1], right[2 * NC - 1];
+static unsigned char c_len[NC], pt_len[NPT];
+static unsigned short blocksize;
+
+static unsigned short c_table[4096], pt_table[256];
+
+static int j; /* remaining bytes to copy */
+
+
+static void error(char *msg)
+{
+ fprintf(stderr, "libayemu: lh5dec.c: %s\n", msg);
+ exit(EXIT_FAILURE);
+}
+
+static void fillbuf(int n) /* Shift bitbuf n bits left, read n bits */
+{
+ bitbuf <<= n;
+ while (n > bitcount) {
+ bitbuf |= subbitbuf << (n -= bitcount);
+ if (compsize != 0) {
+ compsize--; subbitbuf = *in_buf++;
+ } else subbitbuf = 0;
+ bitcount = CHAR_BIT;
+ }
+ bitbuf |= subbitbuf >> (bitcount -= n);
+}
+
+static unsigned short getbits(int n)
+{
+ unsigned short x;
+
+ x = bitbuf >> (BITBUFSIZ - n); fillbuf(n);
+ return x;
+}
+
+// make table for decoding
+
+static void make_table(int nchar, unsigned char bitlen[], int tablebits, unsigned short table[])
+{
+ unsigned short count[17], weight[17], start[18], *p;
+ unsigned short i, k, len, ch, jutbits, avail, nextcode, mask;
+
+ for (i = 1; i <= 16; i++) count[i] = 0;
+ for (i = 0; i < nchar; i++) count[bitlen[i]]++;
+
+ start[1] = 0;
+ for (i = 1; i <= 16; i++)
+ start[i + 1] = start[i] + (count[i] << (16 - i));
+ if (start[17] != (unsigned short)(1U << 16)) error("Bad table");
+
+ jutbits = 16 - tablebits;
+ for (i = 1; i <= tablebits; i++) {
+ start[i] >>= jutbits;
+ weight[i] = 1U << (tablebits - i);
+ }
+ while (i <= 16) weight[i++] = 1U << (16 - i);
+
+ i = start[tablebits + 1] >> jutbits;
+ if (i != (unsigned short)(1U << 16)) {
+ k = 1U << tablebits;
+ while (i != k) table[i++] = 0;
+ }
+
+ avail = nchar;
+ mask = 1U << (15 - tablebits);
+ for (ch = 0; ch < nchar; ch++) {
+ if ((len = bitlen[ch]) == 0) continue;
+ nextcode = start[len] + weight[len];
+ if (len <= tablebits) {
+ for (i = start[len]; i < nextcode; i++) table[i] = ch;
+ } else {
+ k = start[len];
+ p = &table[k >> jutbits];
+ i = len - tablebits;
+ while (i != 0) {
+ if (*p == 0) {
+ right[avail] = left[avail] = 0;
+ *p = avail++;
+ }
+ if (k & mask) p = &right[*p];
+ else p = &left[*p];
+ k <<= 1; i--;
+ }
+ *p = ch;
+ }
+ start[len] = nextcode;
+ }
+}
+
+// static Huffman
+
+static void read_pt_len(int nn, int nbit, int i_special)
+{
+ int i, c, n;
+ unsigned short mask;
+
+ n = getbits(nbit);
+ if (n == 0) {
+ c = getbits(nbit);
+ for (i = 0; i < nn; i++) pt_len[i] = 0;
+ for (i = 0; i < 256; i++) pt_table[i] = c;
+ } else {
+ i = 0;
+ while (i < n) {
+ c = bitbuf >> (BITBUFSIZ - 3);
+ if (c == 7) {
+ mask = 1U << (BITBUFSIZ - 1 - 3);
+ while (mask & bitbuf) { mask >>= 1; c++; }
+ }
+ fillbuf((c < 7) ? 3 : c - 3);
+ pt_len[i++] = c;
+ if (i == i_special) {
+ c = getbits(2);
+ while (--c >= 0) pt_len[i++] = 0;
+ }
+ }
+ while (i < nn) pt_len[i++] = 0;
+ make_table(nn, pt_len, 8, pt_table);
+ }
+}
+
+static void read_c_len(void)
+{
+ int i, c, n;
+ unsigned short mask;
+
+ n = getbits(CBIT);
+ if (n == 0) {
+ c = getbits(CBIT);
+ for (i = 0; i < NC; i++) c_len[i] = 0;
+ for (i = 0; i < 4096; i++) c_table[i] = c;
+ } else {
+ i = 0;
+ while (i < n) {
+ c = pt_table[bitbuf >> (BITBUFSIZ - 8)];
+ if (c >= NT) {
+ mask = 1U << (BITBUFSIZ - 1 - 8);
+ do {
+ if (bitbuf & mask) c = right[c];
+ else c = left [c];
+ mask >>= 1;
+ } while (c >= NT);
+ }
+ fillbuf(pt_len[c]);
+ if (c <= 2) {
+ if (c == 0) c = 1;
+ else if (c == 1) c = getbits(4) + 3;
+ else c = getbits(CBIT) + 20;
+ while (--c >= 0) c_len[i++] = 0;
+ } else c_len[i++] = c - 2;
+ }
+ while (i < NC) c_len[i++] = 0;
+ make_table(NC, c_len, 12, c_table);
+ }
+}
+
+
+static unsigned short decode_c(void)
+{
+ unsigned short j, mask;
+
+ if (blocksize == 0) {
+ blocksize = getbits(16);
+ read_pt_len(NT, TBIT, 3);
+ read_c_len();
+ read_pt_len(NP, PBIT, -1);
+ }
+ blocksize--;
+ j = c_table[bitbuf >> (BITBUFSIZ - 12)];
+ if (j >= NC) {
+ mask = 1U << (BITBUFSIZ - 1 - 12);
+ do {
+ if (bitbuf & mask) j = right[j];
+ else j = left [j];
+ mask >>= 1;
+ } while (j >= NC);
+ }
+ fillbuf(c_len[j]);
+ return j;
+}
+
+
+static unsigned short decode_p(void)
+{
+ unsigned short j, mask;
+
+ j = pt_table[bitbuf >> (BITBUFSIZ - 8)];
+ if (j >= NP) {
+ mask = 1U << (BITBUFSIZ - 1 - 8);
+ do {
+ if (bitbuf & mask) j = right[j];
+ else j = left [j];
+ mask >>= 1;
+ } while (j >= NP);
+ }
+ fillbuf(pt_len[j]);
+ if (j != 0) j = (1U << (j - 1)) + getbits(j - 1);
+ return j;
+}
+
+
+static void decode(unsigned short count, unsigned char buffer[])
+{
+ static unsigned short i;
+ unsigned short r, c;
+
+ r = 0;
+ while (--j >= 0) {
+ buffer[r] = buffer[i];
+ i = (i + 1) & (DICSIZ - 1);
+ if (++r == count) return;
+ }
+ for ( ; ; ) {
+ c = decode_c();
+ if (c <= UCHAR_MAX) {
+ buffer[r] = c & UCHAR_MAX;
+ if (++r == count) return;
+ } else {
+ j = c - (UCHAR_MAX + 1 - THRESHOLD);
+ i = (r - decode_p() - 1) & (DICSIZ - 1);
+ while (--j >= 0) {
+ buffer[r] = buffer[i];
+ i = (i + 1) & (DICSIZ - 1);
+ if (++r == count) return;
+ }
+ }
+ }
+}
+
+void lh5_decode(const unsigned char *inp, unsigned char *outp, unsigned long original_size, unsigned long packed_size)
+{
+ unsigned short n;
+ unsigned char *buffer;
+
+ compsize = packed_size;
+ origsize = original_size;
+ in_buf = inp;
+ out_buf = outp;
+
+#if 0
+ fprintf(stderr, "DEBUG: compsize = %ld, origsize = %ld, first 8 bytes of packed data:\n", packed_size, original_size);
+ fprintf(stderr, " %02x %02x %02x %02x %02x %02x %02x %02x \n",
+ *(inp), *(inp+1),*(inp+2),*(inp+3),
+ *(inp+4),*(inp+5),*(inp+6),*(inp+7));
+#endif
+
+ buffer = (unsigned char *) malloc(DICSIZ);
+ if (!buffer) error ("Out of memory");
+
+ bitbuf = 0; subbitbuf = 0; bitcount = 0;
+ fillbuf(BITBUFSIZ);
+ blocksize = 0;
+ j = 0;
+
+ while (origsize != 0) {
+ n = (origsize > DICSIZ) ? DICSIZ : (unsigned short)origsize;
+ decode(n, buffer);
+ memmove(out_buf, buffer, n);
+ out_buf += n;
+ origsize -= n;
+ }
+
+ if (buffer) free (buffer);
+ buffer = NULL;
+}