123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620 |
- #include <u.h>
- #include <libc.h>
- #include "sac.h"
- typedef struct Huff Huff;
- typedef struct Mtf Mtf;
- typedef struct Decode Decode;
- enum
- {
- ZBase = 2, /* base of code to encode 0 runs */
- LitBase = ZBase-1, /* base of literal values */
- MaxLit = 256,
- MaxLeaf = MaxLit+LitBase,
- MaxHuffBits = 16, /* max bits in a huffman code */
- MaxFlatbits = 5, /* max bits decoded in flat table */
- CombLog = 4,
- CombSpace = 1 << CombLog, /* mtf speedup indices spacing */
- CombMask = CombSpace - 1,
- };
- struct Mtf
- {
- int maxcomb; /* index of last valid comb */
- uchar prev[MaxLit];
- uchar next[MaxLit];
- uchar comb[MaxLit / CombSpace + 1];
- };
- struct Huff
- {
- int maxbits;
- int flatbits;
- ulong flat[1<<MaxFlatbits];
- ulong maxcode[MaxHuffBits];
- ulong last[MaxHuffBits];
- ulong decode[MaxLeaf];
- };
- struct Decode{
- Huff tab;
- Mtf mtf;
- int nbits;
- ulong bits;
- int nzero;
- int base;
- ulong maxblocksym;
- jmp_buf errjmp;
- uchar *src; /* input buffer */
- uchar *smax; /* limit */
- };
- static void fatal(Decode *dec, char*);
- static int hdec(Decode*);
- static void recvtab(Decode*, Huff*, int, ushort*);
- static ulong bitget(Decode*, int);
- static int mtf(uchar*, int);
- #define FORWARD 0
- static void
- mtflistinit(Mtf *m, uchar *front, int n)
- {
- int last, me, f, i, comb;
- if(n == 0)
- return;
- /*
- * add all entries to free list
- */
- last = MaxLit - 1;
- for(i = 0; i < MaxLit; i++){
- m->prev[i] = last;
- m->next[i] = i + 1;
- last = i;
- }
- m->next[last] = 0;
- f = 0;
- /*
- * pull valid entries off free list and enter into mtf list
- */
- comb = 0;
- last = front[0];
- for(i = 0; i < n; i++){
- me = front[i];
- f = m->next[me];
- m->prev[f] = m->prev[me];
- m->next[m->prev[f]] = f;
- m->next[last] = me;
- m->prev[me] = last;
- last = me;
- if((i & CombMask) == 0)
- m->comb[comb++] = me;
- }
- /*
- * pad out the list with dummies to the next comb,
- * using free entries
- */
- for(; i & CombMask; i++){
- me = f;
- f = m->next[me];
- m->prev[f] = m->prev[me];
- m->next[m->prev[f]] = f;
- m->next[last] = me;
- m->prev[me] = last;
- last = me;
- }
- me = front[0];
- m->next[last] = me;
- m->prev[me] = last;
- m->comb[comb] = me;
- m->maxcomb = comb;
- }
- static int
- mtflist(Mtf *m, int pos)
- {
- uchar *next, *prev, *mycomb;
- int c, c0, pc, nc, off;
- if(pos == 0)
- return m->comb[0];
- next = m->next;
- prev = m->prev;
- mycomb = &m->comb[pos >> CombLog];
- off = pos & CombMask;
- if(off >= CombSpace / 2){
- c = mycomb[1];
- for(; off < CombSpace; off++)
- c = prev[c];
- }else{
- c = *mycomb;
- for(; off; off--)
- c = next[c];
- }
- nc = next[c];
- pc = prev[c];
- prev[nc] = pc;
- next[pc] = nc;
- for(; mycomb > m->comb; mycomb--)
- *mycomb = prev[*mycomb];
- c0 = *mycomb;
- *mycomb = c;
- mycomb[m->maxcomb] = c;
- next[c] = c0;
- pc = prev[c0];
- prev[c] = pc;
- prev[c0] = c;
- next[pc] = c;
- return c;
- }
- static void
- hdecblock(Decode *dec, ulong n, ulong I, uchar *buf, ulong *sums, ulong *prev)
- {
- ulong i, nn, sum;
- int m, z, zz, c;
- nn = I;
- n--;
- i = 0;
- again:
- for(; i < nn; i++){
- while((m = hdec(dec)) == 0 && i + dec->nzero < n)
- ;
- if(z = dec->nzero){
- dec->nzero = 0;
- c = dec->mtf.comb[0];
- sum = sums[c];
- sums[c] = sum + z;
- z += i;
- zz = z;
- if(i < I && z > I){
- zz = I;
- z++;
- }
- zagain:
- for(; i < zz; i++){
- buf[i] = c;
- prev[i] = sum++;
- }
- if(i != z){
- zz = z;
- nn = ++n;
- i++;
- goto zagain;
- }
- if(i == nn){
- if(i == n)
- return;
- nn = ++n;
- i++;
- }
- }
- c = mtflist(&dec->mtf, m);
- buf[i] = c;
- sum = sums[c];
- prev[i] = sum++;
- sums[c] = sum;
- }
- if(i == n)
- return;
- nn = ++n;
- i++;
- goto again;
- }
- int
- unsac(uchar *dst, uchar *src, int n, int nsrc)
- {
- Decode *dec;
- uchar *buf, *front;
- ulong *prev, *sums;
- ulong sum, i, I;
- int m, j, c;
- dec = malloc(sizeof *dec);
- buf = malloc(n+2);
- prev = malloc((n+2) * sizeof *prev);
- front = malloc(MaxLit * sizeof *front);
- sums = malloc(MaxLit * sizeof *sums);
- if(dec == nil || buf == nil || prev == nil || front == nil || sums == nil || setjmp(dec->errjmp)){
- free(dec);
- free(buf);
- free(prev);
- free(front);
- free(sums);
- return -1;
- }
- dec->src = src;
- dec->smax = src + nsrc;
- dec->nbits = 0;
- dec->bits = 0;
- dec->nzero = 0;
- for(i = 0; i < MaxLit; i++)
- front[i] = i;
- n++;
- I = bitget(dec, 16);
- if(I >= n)
- fatal(dec, "corrupted input");
- /*
- * decode the character usage map
- */
- for(i = 0; i < MaxLit; i++)
- sums[i] = 0;
- c = bitget(dec, 1);
- for(i = 0; i < MaxLit; ){
- m = bitget(dec, 8) + 1;
- while(m--){
- if(i >= MaxLit)
- fatal(dec, "corrupted char map");
- front[i++] = c;
- }
- c = c ^ 1;
- }
- /*
- * initialize mtf state
- */
- c = 0;
- for(i = 0; i < MaxLit; i++)
- if(front[i])
- front[c++] = i;
- mtflistinit(&dec->mtf, front, c);
- dec->maxblocksym = c + LitBase;
- /*
- * huffman decoding, move to front decoding,
- * along with character counting
- */
- dec->base = 1;
- recvtab(dec, &dec->tab, MaxLeaf, nil);
- hdecblock(dec, n, I, buf, sums, prev);
- sum = 1;
- for(i = 0; i < MaxLit; i++){
- c = sums[i];
- sums[i] = sum;
- sum += c;
- }
- i = 0;
- for(j = n - 2; j >= 0; j--){
- if(i > n || i < 0 || i == I)
- fatal(dec, "corrupted data");
- c = buf[i];
- dst[j] = c;
- i = prev[i] + sums[c];
- }
- free(dec);
- free(buf);
- free(prev);
- free(front);
- free(sums);
- return n;
- }
- static ulong
- bitget(Decode *dec, int nb)
- {
- int c;
- while(dec->nbits < nb){
- if(dec->src >= dec->smax)
- fatal(dec, "premature eof 1");
- c = *dec->src++;
- dec->bits <<= 8;
- dec->bits |= c;
- dec->nbits += 8;
- }
- dec->nbits -= nb;
- return (dec->bits >> dec->nbits) & ((1 << nb) - 1);
- }
- static void
- fillbits(Decode *dec)
- {
- int c;
- while(dec->nbits < 24){
- if(dec->src >= dec->smax)
- fatal(dec, "premature eof 2");
- c = *dec->src++;
- dec->bits <<= 8;
- dec->bits |= c;
- dec->nbits += 8;
- }
- }
- /*
- * decode one symbol
- */
- static int
- hdecsym(Decode *dec, Huff *h, int b)
- {
- long c;
- ulong bits;
- int nbits;
- bits = dec->bits;
- nbits = dec->nbits;
- for(; (c = bits >> (nbits - b)) > h->maxcode[b]; b++)
- ;
- if(b > h->maxbits)
- fatal(dec, "too many bits consumed");
- dec->nbits = nbits - b;
- return h->decode[h->last[b] - c];
- }
- static int
- hdec(Decode *dec)
- {
- ulong c;
- int nbits, nb;
- if(dec->nbits < dec->tab.maxbits)
- fillbits(dec);
- nbits = dec->nbits;
- dec->bits &= (1 << nbits) - 1;
- c = dec->tab.flat[dec->bits >> (nbits - dec->tab.flatbits)];
- nb = c & 0xff;
- c >>= 8;
- if(nb == 0xff)
- c = hdecsym(dec, &dec->tab, c);
- else
- dec->nbits = nbits - nb;
- /*
- * reverse funny run-length coding
- */
- if(c < ZBase){
- dec->nzero += dec->base << c;
- dec->base <<= 1;
- return 0;
- }
- dec->base = 1;
- c -= LitBase;
- return c;
- }
- static void
- hufftab(Decode *dec, Huff *h, char *hb, ulong *bitcount, int maxleaf, int maxbits, int flatbits)
- {
- ulong c, mincode, code, nc[MaxHuffBits];
- int i, b, ec;
- h->maxbits = maxbits;
- if(maxbits < 0)
- return;
- code = 0;
- c = 0;
- for(b = 0; b <= maxbits; b++){
- h->last[b] = c;
- c += bitcount[b];
- mincode = code << 1;
- nc[b] = mincode;
- code = mincode + bitcount[b];
- if(code > (1 << b))
- fatal(dec, "corrupted huffman table");
- h->maxcode[b] = code - 1;
- h->last[b] += code - 1;
- }
- if(code != (1 << maxbits))
- fatal(dec, "huffman table not full");
- if(flatbits > maxbits)
- flatbits = maxbits;
- h->flatbits = flatbits;
- b = 1 << flatbits;
- for(i = 0; i < b; i++)
- h->flat[i] = ~0;
- /*
- * initialize the flat table to include the minimum possible
- * bit length for each code prefix
- */
- for(b = maxbits; b > flatbits; b--){
- code = h->maxcode[b];
- if(code == -1)
- break;
- mincode = code + 1 - bitcount[b];
- mincode >>= b - flatbits;
- code >>= b - flatbits;
- for(; mincode <= code; mincode++)
- h->flat[mincode] = (b << 8) | 0xff;
- }
- for(i = 0; i < maxleaf; i++){
- b = hb[i];
- if(b == -1)
- continue;
- c = nc[b]++;
- if(b <= flatbits){
- code = (i << 8) | b;
- ec = (c + 1) << (flatbits - b);
- if(ec > (1<<flatbits))
- fatal(dec, "flat code too big");
- for(c <<= (flatbits - b); c < ec; c++)
- h->flat[c] = code;
- }else{
- c = h->last[b] - c;
- if(c >= maxleaf)
- fatal(dec, "corrupted huffman table");
- h->decode[c] = i;
- }
- }
- }
- static void
- elimBit(int b, char *tmtf, int maxbits)
- {
- int bb;
- for(bb = 0; bb < maxbits; bb++)
- if(tmtf[bb] == b)
- break;
- while(++bb <= maxbits)
- tmtf[bb - 1] = tmtf[bb];
- }
- static int
- elimBits(int b, ulong *bused, char *tmtf, int maxbits)
- {
- int bb, elim;
- if(b < 0)
- return 0;
- elim = 0;
- /*
- * increase bits counts for all descendants
- */
- for(bb = b + 1; bb < maxbits; bb++){
- bused[bb] += 1 << (bb - b);
- if(bused[bb] == (1 << bb)){
- elim++;
- elimBit(bb, tmtf, maxbits);
- }
- }
- /*
- * steal bits from parent & check for fullness
- */
- for(; b >= 0; b--){
- bused[b]++;
- if(bused[b] == (1 << b)){
- elim++;
- elimBit(b, tmtf, maxbits);
- }
- if((bused[b] & 1) == 0)
- break;
- }
- return elim;
- }
- static void
- recvtab(Decode *dec, Huff *tab, int maxleaf, ushort *map)
- {
- ulong bitcount[MaxHuffBits+1], bused[MaxHuffBits+1];
- char tmtf[MaxHuffBits+1], *hb;
- int i, b, ttb, m, maxbits, max, elim;
- hb = malloc(MaxLeaf * sizeof *hb);
- if(hb == nil)
- fatal(dec, "out of memory");
- /*
- * read the tables for the tables
- */
- max = 8;
- for(i = 0; i <= MaxHuffBits; i++){
- bitcount[i] = 0;
- tmtf[i] = i;
- bused[i] = 0;
- }
- tmtf[0] = -1;
- tmtf[max] = 0;
- elim = 0;
- maxbits = -1;
- for(i = 0; i <= MaxHuffBits && elim != max; i++){
- ttb = 4;
- while(max - elim < (1 << (ttb-1)))
- ttb--;
- b = bitget(dec, ttb);
- if(b > max - elim)
- fatal(dec, "corrupted huffman table table");
- b = tmtf[b];
- hb[i] = b;
- bitcount[b]++;
- if(b > maxbits)
- maxbits = b;
- elim += elimBits(b, bused, tmtf, max);
- }
- if(elim != max)
- fatal(dec, "incomplete huffman table table");
- hufftab(dec, tab, hb, bitcount, i, maxbits, MaxFlatbits);
- for(i = 0; i <= MaxHuffBits; i++){
- tmtf[i] = i;
- bitcount[i] = 0;
- bused[i] = 0;
- }
- tmtf[0] = -1;
- tmtf[MaxHuffBits] = 0;
- elim = 0;
- maxbits = -1;
- for(i = 0; i < maxleaf && elim != MaxHuffBits; i++){
- if(dec->nbits <= tab->maxbits)
- fillbits(dec);
- dec->bits &= (1 << dec->nbits) - 1;
- m = tab->flat[dec->bits >> (dec->nbits - tab->flatbits)];
- b = m & 0xff;
- m >>= 8;
- if(b == 0xff)
- m = hdecsym(dec, tab, m);
- else
- dec->nbits -= b;
- b = tmtf[m];
- for(; m > 0; m--)
- tmtf[m] = tmtf[m-1];
- tmtf[0] = b;
- if(b > MaxHuffBits)
- fatal(dec, "bit length too big");
- m = i;
- if(map != nil)
- m = map[m];
- hb[m] = b;
- bitcount[b]++;
- if(b > maxbits)
- maxbits = b;
- elim += elimBits(b, bused, tmtf, MaxHuffBits);
- }
- if(elim != MaxHuffBits && elim != 0)
- fatal(dec, "incomplete huffman table");
- if(map != nil)
- for(; i < maxleaf; i++)
- hb[map[i]] = -1;
- hufftab(dec, tab, hb, bitcount, i, maxbits, MaxFlatbits);
- free(hb);
- }
- static void
- fatal(Decode *dec, char *msg)
- {
- print("%s: %s\n", argv0, msg);
- longjmp(dec->errjmp, 1);
- }
|