Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/port/unthwack.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname port/unthwack.c 1999/1001
## diff -e /dev/null /n/emeliedump/1999/1001/sys/src/brazil/port/unthwack.c
0a
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"

#include "thwack.h"

typedef struct HuffDec		HuffDec;

struct HuffDec
{
	ulong	maxcode[MaxLen];
	ulong	last[MaxLen];
	ulong	decode[MaxLen];
};

static HuffDec lentab = 
{
/*	0	1	2	3	4	5	6	*/
	{0,	0,	0x2,	0,	0xe,	0x1e,	0x3f},
	{-1,	0+0,	0x2+1,	-1,	0xe+2,	0x1e+5,	0x3f+6},
	{
		0,
		1,
		7, 3, 2,
		4,
		6, 5
	},
};

static ulong	bitget(Unthwack *ut, int nb);
static ulong	iomegaget(Unthwack *ut);

void
unthwackinit(Unthwack *ut)
{
	int i;

	memset(ut, 0, sizeof *ut);
	for(i = 0; i < EWinBlocks; i++)
		ut->blocks[i].data = ut->data[i];
}

/*
 * to speed up, inline bitget
 */
int
unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
{
	UnthwBlock blocks[CompBlocks], *b, *eblocks;
	uchar *s, *es, *d, *dmax;
	ulong cmask, cseq, bseq, utbits, utnbits;
	int off, len, bits, slot, tslot;

	if(nsrc < 4 || nsrc > ThwMaxBlock || waserror())
		return -1;

	ut->src = src + 2;
	ut->smax = src + nsrc;

	/*
	 * find the correct slot for this block,
	 * the oldest block around.  the encoder
	 * doesn't use a history at wraparound,
	 * so don't worry about that case.
	 */
	tslot = ut->slot;
	for(;;){
		slot = tslot - 1;
		if(slot < 0)
			slot += DWinBlocks;
		if(ut->blocks[slot].seq <= seq)
			break;
		ut->blocks[slot] = ut->blocks[slot];
		tslot = slot;
	}
	b = blocks;
	ut->blocks[tslot].seq = seq;
	ut->blocks[tslot].maxoff = 0;
	*b = ut->blocks[tslot];
	d = b->data;
	dmax = d + ndst;

	/*
	 * set up the history blocks
	 */
	cseq = seq - src[0];
	cmask = src[1];
	b++;
	slot = tslot;
	while(cseq != seq && b < blocks + CompBlocks){
		slot--;
		if(slot < 0)
			slot += DWinBlocks;
		if(slot == ut->slot)
			break;
		bseq = ut->blocks[slot].seq;
		if(bseq == cseq){
			*b = ut->blocks[slot];
			b++;
			if(cmask == 0){
				cseq = seq;
				break;
			}
			do{
				bits = cmask & 1;
				cseq--;
				cmask >>= 1;
			}while(!bits);
		}
	}
	eblocks = b;
	if(cseq != seq){
		print("blocks not in decompression window: cseq=%d seq=%d cmask=%ux nb=%d\n", cseq, seq, cmask, eblocks - blocks);
		error("unthwack bad window");
	}

	utnbits = 0;
	utbits = 0;
	while(ut->src < ut->smax || ut->nbits >= MinDecode){
		while(utnbits < 9){
			if(ut->src >= ut->smax)
				error("unthwack eof");
			utbits <<= 8;
			utbits |= *ut->src++;
			utnbits += 8;
		}
		utnbits -= 9;
		off = (utbits >> utnbits) & ((1 << 9) - 1);

		bits = off >> 5;
		if(bits >= MaxOff){
			*d++ = off;
			blocks->maxoff++;
			continue;
		}
		off &= (1 << 5) - 1;
		if(bits){
			bits--;
			off |= 1 << 5;
		}
		bits += OffBase - 5;
		off <<= bits;

		while(utnbits < bits){
			if(ut->src >= ut->smax)
				error("unthwack eof");
			utbits <<= 8;
			utbits |= *ut->src++;
			utnbits += 8;
		}
		utnbits -= bits;
		off |= (utbits >> utnbits) & ((1 << bits) - 1);
		off++;

		len = 0;
		bits = 0;
		do{
			len <<= 1;
			if(utnbits < 1){
				if(ut->src >= ut->smax)
					error("unthwack eof");
				utbits <<= 8;
				utbits |= *ut->src++;
				utnbits += 8;
			}
			utnbits--;
			len |= (utbits >> utnbits) & 1;
			bits++;
		}while(len > lentab.maxcode[bits]);
		len = lentab.decode[lentab.last[bits] - len];

		if(len == MaxLen - 1){
			ut->nbits = utnbits;
			ut->bits = utbits;
			len += iomegaget(ut) - 1;
			utnbits = ut->nbits;
			utbits = ut->bits;
		}
		len += MinMatch;

		b = blocks;
		while(off > b->maxoff){
			off -= b->maxoff;
			b++;
			if(b >= eblocks)
				error("unthwack offset");
		}
		if(d + len > dmax
		|| b != blocks && len > off)
			error("unthwack len");
		s = b->data + b->maxoff - off;
		es = s + len;
		while(s < es)
			*d++ = *s++;
		blocks->maxoff += len;
	}

	len = d - blocks->data;
	memmove(dst, blocks->data, len);
	ut->blocks[tslot].maxoff = len;

	ut->slot++;
	if(ut->slot >= DWinBlocks)
		ut->slot = 0;

	poperror();
	return len;
}

