@@ 1,15 1,28 @@
#include "u.h"
-#include "../port/lib.h"
+#include "lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "thwack.h"
+/*
+ * don't include compressed blocks
+ */
+#define NOUNCOMP
+
typedef struct Huff Huff;
enum
{
+ MaxFastLen = 9,
+ BigLenCode = 0x1f4, /* minimum code for large lenth encoding */
+ BigLenBits = 9,
+ BigLenBase = 4 /* starting items to encode for big lens */
+};
+
+enum
+{
StatBytes,
StatOutBytes,
StatLits,
@@ 32,15 45,15 @@ struct Huff
static Huff lentab[MaxFastLen] =
{
- {1, 0x0}, /* 0 */
{2, 0x2}, /* 10 */
- {4, 0xc}, /* 1100 */
- {4, 0xd}, /* 1101 */
+ {3, 0x6}, /* 110 */
{5, 0x1c}, /* 11100 */
- {6, 0x3a}, /* 111010 */
- {6, 0x3b}, /* 111011 */
- {7, 0x78}, /* 1111000 */
- {7, 0x79}, /* 1111001 */
+ {5, 0x1d}, /* 11101 */
+ {6, 0x3c}, /* 111100 */
+ {7, 0x7a}, /* 1111010 */
+ {7, 0x7b}, /* 1111011 */
+ {8, 0xf8}, /* 11111000 */
+ {8, 0xf9}, /* 11111001 */
};
void
@@ 215,6 228,12 @@ thwack(Thwack *tw, uchar *dst, uchar *src, int n, ulong seq, ulong stats[ThwStat
*twdst++ = seq - cseq;
*twdst++ = cmask;
+#ifndef NOUNCOMP
+ tw->slot++;
+ if(tw->slot >= EWinBlocks)
+ tw->slot = 0;
+#endif
+
cont = (s[0] << 16) | (s[1] << 8) | s[2];
esrc = s + n;
@@ 261,6 280,7 @@ thwack(Thwack *tw, uchar *dst, uchar *src, int n, ulong seq, ulong stats[ThwStat
lits++;
blocks->maxoff++;
+#ifdef NOUNCOMP
/*
* speed hack
* check for compression progress, bail if none achieved
@@ 270,6 290,7 @@ thwack(Thwack *tw, uchar *dst, uchar *src, int n, ulong seq, ulong stats[ThwStat
return -1;
half = esrc;
}
+#endif
if(s + MinMatch <= esrc){
blocks->hash[(h ^ blocks->seq) & HashMask] = now;
@@ 284,18 305,9 @@ thwack(Thwack *tw, uchar *dst, uchar *src, int n, ulong seq, ulong stats[ThwStat
blocks->maxoff += len;
matches++;
- toff--;
- for(bits = OffBase; toff >= (1 << bits); bits++)
- ;
- if(bits >= MaxOff+OffBase)
- panic("thwack offset");
- twbits = (twbits << 4) | 0x8 | (bits - OffBase);
- if(bits != OffBase)
- bits--;
- twbits = (twbits << bits) | toff & ((1 << bits) - 1);
- twnbits += bits + 4;
- offbits += bits + 4;
-
+ /*
+ * length of match
+ */
len -= MinMatch;
if(len < MaxFastLen){
bits = lentab[len].bits;
@@ 303,11 315,6 @@ thwack(Thwack *tw, uchar *dst, uchar *src, int n, ulong seq, ulong stats[ThwStat
twnbits += bits;
lenbits += bits;
}else{
- for(; twnbits >= 8; twnbits -= 8){
- if(twdst >= twdmax)
- return -1;
- *twdst++ = twbits >> (twnbits - 8);
- }
code = BigLenCode;
bits = BigLenBits;
use = BigLenBase;
@@ 315,16 322,40 @@ thwack(Thwack *tw, uchar *dst, uchar *src, int n, ulong seq, ulong stats[ThwStat
while(len >= use){
len -= use;
code = (code + use) << 1;
- use <<= bits & 1;
+ use <<= (bits & 1) ^ 1;
bits++;
}
- if(bits > MaxLenDecode + BigLenBits)
- panic("length too big");
twbits = (twbits << bits) | (code + len);
twnbits += bits;
lenbits += bits;
+
+ for(; twnbits >= 8; twnbits -= 8){
+ if(twdst >= twdmax)
+ return -1;
+ *twdst++ = twbits >> (twnbits - 8);
+ }
}
+ /*
+ * offset in history
+ */
+ toff--;
+ for(bits = OffBase; toff >= (1 << bits); bits++)
+ ;
+ if(bits < MaxOff+OffBase-1){
+ twbits = (twbits << 3) | (bits - OffBase);
+ if(bits != OffBase)
+ bits--;
+ twnbits += bits + 3;
+ offbits += bits + 3;
+ }else{
+ twbits = (twbits << 4) | 0xe | (bits - (MaxOff+OffBase-1));
+ bits--;
+ twnbits += bits + 4;
+ offbits += bits + 4;
+ }
+ twbits = (twbits << bits) | toff & ((1 << bits) - 1);
+
for(; s != ss; s++){
if(s + MinMatch <= esrc){
h = hashit(cont);
@@ 353,9 384,11 @@ thwack(Thwack *tw, uchar *dst, uchar *src, int n, ulong seq, ulong stats[ThwStat
*twdst++ = twbits >> (twnbits - 8);
}
+#ifdef NOUNCOMP
tw->slot++;
if(tw->slot >= EWinBlocks)
tw->slot = 0;
+#endif
stats[StatOutBytes] += twdst - dst;
@@ 8,25 8,20 @@ enum
ThwStats = 8,
ThwMaxBlock = 1600, /* max size of compressible block */
- MinMatch = 3, /* shortest match possible */
HashLog = 12,
HashSize = 1<<HashLog,
HashMask = HashSize - 1,
- MaxFastLen = 9,
- BigLenCode = 0xf4, /* minimum code for large lenth encoding */
- BigLenBase = 4, /* starting items to encode for big lens */
- BigLenBits = 8,
+ MinMatch = 3, /* shortest match possible */
+
MaxOff = 8,
OffBase = 6,
MinDecode = 8, /* minimum bits to decode a match or lit; >= 8 */
- MaxOffDecode = 4 + MaxOff + OffBase - 1,
- MaxLenDecode = 16,
EWinBlocks = 32, /* blocks held in encoder window */
DWinBlocks = 32, /* blocks held in decoder window */
- CompBlocks = 5, /* max blocks used to encode data */
+ CompBlocks = 10, /* max blocks used to encode data */
MaxSeqMask = 8, /* number of bits in coding block mask */
MaxSeqStart = 256 /* max offset of initial coding block */
@@ 70,3 65,4 @@ void unthwackinit(Unthwack*);
int thwack(Thwack*, uchar *dst, uchar *src, int nsrc, ulong seq, ulong stats[ThwStats]);
void thwackack(Thwack*, ulong seq, ulong mask);
int unthwack(Unthwack*, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq);
+int unthwackadd(Unthwack*, uchar *src, int nsrc, ulong seq);
@@ 1,33 1,57 @@
#include "u.h"
-#include "../port/lib.h"
+#include "lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "thwack.h"
-typedef struct HuffDec HuffDec;
+/*
+ * don't include compressed blocks
+ */
+#define NOUNCOMP
-struct HuffDec
+enum
{
- ulong maxcode[MaxFastLen];
- ulong last[MaxFastLen];
- ulong decode[MaxFastLen];
+ DMaxFastLen = 7,
+ DBigLenCode = 0x3c, /* minimum code for large lenth encoding */
+ DBigLenBits = 6,
+ DBigLenBase = 1 /* starting items to encode for big lens */
};
-static HuffDec lentab =
+static uchar lenval[1 << (DBigLenBits - 1)] =
{
-/* 0 1 2 3 4 5 6 7 */
- {0, 0, 0x2, 0, 0xd, 0x1c, 0x3b, 0x79},
- {-1, 0+0, 0x2+1, -1, 0xd+2, 0x1c+4, 0x3b+5, 0x79+7},
- {
- 0,
- 1,
- 3, 2,
- 4,
- 6, 5,
- 8, 7,
- },
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4,
+ 5,
+ 6,
+ 255,
+ 255
+};
+
+static uchar lenbits[] =
+{
+ 0, 0, 0,
+ 2, 3, 5, 5,
+};
+
+static uchar offbits[16] =
+{
+ 5, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 12, 13
+};
+
+static ushort offbase[16] =
+{
+ 0, 0x20,
+ 0x40, 0x60,
+ 0x80, 0xc0,
+ 0x100, 0x180,
+ 0x200, 0x300,
+ 0x400, 0x600,
+ 0x800, 0xc00,
+ 0x1000,
+ 0x2000
};
void
@@ 36,25 60,55 @@ unthwackinit(Unthwack *ut)
int i;
memset(ut, 0, sizeof *ut);
- for(i = 0; i < EWinBlocks; i++)
+ for(i = 0; i < DWinBlocks; i++)
ut->blocks[i].data = ut->data[i];
}
int
+unthwackadd(Unthwack *ut, uchar *src, int nsrc, ulong seq)
+{
+ int slot, tslot;
+
+ if(nsrc > ThwMaxBlock)
+ return -1;
+
+#ifndef NOUNCOMP
+ tslot = ut->slot;
+ for(;;){
+ slot = tslot - 1;
+ if(slot < 0)
+ slot += DWinBlocks;
+ if(ut->blocks[slot].seq <= seq)
+ break;
+ ut->blocks[slot] = ut->blocks[tslot];
+ tslot = slot;
+ }
+ ut->blocks[tslot].seq = seq;
+ ut->blocks[tslot].maxoff = nsrc;
+ memmove(ut->blocks[tslot].data, src, nsrc);
+
+ ut->slot++;
+ if(ut->slot >= DWinBlocks)
+ ut->slot = 0;
+#endif
+ return nsrc;
+}
+
+int
unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
{
UnthwBlock blocks[CompBlocks], *b, *eblocks;
- uchar *s, *es, *d, *dmax, *smax, lit;
+ uchar *s, *d, *dmax, *smax, lit;
ulong cmask, cseq, bseq, utbits, lithist;
- int off, len, bits, slot, tslot, use, code, utnbits, overbits;
+ int i, off, len, bits, slot, tslot, use, code, utnbits, overbits;
if(nsrc < 4 || nsrc > ThwMaxBlock)
return -1;
/*
- * find the correct slot for this block,
- * the oldest block around. the encoder
- * doesn't use a history at wraparound,
+ * insert this block in it's correct sequence number order.
+ * replace the oldest block, which is always pointed to by ut->slot.
+ * the encoder doesn't use a history at wraparound,
* so don't worry about that case.
*/
tslot = ut->slot;
@@ 64,7 118,7 @@ unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
slot += DWinBlocks;
if(ut->blocks[slot].seq <= seq)
break;
- ut->blocks[slot] = ut->blocks[slot];
+ ut->blocks[slot] = ut->blocks[tslot];
tslot = slot;
}
b = blocks;
@@ 104,7 158,7 @@ unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
}
eblocks = b;
if(cseq != seq){
- print("blocks not in decompression window: cseq=%ld seq=%ld cmask=%lux nb=%ld\n", cseq, seq, cmask, eblocks - blocks);
+ print("blocks not in decompression window: cseq=%ld seq=%ld cmask=%lx nb=%ld\n", cseq, seq, cmask, eblocks - blocks);
return -1;
}
@@ 127,7 181,8 @@ unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
/*
* literal
*/
- if(((utbits >> (utnbits - 1)) & 1) == 0){
+ len = lenval[(utbits >> (utnbits - 5)) & 0x1f];
+ if(len == 0){
if(lithist & 0xf){
utnbits -= 9;
lit = (utbits >> utnbits) & 0xff;
@@ 153,58 208,48 @@ unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
}
/*
- * match; next 3 bits decode offset range
+ * length
*/
- utnbits -= 4;
- bits = (utbits >> utnbits) & ((1 << 3) - 1);
- if(bits){
- bits += OffBase - 1;
- off = 1 << bits;
- }else{
- bits = OffBase;
- off = 0;
- }
- utnbits -= bits;
- off |= (utbits >> utnbits) & ((1 << bits) - 1);
- off++;
-
- bits = 0;
- utbits &= (1 << utnbits) - 1;
- do{
- bits++;
- len = utbits >> (utnbits - bits);
- }while(bits < BigLenBits && len > lentab.maxcode[bits]);
- utnbits -= bits;
-
- if(bits < BigLenBits)
- len = lentab.decode[lentab.last[bits] - len];
+ if(len < 255)
+ utnbits -= lenbits[len];
else{
- while(utnbits < MaxLenDecode){
- utbits <<= 8;
- if(src < smax)
- utbits |= *src++;
- else
- overbits += 8;
- utnbits += 8;
- }
-
- code = len - BigLenCode;
- len = MaxFastLen;
- bits = 8;
- use = BigLenBase;
+ utnbits -= DBigLenBits;
+ code = ((utbits >> utnbits) & ((1 << DBigLenBits) - 1)) - DBigLenCode;
+ len = DMaxFastLen;
+ use = DBigLenBase;
+ bits = (DBigLenBits & 1) ^ 1;
while(code >= use){
len += use;
code -= use;
code <<= 1;
utnbits--;
code |= (utbits >> utnbits) & 1;
- use <<= bits & 1;
- bits++;
+ use <<= bits;
+ bits ^= 1;
}
len += code;
+
+ while(utnbits <= 24){
+ utbits <<= 8;
+ if(src < smax)
+ utbits |= *src++;
+ else
+ overbits += 8;
+ utnbits += 8;
+ }
}
- len += MinMatch;
+ /*
+ * offset
+ */
+ utnbits -= 4;
+ bits = (utbits >> utnbits) & 0xf;
+ off = offbase[bits];
+ bits = offbits[bits];
+
+ utnbits -= bits;
+ off |= (utbits >> utnbits) & ((1 << bits) - 1);
+ off++;
b = blocks;
while(off > b->maxoff){
@@ 217,10 262,11 @@ unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
|| b != blocks && len > off)
return -1;
s = b->data + b->maxoff - off;
- es = s + len;
- while(s < es)
- *d++ = *s++;
blocks->maxoff += len;
+
+ for(i = 0; i < len; i++)
+ d[i] = s[i];
+ d += len;
}
if(utnbits < overbits)
return -1;