~kris/9p

9hist

5421ca19ea991e20f85902ecce808495883b16fa — David du Colombier 26 years ago fc344bd
Plan 9 from Bell Labs 1999-11-11
4 files changed, 182 insertions(+), 107 deletions(-)

M port/devsdp.c
M port/thwack.c
M port/thwack.h
M port/unthwack.c
M port/devsdp.c => port/devsdp.c +1 -1
@@ 1737,7 1737,7 @@ writedata(Conv *c, Block *b)
	c->lstats.outDataPackets++;
	c->lstats.outDataBytes += n;

	if(0 && c->out.comp != nil) {
	if(c->out.comp != nil) {
		// must generate same value as convoput
		seq = (c->out.seq + 1) & (SeqMax-1);


M port/thwack.c => port/thwack.c +61 -28
@@ 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;


M port/thwack.h => port/thwack.h +4 -8
@@ 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);

M port/unthwack.c => port/unthwack.c +116 -70
@@ 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;