/*
 * elias's omega code, modified
 * for at least 3 bit transmission
 */
static ulong
iomegaget(Unthwack *ut)
{
	ulong v;
	int b;

	v = bitget(ut, 3);
	if((v & 0x4) == 0)
		return v + 1;
	for(;;){
		b = bitget(ut, 1);
		if(b == 0)
			return v + 1;
		if(v > 16)
			break;
		v--;
		v = (b << v) | bitget(ut, v);
	}
	error("unthwack iomegaget");
	return ~0;
}

static ulong
bitget(Unthwack *ut, int nb)
{
	int c;

	while(ut->nbits < nb){
		if(ut->src >= ut->smax)
			error("unthwack eof");
		c = *ut->src++;
		ut->bits <<= 8;
		ut->bits |= c;
		ut->nbits += 8;
	}
	ut->nbits -= nb;
	return (ut->bits >> ut->nbits) & ((1 << nb) - 1);
}
.
## diffname port/unthwack.c 1999/1007
## diff -e /n/emeliedump/1999/1001/sys/src/brazil/port/unthwack.c /n/emeliedump/1999/1007/sys/src/brazil/port/unthwack.c
210,252d
208d
198a
	if(utnbits < overbits)
		return -1;
.
192c
			return -1;
.
188c
				return -1;
.
180a

.
174,179c
			code = len - BigLenCode;
			len = MaxFastLen;
			bits = 8;
			use = BigLenBase;
			while(code >= use){
				len += use;
				code -= use;
				code <<= 1;
				utnbits--;
				code |= (utbits >> utnbits) & 1;
				use <<= bits & 1;
				bits++;
			}
			len += code;
.
168,172d
165c
				if(src < smax)
					utbits |= *src++;
				else
					overbits += 8;
