spdxl/src/deflate.c

1572 wiersze
39 KiB
C

/*
* dxlAPRS toolchain
*
* Copyright (C) Christian Rabler <oe5dxl@oevsv.at>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#define X2C_int32
#define X2C_index32
#ifndef deflate_H_
#include "deflate.h"
#endif
#define deflate_C_
#ifndef osi_H_
#include "osi.h"
#endif
/* data compressor simplified deflate-lz77 with low overhead for stream and blocks */
static uint32_t Hash(char a, char b, char c)
{
return (uint32_t)(uint8_t)a+131UL*(uint32_t)(uint8_t)
b+851UL*(uint32_t)(uint8_t)c&4095UL;
} /* end Hash() */
/* 131 831 */
extern void deflate_Initexpand(struct deflate_XCONTEXT * c)
{
uint32_t i;
for (i = 0UL; i<=32767UL; i++) {
c->ring[i] = 0;
} /* end for */
c->wp = 0UL;
c->rxbits = 0UL;
c->rxbitbuf = 0UL;
c->rawlen = 0L;
c->compdata = 0;
} /* end Initexpand() */
extern void deflate_Initdeflate(struct deflate_CONTEXT * c)
{
uint32_t i;
for (i = 0UL; i<=32767UL; i++) {
c->ring[i] = 0;
c->hashchain[i] = (uint16_t)i;
} /* end for */
for (i = 0UL; i<=4095UL; i++) {
c->hash[i] = 32768U;
} /* end for */
/* c.hash[0]:=HIGH(c.ring); */
c->wp = 0UL;
c->mlen = 0UL;
c->flen = 0UL;
c->savep = 32768UL;
c->rawr = 0UL;
c->comr = 0UL;
c->sizedif = -32L;
c->raww = 0UL;
c->comw = 0UL;
c->rawwo = 0UL;
c->txbitc = 0UL;
c->txbitbuf = 0UL;
c->wascomp = 0;
} /* end Initdeflate() */
/*
PROCEDURE Hashring(c-:CONTEXT; p:CARDINAL):INTEGER;
BEGIN RETURN Hash(c.ring[p], c.ring[(p+1) MOD BSIZE],
c.ring[(p+2) MOD BSIZE]) END Hashring;
*/
static void findmatch(struct deflate_CONTEXT * c, uint32_t * dist,
uint32_t * len)
{
uint32_t do0;
uint32_t d;
uint32_t i;
uint32_t rp;
uint32_t hp;
*len = 0UL;
do0 = 0UL;
if (c->lastidx>=32768UL) {
for (d = 2UL; d>=1UL; d--) {
/* search in 1 and 2 byte with no hash */
hp = (c->wp+32768UL)-d&32767UL;
i = 0UL;
rp = hp;
while (i<c->mlen && c->ring[rp]==c->matchbuf[i]) {
++i;
rp = rp+1UL&32767UL;
if (rp==c->wp) rp = hp;
}
if (i>=3UL) {
*len = i;
*dist = d;
}
if (i>=c->mlen) return;
} /* end for */
hp = (uint32_t)c->hash[Hash(c->matchbuf[0UL], c->matchbuf[1UL],
c->matchbuf[2UL])]; /* start hash chain */
}
else hp = c->lastidx;
if (hp>=32768UL) return;
/* no hash so no fitting 3 bytes */
for (;;) {
d = (c->wp+32768UL)-hp&32767UL; /* distance to ring write pointer */
if (d<=do0) break;
do0 = d;
if (c->ring[hp+*len&32767UL]==c->matchbuf[*len]) {
/* quick test to save cpu */
i = 0UL;
rp = hp;
while (i<c->mlen && c->ring[rp]==c->matchbuf[i]) {
/* compare strings */
++i;
rp = rp+1UL&32767UL;
if (rp==c->wp) rp = hp;
}
if (i>*len) {
/*& (d>=3)*/
/* new longest match */
*len = i;
*dist = d;
if (i>=c->mlen) {
c->lastidx = hp; /* continue at next search from here */
break;
}
}
}
hp = (uint32_t)c->hashchain[hp]; /* go on in hash chain */
}
} /* end findmatch() */
static void stohash(struct deflate_CONTEXT * c)
{
short hi;
uint32_t p;
p = c->wp+32765UL&32767UL;
hi = (short)Hash(c->ring[p], c->ring[p+1UL&32767UL],
c->ring[p+2UL&32767UL]);
if (c->hash[hi]<32768U) c->hashchain[p] = c->hash[hi];
c->hash[hi] = (uint16_t)p;
} /* end stohash() */
static void codelen(uint32_t len, uint32_t dist, uint32_t * clen,
uint32_t * nlen, uint32_t * dlen, uint32_t * nd)
{
switch (len) {
case 3UL:
case 4UL:
case 5UL:
case 6UL:
case 7UL:
case 8UL:
case 9UL:
case 10UL:
*clen = 7UL;
*nlen = len-2UL;
break;
case 11UL:
case 12UL:
case 13UL:
case 14UL:
case 15UL:
case 16UL:
case 17UL:
case 18UL:
*clen = 8UL;
*nlen = (9UL+(len-11UL)/2UL)*2UL+(len-11UL&1UL);
break;
case 19UL:
case 20UL:
case 21UL:
case 22UL:
case 23UL:
case 24UL:
case 25UL:
case 26UL:
case 27UL:
case 28UL:
case 29UL:
case 30UL:
case 31UL:
case 32UL:
case 33UL:
case 34UL:
*clen = 9UL;
*nlen = (13UL+(len-19UL)/4UL)*4UL+(len-19UL&3UL);
break;
case 35UL:
case 36UL:
case 37UL:
case 38UL:
case 39UL:
case 40UL:
case 41UL:
case 42UL:
case 43UL:
case 44UL:
case 45UL:
case 46UL:
case 47UL:
case 48UL:
case 49UL:
case 50UL:
case 51UL:
case 52UL:
case 53UL:
case 54UL:
case 55UL:
case 56UL:
case 57UL:
case 58UL:
case 59UL:
case 60UL:
case 61UL:
case 62UL:
case 63UL:
case 64UL:
case 65UL:
case 66UL:
*clen = 10UL;
*nlen = (17UL+(len-35UL)/8UL)*8UL+(len-35UL&7UL);
break;
case 67UL:
case 68UL:
case 69UL:
case 70UL:
case 71UL:
case 72UL:
case 73UL:
case 74UL:
case 75UL:
case 76UL:
case 77UL:
case 78UL:
case 79UL:
case 80UL:
case 81UL:
case 82UL:
case 83UL:
case 84UL:
case 85UL:
case 86UL:
case 87UL:
case 88UL:
case 89UL:
case 90UL:
case 91UL:
case 92UL:
case 93UL:
case 94UL:
case 95UL:
case 96UL:
case 97UL:
case 98UL:
case 99UL:
case 100UL:
case 101UL:
case 102UL:
case 103UL:
case 104UL:
case 105UL:
case 106UL:
case 107UL:
case 108UL:
case 109UL:
case 110UL:
case 111UL:
case 112UL:
case 113UL:
case 114UL:
*clen = 11UL;
*nlen = (21UL+(len-67UL)/16UL)*16UL+(len-67UL&15UL);
break;
case 115UL:
case 116UL:
case 117UL:
case 118UL:
case 119UL:
case 120UL:
case 121UL:
case 122UL:
case 123UL:
case 124UL:
case 125UL:
case 126UL:
case 127UL:
case 128UL:
case 129UL:
case 130UL:
*clen = 12UL;
*nlen = 3072UL+(len-115UL&15UL);
break;
case 131UL:
case 132UL:
case 133UL:
case 134UL:
case 135UL:
case 136UL:
case 137UL:
case 138UL:
case 139UL:
case 140UL:
case 141UL:
case 142UL:
case 143UL:
case 144UL:
case 145UL:
case 146UL:
case 147UL:
case 148UL:
case 149UL:
case 150UL:
case 151UL:
case 152UL:
case 153UL:
case 154UL:
case 155UL:
case 156UL:
case 157UL:
case 158UL:
case 159UL:
case 160UL:
case 161UL:
case 162UL:
case 163UL:
case 164UL:
case 165UL:
case 166UL:
case 167UL:
case 168UL:
case 169UL:
case 170UL:
case 171UL:
case 172UL:
case 173UL:
case 174UL:
case 175UL:
case 176UL:
case 177UL:
case 178UL:
case 179UL:
case 180UL:
case 181UL:
case 182UL:
case 183UL:
case 184UL:
case 185UL:
case 186UL:
case 187UL:
case 188UL:
case 189UL:
case 190UL:
case 191UL:
case 192UL:
case 193UL:
case 194UL:
case 195UL:
case 196UL:
case 197UL:
case 198UL:
case 199UL:
case 200UL:
case 201UL:
case 202UL:
case 203UL:
case 204UL:
case 205UL:
case 206UL:
case 207UL:
case 208UL:
case 209UL:
case 210UL:
case 211UL:
case 212UL:
case 213UL:
case 214UL:
case 215UL:
case 216UL:
case 217UL:
case 218UL:
case 219UL:
case 220UL:
case 221UL:
case 222UL:
case 223UL:
case 224UL:
case 225UL:
case 226UL:
case 227UL:
case 228UL:
case 229UL:
case 230UL:
case 231UL:
case 232UL:
case 233UL:
case 234UL:
case 235UL:
case 236UL:
case 237UL:
case 238UL:
case 239UL:
case 240UL:
case 241UL:
case 242UL:
case 243UL:
case 244UL:
case 245UL:
case 246UL:
case 247UL:
case 248UL:
case 249UL:
case 250UL:
case 251UL:
case 252UL:
case 253UL:
case 254UL:
case 255UL:
case 256UL:
case 257UL:
*clen = 13UL;
*nlen = (193UL+(len-131UL)/32UL)*32UL+(len-131UL&31UL);
break;
default:;
*clen = 8UL;
*nlen = 285UL;
break;
} /* end switch */
/*
CASE dist OF
1..4: dlen:=5; nd:=dist-1;
| 5..6: dlen:=6; nd:=4*2+(dist-5) MOD 2;
| 7..8: dlen:=6; nd:=5*2+(dist-7) MOD 2;
| 9..12: dlen:=7; nd:=6*4+(dist-9) MOD 4;
|13..16: dlen:=7; nd:=7*4+(dist-13) MOD 4;
|17..24: dlen:=8; nd:=8*8+(dist-17) MOD 8;
|25..32: dlen:=8; nd:=9*8+(dist-25) MOD 8;
|33..48: dlen:=9; nd:=10*16+(dist-33) MOD 16;
|49..64: dlen:=9; nd:=11*16+(dist-49) MOD 16;
|65..96: dlen:=10; nd:=12*32+(dist-65) MOD 32;
|97..128: dlen:=10; nd:=13*32+(dist-97) MOD 32;
|129..192: dlen:=11; nd:=14*64+(dist-129) MOD 64;
|193..256: dlen:=11; nd:=15*64+(dist-193) MOD 64;
|257..384: dlen:=12; nd:=16*128+(dist-257) MOD 128;
|385..512: dlen:=12; nd:=17*128+(dist-385) MOD 128;
|513..768: dlen:=13; nd:=18*256+(dist-513) MOD 256;
|769..1024: dlen:=13; nd:=19*256+(dist-769) MOD 256;
|1025..1536:dlen:=14; nd:=20*512+(dist-1025) MOD 512;
|1537..2048:dlen:=14; nd:=21*512+(dist-1537) MOD 512;
|2049..3072:dlen:=15; nd:=22*1024+(dist-2049) MOD 1024;
|3073..4096:dlen:=15; nd:=23*1024+(dist-3073) MOD 1024;
|4097..6144:dlen:=16; nd:=24*2048+(dist-4097) MOD 2048;
|6145..8192:dlen:=16; nd:=25*2048+(dist-6145) MOD 2048;
|8193..12288:dlen:=17; nd:=26*4096+(dist-8193) MOD 4096;
|12289..16384:dlen:=17; nd:=27*4096+(dist-12289) MOD 4096;
|16385..24576:dlen:=18; nd:=28*8192+(dist-16385) MOD 8192;
|24577..32768:dlen:=18; nd:=29*8192+(dist-24577) MOD 8192;
END;
*/
switch (dist) {
case 1UL:
case 2UL:
case 3UL:
case 4UL:
*dlen = 5UL;
*nd = dist-1UL;
break;
case 5UL:
case 6UL:
*dlen = 6UL;
*nd = 8UL+(dist-5UL&1UL);
break;
case 7UL:
case 8UL:
*dlen = 6UL;
*nd = 10UL+(dist-7UL&1UL);
break;
case 9UL:
case 10UL:
case 11UL:
case 12UL:
*dlen = 7UL;
*nd = 24UL+(dist-9UL&3UL);
break;
case 13UL:
case 14UL:
case 15UL:
case 16UL:
*dlen = 7UL;
*nd = 28UL+(dist-13UL&3UL);
break;
case 17UL:
case 18UL:
case 19UL:
case 20UL:
case 21UL:
case 22UL:
case 23UL:
case 24UL:
*dlen = 8UL;
*nd = 64UL+(dist-17UL&7UL);
break;
case 25UL:
case 26UL:
case 27UL:
case 28UL:
case 29UL:
case 30UL:
case 31UL:
case 32UL:
*dlen = 8UL;
*nd = 72UL+(dist-25UL&7UL);
break;
case 33UL:
case 34UL:
case 35UL:
case 36UL:
case 37UL:
case 38UL:
case 39UL:
case 40UL:
case 41UL:
case 42UL:
case 43UL:
case 44UL:
case 45UL:
case 46UL:
case 47UL:
case 48UL:
*dlen = 9UL;
*nd = 160UL+(dist-33UL&15UL);
break;
case 49UL:
case 50UL:
case 51UL:
case 52UL:
case 53UL:
case 54UL:
case 55UL:
case 56UL:
case 57UL:
case 58UL:
case 59UL:
case 60UL:
case 61UL:
case 62UL:
case 63UL:
case 64UL:
*dlen = 9UL;
*nd = 176UL+(dist-49UL&15UL);
break;
case 65UL:
case 66UL:
case 67UL:
case 68UL:
case 69UL:
case 70UL:
case 71UL:
case 72UL:
case 73UL:
case 74UL:
case 75UL:
case 76UL:
case 77UL:
case 78UL:
case 79UL:
case 80UL:
case 81UL:
case 82UL:
case 83UL:
case 84UL:
case 85UL:
case 86UL:
case 87UL:
case 88UL:
case 89UL:
case 90UL:
case 91UL:
case 92UL:
case 93UL:
case 94UL:
case 95UL:
case 96UL:
*dlen = 10UL;
*nd = 384UL+(dist-65UL&31UL);
break;
case 97UL:
case 98UL:
case 99UL:
case 100UL:
case 101UL:
case 102UL:
case 103UL:
case 104UL:
case 105UL:
case 106UL:
case 107UL:
case 108UL:
case 109UL:
case 110UL:
case 111UL:
case 112UL:
case 113UL:
case 114UL:
case 115UL:
case 116UL:
case 117UL:
case 118UL:
case 119UL:
case 120UL:
case 121UL:
case 122UL:
case 123UL:
case 124UL:
case 125UL:
case 126UL:
case 127UL:
case 128UL:
*dlen = 10UL;
*nd = 416UL+(dist-97UL&31UL);
break;
case 129UL:
case 130UL:
case 131UL:
case 132UL:
case 133UL:
case 134UL:
case 135UL:
case 136UL:
case 137UL:
case 138UL:
case 139UL:
case 140UL:
case 141UL:
case 142UL:
case 143UL:
case 144UL:
case 145UL:
case 146UL:
case 147UL:
case 148UL:
case 149UL:
case 150UL:
case 151UL:
case 152UL:
case 153UL:
case 154UL:
case 155UL:
case 156UL:
case 157UL:
case 158UL:
case 159UL:
case 160UL:
case 161UL:
case 162UL:
case 163UL:
case 164UL:
case 165UL:
case 166UL:
case 167UL:
case 168UL:
case 169UL:
case 170UL:
case 171UL:
case 172UL:
case 173UL:
case 174UL:
case 175UL:
case 176UL:
case 177UL:
case 178UL:
case 179UL:
case 180UL:
case 181UL:
case 182UL:
case 183UL:
case 184UL:
case 185UL:
case 186UL:
case 187UL:
case 188UL:
case 189UL:
case 190UL:
case 191UL:
case 192UL:
*dlen = 11UL;
*nd = 896UL+(dist-129UL&63UL);
break;
case 193UL:
case 194UL:
case 195UL:
case 196UL:
case 197UL:
case 198UL:
case 199UL:
case 200UL:
case 201UL:
case 202UL:
case 203UL:
case 204UL:
case 205UL:
case 206UL:
case 207UL:
case 208UL:
case 209UL:
case 210UL:
case 211UL:
case 212UL:
case 213UL:
case 214UL:
case 215UL:
case 216UL:
case 217UL:
case 218UL:
case 219UL:
case 220UL:
case 221UL:
case 222UL:
case 223UL:
case 224UL:
case 225UL:
case 226UL:
case 227UL:
case 228UL:
case 229UL:
case 230UL:
case 231UL:
case 232UL:
case 233UL:
case 234UL:
case 235UL:
case 236UL:
case 237UL:
case 238UL:
case 239UL:
case 240UL:
case 241UL:
case 242UL:
case 243UL:
case 244UL:
case 245UL:
case 246UL:
case 247UL:
case 248UL:
case 249UL:
case 250UL:
case 251UL:
case 252UL:
case 253UL:
case 254UL:
case 255UL:
case 256UL:
*dlen = 11UL;
*nd = 960UL+(dist-193UL&63UL);
break;
default:;
if (dist<=384UL) {
*dlen = 12UL;
*nd = 2048UL+(dist-257UL&127UL);
}
else if (dist<=512UL) {
*dlen = 12UL;
*nd = 2176UL+(dist-385UL&127UL);
}
else if (dist<=768UL) {
*dlen = 13UL;
*nd = 4608UL+(dist-513UL&255UL);
}
else if (dist<=1024UL) {
*dlen = 13UL;
*nd = 4864UL+(dist-769UL&255UL);
}
else if (dist<=1536UL) {
*dlen = 14UL;
*nd = 10240UL+(dist-1025UL&511UL);
}
else if (dist<=2048UL) {
*dlen = 14UL;
*nd = 10752UL+(dist-1537UL&511UL);
}
else if (dist<=3072UL) {
*dlen = 15UL;
*nd = 22528UL+(dist-2049UL&1023UL);
}
else if (dist<=4096UL) {
*dlen = 15UL;
*nd = 23552UL+(dist-3073UL&1023UL);
}
else if (dist<=6144UL) {
*dlen = 16UL;
*nd = 49152UL+(dist-4097UL&2047UL);
}
else if (dist<=8192UL) {
*dlen = 16UL;
*nd = 51200UL+(dist-6145UL&2047UL);
}
else if (dist<=12288UL) {
*dlen = 17UL;
*nd = 106496UL+(dist-8193UL&4095UL);
}
else if (dist<=16384UL) {
*dlen = 17UL;
*nd = 110592UL+(dist-12289UL&4095UL);
}
else if (dist<=24576UL) {
*dlen = 18UL;
*nd = 229376UL+(dist-16385UL&8191UL);
}
else {
*dlen = 18UL;
*nd = 237568UL+(dist-24577UL&8191UL);
}
break;
} /* end switch */
} /* end codelen() */
static void txbits(struct deflate_CONTEXT * c, uint32_t b, uint32_t len,
char dbuf[], uint32_t dbuf_len, int32_t * outlen)
{
/* c.txbitbuf:=c.txbitbuf<<len + b; */
c->txbitbuf = (uint32_t)X2C_LSH((uint32_t)c->txbitbuf,32,
(int32_t)len)+b;
c->txbitc += len;
if (len==0UL) {
/* flush */
while (c->txbitc&7UL) {
/* fill zero to full byte */
++c->txbitc;
c->txbitbuf = c->txbitbuf*2UL;
}
}
/* c.txbitc:=0; */
/*WrStrLn("txbit-flush"); */
if (*outlen>=0L) {
while (c->txbitc>=8UL) {
dbuf[*outlen] = (char)(uint32_t)X2C_LSH((uint32_t)
c->txbitbuf,32,8L-(int32_t)c->txbitc);
++*outlen;
if (*outlen>(int32_t)(dbuf_len-1)) *outlen = -2L;
c->txbitc -= 8UL;
}
}
} /* end txbits() */
static void wrrawblock(struct deflate_CONTEXT * c, char dbuf[],
uint32_t dbuf_len, int32_t * outlen)
{
uint32_t b;
uint32_t n;
uint32_t i;
uint32_t tmp;
txbits(c, 1UL, 1UL, dbuf, dbuf_len, outlen); /* switch to raw */
if (c->txbitc==0UL) b = 8UL;
else b = 16UL-c->txbitc;
n = (c->rawwo+32768UL)-c->rawr&32767UL;
i = 1UL;
/* i:=i<<b; */
i = (uint32_t)X2C_LSH(0x1UL,32,(int32_t)b);
if (i<n) n = i;
txbits(c, n-1UL, b, dbuf, dbuf_len, outlen);
tmp = n-1UL;
i = 0UL;
if (i<=tmp) for (;; i++) {
/* send all raw data */
txbits(c, (uint32_t)(uint8_t)c->ring[c->rawr], 8UL, dbuf, dbuf_len,
outlen);
c->rawr = c->rawr+1UL&32767UL;
if (i==tmp) break;
} /* end for */
} /* end wrrawblock() */
static void wrcomp(struct deflate_CONTEXT * c, char dbuf[],
uint32_t dbuf_len, int32_t * outlen)
{
uint32_t dl;
uint32_t ll;
uint32_t d;
uint32_t l;
uint32_t dist;
uint32_t len;
while (c->comr!=c->comw) {
/* send all compressed data */
len = c->combuf[c->comr]&65535UL;
dist = c->combuf[c->comr]/65536UL;
if (dist>0UL) codelen(len, dist, &ll, &l, &dl, &d);
else if (len<144UL) {
ll = 8UL;
l = len+48UL;
}
else if (len<256UL) {
/*WrStr("(");WrStr(CHR(len));WrStr(")"); */
ll = 9UL;
l = len+256UL;
}
else if (len==256UL) {
ll = 7UL;
l = 0UL;
}
else {
ll = 8UL;
l = len+192UL;
}
/*IF dist>0 THEN WrStr("L(");WrInt(len,1);ELSE WrStr("C(");
WrHex(len,1); END; WrStr(")"); */
txbits(c, l, ll, dbuf, dbuf_len, outlen);
if (dist>0UL) {
/*WrStr("D(");WrInt(dist,1);WrStr(")"); */
txbits(c, d, dl, dbuf, dbuf_len, outlen);
}
c->comr = c->comr+1UL&2047UL;
}
} /* end wrcomp() */
static void endcomp(struct deflate_CONTEXT * c, char finish,
char dbuf[], uint32_t dbuf_len, int32_t * outlen)
{
txbits(c, 0UL, 7UL, dbuf, dbuf_len, outlen);
if (finish) txbits(c, 0UL, 1UL, dbuf, dbuf_len, outlen);
/* c.savep:=BSIZE; */
/* c.mlen:=0; */
/* txbits(c, 1, 1); */
} /* end endcomp() */
static void checkbufs(struct deflate_CONTEXT * c, char flush,
char dbuf[], uint32_t dbuf_len, int32_t * outlen)
{
/*WrStr("(");WrInt(c.sizedif, 1);WrStr(")"); */
if (c->sizedif>=0L) {
/* compressed state or compare */
if (!c->wascomp) {
while (c->rawr!=c->rawwo) wrrawblock(c, dbuf, dbuf_len, outlen);
txbits(c, 0UL, 1UL, dbuf, dbuf_len, outlen);
/* switch to compressed */
/*WrStrLn("");WrStrLn(" TOCOMP "); */
c->wascomp = 1;
c->sizedif = 32L;
}
if (c->sizedif>=32L || ((c->comw+2048UL)-c->comr&2047UL)>=1791UL) {
wrcomp(c, dbuf, dbuf_len, outlen); /* send all compressed data */
c->rawr = c->raww; /* delete all raw data */
c->rawwo = c->raww;
c->sizedif = 32L;
}
if (flush) {
wrcomp(c, dbuf, dbuf_len, outlen); /* send all comprssed data */
endcomp(c, flush=='\002', dbuf, dbuf_len, outlen);
}
}
else {
/*WrStrLn("-endcomp-"); WrInt(sum DIV 8, 12); WrInt(sum1, 12);
WrStrLn(""); */
/* uncompressed state or compare */
if (c->wascomp) {
endcomp(c, 0, dbuf, dbuf_len, outlen);
/*WrStrLn("");WrStrLn(" TORAW "); */
c->wascomp = 0;
c->sizedif = -32L;
}
if (c->sizedif<=-32L || ((c->raww+32768UL)-c->rawr&32767UL)>=16384UL) {
/* uncompressed */
c->rawwo = c->raww; /* undeletable to raw buffer */
while (((c->rawwo+32768UL)-c->rawr&32767UL)>=16384UL) {
wrrawblock(c, dbuf, dbuf_len, outlen);
}
c->comr = c->comw; /* delete all compressd data */
c->sizedif = -32L;
}
if (flush) {
c->comr = c->comw; /* delete all compressd data */
c->rawwo = c->raww;
while (c->rawr!=c->rawwo) wrrawblock(c, dbuf, dbuf_len, outlen);
if (flush=='\002') {
/* with EOF */
txbits(c, 0UL, 1UL, dbuf, dbuf_len, outlen);
/* switch to compressed */
endcomp(c, 0, dbuf, dbuf_len, outlen);
/* zero data compressed is EOF*/
}
}
}
/* c.comr:=c.comw; */
} /* end checkbufs() */
static void sendchar(struct deflate_CONTEXT * c, char dbuf[],
uint32_t dbuf_len, int32_t * outlen)
{
uint32_t code;
code = (uint32_t)(uint8_t)c->ring[c->savep];
c->combuf[c->comw] = code;
c->comw = c->comw+1UL&2047UL;
c->raww = c->savep+1UL&32767UL;
if (code>143UL) --c->sizedif;
checkbufs(c, 0, dbuf, dbuf_len, outlen);
} /* end sendchar() */
static void send(struct deflate_CONTEXT * c, uint32_t len, uint32_t dist,
char dbuf[], uint32_t dbuf_len, int32_t * outlen)
{
uint32_t nl;
uint32_t nd;
uint32_t dlen;
uint32_t clen;
uint32_t p1;
uint32_t p0;
uint32_t p;
checkbufs(c, 0, dbuf, dbuf_len, outlen);
c->combuf[c->comw] = len+65536UL*dist;
c->comw = c->comw+1UL&2047UL;
codelen(len, dist, &clen, &nl, &dlen, &nd);
p0 = c->wp+(32768UL-dist)&32767UL;
p = p0;
p1 = c->wp;
while (len>0UL) {
c->ring[c->wp] = c->ring[p];
c->wp = c->wp+1UL&32767UL;
stohash(c);
c->sizedif += 8L;
/*WrBin(1, c.ring[p], 1); */
c->raww = c->wp;
p = p+1UL&32767UL;
if (p==p1) p = p0;
--len;
}
c->sizedif -= (int32_t)(clen+dlen);
} /* end send() */
extern void deflate_Deflatbyte(struct deflate_CONTEXT * c, char ch,
char flush, char dbuf[], uint32_t dbuf_len,
int32_t * outlen)
/* 1C send no blockend, 2C send it */
{
uint32_t len;
uint32_t dist;
uint32_t i;
uint32_t tmp;
if (flush==0) {
c->matchbuf[c->mlen] = ch;
++c->mlen;
}
/*WrStr("{");WrInt(c.mlen, 1);WrStr("}"); */
for (;;) {
if (c->mlen<3UL) {
c->lastidx = 32768UL;
break;
}
findmatch(c, &dist, &len);
if (len==c->mlen) {
/* match found */
if (c->savep<32768UL) {
stohash(c);
sendchar(c, dbuf, dbuf_len, outlen);
c->savep = 32768UL;
c->flen = len;
c->fdist = dist;
}
else {
c->flen = len;
c->fdist = dist;
}
if (c->mlen>=257UL || flush) {
/* no longer match allowed so send it now */
send(c, c->flen, c->fdist, dbuf, dbuf_len, outlen);
c->mlen = 0UL;
c->flen = 0UL;
}
break;
}
/* no match found */
c->lastidx = 32768UL;
if (c->savep<32768UL) {
/* send old variante */
if (c->flen>0UL) {
c->wp = c->wp+32767UL&32767UL;
/* restore ring to 1 char before */
send(c, c->flen, c->fdist, dbuf, dbuf_len, outlen);
c->matchbuf[0UL] = c->matchbuf[c->mlen-1UL];
/* not found last char */
c->mlen = 1UL;
c->flen = 0UL;
c->savep = 32768UL;
}
else {
stohash(c);
sendchar(c, dbuf, dbuf_len, outlen);
c->savep = 32768UL;
}
}
else {
c->ring[c->wp] = c->matchbuf[0UL];
c->savep = c->wp; /* remove first char */
c->wp = c->wp+1UL&32767UL;
tmp = c->mlen-1UL;
i = 1UL;
if (i<=tmp) for (;; i++) {
c->matchbuf[i-1UL] = c->matchbuf[i];
if (i==tmp) break;
} /* end for */
--c->mlen;
}
}
if (flush) {
if (c->savep<32768UL) {
/* send first char of string */
stohash(c);
sendchar(c, dbuf, dbuf_len, outlen);
c->savep = 32768UL;
}
tmp = c->mlen;
i = 1UL;
if (i<=tmp) for (;; i++) {
/* send rest of string */
c->ring[c->wp] = c->matchbuf[i-1UL];
c->savep = c->wp;
c->wp = c->wp+1UL&32767UL;
stohash(c);
sendchar(c, dbuf, dbuf_len, outlen);
if (i==tmp) break;
} /* end for */
/* wrcomp(c, dbuf, outlen);
(* send all comprssed data *) */
c->mlen = 0UL;
checkbufs(c, flush, dbuf, dbuf_len, outlen);
txbits(c, 0UL, 0UL, dbuf, dbuf_len, outlen); /* send remaining bits */
c->wascomp = 0;
c->flen = 0UL;
/* c.comr:=c.comw; */
c->savep = 32768UL;
}
/* c.sizedif:=0; */
/*WrStrLn(""); */
/*FOR i:=0 TO HIGH(c.ring) DO WrStr(c.ring[i]) END; WrStrLn(""); */
} /* end Deflatbyte() */
static void xsend(struct deflate_XCONTEXT * c, char ch, char dbuf[],
uint32_t dbuf_len, int32_t * outlen)
{
if (*outlen<0L || *outlen>(int32_t)(dbuf_len-1)) *outlen = -1L;
else {
c->ring[c->wp] = ch;
c->wp = c->wp+1UL&32767UL;
dbuf[*outlen] = ch;
++*outlen;
}
} /* end xsend() */
/*
PROCEDURE Expandbyte(VAR c:XCONTEXT; ch:CHAR; flush:BOOLEAN;
VAR dbuf:ARRAY OF CHAR; VAR outlen:INTEGER;
VAR done:BOOLEAN);
CONST DISTAB=ARRAY OF CARDINAL {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,
257,385,513,
769,1025,1537,2049,3073,4097,6145,8193,12289,
16385,24577,0,0};
LENTAB=ARRAY OF CARDINAL {0,3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,
35,43,51,
59,67,83,99,115,131,163,195,227,285,0,0};
VAR i, n, dist:CARDINAL;
BEGIN
--WrStr("!"); wh(ch);WrStr("!");
<* IF DEB THEN *>
WrHex(sum3, 5);WrStr("H");
INC(sum3);
<* END *>
c.rxbitbuf:=c.rxbitbuf*256 + ORD(ch);
INC(c.rxbits, 8);
done:=FALSE;
WHILE (c.rxbits>=20) OR flush DO
-- i:=1;
-- c.rxbitbuf:=c.rxbitbuf MOD (i<<c.rxbits);
-- c.rxbitbuf:=CAST(CARD32, CAST(SET32, c.rxbitbuf) * CAST(SET32,
CAST(CARD32,SHIFT(CAST(SET32, i), VAL(INTEGER,
c.rxbits)))-1));
c.rxbitbuf:=CAST(CARD32, CAST(SET32, c.rxbitbuf) * SHIFT(SET32{0..31}
, VAL(INTEGER, c.rxbits)-32));
<* IF DEB THEN *>
WrStr(" ["); WrInt(c.rxbits, 1);WrStr(",");WrHex(c.rxbitbuf,1);WrStr("]");
<* END *>
IF flush & (c.rxbits<20) THEN (* append zeros as end of data *)
c.rxbitbuf:=c.rxbitbuf*256;
INC(c.rxbits, 8);
END;
IF c.rawlen>0 THEN (* in uncompressed mode *)
--WrStr("[");WrInt(c.rawlen, 1);WrStr("]");
-- ch:=CHR(c.rxbitbuf>>(c.rxbits-8));
ch:=CHR(CAST(CARD32, SHIFT(CAST(SET32, c.rxbitbuf), 8-VAL(INTEGER,
c.rxbits))));
DEC(c.rxbits, 8);
xsend(c, ch, dbuf, outlen);
DEC(c.rawlen);
ELSIF c.compmod=1C THEN (* get lengh word *)
-- IF c.rxbitbuf>>(c.rxbits-7)<24 THEN
IF CAST(CARD32, SHIFT(CAST(SET32, c.rxbitbuf), 7-VAL(INTEGER,
c.rxbits)))<24 THEN
c.lencode:=CAST(CARD32, SHIFT(CAST(SET32, c.rxbitbuf), 7-VAL(INTEGER,
c.rxbits)));
-- c.lencode:=c.rxbitbuf>>(c.rxbits-7);
DEC(c.rxbits, 7);
<* IF DEB THEN *>
WrInt(c.lencode,3);WrStr("=LENC ");
<* END *>
IF c.lencode=ENDCOMP-256 THEN (* end of compressed data *)
<* IF DEB THEN *>
WrStrLn("ENDCOMP");
<* END *>
IF c.justcomp THEN
<* IF DEB THEN *>
WrStrLn("QUICKENDCOMP");
<* END *>
done:=TRUE;
WrStrLn(" LIBDONE2 ");
c.compmod:=0C;
c.justcomp:=FALSE;
flush:=FALSE;
ELSE c.compmod:=3C END;
ELSE (* get distance word *)
c.compmod:=2C;
c.justcomp:=FALSE;
END;
-- ELSIF c.rxbitbuf>>(c.rxbits-8)<192 THEN (* literal <144 *)
ELSIF CAST(CARD32, SHIFT(CAST(SET32, c.rxbitbuf), 8-VAL(INTEGER,
c.rxbits)))<192 THEN (* literal <144 *)
--WrHex(c.rxbitbuf>>(c.rxbits-8)-48,4);WrStr(",");WrInt(c.rxbits,1);
WrStr(",");WrInt(ORD(flush),1);WrStr("=LITC ");
--WrStr("<(");WrHex(c.rxbitbuf>>(c.rxbits-8)-48,1); WrStr(")>");
xsend(c, CHR(CAST(CARD32, SHIFT(CAST(SET32, c.rxbitbuf),
8-VAL(INTEGER, c.rxbits)))-48), dbuf, outlen);
DEC(c.rxbits, 8);
c.justcomp:=FALSE;
ELSIF CAST(CARD32, SHIFT(CAST(SET32, c.rxbitbuf), 8-VAL(INTEGER,
c.rxbits)))<200 THEN (* len *)
c.lencode:=CAST(CARD32, SHIFT(CAST(SET32, c.rxbitbuf), 8-VAL(INTEGER,
c.rxbits))) - (192-24);
DEC(c.rxbits, 8);
c.compmod:=2C; (* get distance word *)
c.justcomp:=FALSE;
--WrInt(c.lencode,3);WrStr("=LENCC ");
ELSE (* literal >=144 *)
c.justcomp:=FALSE;
--WrStr("<[");WrHex(c.rxbitbuf>>(c.rxbits-9)-(400-144),1); WrStr("]>");
xsend(c, CHR(CAST(CARD32, SHIFT(CAST(SET32, c.rxbitbuf),
9-VAL(INTEGER, c.rxbits)))-(400-144)), dbuf, outlen);
DEC(c.rxbits, 9);
c.compmod:=1C;
END;
IF c.compmod=2C THEN
IF c.lencode>=9 THEN (* get extra length bits *)
-- i:=1;
-- c.rxbitbuf:=c.rxbitbuf MOD (i<<c.rxbits);
c.rxbitbuf:=CAST(CARD32, CAST(SET32,
c.rxbitbuf) * SHIFT(SET32{0..31}
, VAL(INTEGER, c.rxbits)-32));
n:=(c.lencode-5) DIV 4; (* bit count *)
-- c.lencode:=LENTAB[c.lencode] + c.rxbitbuf>>(VAL(CARDINAL,
c.rxbits)-n);
c.lencode:=LENTAB[c.lencode] + CAST(CARD32, SHIFT(CAST(SET32,
c.rxbitbuf), VAL(INTEGER, n)-VAL(INTEGER, c.rxbits)));
DEC(c.rxbits, n);
ELSE c.lencode:=LENTAB[c.lencode] END;
END;
--WrInt(c.lencode,4);WrStr("=LEN ");
ELSIF c.compmod=2C THEN (* get lengh word *)
-- dist:=c.rxbitbuf>>(c.rxbits-5); (* fixed 5 bit of distance *)
dist:=CAST(CARD32, SHIFT(CAST(SET32, c.rxbitbuf), 5-VAL(INTEGER,
c.rxbits)));
--WrInt(dist,3);WrStr("=DIST5 ");
DEC(c.rxbits, 5);
IF dist>=4 THEN
-- i:=1;
-- c.rxbitbuf:=c.rxbitbuf MOD (i<<c.rxbits);
c.rxbitbuf:=CAST(CARD32, CAST(SET32, c.rxbitbuf) * SHIFT(SET32{0..31}
, VAL(INTEGER, c.rxbits)-32));
n:=dist DIV 2-1; (* bit count extra bits *)
-- dist:=DISTAB[dist] + c.rxbitbuf>>(VAL(CARDINAL,c.rxbits)-n);
dist:=DISTAB[dist] + CAST(CARD32, SHIFT(CAST(SET32, c.rxbitbuf),
VAL(INTEGER, n)-VAL(INTEGER, c.rxbits)));
DEC(c.rxbits, n);
ELSE INC(dist) END;
<* IF DEB THEN *>
WrInt(dist,3);WrStr("=DIST ");WrStrLn("");
<* END *>
IF c.lencode<3 THEN outlen:=-2 END; (* decode error *)
n:=c.wp;
i:=(n+BSIZE-dist) MOD BSIZE; (* start in ring *)
WHILE c.lencode>0 DO
--WrStr("<<");WrHex(ORD(c.ring[i]),1);WrStr(">>");
xsend(c, c.ring[i], dbuf, outlen); (* copy string *)
i:=(i+1) MOD BSIZE;
IF i=n THEN i:=(n+BSIZE-dist) MOD BSIZE END; (* looping string *)
DEC(c.lencode);
--WrInt(c.lencode, 15);
END;
--WrStr("=LOOPEND= "); WrStrLn("");
c.compmod:=1C;
ELSIF NOT c.justcomp & ODD(CAST(CARD32, SHIFT(CAST(SET32, c.rxbitbuf),
1-VAL(INTEGER, c.rxbits)))) THEN (* switch to raw *)
<* IF DEB THEN *>
WrStrLn("");WrStrLn("TORAW");
<* END *>
DEC(c.rxbits);
-- i:=1;
-- c.rxbitbuf:=c.rxbitbuf MOD (i<<c.rxbits);
c.rxbitbuf:=CAST(CARD32, CAST(SET32, c.rxbitbuf) * SHIFT(SET32{0..31}
, VAL(INTEGER, c.rxbits)-32));
n:=8+VAL(CARDINAL, c.rxbits) MOD 8;
-- c.rawlen:=c.rxbitbuf>>(VAL(CARDINAL,c.rxbits)-n)+1;
c.rawlen:=CAST(CARD32, SHIFT(CAST(SET32, c.rxbitbuf), VAL(INTEGER,
n)-VAL(INTEGER, c.rxbits)))+1;
<* IF DEB THEN *>
WrHex(c.rawlen,9);WrStr("=RLEH ");
<* END *>
DEC(c.rxbits, n);
c.compmod:=0C;
ELSE (* switch to compressed *)
IF NOT c.justcomp OR (c.compmod<>3C) THEN
<* IF DEB THEN *>
WrStrLn("");WrStrLn("DEC1");
<* END *>
DEC(c.rxbits);
END;
c.justcomp:=TRUE;
<* IF DEB THEN *>
WrStrLn("");WrStrLn("TOCOMP");
<* END *>
IF c.compmod=3C THEN (* end of compressed and got to compressed is EOF *)
<* IF DEB THEN *>
WrStrLn("");WrStrLn("DATAEND");
<* END *>
flush:=FALSE;
<* IF DEB THEN *>
th(c, 0C);
<* END *>
c.rxbits:=((c.rxbits+1) DIV 8)*8;
<* IF DEB THEN *>
th(c, 0C);
<* END *>
done:=TRUE;
WrStrLn(" LIBDONE1 ");
c.compmod:=0C;
ELSE c.compmod:=1C END;
END;
END;
END Expandbyte;
*/
static uint32_t deflate_DISTAB[32] = {1UL,2UL,3UL,4UL,5UL,7UL,9UL,13UL,
17UL,25UL,33UL,49UL,65UL,97UL,129UL,193UL,257UL,385UL,513UL,
769UL,1025UL,1537UL,2049UL,3073UL,4097UL,6145UL,8193UL,
12289UL,16385UL,24577UL,0UL,0UL};
static uint32_t deflate_LENTAB[32] = {0UL,3UL,4UL,5UL,6UL,7UL,8UL,9UL,10UL,
11UL,13UL,15UL,17UL,19UL,23UL,27UL,31UL,35UL,43UL,51UL,59UL,
67UL,83UL,99UL,115UL,131UL,163UL,195UL,227UL,285UL,0UL,0UL};
static void copystr(char dbuf[], uint32_t dbuf_len, int32_t * outlen,
struct deflate_XCONTEXT * c)
{
uint32_t n;
uint32_t i;
if (c->lencode<3UL) *outlen = -2L;
n = c->wp;
i = (n+32768UL)-c->distcode&32767UL; /* start in ring */
while (c->lencode>0UL) {
xsend(c, c->ring[i], dbuf, dbuf_len, outlen); /* copy string */
i = i+1UL&32767UL;
if (i==n) i = (n+32768UL)-c->distcode&32767UL;
--c->lencode;
}
} /* end copystr() */
static uint32_t _cnst0[32] = {1UL,2UL,3UL,4UL,5UL,7UL,9UL,13UL,17UL,25UL,
33UL,49UL,65UL,97UL,129UL,193UL,257UL,385UL,513UL,769UL,
1025UL,1537UL,2049UL,3073UL,4097UL,6145UL,8193UL,12289UL,
16385UL,24577UL,0UL,0UL};
static uint32_t _cnst[32] = {0UL,3UL,4UL,5UL,6UL,7UL,8UL,9UL,10UL,11UL,
13UL,15UL,17UL,19UL,23UL,27UL,31UL,35UL,43UL,51UL,59UL,67UL,
83UL,99UL,115UL,131UL,163UL,195UL,227UL,285UL,0UL,0UL};
extern void deflate_Expandbyte(struct deflate_XCONTEXT * c, char ch,
char dbuf[], uint32_t dbuf_len, int32_t * outlen,
char * done)
{
uint32_t w;
uint32_t n;
c->rxbitbuf = c->rxbitbuf*256UL+(uint32_t)(uint8_t)ch;
/* append new bits */
c->rxbits += 8UL;
*done = 0;
for (;;) {
c->rxbitbuf = (uint32_t)((uint32_t)
c->rxbitbuf&X2C_LSH(0xFFFFFFFFUL,32,
(int32_t)c->rxbits-32L)); /* strip old bits */
if (c->rawlen==0L) n = 1UL;
else if (c->rawlen==-1L) {
/* get raw len */
n = 8UL+(c->rxbits&7UL);
}
else if (c->rawlen==-2L) n = 7UL;
else if (c->rawlen==-3L) n = 8UL;
else if (c->rawlen==-4L) n = 9UL;
else if (c->rawlen==-5L) {
/* get extra len bits */
n = (c->lencode-5UL)/4UL; /* bit count */
}
else if (c->rawlen==-6L) n = 5UL;
else if (c->rawlen==-7L) {
/* get extra dist code */
n = c->distcode/2UL-1UL; /* bit count extra bits */
}
else n = 8UL;
if (c->rxbits<n) break;
w = (uint32_t)X2C_LSH((uint32_t)c->rxbitbuf,32,
(int32_t)n-(int32_t)c->rxbits);
if (c->rawlen>0L) {
/* in uncompressed mode */
xsend(c, (char)w, dbuf, dbuf_len, outlen);
--c->rawlen;
c->rxbits -= 8UL;
}
else if (c->rawlen==0L) {
/* comp or raw mode bit */
--c->rxbits;
if (w==1UL) c->rawlen = -1L;
else {
if (c->compdata) {
/* was in compressed go to compressed is EOF */
*done = 1;
c->compdata = 0;
c->rawlen = 0L;
c->rxbits = 0UL;
break;
}
c->rawlen = -2L; /* start compressed */
c->compdata = 1;
}
}
else if (c->rawlen==-1L) {
/* get raw len */
c->rawlen = (int32_t)(w+1UL);
c->rxbits -= n;
c->compdata = 0;
}
else if (c->rawlen==-2L) {
/* get 7 bit len code */
if (w<24UL) {
c->rxbits -= 7UL;
c->lencode = w;
if (w==0UL) {
/* end comp */
c->rawlen = 0L;
if (c->compdata) {
/* to comp followed bei endcomp is EOF */
c->compdata = 0;
*done = 1;
c->rxbits = 0UL;
break;
}
c->compdata = 1;
}
else if (w>=9UL && w<29UL) c->rawlen = -5L;
else {
/* next extra len */
c->lencode = _cnst[c->lencode];
c->rawlen = -6L; /* next get 5 bit dist code */
}
}
else c->rawlen = -3L;
}
else if (c->rawlen==-3L) {
/* get 8 bit len code */
c->compdata = 0;
if (w<192UL) {
/* literal < 144 */
xsend(c, (char)(w-48UL), dbuf, dbuf_len, outlen);
c->rxbits -= 8UL;
c->rawlen = -2L; /* continue comp mode */
}
else if (w<200UL) {
/* len codes 24..29 */
c->lencode = w-168UL;
c->rxbits -= 8UL;
c->rawlen = -5L; /* next get extra len */
}
else c->rawlen = -4L;
}
else if (c->rawlen==-4L) {
/* get 9 bit len code */
c->compdata = 0;
xsend(c, (char)(w-256UL), dbuf, dbuf_len, outlen);
c->rxbits -= 9UL;
c->rawlen = -2L; /* continue comp mode */
}
else if (c->rawlen==-5L) {
/* get extra len bits */
c->lencode = _cnst[c->lencode]+w;
c->rxbits -= n;
c->rawlen = -6L; /* next dist code */
}
else if (c->rawlen==-6L) {
/* get 5 bit dist code */
c->compdata = 0;
c->rxbits -= 5UL;
if (w>=4UL) {
c->distcode = w;
c->rawlen = -7L; /* next extra dist code */
}
else {
c->distcode = _cnst0[w];
c->rawlen = -2L; /* continue comp mode */
copystr(dbuf, dbuf_len, outlen, c);
}
}
else if (c->rawlen==-7L) {
/* get extra dist code */
c->rxbits -= c->distcode/2UL-1UL;
c->distcode = _cnst0[c->distcode]+w;
c->rawlen = -2L; /* continue comp mode */
copystr(dbuf, dbuf_len, outlen, c);
}
}
} /* end Expandbyte() */
extern void deflate_BEGIN(void)
{
static int deflate_init = 0;
if (deflate_init) return;
deflate_init = 1;
if (sizeof(uint8_t)!=1) X2C_ASSERT(0);
if (sizeof(uint32_t)!=4) X2C_ASSERT(0);
osi_BEGIN();
}