From 5421ca19ea991e20f85902ecce808495883b16fa Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 11 Nov 1999 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1999-11-11 --- port/devsdp.c | 2 +- port/thwack.c | 89 +++++++++++++++-------- port/thwack.h | 12 ++-- port/unthwack.c | 186 ++++++++++++++++++++++++++++++------------------ 4 files changed, 182 insertions(+), 107 deletions(-) diff --git a/port/devsdp.c b/port/devsdp.c index 65959f564f5a19e7c737a2ae9a47783a391f6107..c711391345a0d4b1c9ea9e5114cb925514454209 100644 --- a/port/devsdp.c +++ b/port/devsdp.c @@ -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); diff --git a/port/thwack.c b/port/thwack.c index 70f6495aaa392346d739456679a11feba4b8a707..bc7935cf848621755b245cd1b0f22bbdca7fa447 100644 --- a/port/thwack.c +++ b/port/thwack.c @@ -1,13 +1,26 @@ #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, @@ -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; diff --git a/port/thwack.h b/port/thwack.h index 735b586d323433c323fea706b18c83232b858e7e..2d97e371999d8a7b736ee29a755d44e07b0132fb 100644 --- a/port/thwack.h +++ b/port/thwack.h @@ -8,25 +8,20 @@ enum ThwStats = 8, ThwMaxBlock = 1600, /* max size of compressible block */ - MinMatch = 3, /* shortest match possible */ HashLog = 12, HashSize = 1<= 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); diff --git a/port/unthwack.c b/port/unthwack.c index 651aad8c998d2c33e5b454fc3bfc54a017fb7834..7bd08accc20fbb2744e4b44a461b73f78e5831c9 100644 --- a/port/unthwack.c +++ b/port/unthwack.c @@ -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;