.
160,163c
			bits++;
			len = utbits >> (utnbits - bits);
		}while(bits < BigLenBits && len > lentab.maxcode[bits]);
		utnbits -= bits;

		if(bits < BigLenBits)
			len = lentab.decode[lentab.last[bits] - len];
		else{
			while(utnbits < MaxLenDecode){
.
158a
		utbits &= (1 << utnbits) - 1;
.
157d
146,152d
131a
		/*
		 * literal
		 */
.
126c
			if(src < smax)
				utbits |= *src++;
			else
				overbits += 8;
.
121,124c
	overbits = 0;
	while(src < smax || utnbits - overbits >= MinDecode){
		while(utnbits < MaxOffDecode + BigLenBits){
.
118a
	smax = src + nsrc;
	src += 2;
.
115,116c
		print("blocks not in decompression window: cseq=%ld seq=%ld cmask=%lux nb=%ld\n", cseq, seq, cmask, eblocks - blocks);
		return -1;
.
59,61d
56c
	if(nsrc < 4 || nsrc > ThwMaxBlock)
.
52,54c
	uchar *s, *es, *d, *dmax, *smax;
	ulong cmask, cseq, bseq, utbits;
	int off, len, bits, slot, tslot, use, code, utnbits, overbits;
.
45,47d
32,34d
28c
		6, 5,
		8, 7,
.
26c
		3, 2,
.
20,22c
/*	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},
.
13,15c
	ulong	maxcode[MaxFastLen];
	ulong	last[MaxFastLen];
	ulong	decode[MaxFastLen];
.
2c
#include "lib.h"
.
## diffname port/unthwack.c 1999/1022
## diff -e /n/emeliedump/1999/1007/sys/src/brazil/port/unthwack.c /n/emeliedump/1999/1022/sys/src/brazil/port/unthwack.c
142,144d
139,140c
			bits += OffBase - 1;
			off = 1 << bits;
		}else{
			bits = OffBase;
			off = 0;
.
137c

		/*
		 * match; next 3 bits decode offset range
		 */
		utnbits -= 4;
		bits = (utbits >> utnbits) & ((1 << 3) - 1);
.
131,133c
		if(((utbits >> (utnbits - 1)) & 1) == 0){
			if(lithist & 0xf){
				utnbits -= 9;
				lit = (utbits >> utnbits) & 0xff;
				lit &= 255;
			}else{
				utnbits -= 8;
				lit = (utbits >> utnbits) & 0x7f;
				if(lit < 32){
					if(lit < 24){
						utnbits -= 2;
						lit = (lit << 2) | ((utbits >> utnbits) & 3);
					}else{
						utnbits -= 3;
						lit = (lit << 3) | ((utbits >> utnbits) & 7);
					}
					lit = (lit - 64) & 0xff;
				}
			}
			*d++ = lit;
			lithist = (lithist << 1) | lit < 32 | lit > 127;
.
125,126d
117c
		while(utnbits <= 24){
.
115a
	lithist = ~0;
.
47,48c
	uchar *s, *es, *d, *dmax, *smax, lit;
	ulong cmask, cseq, bseq, utbits, lithist;
.
2c
#include "../port/lib.h"
.
## diffname port/unthwack.c 1999/1111
## diff -e /n/emeliedump/1999/1022/sys/src/brazil/port/unthwack.c /n/emeliedump/1999/1111/sys/src/9/port/unthwack.c
223a

		for(i = 0; i < len; i++)
			d[i] = s[i];
		d += len;
.
220,222d
208a
		utnbits -= bits;
		off |= (utbits >> utnbits) & ((1 << bits) - 1);
		off++;

.
207c
		/*
		 * offset
		 */
		utnbits -= 4;
		bits = (utbits >> utnbits) & 0xf;
		off = offbase[bits];
		bits = offbits[bits];
.
204a

			while(utnbits <= 24){
				utbits <<= 8;
				if(src < smax)
					utbits |= *src++;
				else
					overbits += 8;
				utnbits += 8;
			}
.
201,202c
				use <<= bits;
				bits ^= 1;
.
182,194c
			utnbits -= DBigLenBits;
			code = ((utbits >> utnbits) & ((1 << DBigLenBits) - 1)) - DBigLenCode;
			len = DMaxFastLen;
			use = DBigLenBase;
			bits = (DBigLenBits & 1) ^ 1;
.
158,180c
		if(len < 255)
			utnbits -= lenbits[len];
.
156c
		 * length
.
130c
		len = lenval[(utbits >> (utnbits - 5)) & 0x1f];
		if(len == 0){
.
107c
		print("blocks not in decompression window: cseq=%ld seq=%ld cmask=%lx nb=%ld\n", cseq, seq, cmask, eblocks - blocks);
.
67c
		ut->blocks[slot] = ut->blocks[tslot];
.
55,57c
	 * 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,
.
49c
	int i, off, len, bits, slot, tslot, use, code, utnbits, overbits;
.
47c
	uchar *s, *d, *dmax, *smax, lit;
.
43a
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
.
39c
	for(i = 0; i < DWinBlocks; i++)
.
32a
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
};

.
20,30c
	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
.
18c
static uchar lenval[1 << (DBigLenBits - 1)] =
.
13,15c
	DMaxFastLen	= 7,
	DBigLenCode	= 0x3c,		/* minimum code for large lenth encoding */
	DBigLenBits	= 6,
	DBigLenBase	= 1		/* starting items to encode for big lens */
.
11c
enum
.
9c
/*
 * don't include compressed blocks
 */
#define NOUNCOMP
.
2c
#include "lib.h"
.
## diffname port/unthwack.c 1999/1116
## diff -e /n/emeliedump/1999/1111/sys/src/9/port/unthwack.c /n/emeliedump/1999/1116/sys/src/9/port/unthwack.c
121c
		d = ut->blocks[tslot].data;
		ut->blocks[tslot] = ut->blocks[slot];
		ut->blocks[slot].data = d;
.
68,97d
9,13d
## diffname port/unthwack.c 2000/0912
## diff -e /n/emeliedump/1999/1116/sys/src/9/port/unthwack.c /n/emeliedump/2000/0912/sys/src/9/port/unthwack.c
192a
				if(utnbits < 0)
					return -1;
.
172c
			lithist = (lithist << 1) | (lit < 32) | (lit > 127);
.
## diffname port/unthwack.c 2001/0116
## diff -e /n/emeliedump/2000/0912/sys/src/9/port/unthwack.c /n/emeliedump/2001/0116/sys/src/9/port/unthwack.c
170a
			if(d >= dmax)
				return -1;
.
## diffname port/unthwack.c 2001/0214
## diff -e /n/emeliedump/2001/0116/sys/src/9/port/unthwack.c /n/emeliedump/2001/0214/sys/src/9/port/unthwack.c
249,251c
	unthwackinsert(ut, len, seq);
.
247d
128,129c
		print("blocks dropped: seq=%ld cseq=%ld %d cmask=%#lx %#x\n", seq, cseq, src[0], cmask, src[1]);
		return -2;
.
104d
93,94c
	ut->blocks[tslot].maxoff = len;

	ut->slot++;
	if(ut->slot >= DWinBlocks)
		ut->slot = 0;

	ut->blocks[ut->slot].seq = ~0UL;
	ut->blocks[ut->slot].maxoff = 0;

	return tslot;
}

int
unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
{
	UnthwBlock blocks[CompBlocks], *b, *eblocks;
	uchar *s, *d, *dmax, *smax, lit;
	ulong cmask, cseq, bseq, utbits;
	int i, off, len, bits, slot, use, code, utnbits, overbits, lithist;

	if(nsrc < 4 || nsrc > ThwMaxBlock)
		return -1;

	slot = ut->slot;
	b = blocks;
	*b = ut->blocks[slot];
.
91d
84c
		if(ut->blocks[slot].seq <= seq || ut->blocks[slot].maxoff == 0)
.
73,78c
/*
 * 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.
 */
static int
unthwackinsert(Unthwack *ut, int len, ulong seq)
{
	uchar *d;
	int slot, tslot;

.
70,71c
	seq = ~0UL;
	m = 0;
	slot = ut->slot;
	for(;;){
		slot--;
		if(slot < 0)
			slot += DWinBlocks;
		if(slot == ut->slot)
			break;
		if(ut->blocks[slot].maxoff == 0)
			continue;
		bseq = ut->blocks[slot].seq;
		if(seq == ~0UL)
			seq = bseq;
		else if(seq - bseq > MaxSeqMask)
			break;
		else
			m |= 1 << (seq - bseq - 1);
	}
	*mask = m;
	return seq;
}
.
65,68c
	ulong bseq, seq;
	int slot, m;
.
62,63c
ulong
unthwackstate(Unthwack *ut, uchar *mask)
.
## diffname port/unthwack.c 2001/0527
## diff -e /n/emeliedump/2001/0214/sys/src/9/port/unthwack.c /n/emeliedump/2001/0527/sys/src/9/port/unthwack.c
294c
	ut->slot++;
	if(ut->slot >= DWinBlocks)
		ut->slot = 0;
.
292a
	ut->blocks[tslot].maxoff = len;
.
217,218d
174,175c
		print("blocks not in decompression window: cseq=%ld seq=%ld cmask=%lx nb=%ld\n", cseq, seq, cmask, eblocks - blocks);
		return -1;
.
150a
	slot = tslot;
.
141c
	ut->blocks[tslot].seq = seq;
	ut->blocks[tslot].maxoff = 0;
	*b = ut->blocks[tslot];
.
115,139d
108c
		if(ut->blocks[slot].seq <= seq)
.
91,102c
	/*
	 * 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.
	 */
.
68,89c
	if(nsrc < 4 || nsrc > ThwMaxBlock)
		return -1;
.
65,66c
	UnthwBlock blocks[CompBlocks], *b, *eblocks;
	uchar *s, *d, *dmax, *smax, lit;
	ulong cmask, cseq, bseq, utbits, lithist;
	int i, off, len, bits, slot, tslot, use, code, utnbits, overbits;
.
62,63c
int
unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
.
## diffname port/unthwack.c 2001/0609
## diff -e /n/emeliedump/2001/0527/sys/src/9/port/unthwack.c /n/emeliedump/2001/0609/sys/src/9/port/unthwack.c
247,249c
	unthwackinsert(ut, len, seq);
.
245d
170a
			if(d >= dmax)
				return -1;
.
128,129c
		print("blocks dropped: seq=%ld cseq=%ld %d cmask=%#lx %#x\n", seq, cseq, src[0], cmask, src[1]);
		return -2;
.
104d
93,94c
	ut->blocks[tslot].maxoff = len;

	ut->slot++;
	if(ut->slot >= DWinBlocks)
		ut->slot = 0;

	ut->blocks[ut->slot].seq = ~0UL;
	ut->blocks[ut->slot].maxoff = 0;

	return tslot;
}

int
unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
{
	UnthwBlock blocks[CompBlocks], *b, *eblocks;
	uchar *s, *d, *dmax, *smax, lit;
	ulong cmask, cseq, bseq, utbits;
	int i, off, len, bits, slot, use, code, utnbits, overbits, lithist;

	if(nsrc < 4 || nsrc > ThwMaxBlock)
		return -1;

	slot = ut->slot;
	b = blocks;
	*b = ut->blocks[slot];
.
91d
84c
		if(ut->blocks[slot].seq <= seq || ut->blocks[slot].maxoff == 0)
.
73,78c
/*
 * 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.
 */
static int
unthwackinsert(Unthwack *ut, int len, ulong seq)
{
	uchar *d;
	int slot, tslot;

.
70,71c
	seq = ~0UL;
	m = 0;
	slot = ut->slot;
	for(;;){
		slot--;
		if(slot < 0)
			slot += DWinBlocks;
		if(slot == ut->slot)
			break;
		if(ut->blocks[slot].maxoff == 0)
			continue;
		bseq = ut->blocks[slot].seq;
		if(seq == ~0UL)
			seq = bseq;
		else if(seq - bseq > MaxSeqMask)
			break;
		else
			m |= 1 << (seq - bseq - 1);
	}
	*mask = m;
	return seq;
}
.
65,68c
	ulong bseq, seq;
	int slot, m;
.
62,63c
ulong
unthwackstate(Unthwack *ut, uchar *mask)
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].