/*
* find a string in the dictionary
*/
static int
thwmatch(ThwBlock *b, ThwBlock *eblocks, uchar **ss, uchar *esrc, ulong h)
{
int then, toff, w, ok;
uchar *s, *t;
s = *ss;
if(esrc < s + MinMatch)
return 0;
toff = 0;
for(; b < eblocks; b++){
then = b->hash[(h ^ b->seq) & HashMask];
toff += b->maxoff;
w = (ushort)(then - b->begin);
if(w >= b->maxoff)
continue;
/*
* don't need to check for the end because
* 1) s too close check above
* 2) entries too close not added to hash tables
*/
t = w + b->data;
if(s[0] != t[0] || s[1] != t[1] || s[2] != t[2])
continue;
ok = b->edata - t;
if(esrc - s > ok)
esrc = s + ok;
/*
* knuth vol. 3 multiplicative hashing
* each byte x chosen according to rules
* 1/4 < x < 3/10, 1/3 x < < 3/7, 4/7 < x < 2/3, 7/10 < x < 3/4
* with reasonable spread between the bytes & their complements
*
* the 3 byte value appears to be as almost good as the 4 byte value,
* and might be faster on some machines
*/
/*
#define hashit(c) (((ulong)(c) * 0x6b43a9) >> (24 - HashLog))
*/
#define hashit(c) ((((ulong)(c) & 0xffffff) * 0x6b43a9b5) >> (32 - HashLog))
/*
* lz77 compression with single lookup in a hash table for each block
*/
int
thwack(Thwack *tw, int mustadd, uchar *dst, int ndst, Block *bsrc, ulong seq, ulong stats[ThwStats])
{
ThwBlock *eblocks, *b, blocks[CompBlocks];
uchar *s, *ss, *sss, *esrc, *half, *twdst, *twdmax;
ulong cont, cseq, bseq, cmask, code, twbits;
int n, now, toff, lithist, h, len, slot, bits, use, twnbits, lits, matches, offbits, lenbits, nhist;
n = BLEN(bsrc);
if(n > ThwMaxBlock || n < MinMatch)
return -1;
twdst = dst;
twdmax = dst + ndst;
/*
* add source to the coding window
* there is always enough space
*/
qlock(&tw->acklock);
slot = tw->slot;
b = &tw->blocks[slot];
b->seq = seq;
b->acked = 0;
now = b->begin + b->maxoff;
if(tw->data[slot] != nil){
freeb(tw->data[slot]);
tw->data[slot] = nil;
}
s = bsrc->rptr;
b->data = s;
b->edata = s + n;
b->begin = now;
b->maxoff = n;