summaryrefslogtreecommitdiffstats
path: root/lib/rbcodec/codecs/libayumi/lzh.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/libayumi/lzh.c')
-rw-r--r--lib/rbcodec/codecs/libayumi/lzh.c420
1 files changed, 420 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libayumi/lzh.c b/lib/rbcodec/codecs/libayumi/lzh.c
new file mode 100644
index 0000000000..786d3bbafe
--- /dev/null
+++ b/lib/rbcodec/codecs/libayumi/lzh.c
@@ -0,0 +1,420 @@
+#include "lzh.h"
+
+#include <string.h>
+
+#define BUFSIZE (1024 * 4)
+
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+#ifndef UCHAR_MAX
+#define UCHAR_MAX 255
+#endif
+
+typedef ushort BITBUFTYPE;
+
+#define BITBUFSIZ (CHAR_BIT * sizeof(BITBUFTYPE))
+#define DICBIT 13 /* 12(-lh4-) or 13(-lh5-) */
+#define DICSIZ (1U << DICBIT)
+#define MAXMATCH 256 /* formerly F (not more than UCHAR_MAX + 1) */
+#define THRESHOLD 3 /* choose optimal value */
+#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD) /* alphabet = {0, 1, 2, ..., NC - 1} */
+#define CBIT 9 /* $\lfloor \log_2 NC \rfloor + 1$ */
+#define CODE_BIT 16 /* codeword length */
+
+#define MAX_HASH_VAL (3 * DICSIZ + (DICSIZ / 512 + 1) * UCHAR_MAX)
+
+#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
+
+uchar *m_pSrc;
+int m_srcSize;
+uchar *m_pDst;
+int m_dstSize;
+
+int DataIn(void *pBuffer, int nBytes);
+int DataOut(void *pOut, int nBytes);
+
+void fillbuf(int n);
+ushort getbits(int n);
+void init_getbits(void);
+int make_table(int nchar, uchar *bitlen, int tablebits, ushort *table);
+void read_pt_len(int nn, int nbit, int i_special);
+void read_c_len(void);
+ushort decode_c(void);
+ushort decode_p(void);
+void huf_decode_start(void);
+void decode_start(void);
+void decode(uint count, uchar buffer[]);
+
+int fillbufsize;
+uchar buf[BUFSIZE];
+uchar outbuf[DICSIZ];
+ushort left[2 * NC - 1];
+ushort right[2 * NC - 1];
+BITBUFTYPE bitbuf;
+uint subbitbuf;
+int bitcount;
+int decode_j; /* remaining bytes to copy */
+uchar c_len[NC];
+uchar pt_len[NPT];
+uint blocksize;
+ushort c_table[4096];
+ushort pt_table[256];
+int with_error;
+
+uint fillbuf_i; /* NOTE: these ones are not initialized at constructor time but inside the fillbuf and decode func. */
+uint decode_i;
+
+/* Additions */
+
+int DataIn(void *pBuffer, int nBytes)
+{
+ const int np = (nBytes <= m_srcSize) ? nBytes : m_srcSize;
+ if (np > 0) {
+ memcpy(pBuffer, m_pSrc, np);
+ m_pSrc += np;
+ m_srcSize -= np;
+ }
+ return np;
+}
+
+int DataOut(void *pBuffer, int nBytes)
+{
+ const int np = (nBytes <= m_dstSize) ? nBytes : m_dstSize;
+ if (np > 0) {
+ memcpy(m_pDst, pBuffer, np);
+ m_pDst += np;
+ m_dstSize -= np;
+ }
+ return np;
+}
+
+/* io.c */
+
+/* Shift bitbuf n bits left, read n bits */
+void fillbuf(int n)
+{
+ bitbuf = (bitbuf << n) & 0xffff;
+ while (n > bitcount) {
+ bitbuf |= subbitbuf << (n -= bitcount);
+ if (fillbufsize == 0) {
+ fillbuf_i = 0;
+ fillbufsize = DataIn(buf, BUFSIZE - 32);
+ }
+ if (fillbufsize > 0)
+ fillbufsize--, subbitbuf = buf[fillbuf_i++];
+ else
+ subbitbuf = 0;
+ bitcount = CHAR_BIT;
+ }
+ bitbuf |= subbitbuf >> (bitcount -= n);
+}
+
+ushort getbits(int n)
+{
+ ushort x;
+ x = bitbuf >> (BITBUFSIZ - n);
+ fillbuf(n);
+ return x;
+}
+
+void init_getbits(void)
+{
+ bitbuf = 0;
+ subbitbuf = 0;
+ bitcount = 0;
+ fillbuf(BITBUFSIZ);
+}
+
+/* maketbl.c */
+
+int make_table(int nchar, uchar * bitlen, int tablebits, ushort * table)
+{
+ ushort count[17], weight[17], start[18], *p;
+ uint jutbits, avail, mask;
+ int i, ch, len, nextcode;
+
+ 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] != (ushort) (1U << 16))
+ return (1); /* 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++;
+ }
+
+ i = start[tablebits + 1] >> jutbits;
+ if (i != (ushort) (1U << 16)) {
+ int 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 {
+ uint 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;
+ }
+ return (0);
+}
+
+/* huf.c */
+
+void read_pt_len(int nn, int nbit, int i_special)
+{
+ int i, n;
+ short c;
+ ushort 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++] = (unsigned char) (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);
+ }
+}
+
+void read_c_len(void)
+{
+ short i, c, n;
+ ushort 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);
+ }
+}
+
+ushort decode_c(void)
+{
+ ushort 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;
+}
+
+ushort decode_p(void)
+{
+ ushort 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;
+}
+
+void huf_decode_start(void)
+{
+ init_getbits();
+ blocksize = 0;
+}
+
+/* decode.c */
+
+void decode_start(void)
+{
+ fillbufsize = 0;
+ huf_decode_start();
+ decode_j = 0;
+}
+
+/*
+ * The calling function must keep the number of bytes to be processed. This
+ * function decodes either 'count' bytes or 'DICSIZ' bytes, whichever is
+ * smaller, into the array 'buffer[]' of size 'DICSIZ' or more. Call
+ * decode_start() once for each new file before calling this function.
+ */
+void decode(uint count, uchar buffer[])
+{
+ uint r, c;
+
+ r = 0;
+ while (--decode_j >= 0) {
+ buffer[r] = buffer[decode_i];
+ decode_i = (decode_i + 1) & (DICSIZ - 1);
+ if (++r == count)
+ return;
+ }
+ for (;;) {
+ c = decode_c();
+ if (c <= UCHAR_MAX) {
+ buffer[r] = c;
+ if (++r == count)
+ return;
+ } else {
+ decode_j = c - (UCHAR_MAX + 1 - THRESHOLD);
+ decode_i = (r - decode_p() - 1) & (DICSIZ - 1);
+ while (--decode_j >= 0) {
+ buffer[r] = buffer[decode_i];
+ decode_i = (decode_i + 1) & (DICSIZ - 1);
+ if (++r == count)
+ return;
+ }
+ }
+ }
+}
+
+int LzUnpack(void *pSrc, int srcSize, void *pDst, int dstSize)
+{
+ with_error = 0;
+
+ m_pSrc = (uchar *) pSrc;
+ m_srcSize = srcSize;
+ m_pDst = (uchar *) pDst;
+ m_dstSize = dstSize;
+
+ decode_start();
+
+ unsigned int origsize = dstSize;
+ while (origsize != 0) {
+ int n = (uint) ((origsize > DICSIZ) ? DICSIZ : origsize);
+ decode(n, outbuf);
+ if (with_error)
+ break;
+
+ DataOut(outbuf, n);
+ origsize -= n;
+ if (with_error)
+ break;
+ }
+
+ return (with_error);
+}