/* deflate and inflate return values */
enum {
- FlateOk = 0,
- FlateErr = -1,
- FlateIn = -2,
- FlateOut = -3
+ FlateOk = 0,
+ FlateErr = -1,
+ FlateIn = -2,
+ FlateOut = -3
};
typedef struct {
- int nin;
- int nout;
- uchar *in;
- uchar *out;
- char *err;
- void *state;
+ int nin;
+ int nout;
+ uchar *in;
+ uchar *out;
+ char *err;
+ void *state;
} FlateStream;
int deflate(FlateStream *s);
uint crctab[256];
void crc32init(void) {
- static const uint poly = 0xedb88320;
- int i,j;
-
- for (i = 0; i < 256; ++i) {
- uint crc = i;
-
- for (j = 0; j < 8; j++) {
- if (crc & 1)
- crc = (crc >> 1) ^ poly;
- else
- crc >>= 1;
- }
- crctab[i] = crc;
- }
+ static const uint poly = 0xedb88320;
+ int i,j;
+
+ for (i = 0; i < 256; ++i) {
+ uint crc = i;
+
+ for (j = 0; j < 8; j++) {
+ if (crc & 1)
+ crc = (crc >> 1) ^ poly;
+ else
+ crc >>= 1;
+ }
+ crctab[i] = crc;
+ }
}
uint crc32(uchar *p, int n, uint crc) {
- uchar *ep = p + n;
+ uchar *ep = p + n;
- crc ^= 0xffffffff;
- while (p < ep)
- crc = crctab[(crc & 0xff) ^ *p++] ^ (crc >> 8);
- return crc ^ 0xffffffff;
+ crc ^= 0xffffffff;
+ while (p < ep)
+ crc = crctab[(crc & 0xff) ^ *p++] ^ (crc >> 8);
+ return crc ^ 0xffffffff;
}
enum {
- AdlerBase = 65521, /* largest 16bit prime */
- AdlerN = 5552 /* max iters before 32bit overflow */
+ AdlerBase = 65521, /* largest 16bit prime */
+ AdlerN = 5552 /* max iters before 32bit overflow */
};
uint adler32(uchar *p, int n, uint adler) {
- uint s1 = adler & 0xffff;
- uint s2 = (adler >> 16) & 0xffff;
- uchar *ep;
- int k;
-
- for (; n >= 16; n -= k) {
- k = n < AdlerN ? n : AdlerN;
- k &= ~0xf;
- for (ep = p + k; p < ep; p += 16) {
- s1 += p[0];
- s2 += s1;
- s1 += p[1];
- s2 += s1;
- s1 += p[2];
- s2 += s1;
- s1 += p[3];
- s2 += s1;
- s1 += p[4];
- s2 += s1;
- s1 += p[5];
- s2 += s1;
- s1 += p[6];
- s2 += s1;
- s1 += p[7];
- s2 += s1;
- s1 += p[8];
- s2 += s1;
- s1 += p[9];
- s2 += s1;
- s1 += p[10];
- s2 += s1;
- s1 += p[11];
- s2 += s1;
- s1 += p[12];
- s2 += s1;
- s1 += p[13];
- s2 += s1;
- s1 += p[14];
- s2 += s1;
- s1 += p[15];
- s2 += s1;
- }
- s1 %= AdlerBase;
- s2 %= AdlerBase;
- }
- if (n) {
- for (ep = p + n; p < ep; p++) {
- s1 += p[0];
- s2 += s1;
- }
- s1 %= AdlerBase;
- s2 %= AdlerBase;
- }
- return (s2 << 16) + s1;
+ uint s1 = adler & 0xffff;
+ uint s2 = (adler >> 16) & 0xffff;
+ uchar *ep;
+ int k;
+
+ for (; n >= 16; n -= k) {
+ k = n < AdlerN ? n : AdlerN;
+ k &= ~0xf;
+ for (ep = p + k; p < ep; p += 16) {
+ s1 += p[0];
+ s2 += s1;
+ s1 += p[1];
+ s2 += s1;
+ s1 += p[2];
+ s2 += s1;
+ s1 += p[3];
+ s2 += s1;
+ s1 += p[4];
+ s2 += s1;
+ s1 += p[5];
+ s2 += s1;
+ s1 += p[6];
+ s2 += s1;
+ s1 += p[7];
+ s2 += s1;
+ s1 += p[8];
+ s2 += s1;
+ s1 += p[9];
+ s2 += s1;
+ s1 += p[10];
+ s2 += s1;
+ s1 += p[11];
+ s2 += s1;
+ s1 += p[12];
+ s2 += s1;
+ s1 += p[13];
+ s2 += s1;
+ s1 += p[14];
+ s2 += s1;
+ s1 += p[15];
+ s2 += s1;
+ }
+ s1 %= AdlerBase;
+ s2 %= AdlerBase;
+ }
+ if (n) {
+ for (ep = p + n; p < ep; p++) {
+ s1 += p[0];
+ s2 += s1;
+ }
+ s1 %= AdlerBase;
+ s2 %= AdlerBase;
+ }
+ return (s2 << 16) + s1;
}
enum {
- CodeBits = 16, /* max number of bits in a code + 1 */
- LitlenTableBits = 9, /* litlen code bits used in lookup table */
- DistTableBits = 6, /* dist code bits used in lookup table */
- ClenTableBits = 6, /* clen code bits used in lookup table */
- TableBits = LitlenTableBits, /* log2(lookup table size) */
- Nlit = 256, /* number of lit codes */
- Nlen = 29, /* number of len codes */
- Nlitlen = Nlit+Nlen+3, /* litlen codes + block end + 2 unused */
- Ndist = 30, /* number of distance codes */
- Nclen = 19, /* number of code length codes */
-
- EOB = 256, /* end of block symbol */
- MinMatch = 3, /* min match length */
- MaxMatch = 258, /* max match length */
- WinSize = 1 << 15, /* sliding window size */
-
- MaxChainLen = 256, /* max length of hash chain */
- HashBits = 13,
- HashSize = 1 << HashBits, /* hash table size */
- BigDist = 1 << 12, /* max match distance for short match length */
- MaxDist = WinSize,
- BlockSize = 1 << 15, /* TODO */
- SrcSize = 2*WinSize + MaxMatch,
- DstSize = BlockSize + MaxMatch + 6, /* worst case compressed block size */
- LzSize = 1 << 13, /* lz buffer size */
- LzGuard = LzSize - 2,
- LzLitFlag = 1 << 15 /* marks literal run length in lz buffer */
+ CodeBits = 16, /* max number of bits in a code + 1 */
+ LitlenTableBits = 9, /* litlen code bits used in lookup table */
+ DistTableBits = 6, /* dist code bits used in lookup table */
+ ClenTableBits = 6, /* clen code bits used in lookup table */
+ TableBits = LitlenTableBits, /* log2(lookup table size) */
+ Nlit = 256, /* number of lit codes */
+ Nlen = 29, /* number of len codes */
+ Nlitlen = Nlit+Nlen+3, /* litlen codes + block end + 2 unused */
+ Ndist = 30, /* number of distance codes */
+ Nclen = 19, /* number of code length codes */
+
+ EOB = 256, /* end of block symbol */
+ MinMatch = 3, /* min match length */
+ MaxMatch = 258, /* max match length */
+ WinSize = 1 << 15, /* sliding window size */
+
+ MaxChainLen = 256, /* max length of hash chain */
+ HashBits = 13,
+ HashSize = 1 << HashBits, /* hash table size */
+ BigDist = 1 << 12, /* max match distance for short match length */
+ MaxDist = WinSize,
+ BlockSize = 1 << 15, /* TODO */
+ SrcSize = 2*WinSize + MaxMatch,
+ DstSize = BlockSize + MaxMatch + 6, /* worst case compressed block size */
+ LzSize = 1 << 13, /* lz buffer size */
+ LzGuard = LzSize - 2,
+ LzLitFlag = 1 << 15 /* marks literal run length in lz buffer */
};
/* states */
enum {
- BlockHead,
- UncompressedBlock,
- CopyUncompressed,
- FixedHuff,
- DynamicHuff,
- DynamicHuffClen,
- DynamicHuffLitlenDist,
- DynamicHuffContinue,
- DecodeBlock,
- DecodeBlockLenBits,
- DecodeBlockDist,
- DecodeBlockDistBits,
- DecodeBlockCopy
+ BlockHead,
+ UncompressedBlock,
+ CopyUncompressed,
+ FixedHuff,
+ DynamicHuff,
+ DynamicHuffClen,
+ DynamicHuffLitlenDist,
+ DynamicHuffContinue,
+ DecodeBlock,
+ DecodeBlockLenBits,
+ DecodeBlockDist,
+ DecodeBlockDistBits,
+ DecodeBlockCopy
};
typedef struct {
- short len; /* code length */
- ushort sym; /* symbol */
+ short len; /* code length */
+ ushort sym; /* symbol */
} Entry;
/* huffman code tree */
typedef struct {
- Entry table[1 << TableBits]; /* prefix lookup table */
- uint nbits; /* prefix length (table size is 1 << nbits) */
- uint sum; /* full codes in table: sum(count[0..nbits]) */
- ushort count[CodeBits]; /* number of codes with given length */
- ushort symbol[Nlitlen]; /* symbols ordered by code length (lexic.) */
+ Entry table[1 << TableBits]; /* prefix lookup table */
+ uint nbits; /* prefix length (table size is 1 << nbits) */
+ uint sum; /* full codes in table: sum(count[0..nbits]) */
+ ushort count[CodeBits]; /* number of codes with given length */
+ ushort symbol[Nlitlen]; /* symbols ordered by code length (lexic.) */
} Huff;
typedef struct {
- uchar *src; /* input buffer pointer */
- uchar *srcend;
-
- uint bits;
- uint nbits;
-
- uchar win[WinSize]; /* output window */
- uint pos; /* window pos */
- uint posout; /* used for flushing win */
-
- int state; /* decode state */
- int final; /* last block flag */
- char *err; /* TODO: error message */
-
- /* for decoding dynamic code trees in inflate() */
- int nlit;
- int ndist;
- int nclen; /* also used in decode_block() */
- int lenpos; /* also used in decode_block() */
- uchar lens[Nlitlen + Ndist];
-
- int fixed; /* fixed code tree flag */
- Huff lhuff; /* dynamic lit/len huffman code tree */
- Huff dhuff; /* dynamic distance huffman code tree */
+ uchar *src; /* input buffer pointer */
+ uchar *srcend;
+
+ uint bits;
+ uint nbits;
+
+ uchar win[WinSize]; /* output window */
+ uint pos; /* window pos */
+ uint posout; /* used for flushing win */
+
+ int state; /* decode state */
+ int final; /* last block flag */
+ char *err; /* TODO: error message */
+
+ /* for decoding dynamic code trees in inflate() */
+ int nlit;
+ int ndist;
+ int nclen; /* also used in decode_block() */
+ int lenpos; /* also used in decode_block() */
+ uchar lens[Nlitlen + Ndist];
+
+ int fixed; /* fixed code tree flag */
+ Huff lhuff; /* dynamic lit/len huffman code tree */
+ Huff dhuff; /* dynamic distance huffman code tree */
} DecodeState;
/* TODO: globals.. initialization is not thread safe */
/* base offset and extra bits tables */
static uchar lenbits[Nlen] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
};
static ushort lenbase[Nlen] = {
- 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, 258
+ 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, 258
};
static uchar distbits[Ndist] = {
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13
};
static ushort distbase[Ndist] = {
- 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
+ 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
};
/* ordering of code lengths */
static uchar clenorder[Nclen] = {
- 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
};
/* TODO: this or normal inc + reverse() */
/* increment bitwise reversed n (msb is bit 0, lsb is bit len-1) */
static uint revinc(uint n, uint len) {
- uint i = 1 << (len - 1);
-
- while (n & i)
- i >>= 1;
- if (i) {
- n &= i - 1;
- n |= i;
- } else
- n = 0;
- return n;
+ uint i = 1 << (len - 1);
+
+ while (n & i)
+ i >>= 1;
+ if (i) {
+ n &= i - 1;
+ n |= i;
+ } else
+ n = 0;
+ return n;
}
/* build huffman code tree from code lengths (each should be < CodeBits) */
static int build_huff(Huff *huff, uchar *lens, uint n, uint nbits) {
- int offs[CodeBits];
- int left;
- uint i, c, sum, code, len, min, max;
- ushort *count = huff->count;
- ushort *symbol = huff->symbol;
- Entry *table = huff->table;
- Entry entry;
-
- /* count code lengths */
- for (i = 0; i < CodeBits; i++)
- count[i] = 0;
- for (i = 0; i < n; i++)
- count[lens[i]]++;
- if (count[0] == n) {
- huff->nbits = table[0].len = 0;
- return 0;
- }
- count[0] = 0;
-
- /* bound code lengths, force nbits to be within the bounds */
- for (max = CodeBits - 1; max > 0; max--)
- if (count[max] != 0)
- break;
- if (nbits > max)
- nbits = max;
- for (min = 1; min < CodeBits; min++)
- if (count[min] != 0)
- break;
- if (nbits < min) {
- nbits = min;
- if (nbits > TableBits)
- return -1;
- }
- huff->nbits = nbits;
-
- /* check if length is over-subscribed or incomplete */
- for (left = 1 << min, i = min; i <= max; left <<= 1, i++) {
- left -= count[i];
- /* left < 0: over-subscribed, left > 0: incomplete */
- if (left < 0)
- return -1;
- }
-
- for (sum = 0, i = 0; i <= max; i++) {
- offs[i] = sum;
- sum += count[i];
- }
- /* needed for decoding codes longer than nbits */
- if (nbits < max)
- huff->sum = offs[nbits + 1];
-
- /* sort symbols by code length (lexicographic order) */
- for (i = 0; i < n; i++)
- if (lens[i])
- symbol[offs[lens[i]]++] = i;
-
- /* lookup table for decoding nbits from input.. */
- for (i = 0; i < 1 << nbits; i++)
- table[i].len = table[i].sym = 0;
- code = 0;
- /* ..if code is at most nbits (bits are in reverse order, sigh..) */
- for (len = min; len <= nbits; len++)
- for (c = count[len]; c > 0; c--) {
- entry.len = len;
- entry.sym = *symbol;
- for (i = code; i < 1 << nbits; i += 1 << len)
- table[i] = entry;
- /* next code */
- symbol++;
- code = revinc(code, len);
- }
- /* ..if code is longer than nbits: values for simple bitwise decode */
- for (i = 0; code; i++) {
- table[code].len = -1;
- table[code].sym = i << 1;
- code = revinc(code, nbits);
- }
- return 0;
+ int offs[CodeBits];
+ int left;
+ uint i, c, sum, code, len, min, max;
+ ushort *count = huff->count;
+ ushort *symbol = huff->symbol;
+ Entry *table = huff->table;
+ Entry entry;
+
+ /* count code lengths */
+ for (i = 0; i < CodeBits; i++)
+ count[i] = 0;
+ for (i = 0; i < n; i++)
+ count[lens[i]]++;
+ if (count[0] == n) {
+ huff->nbits = table[0].len = 0;
+ return 0;
+ }
+ count[0] = 0;
+
+ /* bound code lengths, force nbits to be within the bounds */
+ for (max = CodeBits - 1; max > 0; max--)
+ if (count[max] != 0)
+ break;
+ if (nbits > max)
+ nbits = max;
+ for (min = 1; min < CodeBits; min++)
+ if (count[min] != 0)
+ break;
+ if (nbits < min) {
+ nbits = min;
+ if (nbits > TableBits)
+ return -1;
+ }
+ huff->nbits = nbits;
+
+ /* check if length is over-subscribed or incomplete */
+ for (left = 1 << min, i = min; i <= max; left <<= 1, i++) {
+ left -= count[i];
+ /* left < 0: over-subscribed, left > 0: incomplete */
+ if (left < 0)
+ return -1;
+ }
+
+ for (sum = 0, i = 0; i <= max; i++) {
+ offs[i] = sum;
+ sum += count[i];
+ }
+ /* needed for decoding codes longer than nbits */
+ if (nbits < max)
+ huff->sum = offs[nbits + 1];
+
+ /* sort symbols by code length (lexicographic order) */
+ for (i = 0; i < n; i++)
+ if (lens[i])
+ symbol[offs[lens[i]]++] = i;
+
+ /* lookup table for decoding nbits from input.. */
+ for (i = 0; i < 1 << nbits; i++)
+ table[i].len = table[i].sym = 0;
+ code = 0;
+ /* ..if code is at most nbits (bits are in reverse order, sigh..) */
+ for (len = min; len <= nbits; len++)
+ for (c = count[len]; c > 0; c--) {
+ entry.len = len;
+ entry.sym = *symbol;
+ for (i = code; i < 1 << nbits; i += 1 << len)
+ table[i] = entry;
+ /* next code */
+ symbol++;
+ code = revinc(code, len);
+ }
+ /* ..if code is longer than nbits: values for simple bitwise decode */
+ for (i = 0; code; i++) {
+ table[code].len = -1;
+ table[code].sym = i << 1;
+ code = revinc(code, nbits);
+ }
+ return 0;
}
/* fixed huffman code trees (should be done at compile time..) */
static void init_fixed_huffs(void) {
- int i;
- uchar lens[Nlitlen];
-
- for (i = 0; i < 144; i++)
- lens[i] = 8;
- for (; i < 256; i++)
- lens[i] = 9;
- for (; i < 280; i++)
- lens[i] = 7;
- for (; i < Nlitlen; i++)
- lens[i] = 8;
- build_huff(&lhuff, lens, Nlitlen, 8);
-
- for (i = 0; i < Ndist; i++)
- lens[i] = 5;
- build_huff(&dhuff, lens, Ndist, 5);
+ int i;
+ uchar lens[Nlitlen];
+
+ for (i = 0; i < 144; i++)
+ lens[i] = 8;
+ for (; i < 256; i++)
+ lens[i] = 9;
+ for (; i < 280; i++)
+ lens[i] = 7;
+ for (; i < Nlitlen; i++)
+ lens[i] = 8;
+ build_huff(&lhuff, lens, Nlitlen, 8);
+
+ for (i = 0; i < Ndist; i++)
+ lens[i] = 5;
+ build_huff(&dhuff, lens, Ndist, 5);
}
/* fill *bits with n bits from *src */
static int fillbits_fast(uchar **src, uchar *srcend, uint *bits, uint *nbits, uint n) {
- while (*nbits < n) {
- if (*src == srcend)
- return 0;
- *bits |= *(*src)++ << *nbits;
- *nbits += 8;
- }
- return 1;
+ while (*nbits < n) {
+ if (*src == srcend)
+ return 0;
+ *bits |= *(*src)++ << *nbits;
+ *nbits += 8;
+ }
+ return 1;
}
/* get n bits from *bits */
static uint getbits_fast(uint *bits, uint *nbits, int n) {
- uint k;
+ uint k;
- k = *bits & ((1 << n) - 1);
- *bits >>= n;
- *nbits -= n;
- return k;
+ k = *bits & ((1 << n) - 1);
+ *bits >>= n;
+ *nbits -= n;
+ return k;
}
static int fillbits(DecodeState *s, uint n) {
- return fillbits_fast(&s->src, s->srcend, &s->bits, &s->nbits, n);
+ return fillbits_fast(&s->src, s->srcend, &s->bits, &s->nbits, n);
}
static uint getbits(DecodeState *s, uint n) {
- return getbits_fast(&s->bits, &s->nbits, n);
+ return getbits_fast(&s->bits, &s->nbits, n);
}
/* decode symbol bitwise if code is longer than huffbits */
static uint decode_symbol_long(DecodeState *s, Huff *huff, uint bits, uint nbits, int cur) {
- int sum = huff->sum;
- uint huffbits = huff->nbits;
- ushort *count = huff->count + huffbits + 1;
-
- /* get bits if we are near the end */
- if (s->src + 2 >= s->srcend) {
- while (nbits < CodeBits - 1 && s->src < s->srcend) {
- bits |= *s->src++ << nbits;
- nbits += 8;
- }
- s->bits = bits;
- s->nbits = nbits;
- }
- bits >>= huffbits;
- nbits -= huffbits;
- for (;;) {
- if (!nbits--) {
- if (s->src == s->srcend)
- return FlateIn;
- bits = *s->src++;
- nbits = 7;
- }
- cur |= bits & 1;
- bits >>= 1;
- sum += *count;
- cur -= *count;
- if (cur < 0)
- break;
- cur <<= 1;
- count++;
- if (count == huff->count + CodeBits)
- return s->err = "symbol decoding failed.", FlateErr;
- }
- s->bits = bits;
- s->nbits = nbits;
- return huff->symbol[sum + cur];
+ int sum = huff->sum;
+ uint huffbits = huff->nbits;
+ ushort *count = huff->count + huffbits + 1;
+
+ /* get bits if we are near the end */
+ if (s->src + 2 >= s->srcend) {
+ while (nbits < CodeBits - 1 && s->src < s->srcend) {
+ bits |= *s->src++ << nbits;
+ nbits += 8;
+ }
+ s->bits = bits;
+ s->nbits = nbits;
+ }
+ bits >>= huffbits;
+ nbits -= huffbits;
+ for (;;) {
+ if (!nbits--) {
+ if (s->src == s->srcend)
+ return FlateIn;
+ bits = *s->src++;
+ nbits = 7;
+ }
+ cur |= bits & 1;
+ bits >>= 1;
+ sum += *count;
+ cur -= *count;
+ if (cur < 0)
+ break;
+ cur <<= 1;
+ count++;
+ if (count == huff->count + CodeBits)
+ return s->err = "symbol decoding failed.", FlateErr;
+ }
+ s->bits = bits;
+ s->nbits = nbits;
+ return huff->symbol[sum + cur];
}
/* decode a symbol from stream with huff code */
static uint decode_symbol(DecodeState *s, Huff *huff) {
- uint huffbits = huff->nbits;
- uint nbits = s->nbits;
- uint bits = s->bits;
- uint mask = (1 << huffbits) - 1;
- Entry entry;
-
- /* get enough bits efficiently */
- if (nbits < huffbits) {
- uchar *src = s->src;
-
- if (src + 2 < s->srcend) {
- /* we assume huffbits <= 9 */
- bits |= *src++ << nbits;
- nbits += 8;
- bits |= *src++ << nbits;
- nbits += 8;
- bits |= *src++ << nbits;
- nbits += 8;
- s->src = src;
- } else /* rare */
- do {
- if (s->src == s->srcend) {
- entry = huff->table[bits & mask];
- if (entry.len > 0 && entry.len <= nbits) {
- s->bits = bits >> entry.len;
- s->nbits = nbits - entry.len;
- return entry.sym;
- }
- s->bits = bits;
- s->nbits = nbits;
- return FlateIn;
- }
- bits |= *s->src++ << nbits;
- nbits += 8;
- } while (nbits < huffbits);
- }
- /* decode bits */
- entry = huff->table[bits & mask];
- if (entry.len > 0) {
- s->bits = bits >> entry.len;
- s->nbits = nbits - entry.len;
- return entry.sym;
- } else if (entry.len == 0)
- return s->err = "symbol decoding failed.", FlateErr;
- return decode_symbol_long(s, huff, bits, nbits, entry.sym);
+ uint huffbits = huff->nbits;
+ uint nbits = s->nbits;
+ uint bits = s->bits;
+ uint mask = (1 << huffbits) - 1;
+ Entry entry;
+
+ /* get enough bits efficiently */
+ if (nbits < huffbits) {
+ uchar *src = s->src;
+
+ if (src + 2 < s->srcend) {
+ /* we assume huffbits <= 9 */
+ bits |= *src++ << nbits;
+ nbits += 8;
+ bits |= *src++ << nbits;
+ nbits += 8;
+ bits |= *src++ << nbits;
+ nbits += 8;
+ s->src = src;
+ } else /* rare */
+ do {
+ if (s->src == s->srcend) {
+ entry = huff->table[bits & mask];
+ if (entry.len > 0 && entry.len <= nbits) {
+ s->bits = bits >> entry.len;
+ s->nbits = nbits - entry.len;
+ return entry.sym;
+ }
+ s->bits = bits;
+ s->nbits = nbits;
+ return FlateIn;
+ }
+ bits |= *s->src++ << nbits;
+ nbits += 8;
+ } while (nbits < huffbits);
+ }
+ /* decode bits */
+ entry = huff->table[bits & mask];
+ if (entry.len > 0) {
+ s->bits = bits >> entry.len;
+ s->nbits = nbits - entry.len;
+ return entry.sym;
+ } else if (entry.len == 0)
+ return s->err = "symbol decoding failed.", FlateErr;
+ return decode_symbol_long(s, huff, bits, nbits, entry.sym);
}
/* decode a block of data from stream with trees */
static int decode_block(DecodeState *s, Huff *lhuff, Huff *dhuff) {
- uchar *win = s->win;
- uint pos = s->pos;
- uint sym = s->nclen;
- uint len = s->lenpos;
- uint dist = s->nclen;
-
- switch (s->state) {
- case DecodeBlock:
- for (;;) {
- sym = decode_symbol(s, lhuff);
- if (sym < 256) {
- win[pos++] = sym;
- if (pos == WinSize) {
- s->pos = WinSize;
- s->state = DecodeBlock;
- return FlateOut;
- }
- } else if (sym > 256) {
- sym -= 257;
- if (sym >= Nlen) {
- s->pos = pos;
- s->state = DecodeBlock;
- if (sym + 257 == (uint)FlateIn)
- return FlateIn;
- return FlateErr;
- }
- case DecodeBlockLenBits:
- if (!fillbits_fast(&s->src, s->srcend, &s->bits, &s->nbits, lenbits[sym])) {
- s->nclen = sym; /* using nclen to store sym */
- s->pos = pos;
- s->state = DecodeBlockLenBits;
- return FlateIn;
- }
- len = lenbase[sym] + getbits_fast(&s->bits, &s->nbits, lenbits[sym]);
- case DecodeBlockDist:
- sym = decode_symbol(s, dhuff);
- if (sym == (uint)FlateIn) {
- s->pos = pos;
- s->lenpos = len;
- s->state = DecodeBlockDist;
- return FlateIn;
- }
- if (sym >= Ndist)
- return FlateErr;
- case DecodeBlockDistBits:
- if (!fillbits_fast(&s->src, s->srcend, &s->bits, &s->nbits, distbits[sym])) {
- s->nclen = sym; /* using nclen to store sym */
- s->pos = pos;
- s->lenpos = len;
- s->state = DecodeBlockDistBits;
- return FlateIn;
- }
- dist = distbase[sym] + getbits_fast(&s->bits, &s->nbits, distbits[sym]);
- /* copy match, loop unroll in common case */
- if (pos + len < WinSize) {
- /* lenbase[sym] >= 3 */
- do {
- win[pos] = win[(pos - dist) % WinSize];
- pos++;
- win[pos] = win[(pos - dist) % WinSize];
- pos++;
- win[pos] = win[(pos - dist) % WinSize];
- pos++;
- len -= 3;
- } while (len >= 3);
- if (len--) {
- win[pos] = win[(pos - dist) % WinSize];
- pos++;
- if (len) {
- win[pos] = win[(pos - dist) % WinSize];
- pos++;
- }
- }
- } else { /* rare */
- case DecodeBlockCopy:
- while (len--) {
- win[pos] = win[(pos - dist) % WinSize];
- pos++;
- if (pos == WinSize) {
- s->pos = WinSize;
- s->lenpos = len;
- s->nclen = dist; /* using nclen to store dist */
- s->state = DecodeBlockCopy;
- return FlateOut;
- }
- }
- }
- } else { /* EOB: sym == 256 */
- s->pos = pos;
- return FlateOk;
- }
- } /* for (;;) */
- } /* switch () */
- return s->err = "corrupted state.", FlateErr;
+ uchar *win = s->win;
+ uint pos = s->pos;
+ uint sym = s->nclen;
+ uint len = s->lenpos;
+ uint dist = s->nclen;
+
+ switch (s->state) {
+ case DecodeBlock:
+ for (;;) {
+ sym = decode_symbol(s, lhuff);
+ if (sym < 256) {
+ win[pos++] = sym;
+ if (pos == WinSize) {
+ s->pos = WinSize;
+ s->state = DecodeBlock;
+ return FlateOut;
+ }
+ } else if (sym > 256) {
+ sym -= 257;
+ if (sym >= Nlen) {
+ s->pos = pos;
+ s->state = DecodeBlock;
+ if (sym + 257 == (uint)FlateIn)
+ return FlateIn;
+ return FlateErr;
+ }
+ case DecodeBlockLenBits:
+ if (!fillbits_fast(&s->src, s->srcend, &s->bits, &s->nbits, lenbits[sym])) {
+ s->nclen = sym; /* using nclen to store sym */
+ s->pos = pos;
+ s->state = DecodeBlockLenBits;
+ return FlateIn;
+ }
+ len = lenbase[sym] + getbits_fast(&s->bits, &s->nbits, lenbits[sym]);
+ case DecodeBlockDist:
+ sym = decode_symbol(s, dhuff);
+ if (sym == (uint)FlateIn) {
+ s->pos = pos;
+ s->lenpos = len;
+ s->state = DecodeBlockDist;
+ return FlateIn;
+ }
+ if (sym >= Ndist)
+ return FlateErr;
+ case DecodeBlockDistBits:
+ if (!fillbits_fast(&s->src, s->srcend, &s->bits, &s->nbits, distbits[sym])) {
+ s->nclen = sym; /* using nclen to store sym */
+ s->pos = pos;
+ s->lenpos = len;
+ s->state = DecodeBlockDistBits;
+ return FlateIn;
+ }
+ dist = distbase[sym] + getbits_fast(&s->bits, &s->nbits, distbits[sym]);
+ /* copy match, loop unroll in common case */
+ if (pos + len < WinSize) {
+ /* lenbase[sym] >= 3 */
+ do {
+ win[pos] = win[(pos - dist) % WinSize];
+ pos++;
+ win[pos] = win[(pos - dist) % WinSize];
+ pos++;
+ win[pos] = win[(pos - dist) % WinSize];
+ pos++;
+ len -= 3;
+ } while (len >= 3);
+ if (len--) {
+ win[pos] = win[(pos - dist) % WinSize];
+ pos++;
+ if (len) {
+ win[pos] = win[(pos - dist) % WinSize];
+ pos++;
+ }
+ }
+ } else { /* rare */
+ case DecodeBlockCopy:
+ while (len--) {
+ win[pos] = win[(pos - dist) % WinSize];
+ pos++;
+ if (pos == WinSize) {
+ s->pos = WinSize;
+ s->lenpos = len;
+ s->nclen = dist; /* using nclen to store dist */
+ s->state = DecodeBlockCopy;
+ return FlateOut;
+ }
+ }
+ }
+ } else { /* EOB: sym == 256 */
+ s->pos = pos;
+ return FlateOk;
+ }
+ } /* for (;;) */
+ } /* switch () */
+ return s->err = "corrupted state.", FlateErr;
}
/* inflate state machine (decodes s->src into s->win) */
static int inflate_state(DecodeState *s) {
- int n;
-
- if (s->posout)
- return FlateOut;
- for (;;) {
- switch (s->state) {
- case BlockHead:
- if (s->final) {
- if (s->pos)
- return FlateOut;
- else
- return FlateOk;
- }
- if (!fillbits(s, 3))
- return FlateIn;
- s->final = getbits(s, 1);
- n = getbits(s, 2);
- if (n == 0)
- s->state = UncompressedBlock;
- else if (n == 1)
- s->state = FixedHuff;
- else if (n == 2)
- s->state = DynamicHuff;
- else
- return s->err = "corrupt block header.", FlateErr;
- break;
- case UncompressedBlock:
- /* start block on a byte boundary */
- s->bits >>= s->nbits & 7;
- s->nbits &= ~7;
- if (!fillbits(s, 32))
- return FlateIn;
- s->lenpos = getbits(s, 16);
- n = getbits(s, 16);
- if (s->lenpos != (~n & 0xffff))
- return s->err = "corrupt uncompressed length.", FlateErr;
- s->state = CopyUncompressed;
- case CopyUncompressed:
- /* TODO: untested, slow, memcpy etc */
- /* s->nbits should be 0 here */
- while (s->lenpos) {
- if (s->src == s->srcend)
- return FlateIn;
- s->lenpos--;
- s->win[s->pos++] = *s->src++;
- if (s->pos == WinSize)
- return FlateOut;
- }
- s->state = BlockHead;
- break;
- case FixedHuff:
- s->fixed = 1;
- s->state = DecodeBlock;
- break;
- case DynamicHuff:
- /* decode dynamic huffman code trees */
- if (!fillbits(s, 14))
- return FlateIn;
- s->nlit = 257 + getbits(s, 5);
- s->ndist = 1 + getbits(s, 5);
- s->nclen = 4 + getbits(s, 4);
- if (s->nlit > Nlitlen || s->ndist > Ndist)
- return s->err = "corrupt code tree.", FlateErr;
- /* build code length tree */
- for (n = 0; n < Nclen; n++)
- s->lens[n] = 0;
- s->fixed = 0;
- s->state = DynamicHuffClen;
- s->lenpos = 0;
- case DynamicHuffClen:
- for (n = s->lenpos; n < s->nclen; n++)
- if (fillbits(s, 3)) {
- s->lens[clenorder[n]] = getbits(s, 3);
- } else {
- s->lenpos = n;
- return FlateIn;
- }
- /* using lhuff for code length huff code */
- if (build_huff(&s->lhuff, s->lens, Nclen, ClenTableBits) < 0)
- return s->err = "building clen tree failed.", FlateErr;
- s->state = DynamicHuffLitlenDist;
- s->lenpos = 0;
- case DynamicHuffLitlenDist:
- /* decode code lengths for the dynamic trees */
- for (n = s->lenpos; n < s->nlit + s->ndist; ) {
- uint sym = decode_symbol(s, &s->lhuff);
- uint len;
- uchar c;
-
- if (sym < 16) {
- s->lens[n++] = sym;
- continue;
- } else if (sym == (uint)FlateIn) {
- s->lenpos = n;
- return FlateIn;
- case DynamicHuffContinue:
- n = s->lenpos;
- sym = s->nclen;
- s->state = DynamicHuffLitlenDist;
- }
- if (!fillbits(s, 7)) {
- /* TODO: 7 is too much when an almost empty block is at the end */
- if (sym == (uint)FlateErr)
- return FlateErr;
- s->nclen = sym;
- s->lenpos = n;
- s->state = DynamicHuffContinue;
- return FlateIn;
- }
- /* TODO: bound check s->lens */
- if (sym == 16) {
- /* copy previous code length 3-6 times */
- c = s->lens[n - 1];
- for (len = 3 + getbits(s, 2); len; len--)
- s->lens[n++] = c;
- } else if (sym == 17) {
- /* repeat 0 for 3-10 times */
- for (len = 3 + getbits(s, 3); len; len--)
- s->lens[n++] = 0;
- } else if (sym == 18) {
- /* repeat 0 for 11-138 times */
- for (len = 11 + getbits(s, 7); len; len--)
- s->lens[n++] = 0;
- } else
- return s->err = "corrupt code tree.", FlateErr;
- }
- /* build dynamic huffman code trees */
- if (build_huff(&s->lhuff, s->lens, s->nlit, LitlenTableBits) < 0)
- return s->err = "building litlen tree failed.", FlateErr;
- if (build_huff(&s->dhuff, s->lens + s->nlit, s->ndist, DistTableBits) < 0)
- return s->err = "building dist tree failed.", FlateErr;
- s->state = DecodeBlock;
- case DecodeBlock:
- case DecodeBlockLenBits:
- case DecodeBlockDist:
- case DecodeBlockDistBits:
- case DecodeBlockCopy:
- n = decode_block(s, s->fixed ? &lhuff : &s->lhuff, s->fixed ? &dhuff : &s->dhuff);
- if (n != FlateOk)
- return n;
- s->state = BlockHead;
- break;
- default:
- return s->err = "corrupt internal state.", FlateErr;
- }
- }
+ int n;
+
+ if (s->posout)
+ return FlateOut;
+ for (;;) {
+ switch (s->state) {
+ case BlockHead:
+ if (s->final) {
+ if (s->pos)
+ return FlateOut;
+ else
+ return FlateOk;
+ }
+ if (!fillbits(s, 3))
+ return FlateIn;
+ s->final = getbits(s, 1);
+ n = getbits(s, 2);
+ if (n == 0)
+ s->state = UncompressedBlock;
+ else if (n == 1)
+ s->state = FixedHuff;
+ else if (n == 2)
+ s->state = DynamicHuff;
+ else
+ return s->err = "corrupt block header.", FlateErr;
+ break;
+ case UncompressedBlock:
+ /* start block on a byte boundary */
+ s->bits >>= s->nbits & 7;
+ s->nbits &= ~7;
+ if (!fillbits(s, 32))
+ return FlateIn;
+ s->lenpos = getbits(s, 16);
+ n = getbits(s, 16);
+ if (s->lenpos != (~n & 0xffff))
+ return s->err = "corrupt uncompressed length.", FlateErr;
+ s->state = CopyUncompressed;
+ case CopyUncompressed:
+ /* TODO: untested, slow, memcpy etc */
+ /* s->nbits should be 0 here */
+ while (s->lenpos) {
+ if (s->src == s->srcend)
+ return FlateIn;
+ s->lenpos--;
+ s->win[s->pos++] = *s->src++;
+ if (s->pos == WinSize)
+ return FlateOut;
+ }
+ s->state = BlockHead;
+ break;
+ case FixedHuff:
+ s->fixed = 1;
+ s->state = DecodeBlock;
+ break;
+ case DynamicHuff:
+ /* decode dynamic huffman code trees */
+ if (!fillbits(s, 14))
+ return FlateIn;
+ s->nlit = 257 + getbits(s, 5);
+ s->ndist = 1 + getbits(s, 5);
+ s->nclen = 4 + getbits(s, 4);
+ if (s->nlit > Nlitlen || s->ndist > Ndist)
+ return s->err = "corrupt code tree.", FlateErr;
+ /* build code length tree */
+ for (n = 0; n < Nclen; n++)
+ s->lens[n] = 0;
+ s->fixed = 0;
+ s->state = DynamicHuffClen;
+ s->lenpos = 0;
+ case DynamicHuffClen:
+ for (n = s->lenpos; n < s->nclen; n++)
+ if (fillbits(s, 3)) {
+ s->lens[clenorder[n]] = getbits(s, 3);
+ } else {
+ s->lenpos = n;
+ return FlateIn;
+ }
+ /* using lhuff for code length huff code */
+ if (build_huff(&s->lhuff, s->lens, Nclen, ClenTableBits) < 0)
+ return s->err = "building clen tree failed.", FlateErr;
+ s->state = DynamicHuffLitlenDist;
+ s->lenpos = 0;
+ case DynamicHuffLitlenDist:
+ /* decode code lengths for the dynamic trees */
+ for (n = s->lenpos; n < s->nlit + s->ndist; ) {
+ uint sym = decode_symbol(s, &s->lhuff);
+ uint len;
+ uchar c;
+
+ if (sym < 16) {
+ s->lens[n++] = sym;
+ continue;
+ } else if (sym == (uint)FlateIn) {
+ s->lenpos = n;
+ return FlateIn;
+ case DynamicHuffContinue:
+ n = s->lenpos;
+ sym = s->nclen;
+ s->state = DynamicHuffLitlenDist;
+ }
+ if (!fillbits(s, 7)) {
+ /* TODO: 7 is too much when an almost empty block is at the end */
+ if (sym == (uint)FlateErr)
+ return FlateErr;
+ s->nclen = sym;
+ s->lenpos = n;
+ s->state = DynamicHuffContinue;
+ return FlateIn;
+ }
+ /* TODO: bound check s->lens */
+ if (sym == 16) {
+ /* copy previous code length 3-6 times */
+ c = s->lens[n - 1];
+ for (len = 3 + getbits(s, 2); len; len--)
+ s->lens[n++] = c;
+ } else if (sym == 17) {
+ /* repeat 0 for 3-10 times */
+ for (len = 3 + getbits(s, 3); len; len--)
+ s->lens[n++] = 0;
+ } else if (sym == 18) {
+ /* repeat 0 for 11-138 times */
+ for (len = 11 + getbits(s, 7); len; len--)
+ s->lens[n++] = 0;
+ } else
+ return s->err = "corrupt code tree.", FlateErr;
+ }
+ /* build dynamic huffman code trees */
+ if (build_huff(&s->lhuff, s->lens, s->nlit, LitlenTableBits) < 0)
+ return s->err = "building litlen tree failed.", FlateErr;
+ if (build_huff(&s->dhuff, s->lens + s->nlit, s->ndist, DistTableBits) < 0)
+ return s->err = "building dist tree failed.", FlateErr;
+ s->state = DecodeBlock;
+ case DecodeBlock:
+ case DecodeBlockLenBits:
+ case DecodeBlockDist:
+ case DecodeBlockDistBits:
+ case DecodeBlockCopy:
+ n = decode_block(s, s->fixed ? &lhuff : &s->lhuff, s->fixed ? &dhuff : &s->dhuff);
+ if (n != FlateOk)
+ return n;
+ s->state = BlockHead;
+ break;
+ default:
+ return s->err = "corrupt internal state.", FlateErr;
+ }
+ }
}
static DecodeState *alloc_decode_state(void) {
- DecodeState *s = malloc(sizeof(DecodeState));
-
- if (s) {
- s->final = s->pos = s->posout = s->bits = s->nbits = 0;
- s->state = BlockHead;
- s->src = s->srcend = 0;
- s->err = 0;
- /* TODO: globals.. */
- if (lhuff.nbits == 0)
- init_fixed_huffs();
- }
- return s;
+ DecodeState *s = malloc(sizeof(DecodeState));
+
+ if (s) {
+ s->final = s->pos = s->posout = s->bits = s->nbits = 0;
+ s->state = BlockHead;
+ s->src = s->srcend = 0;
+ s->err = 0;
+ /* TODO: globals.. */
+ if (lhuff.nbits == 0)
+ init_fixed_huffs();
+ }
+ return s;
}
/* extern */
int inflate(FlateStream *stream) {
- DecodeState *s = stream->state;
- int n;
-
- if (stream->err) {
- if (s) {
- free(s);
- stream->state = 0;
- }
- return FlateErr;
- }
- if (!s) {
- s = stream->state = alloc_decode_state();
- if (!s)
- return stream->err = "no mem.", FlateErr;
- }
- if (stream->nin) {
- s->src = stream->in;
- s->srcend = s->src + stream->nin;
- stream->nin = 0;
- }
- n = inflate_state(s);
- if (n == FlateOut) {
- if (s->pos < stream->nout)
- stream->nout = s->pos;
- memcpy(stream->out, s->win + s->posout, stream->nout);
- s->pos -= stream->nout;
- if (s->pos)
- s->posout += stream->nout;
- else
- s->posout = 0;
- }
- if (n == FlateOk || n == FlateErr) {
- if (s->nbits || s->src < s->srcend) {
- s->nbits /= 8;
- stream->in = s->src - s->nbits;
- stream->nin = s->srcend - s->src + s->nbits;
- }
- stream->err = s->err;
- free(s);
- stream->state = 0;
- }
- return n;
+ DecodeState *s = stream->state;
+ int n;
+
+ if (stream->err) {
+ if (s) {
+ free(s);
+ stream->state = 0;
+ }
+ return FlateErr;
+ }
+ if (!s) {
+ s = stream->state = alloc_decode_state();
+ if (!s)
+ return stream->err = "no mem.", FlateErr;
+ }
+ if (stream->nin) {
+ s->src = stream->in;
+ s->srcend = s->src + stream->nin;
+ stream->nin = 0;
+ }
+ n = inflate_state(s);
+ if (n == FlateOut) {
+ if (s->pos < stream->nout)
+ stream->nout = s->pos;
+ memcpy(stream->out, s->win + s->posout, stream->nout);
+ s->pos -= stream->nout;
+ if (s->pos)
+ s->posout += stream->nout;
+ else
+ s->posout = 0;
+ }
+ if (n == FlateOk || n == FlateErr) {
+ if (s->nbits || s->src < s->srcend) {
+ s->nbits /= 8;
+ stream->in = s->src - s->nbits;
+ stream->nin = s->srcend - s->src + s->nbits;
+ }
+ stream->err = s->err;
+ free(s);
+ stream->state = 0;
+ }
+ return n;
}
typedef struct {
- ushort dist;
- ushort len;
+ ushort dist;
+ ushort len;
} Match;
typedef struct {
- ushort n;
- ushort bits;
+ ushort n;
+ ushort bits;
} LzCode;
typedef struct {
- int pos; /* position in input src */
- int startpos; /* block start pos in input src */
- int endpos; /* end of available bytes in src */
- int skip; /* skipped hash chain updates (until next iter) */
- Match prevm; /* previous (deferred) match */
- int state; /* prev return value */
- int eof; /* end of input */
- uchar *in; /* input data (not yet in src) */
- uchar *inend;
- uint bits; /* for output */
- int nbits; /* for output */
- uchar *dst; /* compressed output (position in dstbuf) */
- uchar *dstbegin; /* start position of unflushed data in dstbuf */
- LzCode *lz; /* current pos in lzbuf */
- int nlit; /* literal run length in lzbuf */
- ushort head[HashSize]; /* position of hash chain heads */
- ushort chain[WinSize]; /* hash chain */
- ushort lfreq[Nlitlen];
- ushort dfreq[Ndist];
- uchar src[SrcSize]; /* input buf */
- uchar dstbuf[DstSize];
- LzCode lzbuf[LzSize]; /* literal run length, match len, match dist */
+ int pos; /* position in input src */
+ int startpos; /* block start pos in input src */
+ int endpos; /* end of available bytes in src */
+ int skip; /* skipped hash chain updates (until next iter) */
+ Match prevm; /* previous (deferred) match */
+ int state; /* prev return value */
+ int eof; /* end of input */
+ uchar *in; /* input data (not yet in src) */
+ uchar *inend;
+ uint bits; /* for output */
+ int nbits; /* for output */
+ uchar *dst; /* compressed output (position in dstbuf) */
+ uchar *dstbegin; /* start position of unflushed data in dstbuf */
+ LzCode *lz; /* current pos in lzbuf */
+ int nlit; /* literal run length in lzbuf */
+ ushort head[HashSize]; /* position of hash chain heads */
+ ushort chain[WinSize]; /* hash chain */
+ ushort lfreq[Nlitlen];
+ ushort dfreq[Ndist];
+ uchar src[SrcSize]; /* input buf */
+ uchar dstbuf[DstSize];
+ LzCode lzbuf[LzSize]; /* literal run length, match len, match dist */
} State;
static uchar fixllen[Nlitlen]; /* fixed lit/len huffman code tree */
static ushort fixdcode[Ndist];
static uint revcode(uint c, int n) {
- int i;
- uint r = 0;
-
- for (i = 0; i < n; i++) {
- r = (r << 1) | (c & 1);
- c >>= 1;
- }
- return r;
+ int i;
+ uint r = 0;
+
+ for (i = 0; i < n; i++) {
+ r = (r << 1) | (c & 1);
+ c >>= 1;
+ }
+ return r;
}
/* build huffman code tree from code lengths */
static void huffcodes(ushort *codes, const uchar *lens, int n) {
- int c[CodeBits];
- int i, code, count;
-
- /* count code lengths and calc first code for each length */
- for (i = 0; i < CodeBits; i++)
- c[i] = 0;
- for (i = 0; i < n; i++)
- c[lens[i]]++;
- for (code = 0, i = 1; i < CodeBits; i++) {
- count = c[i];
- c[i] = code;
- code += count;
- if (code > (1 << i))
- abort(); /* over-subscribed */
- code <<= 1;
- }
- if (code < (1 << i))
- /* incomplete */;
-
- for (i = 0; i < n; i++)
- if (lens[i])
- codes[i] = revcode(c[lens[i]]++, lens[i]);
- else
- codes[i] = 0;
+ int c[CodeBits];
+ int i, code, count;
+
+ /* count code lengths and calc first code for each length */
+ for (i = 0; i < CodeBits; i++)
+ c[i] = 0;
+ for (i = 0; i < n; i++)
+ c[lens[i]]++;
+ for (code = 0, i = 1; i < CodeBits; i++) {
+ count = c[i];
+ c[i] = code;
+ code += count;
+ if (code > (1 << i))
+ abort(); /* over-subscribed */
+ code <<= 1;
+ }
+ if (code < (1 << i))
+ /* incomplete */;
+
+ for (i = 0; i < n; i++)
+ if (lens[i])
+ codes[i] = revcode(c[lens[i]]++, lens[i]);
+ else
+ codes[i] = 0;
}
static int heapparent(int n) {return (n - 2)/4 * 2;}
static int heapchild(int n) {return 2 * n + 2;}
static int heappush(int *heap, int len, int w, int n) {
- int p, c, tmp;
-
- c = len;
- heap[len++] = n;
- heap[len++] = w;
- while (c > 0) {
- p = heapparent(c);
- if (heap[c+1] < heap[p+1]) {
- tmp = heap[c]; heap[c] = heap[p]; heap[p] = tmp;
- tmp = heap[c+1]; heap[c+1] = heap[p+1]; heap[p+1] = tmp;
- c = p;
- } else
- break;
- }
- return len;
+ int p, c, tmp;
+
+ c = len;
+ heap[len++] = n;
+ heap[len++] = w;
+ while (c > 0) {
+ p = heapparent(c);
+ if (heap[c+1] < heap[p+1]) {
+ tmp = heap[c]; heap[c] = heap[p]; heap[p] = tmp;
+ tmp = heap[c+1]; heap[c+1] = heap[p+1]; heap[p+1] = tmp;
+ c = p;
+ } else
+ break;
+ }
+ return len;
}
static int heappop(int *heap, int len, int *w, int *n) {
- int p, c, tmp;
-
- *n = heap[0];
- *w = heap[1];
- heap[1] = heap[--len];
- heap[0] = heap[--len];
- p = 0;
- for (;;) {
- c = heapchild(p);
- if (c >= len)
- break;
- if (c+2 < len && heap[c+3] < heap[c+1])
- c += 2;
- if (heap[p+1] > heap[c+1]) {
- tmp = heap[p]; heap[p] = heap[c]; heap[c] = tmp;
- tmp = heap[p+1]; heap[p+1] = heap[c+1]; heap[c+1] = tmp;
- } else
- break;
- p = c;
- }
- return len;
+ int p, c, tmp;
+
+ *n = heap[0];
+ *w = heap[1];
+ heap[1] = heap[--len];
+ heap[0] = heap[--len];
+ p = 0;
+ for (;;) {
+ c = heapchild(p);
+ if (c >= len)
+ break;
+ if (c+2 < len && heap[c+3] < heap[c+1])
+ c += 2;
+ if (heap[p+1] > heap[c+1]) {
+ tmp = heap[p]; heap[p] = heap[c]; heap[c] = tmp;
+ tmp = heap[p+1]; heap[p+1] = heap[c+1]; heap[c+1] = tmp;
+ } else
+ break;
+ p = c;
+ }
+ return len;
}
/* symbol frequencies -> code lengths (limited to 255) */
static void hufflens(uchar *lens, ushort *freqs, int nsym, int limit) {
- /* 2 <= nsym <= Nlitlen, log(nsym) <= limit <= CodeBits-1 */
- int parent[2*Nlitlen-1];
- int count[CodeBits];
- int heap[2*Nlitlen];
- int n, len, top, overflow;
- int i, j;
- int wi, wj;
-
- for (n = 0; n < limit+1; n++)
- count[n] = 0;
- for (len = n = 0; n < nsym; n++)
- if (freqs[n] > 0)
- len = heappush(heap, len, freqs[n], n);
- else
- lens[n] = 0;
- /* deflate: fewer than two symbols: add new */
- for (n = 0; len < 4; n++)
- if (freqs[n] == 0)
- len = heappush(heap, len, ++freqs[n], n);
- /* build code tree */
- top = len;
- for (n = nsym; len > 2; n++) {
- len = heappop(heap, len, &wi, &i);
- len = heappop(heap, len, &wj, &j);
- parent[i] = n;
- parent[j] = n;
- len = heappush(heap, len, wi + wj, n);
- /* keep an ordered list of nodes at the end */
- heap[len+1] = i;
- heap[len] = j;
- }
- /* calc code lengths (deflate: with limit) */
- overflow = 0;
- parent[--n] = 0;
- for (i = 2; i < top; i++) {
- n = heap[i];
- if (n >= nsym) {
- /* overwrite parent index with length */
- parent[n] = parent[parent[n]] + 1;
- if (parent[n] > limit)
- overflow++;
- } else {
- lens[n] = parent[parent[n]] + 1;
- if (lens[n] > limit) {
- lens[n] = limit;
- overflow++;
- }
- count[lens[n]]++;
- }
- }
- if (overflow == 0)
- return;
- /* modify code tree to fix overflow (from zlib) */
- while (overflow > 0) {
- for (n = limit-1; count[n] == 0; n--);
- count[n]--;
- count[n+1] += 2;
- count[limit]--;
- overflow -= 2;
- }
- for (len = limit; len > 0; len--)
- for (i = count[len]; i > 0;) {
- n = heap[--top];
- if (n < nsym) {
- lens[n] = len;
- i--;
- }
- }
+ /* 2 <= nsym <= Nlitlen, log(nsym) <= limit <= CodeBits-1 */
+ int parent[2*Nlitlen-1];
+ int count[CodeBits];
+ int heap[2*Nlitlen];
+ int n, len, top, overflow;
+ int i, j;
+ int wi, wj;
+
+ for (n = 0; n < limit+1; n++)
+ count[n] = 0;
+ for (len = n = 0; n < nsym; n++)
+ if (freqs[n] > 0)
+ len = heappush(heap, len, freqs[n], n);
+ else
+ lens[n] = 0;
+ /* deflate: fewer than two symbols: add new */
+ for (n = 0; len < 4; n++)
+ if (freqs[n] == 0)
+ len = heappush(heap, len, ++freqs[n], n);
+ /* build code tree */
+ top = len;
+ for (n = nsym; len > 2; n++) {
+ len = heappop(heap, len, &wi, &i);
+ len = heappop(heap, len, &wj, &j);
+ parent[i] = n;
+ parent[j] = n;
+ len = heappush(heap, len, wi + wj, n);
+ /* keep an ordered list of nodes at the end */
+ heap[len+1] = i;
+ heap[len] = j;
+ }
+ /* calc code lengths (deflate: with limit) */
+ overflow = 0;
+ parent[--n] = 0;
+ for (i = 2; i < top; i++) {
+ n = heap[i];
+ if (n >= nsym) {
+ /* overwrite parent index with length */
+ parent[n] = parent[parent[n]] + 1;
+ if (parent[n] > limit)
+ overflow++;
+ } else {
+ lens[n] = parent[parent[n]] + 1;
+ if (lens[n] > limit) {
+ lens[n] = limit;
+ overflow++;
+ }
+ count[lens[n]]++;
+ }
+ }
+ if (overflow == 0)
+ return;
+ /* modify code tree to fix overflow (from zlib) */
+ while (overflow > 0) {
+ for (n = limit-1; count[n] == 0; n--);
+ count[n]--;
+ count[n+1] += 2;
+ count[limit]--;
+ overflow -= 2;
+ }
+ for (len = limit; len > 0; len--)
+ for (i = count[len]; i > 0;) {
+ n = heap[--top];
+ if (n < nsym) {
+ lens[n] = len;
+ i--;
+ }
+ }
}
/* output n (<= 16) bits */
static void putbits(State *s, uint bits, int n) {
- s->bits |= bits << s->nbits;
- s->nbits += n;
- while (s->nbits >= 8) {
- *s->dst++ = s->bits & 0xff;
- s->bits >>= 8;
- s->nbits -= 8;
- }
+ s->bits |= bits << s->nbits;
+ s->nbits += n;
+ while (s->nbits >= 8) {
+ *s->dst++ = s->bits & 0xff;
+ s->bits >>= 8;
+ s->nbits -= 8;
+ }
}
/* run length encode literal and dist code lengths into codes and extra */
static int clencodes(uchar *codes, uchar *extra, uchar *llen, int nlit, uchar *dlen, int ndist) {
- int i, c, r, rr;
- int n = 0;
-
- for (i = 0; i < nlit; i++)
- codes[i] = llen[i];
- for (i = 0; i < ndist; i++)
- codes[nlit + i] = dlen[i];
- for (i = 0; i < nlit + ndist;) {
- c = codes[i];
- for (r = 1; i + r < nlit + ndist && codes[i + r] == c; r++);
- i += r;
- if (c == 0) {
- while (r >= 11) {
- rr = r > 138 ? 138 : r;
- codes[n] = 18;
- extra[n++] = rr - 11;
- r -= rr;
- }
- if (r >= 3) {
- codes[n] = 17;
- extra[n++] = r - 3;
- r = 0;
- }
- }
- while (r--) {
- codes[n++] = c;
- while (r >= 3) {
- rr = r > 6 ? 6 : r;
- codes[n] = 16;
- extra[n++] = rr - 3;
- r -= rr;
- }
- }
- }
- return n;
+ int i, c, r, rr;
+ int n = 0;
+
+ for (i = 0; i < nlit; i++)
+ codes[i] = llen[i];
+ for (i = 0; i < ndist; i++)
+ codes[nlit + i] = dlen[i];
+ for (i = 0; i < nlit + ndist;) {
+ c = codes[i];
+ for (r = 1; i + r < nlit + ndist && codes[i + r] == c; r++);
+ i += r;
+ if (c == 0) {
+ while (r >= 11) {
+ rr = r > 138 ? 138 : r;
+ codes[n] = 18;
+ extra[n++] = rr - 11;
+ r -= rr;
+ }
+ if (r >= 3) {
+ codes[n] = 17;
+ extra[n++] = r - 3;
+ r = 0;
+ }
+ }
+ while (r--) {
+ codes[n++] = c;
+ while (r >= 3) {
+ rr = r > 6 ? 6 : r;
+ codes[n] = 16;
+ extra[n++] = rr - 3;
+ r -= rr;
+ }
+ }
+ }
+ return n;
}
/* compress block data into s->dstbuf using given codes */
static void putblock(State *s, ushort *lcode, uchar *llen, ushort *dcode, uchar *dlen) {
- int n;
- LzCode *lz;
- uchar *p;
-
- for (lz = s->lzbuf, p = s->src + s->startpos; lz != s->lz; lz++)
- if (lz->bits & LzLitFlag)
- for (n = lz->n; n > 0; n--, p++)
- putbits(s, lcode[*p], llen[*p]);
- else {
- p += lenbase[lz->n] + lz->bits;
- putbits(s, lcode[Nlit + lz->n + 1], llen[Nlit + lz->n + 1]);
- putbits(s, lz->bits, lenbits[lz->n]);
- lz++;
- putbits(s, dcode[lz->n], dlen[lz->n]);
- putbits(s, lz->bits, distbits[lz->n]);
- }
- putbits(s, lcode[EOB], llen[EOB]);
+ int n;
+ LzCode *lz;
+ uchar *p;
+
+ for (lz = s->lzbuf, p = s->src + s->startpos; lz != s->lz; lz++)
+ if (lz->bits & LzLitFlag)
+ for (n = lz->n; n > 0; n--, p++)
+ putbits(s, lcode[*p], llen[*p]);
+ else {
+ p += lenbase[lz->n] + lz->bits;
+ putbits(s, lcode[Nlit + lz->n + 1], llen[Nlit + lz->n + 1]);
+ putbits(s, lz->bits, lenbits[lz->n]);
+ lz++;
+ putbits(s, dcode[lz->n], dlen[lz->n]);
+ putbits(s, lz->bits, distbits[lz->n]);
+ }
+ putbits(s, lcode[EOB], llen[EOB]);
}
/* build code trees and select dynamic/fixed/uncompressed block compression */
static void deflate_block(State *s) {
- uchar codes[Nlitlen + Ndist], extra[Nlitlen + Ndist];
- uchar llen[Nlitlen], dlen[Ndist], clen[Nclen];
- ushort cfreq[Nclen];
- /* freq can be overwritten by code */
- ushort *lcode = s->lfreq, *dcode = s->dfreq, *ccode = cfreq;
- int i, c, n, ncodes;
- int nlit, ndist, nclen;
- LzCode *lz;
- uchar *p;
- int dynsize, fixsize, uncsize;
- int blocklen = s->pos - s->startpos;
+ uchar codes[Nlitlen + Ndist], extra[Nlitlen + Ndist];
+ uchar llen[Nlitlen], dlen[Ndist], clen[Nclen];
+ ushort cfreq[Nclen];
+ /* freq can be overwritten by code */
+ ushort *lcode = s->lfreq, *dcode = s->dfreq, *ccode = cfreq;
+ int i, c, n, ncodes;
+ int nlit, ndist, nclen;
+ LzCode *lz;
+ uchar *p;
+ int dynsize, fixsize, uncsize;
+ int blocklen = s->pos - s->startpos;
/* int dyntree; */
- /* calc dynamic codes */
- hufflens(llen, s->lfreq, Nlitlen, CodeBits-1);
- hufflens(dlen, s->dfreq, Ndist, CodeBits-1);
- huffcodes(lcode, llen, Nlitlen);
- huffcodes(dcode, dlen, Ndist);
- for (nlit = Nlitlen; nlit > Nlit && llen[nlit-1] == 0; nlit--);
- for (ndist = Ndist; ndist > 1 && dlen[ndist-1] == 0; ndist--);
- ncodes = clencodes(codes, extra, llen, nlit, dlen, ndist);
- memset(cfreq, 0, sizeof(cfreq));
- for (i = 0; i < ncodes; i++)
- cfreq[codes[i]]++;
- hufflens(clen, cfreq, Nclen, 7);
- huffcodes(ccode, clen, Nclen);
- for (nclen = Nclen; nclen > 4 && clen[clenorder[nclen-1]] == 0; nclen--);
-
- /* calc compressed size */
- uncsize = 3 + 16 + 8 * blocklen + (16 - 3 - s->nbits) % 8; /* byte aligned */
- fixsize = 3;
- dynsize = 3 + 5 + 5 + 4 + 3 * nclen;
- for (i = 0; i < ncodes; i++) {
- c = codes[i];
- dynsize += clen[c];
- if (c == 16)
- dynsize += 2;
- if (c == 17)
- dynsize += 3;
- if (c == 18)
- dynsize += 7;
- }
+ /* calc dynamic codes */
+ hufflens(llen, s->lfreq, Nlitlen, CodeBits-1);
+ hufflens(dlen, s->dfreq, Ndist, CodeBits-1);
+ huffcodes(lcode, llen, Nlitlen);
+ huffcodes(dcode, dlen, Ndist);
+ for (nlit = Nlitlen; nlit > Nlit && llen[nlit-1] == 0; nlit--);
+ for (ndist = Ndist; ndist > 1 && dlen[ndist-1] == 0; ndist--);
+ ncodes = clencodes(codes, extra, llen, nlit, dlen, ndist);
+ memset(cfreq, 0, sizeof(cfreq));
+ for (i = 0; i < ncodes; i++)
+ cfreq[codes[i]]++;
+ hufflens(clen, cfreq, Nclen, 7);
+ huffcodes(ccode, clen, Nclen);
+ for (nclen = Nclen; nclen > 4 && clen[clenorder[nclen-1]] == 0; nclen--);
+
+ /* calc compressed size */
+ uncsize = 3 + 16 + 8 * blocklen + (16 - 3 - s->nbits) % 8; /* byte aligned */
+ fixsize = 3;
+ dynsize = 3 + 5 + 5 + 4 + 3 * nclen;
+ for (i = 0; i < ncodes; i++) {
+ c = codes[i];
+ dynsize += clen[c];
+ if (c == 16)
+ dynsize += 2;
+ if (c == 17)
+ dynsize += 3;
+ if (c == 18)
+ dynsize += 7;
+ }
/* dyntree = dynsize - 3; */
- for (lz = s->lzbuf, p = s->src + s->startpos; lz != s->lz; lz++)
- if (lz->bits & LzLitFlag)
- for (n = lz->n; n > 0; n--, p++) {
- fixsize += fixllen[*p];
- dynsize += llen[*p];
- }
- else {
- p += lenbase[lz->n] + lz->bits;
- fixsize += fixllen[Nlit + lz->n + 1];
- dynsize += llen[Nlit + lz->n + 1];
- fixsize += lenbits[lz->n];
- dynsize += lenbits[lz->n];
- lz++;
- fixsize += fixdlen[lz->n];
- dynsize += dlen[lz->n];
- fixsize += distbits[lz->n];
- dynsize += distbits[lz->n];
- }
- fixsize += fixllen[EOB];
- dynsize += llen[EOB];
-
- /* emit block */
- putbits(s, s->eof && s->pos == s->endpos, 1);
- if (dynsize < fixsize && dynsize < uncsize) {
- /* dynamic code */
- putbits(s, 2, 2);
- putbits(s, nlit - 257, 5);
- putbits(s, ndist - 1, 5);
- putbits(s, nclen - 4, 4);
- for (i = 0; i < nclen; i++)
- putbits(s, clen[clenorder[i]], 3);
- for (i = 0; i < ncodes; i++) {
- c = codes[i];
- putbits(s, ccode[c], clen[c]);
- if (c == 16)
- putbits(s, extra[i], 2);
- if (c == 17)
- putbits(s, extra[i], 3);
- if (c == 18)
- putbits(s, extra[i], 7);
- }
- putblock(s, lcode, llen, dcode, dlen);
- } else if (fixsize < uncsize) {
- /* fixed code */
- putbits(s, 1, 2);
- putblock(s, fixlcode, fixllen, fixdcode, fixdlen);
- } else {
- /* uncompressed */
- putbits(s, 0, 2);
- putbits(s, 0, 7); /* align to byte boundary */
- s->nbits = 0;
- putbits(s, blocklen, 16);
- putbits(s, ~blocklen & 0xffff, 16);
- memcpy(s->dst, s->src + s->startpos, blocklen);
- s->dst += blocklen;
- }
+ for (lz = s->lzbuf, p = s->src + s->startpos; lz != s->lz; lz++)
+ if (lz->bits & LzLitFlag)
+ for (n = lz->n; n > 0; n--, p++) {
+ fixsize += fixllen[*p];
+ dynsize += llen[*p];
+ }
+ else {
+ p += lenbase[lz->n] + lz->bits;
+ fixsize += fixllen[Nlit + lz->n + 1];
+ dynsize += llen[Nlit + lz->n + 1];
+ fixsize += lenbits[lz->n];
+ dynsize += lenbits[lz->n];
+ lz++;
+ fixsize += fixdlen[lz->n];
+ dynsize += dlen[lz->n];
+ fixsize += distbits[lz->n];
+ dynsize += distbits[lz->n];
+ }
+ fixsize += fixllen[EOB];
+ dynsize += llen[EOB];
+
+ /* emit block */
+ putbits(s, s->eof && s->pos == s->endpos, 1);
+ if (dynsize < fixsize && dynsize < uncsize) {
+ /* dynamic code */
+ putbits(s, 2, 2);
+ putbits(s, nlit - 257, 5);
+ putbits(s, ndist - 1, 5);
+ putbits(s, nclen - 4, 4);
+ for (i = 0; i < nclen; i++)
+ putbits(s, clen[clenorder[i]], 3);
+ for (i = 0; i < ncodes; i++) {
+ c = codes[i];
+ putbits(s, ccode[c], clen[c]);
+ if (c == 16)
+ putbits(s, extra[i], 2);
+ if (c == 17)
+ putbits(s, extra[i], 3);
+ if (c == 18)
+ putbits(s, extra[i], 7);
+ }
+ putblock(s, lcode, llen, dcode, dlen);
+ } else if (fixsize < uncsize) {
+ /* fixed code */
+ putbits(s, 1, 2);
+ putblock(s, fixlcode, fixllen, fixdcode, fixdlen);
+ } else {
+ /* uncompressed */
+ putbits(s, 0, 2);
+ putbits(s, 0, 7); /* align to byte boundary */
+ s->nbits = 0;
+ putbits(s, blocklen, 16);
+ putbits(s, ~blocklen & 0xffff, 16);
+ memcpy(s->dst, s->src + s->startpos, blocklen);
+ s->dst += blocklen;
+ }
/*
fprintf(stderr, "blen:%d [%d,%d] lzlen:%d dynlen:%d (tree:%d rate:%.3f) fixlen:%d (rate:%.3f) unclen:%d (rate:%.3f)\n",
- blocklen, s->startpos, s->pos, s->lz - s->lzbuf, dynsize, dyntree, dynsize/(float)blocklen,
- fixsize, fixsize/(float)blocklen, uncsize, uncsize/(float)blocklen);
+ blocklen, s->startpos, s->pos, s->lz - s->lzbuf, dynsize, dyntree, dynsize/(float)blocklen,
+ fixsize, fixsize/(float)blocklen, uncsize, uncsize/(float)blocklen);
*/
}
/* find n in base */
static int bisect(ushort *base, int len, int n) {
- int lo = 0;
- int hi = len;
- int k;
-
- while (lo < hi) {
- k = (lo + hi) / 2;
- if (n < base[k])
- hi = k;
- else
- lo = k + 1;
- }
- return lo - 1;
+ int lo = 0;
+ int hi = len;
+ int k;
+
+ while (lo < hi) {
+ k = (lo + hi) / 2;
+ if (n < base[k])
+ hi = k;
+ else
+ lo = k + 1;
+ }
+ return lo - 1;
}
/* add literal run length to lzbuf */
static void flushlit(State *s) {
- if (s->nlit) {
- s->lz->bits = LzLitFlag;
- s->lz->n = s->nlit;
- s->lz++;
- s->nlit = 0;
- }
+ if (s->nlit) {
+ s->lz->bits = LzLitFlag;
+ s->lz->n = s->nlit;
+ s->lz++;
+ s->nlit = 0;
+ }
}
/* add match to lzbuf and update freq counts */
static void recordmatch(State *s, Match m) {
- int n;
+ int n;
/*fprintf(stderr, "m %d %d\n", m.len, m.dist);*/
- flushlit(s);
- n = bisect(lenbase, Nlen, m.len);
- s->lz->n = n;
- s->lz->bits = m.len - lenbase[n];
- s->lz++;
- s->lfreq[Nlit + n + 1]++;
- n = bisect(distbase, Ndist, m.dist);
- s->lz->n = n;
- s->lz->bits = m.dist - distbase[n];
- s->lz++;
- s->dfreq[n]++;
+ flushlit(s);
+ n = bisect(lenbase, Nlen, m.len);
+ s->lz->n = n;
+ s->lz->bits = m.len - lenbase[n];
+ s->lz++;
+ s->lfreq[Nlit + n + 1]++;
+ n = bisect(distbase, Ndist, m.dist);
+ s->lz->n = n;
+ s->lz->bits = m.dist - distbase[n];
+ s->lz++;
+ s->dfreq[n]++;
}
/* update literal run length */
static void recordlit(State *s, int c) {
/*fprintf(stderr, "l %c\n", c);*/
- s->nlit++;
- s->lfreq[c]++;
+ s->nlit++;
+ s->lfreq[c]++;
}
/* multiplicative hash (using a prime close to golden ratio * 2^32) */
static int gethash(uchar *p) {
- return (0x9e3779b1 * ((p[0]<<16) + (p[1]<<8) + p[2]) >> (32 - HashBits)) % HashSize;
+ return (0x9e3779b1 * ((p[0]<<16) + (p[1]<<8) + p[2]) >> (32 - HashBits)) % HashSize;
}
/* update hash chain at the current position */
static int updatechain(State *s) {
- int hash, next = 0, p = s->pos, i;
-
- if (s->endpos - p < MinMatch)
- p = s->endpos - MinMatch;
- for (i = s->pos - s->skip; i <= p; i++) {
- hash = gethash(s->src + i);
- next = s->head[hash];
- s->head[hash] = i;
- if (next >= i || i - next >= MaxDist)
- next = 0;
- s->chain[i % WinSize] = next;
- }
- s->skip = 0;
- return next;
+ int hash, next = 0, p = s->pos, i;
+
+ if (s->endpos - p < MinMatch)
+ p = s->endpos - MinMatch;
+ for (i = s->pos - s->skip; i <= p; i++) {
+ hash = gethash(s->src + i);
+ next = s->head[hash];
+ s->head[hash] = i;
+ if (next >= i || i - next >= MaxDist)
+ next = 0;
+ s->chain[i % WinSize] = next;
+ }
+ s->skip = 0;
+ return next;
}
/* find longest match, next position in the hash chain is given */
static Match getmatch(State *s, int next) {
- Match m = {0, MinMatch-1};
- int len;
- int limit = s->pos - MaxDist;
- int chainlen = MaxChainLen;
- uchar *q;
- uchar *p = s->src + s->pos;
- uchar *end = p + MaxMatch;
-
- do {
- q = s->src + next;
+ Match m = {0, MinMatch-1};
+ int len;
+ int limit = s->pos - MaxDist;
+ int chainlen = MaxChainLen;
+ uchar *q;
+ uchar *p = s->src + s->pos;
+ uchar *end = p + MaxMatch;
+
+ do {
+ q = s->src + next;
/*fprintf(stderr,"match: next:%d pos:%d limit:%d\n", next, s->pos, limit);*/
- /* next match should be at least m.len+1 long */
- if (q[m.len] != p[m.len] || q[m.len-1] != p[m.len-1] || q[0] != p[0])
- continue;
- while (++p != end && *++q == *p);
- len = MaxMatch - (end - p);
- p -= len;
+ /* next match should be at least m.len+1 long */
+ if (q[m.len] != p[m.len] || q[m.len-1] != p[m.len-1] || q[0] != p[0])
+ continue;
+ while (++p != end && *++q == *p);
+ len = MaxMatch - (end - p);
+ p -= len;
/*fprintf(stderr,"match: len:%d dist:%d\n", len, s->pos - next);*/
- if (len > m.len) {
- m.dist = s->pos - next;
- m.len = len;
- if (s->pos + len >= s->endpos) { /* TODO: overflow */
- m.len = s->endpos - s->pos;
- return m;
- }
- if (len == MaxMatch)
- return m;
- }
- } while ((next = s->chain[next % WinSize]) > limit && --chainlen);
- if (m.len < MinMatch || (m.len == MinMatch && m.dist > BigDist))
- m.len = 0;
- return m;
+ if (len > m.len) {
+ m.dist = s->pos - next;
+ m.len = len;
+ if (s->pos + len >= s->endpos) { /* TODO: overflow */
+ m.len = s->endpos - s->pos;
+ return m;
+ }
+ if (len == MaxMatch)
+ return m;
+ }
+ } while ((next = s->chain[next % WinSize]) > limit && --chainlen);
+ if (m.len < MinMatch || (m.len == MinMatch && m.dist > BigDist))
+ m.len = 0;
+ return m;
}
static void startblock(State *s) {
- s->startpos = s->pos;
- s->dst = s->dstbegin = s->dstbuf;
- s->lz = s->lzbuf;
- s->nlit = 0;
- memset(s->lfreq, 0, sizeof(s->lfreq));
- memset(s->dfreq, 0, sizeof(s->dfreq));
- s->lfreq[EOB]++;
+ s->startpos = s->pos;
+ s->dst = s->dstbegin = s->dstbuf;
+ s->lz = s->lzbuf;
+ s->nlit = 0;
+ memset(s->lfreq, 0, sizeof(s->lfreq));
+ memset(s->dfreq, 0, sizeof(s->dfreq));
+ s->lfreq[EOB]++;
}
static int shiftwin(State *s) {
- int n;
-
- if (s->startpos < WinSize)
- return 0;
- memmove(s->src, s->src + WinSize, SrcSize - WinSize);
- for (n = 0; n < HashSize; n++)
- s->head[n] = s->head[n] > WinSize ? s->head[n] - WinSize : 0;
- for (n = 0; n < WinSize; n++)
- s->chain[n] = s->chain[n] > WinSize ? s->chain[n] - WinSize : 0;
- s->pos -= WinSize;
- s->startpos -= WinSize;
- s->endpos -= WinSize;
- return 1;
+ int n;
+
+ if (s->startpos < WinSize)
+ return 0;
+ memmove(s->src, s->src + WinSize, SrcSize - WinSize);
+ for (n = 0; n < HashSize; n++)
+ s->head[n] = s->head[n] > WinSize ? s->head[n] - WinSize : 0;
+ for (n = 0; n < WinSize; n++)
+ s->chain[n] = s->chain[n] > WinSize ? s->chain[n] - WinSize : 0;
+ s->pos -= WinSize;
+ s->startpos -= WinSize;
+ s->endpos -= WinSize;
+ return 1;
}
static int endblock(State *s) {
- if ((s->pos >= 2*WinSize && !shiftwin(s)) || s->pos - s->startpos >= BlockSize ||
- s->lz - s->lzbuf >= LzGuard || (s->eof && s->pos == s->endpos)) {
- /* deflate block */
- flushlit(s);
- if (s->prevm.len)
- s->pos--;
- deflate_block(s);
- if (s->eof && s->pos == s->endpos)
- putbits(s, 0, 7);
- return 1;
- }
- return 0;
+ if ((s->pos >= 2*WinSize && !shiftwin(s)) || s->pos - s->startpos >= BlockSize ||
+ s->lz - s->lzbuf >= LzGuard || (s->eof && s->pos == s->endpos)) {
+ /* deflate block */
+ flushlit(s);
+ if (s->prevm.len)
+ s->pos--;
+ deflate_block(s);
+ if (s->eof && s->pos == s->endpos)
+ putbits(s, 0, 7);
+ return 1;
+ }
+ return 0;
}
static int fillsrc(State *s) {
- int n, k;
-
- if (s->endpos < SrcSize && !s->eof) {
- n = SrcSize - s->endpos;
- k = s->inend - s->in;
- if (n > k)
- n = k;
- memcpy(s->src + s->endpos, s->in, n);
- s->in += n;
- s->endpos += n;
- if (s->endpos < SrcSize)
- return 0;
- }
- return 1;
+ int n, k;
+
+ if (s->endpos < SrcSize && !s->eof) {
+ n = SrcSize - s->endpos;
+ k = s->inend - s->in;
+ if (n > k)
+ n = k;
+ memcpy(s->src + s->endpos, s->in, n);
+ s->in += n;
+ s->endpos += n;
+ if (s->endpos < SrcSize)
+ return 0;
+ }
+ return 1;
}
static int calcguard(State *s) {
- int p = s->endpos - MaxMatch;
- int q = s->startpos + BlockSize;
+ int p = s->endpos - MaxMatch;
+ int q = s->startpos + BlockSize;
- return p < q ? p : q;
+ return p < q ? p : q;
}
/* deflate compress from s->src into s->dstbuf */
static int deflate_state(State *s) {
- Match m;
- int next;
- int guard;
-
- if (s->state == FlateIn)
- s->eof = s->in == s->inend;
- else if (s->state == FlateOut) {
- if (s->dstbegin < s->dst)
- return (s->state = FlateOut);
- if (s->eof && s->pos == s->endpos)
- return (s->state = FlateOk);
- startblock(s);
- if (s->prevm.len)
- s->pos++;
- } else
- return s->state;
-
- guard = calcguard(s);
- for (;;) {
- if (s->pos >= guard || s->lz - s->lzbuf >= LzGuard) {
+ Match m;
+ int next;
+ int guard;
+
+ if (s->state == FlateIn)
+ s->eof = s->in == s->inend;
+ else if (s->state == FlateOut) {
+ if (s->dstbegin < s->dst)
+ return (s->state = FlateOut);
+ if (s->eof && s->pos == s->endpos)
+ return (s->state = FlateOk);
+ startblock(s);
+ if (s->prevm.len)
+ s->pos++;
+ } else
+ return s->state;
+
+ guard = calcguard(s);
+ for (;;) {
+ if (s->pos >= guard || s->lz - s->lzbuf >= LzGuard) {
/*fprintf(stderr,"guard:%d pos:%d len:%d lzlen:%d end:%d start:%d nin:%d eof:%d\n", guard, s->pos, s->pos - s->startpos, s->lz - s->lzbuf, s->endpos, s->startpos, s->inend - s->in, s->eof);*/
- if (endblock(s))
- return (s->state = FlateOut);
- if (!fillsrc(s))
- return (s->state = FlateIn);
- guard = calcguard(s);
- }
- next = updatechain(s);
- if (next)
- m = getmatch(s, next);
- if (next && m.len > s->prevm.len) {
- if (s->prevm.len)
- recordlit(s, s->src[s->pos-1]);
- s->prevm = m;
- } else if (s->prevm.len) {
- recordmatch(s, s->prevm);
- s->skip = s->prevm.len - 2;
- s->prevm.len = 0;
- s->pos += s->skip;
- } else
- recordlit(s, s->src[s->pos]);
- s->pos++;
- }
+ if (endblock(s))
+ return (s->state = FlateOut);
+ if (!fillsrc(s))
+ return (s->state = FlateIn);
+ guard = calcguard(s);
+ }
+ next = updatechain(s);
+ if (next)
+ m = getmatch(s, next);
+ if (next && m.len > s->prevm.len) {
+ if (s->prevm.len)
+ recordlit(s, s->src[s->pos-1]);
+ s->prevm = m;
+ } else if (s->prevm.len) {
+ recordmatch(s, s->prevm);
+ s->skip = s->prevm.len - 2;
+ s->prevm.len = 0;
+ s->pos += s->skip;
+ } else
+ recordlit(s, s->src[s->pos]);
+ s->pos++;
+ }
}
/* alloc and init state */
static State *alloc_state(void) {
- State *s = malloc(sizeof(State));
- int i;
-
- if (!s)
- return s;
- memset(s->chain, 0, sizeof(s->chain));
- memset(s->head, 0, sizeof(s->head));
- s->bits = s->nbits = 0;
- /* TODO: globals */
- if (fixllen[0] == 0) {
- for (i = 0; i < 144; i++)
- fixllen[i] = 8;
- for (; i < 256; i++)
- fixllen[i] = 9;
- for (; i < 280; i++)
- fixllen[i] = 7;
- for (; i < Nlitlen; i++)
- fixllen[i] = 8;
- for (i = 0; i < Ndist; i++)
- fixdlen[i] = 5;
- huffcodes(fixlcode, fixllen, Nlitlen);
- huffcodes(fixdcode, fixdlen, Ndist);
- }
- s->state = FlateOut;
- s->in = s->inend = 0;
- s->dst = s->dstbegin = s->dstbuf;
- s->pos = s->startpos = s->endpos = WinSize;
- s->eof = 0;
- s->skip = 0;
- s->prevm.len = 0;
- return s;
+ State *s = malloc(sizeof(State));
+ int i;
+
+ if (!s)
+ return s;
+ memset(s->chain, 0, sizeof(s->chain));
+ memset(s->head, 0, sizeof(s->head));
+ s->bits = s->nbits = 0;
+ /* TODO: globals */
+ if (fixllen[0] == 0) {
+ for (i = 0; i < 144; i++)
+ fixllen[i] = 8;
+ for (; i < 256; i++)
+ fixllen[i] = 9;
+ for (; i < 280; i++)
+ fixllen[i] = 7;
+ for (; i < Nlitlen; i++)
+ fixllen[i] = 8;
+ for (i = 0; i < Ndist; i++)
+ fixdlen[i] = 5;
+ huffcodes(fixlcode, fixllen, Nlitlen);
+ huffcodes(fixdcode, fixdlen, Ndist);
+ }
+ s->state = FlateOut;
+ s->in = s->inend = 0;
+ s->dst = s->dstbegin = s->dstbuf;
+ s->pos = s->startpos = s->endpos = WinSize;
+ s->eof = 0;
+ s->skip = 0;
+ s->prevm.len = 0;
+ return s;
}
/* extern */
int deflate(FlateStream *stream) {
- State *s = stream->state;
- int n, k;
-
- if (stream->err) {
- free(s);
- stream->state = 0;
- return FlateErr;
- }
- if (!s) {
- s = stream->state = alloc_state();
- if (!s)
- return stream->err = "no mem.", FlateErr;
- }
- if (stream->nin) {
- s->in = stream->in;
- s->inend = s->in + stream->nin;
- stream->nin = 0;
- }
- n = deflate_state(s);
- if (n == FlateOut) {
- k = s->dst - s->dstbegin;
- if (k < stream->nout)
- stream->nout = k;
- memcpy(stream->out, s->dstbegin, stream->nout);
- s->dstbegin += stream->nout;
- }
- if (n == FlateOk || n == FlateErr) {
- free(s);
- stream->state = 0;
- }
- return n;
+ State *s = stream->state;
+ int n, k;
+
+ if (stream->err) {
+ free(s);
+ stream->state = 0;
+ return FlateErr;
+ }
+ if (!s) {
+ s = stream->state = alloc_state();
+ if (!s)
+ return stream->err = "no mem.", FlateErr;
+ }
+ if (stream->nin) {
+ s->in = stream->in;
+ s->inend = s->in + stream->nin;
+ stream->nin = 0;
+ }
+ n = deflate_state(s);
+ if (n == FlateOut) {
+ k = s->dst - s->dstbegin;
+ if (k < stream->nout)
+ stream->nout = k;
+ memcpy(stream->out, s->dstbegin, stream->nout);
+ s->dstbegin += stream->nout;
+ }
+ if (n == FlateOk || n == FlateErr) {
+ free(s);
+ stream->state = 0;
+ }
+ return n;
}
static void set32(uchar *p, uint n) {
- p[0] = n >> 24;
- p[1] = n >> 16;
- p[2] = n >> 8;
- p[3] = n;
+ p[0] = n >> 24;
+ p[1] = n >> 16;
+ p[2] = n >> 8;
+ p[3] = n;
}
static void set32le(uchar *p, uint n) {
- p[0] = n;
- p[1] = n >> 8;
- p[2] = n >> 16;
- p[3] = n >> 24;
+ p[0] = n;
+ p[1] = n >> 8;
+ p[2] = n >> 16;
+ p[3] = n >> 24;
}
static int check32(uchar *p, uint n) {
- return n == ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+ return n == ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
}
static int check32le(uchar *p, uint n) {
- return n == (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
+ return n == (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
}
enum {
- ZlibCM = 7 << 4,
- ZlibCINFO = 8,
- ZlibFLEV = 3 << 6,
- ZlibFDICT = 1 << 5,
- ZlibFCHK = 31 - (((ZlibCM | ZlibCINFO) << 8) | ZlibFLEV) % 31
+ ZlibCM = 7 << 4,
+ ZlibCINFO = 8,
+ ZlibFLEV = 3 << 6,
+ ZlibFDICT = 1 << 5,
+ ZlibFCHK = 31 - (((ZlibCM | ZlibCINFO) << 8) | ZlibFLEV) % 31
};
int deflate_zlib_header(uchar *p, int n) {
- if (n < 2)
- return FlateErr;
- p[0] = ZlibCM | ZlibCINFO; /* deflate method, 32K window size */
- p[1] = ZlibFLEV | ZlibFCHK; /* highest compression */
- return 2;
+ if (n < 2)
+ return FlateErr;
+ p[0] = ZlibCM | ZlibCINFO; /* deflate method, 32K window size */
+ p[1] = ZlibFLEV | ZlibFCHK; /* highest compression */
+ return 2;
}
int deflate_zlib_footer(uchar *p, int n, uint sum, uint len, uint zlen) {
- if (n < 4)
- return FlateErr;
- set32(p, sum);
- return 4;
+ if (n < 4)
+ return FlateErr;
+ set32(p, sum);
+ return 4;
}
int inflate_zlib_header(uchar *p, int n) {
- if (n < 2)
- return FlateErr;
- if (((p[0] << 8) | p[1]) % 31)
- return FlateErr;
- if ((p[0] & 0xf0) != ZlibCM || (p[0] & 0x0f) > ZlibCINFO)
- return FlateErr;
- if (p[1] & ZlibFDICT)
- return FlateErr;
- return 2;
+ if (n < 2)
+ return FlateErr;
+ if (((p[0] << 8) | p[1]) % 31)
+ return FlateErr;
+ if ((p[0] & 0xf0) != ZlibCM || (p[0] & 0x0f) > ZlibCINFO)
+ return FlateErr;
+ if (p[1] & ZlibFDICT)
+ return FlateErr;
+ return 2;
}
int inflate_zlib_footer(uchar *p, int n, uint sum, uint len, uint zlen) {
- if (n < 4 || !check32(p, sum))
- return FlateErr;
- return 4;
+ if (n < 4 || !check32(p, sum))
+ return FlateErr;
+ return 4;
}
enum {
- GZipID1 = 0x1f,
- GZipID2 = 0x8b,
- GZipCM = 8,
- GZipFHCRC = 1 << 1,
- GZipFEXTRA = 1 << 2,
- GZipFNAME = 1 << 3,
- GZipFCOMM = 1 << 4,
- GZipXFL = 2,
- GZipOS = 255
+ GZipID1 = 0x1f,
+ GZipID2 = 0x8b,
+ GZipCM = 8,
+ GZipFHCRC = 1 << 1,
+ GZipFEXTRA = 1 << 2,
+ GZipFNAME = 1 << 3,
+ GZipFCOMM = 1 << 4,
+ GZipXFL = 2,
+ GZipOS = 255
};
int deflate_gzip_header(uchar *p, int n) {
- if (n < 10)
- return FlateErr;
- memset(p, 0, 10);
- p[0] = GZipID1;
- p[1] = GZipID2;
- p[2] = GZipCM;
- p[8] = GZipXFL;
- p[9] = GZipOS;
- return 10;
+ if (n < 10)
+ return FlateErr;
+ memset(p, 0, 10);
+ p[0] = GZipID1;
+ p[1] = GZipID2;
+ p[2] = GZipCM;
+ p[8] = GZipXFL;
+ p[9] = GZipOS;
+ return 10;
}
int deflate_gzip_footer(uchar *p, int n, uint sum, uint len, uint zlen) {
- if (n < 8)
- return FlateErr;
- set32le(p, sum);
- set32le(p+4, len);
- return 8;
+ if (n < 8)
+ return FlateErr;
+ set32le(p, sum);
+ set32le(p+4, len);
+ return 8;
}
int inflate_gzip_header(uchar *p, int n) {
- int k = 10;
-
- if (k > n)
- return FlateErr;
- if (p[0] != GZipID1 || p[1] != GZipID2 || p[2] != GZipCM)
- return FlateErr;
- if (p[3] & GZipFEXTRA) {
- k += 2 + ((p[k] << 8) | p[k+1]);
- if (k > n)
- return FlateErr;
- }
- if (p[3] & GZipFNAME) {
- for (; k < n; k++)
- if (p[k] == 0)
- break;
- k++;
- if (k > n)
- return FlateErr;
- }
- if (p[3] & GZipFCOMM) {
- for (; k < n; k++)
- if (p[k] == 0)
- break;
- k++;
- if (k > n)
- return FlateErr;
- }
- if (p[3] & GZipFHCRC) {
- k += 2;
- if (k > n)
- return FlateErr;
- }
- return k;
+ int k = 10;
+
+ if (k > n)
+ return FlateErr;
+ if (p[0] != GZipID1 || p[1] != GZipID2 || p[2] != GZipCM)
+ return FlateErr;
+ if (p[3] & GZipFEXTRA) {
+ k += 2 + ((p[k] << 8) | p[k+1]);
+ if (k > n)
+ return FlateErr;
+ }
+ if (p[3] & GZipFNAME) {
+ for (; k < n; k++)
+ if (p[k] == 0)
+ break;
+ k++;
+ if (k > n)
+ return FlateErr;
+ }
+ if (p[3] & GZipFCOMM) {
+ for (; k < n; k++)
+ if (p[k] == 0)
+ break;
+ k++;
+ if (k > n)
+ return FlateErr;
+ }
+ if (p[3] & GZipFHCRC) {
+ k += 2;
+ if (k > n)
+ return FlateErr;
+ }
+ return k;
}
int inflate_gzip_footer(uchar *p, int n, uint sum, uint len, uint zlen) {
- if (n < 8 || !check32le(p, sum) || !check32le(p+4, len))
- return FlateErr;
- return 8;
+ if (n < 8 || !check32le(p, sum) || !check32le(p+4, len))
+ return FlateErr;
+ return 8;
}
static char pkname[] = "sflate_stream";
enum {
- PKHeadID = 0x04034b50,
- PKDataID = 0x08074b50,
- PKDirID = 0x02014b50,
- PKFootID = 0x06054b50,
- PKVersion = 20,
- PKFlag = 1 << 3,
- PKMethod = 8,
- PKDate = ((2009 - 1980) << 25) | (1 << 21) | (1 << 16),
- PKHeadSize = 30,
- PKDirSize = 46,
- PKNameLen = sizeof(pkname) - 1
+ PKHeadID = 0x04034b50,
+ PKDataID = 0x08074b50,
+ PKDirID = 0x02014b50,
+ PKFootID = 0x06054b50,
+ PKVersion = 20,
+ PKFlag = 1 << 3,
+ PKMethod = 8,
+ PKDate = ((2009 - 1980) << 25) | (1 << 21) | (1 << 16),
+ PKHeadSize = 30,
+ PKDirSize = 46,
+ PKNameLen = sizeof(pkname) - 1
};
int deflate_pkzip_header(uchar *p, int n) {
- if (n < PKHeadSize + PKNameLen)
- return FlateErr;
- memset(p, 0, PKHeadSize);
- set32le(p, PKHeadID);
- set32le(p+4, PKVersion);
- set32le(p+6, PKFlag);
- set32le(p+8, PKMethod);
- set32le(p+10, PKDate);
- set32le(p+26, PKNameLen);
- memcpy(p + PKHeadSize, pkname, PKNameLen);
- return PKHeadSize + PKNameLen;
+ if (n < PKHeadSize + PKNameLen)
+ return FlateErr;
+ memset(p, 0, PKHeadSize);
+ set32le(p, PKHeadID);
+ set32le(p+4, PKVersion);
+ set32le(p+6, PKFlag);
+ set32le(p+8, PKMethod);
+ set32le(p+10, PKDate);
+ set32le(p+26, PKNameLen);
+ memcpy(p + PKHeadSize, pkname, PKNameLen);
+ return PKHeadSize + PKNameLen;
}
int deflate_pkzip_footer(uchar *p, int n, uint sum, uint len, uint zlen) {
- if (n < PKDirSize + PKNameLen + 22)
- return FlateErr;
- /* unzip bug */
+ if (n < PKDirSize + PKNameLen + 22)
+ return FlateErr;
+ /* unzip bug */
/*
- if (n < 16 + PKDirSize + PKNameLen + 22)
- return FlateErr;
- set32le(p, PKDataID);
- set32le(p+4, sum);
- set32le(p+8, zlen);
- set32le(p+12, len);
- p += 16;
+ if (n < 16 + PKDirSize + PKNameLen + 22)
+ return FlateErr;
+ set32le(p, PKDataID);
+ set32le(p+4, sum);
+ set32le(p+8, zlen);
+ set32le(p+12, len);
+ p += 16;
*/
- memset(p, 0, PKDirSize);
- set32le(p, PKDirID);
- set32le(p+4, PKVersion | (PKVersion << 16));
- set32le(p+8, PKFlag);
- set32le(p+10, PKMethod);
- set32le(p+12, PKDate);
- set32le(p+16, sum);
- set32le(p+20, zlen);
- set32le(p+24, len);
- set32le(p+28, PKNameLen);
- memcpy(p + PKDirSize, pkname, PKNameLen);
- p += PKDirSize + PKNameLen;
- memset(p, 0, 22);
- set32le(p, PKFootID);
- p[8] = p[10] = 1;
- set32le(p+12, PKDirSize + PKNameLen);
- set32le(p+16, zlen + PKHeadSize + PKNameLen);
- return PKDirSize + PKNameLen + 22;
+ memset(p, 0, PKDirSize);
+ set32le(p, PKDirID);
+ set32le(p+4, PKVersion | (PKVersion << 16));
+ set32le(p+8, PKFlag);
+ set32le(p+10, PKMethod);
+ set32le(p+12, PKDate);
+ set32le(p+16, sum);
+ set32le(p+20, zlen);
+ set32le(p+24, len);
+ set32le(p+28, PKNameLen);
+ memcpy(p + PKDirSize, pkname, PKNameLen);
+ p += PKDirSize + PKNameLen;
+ memset(p, 0, 22);
+ set32le(p, PKFootID);
+ p[8] = p[10] = 1;
+ set32le(p+12, PKDirSize + PKNameLen);
+ set32le(p+16, zlen + PKHeadSize + PKNameLen);
+ return PKDirSize + PKNameLen + 22;
/*
- set32le(p+12, 16 + PKDirSize + PKNameLen);
- set32le(p+16, zlen + PKHeadSize + PKNameLen);
- return 16 + PKDirSize + PKNameLen + 22;
+ set32le(p+12, 16 + PKDirSize + PKNameLen);
+ set32le(p+16, zlen + PKHeadSize + PKNameLen);
+ return 16 + PKDirSize + PKNameLen + 22;
*/
}
int inflate_pkzip_header(uchar *p, int n) {
- int k = 30;
-
- if (k > n)
- return FlateErr;
- if (!check32le(p, PKHeadID))
- return FlateErr;
- if ((p[4] | (p[5] << 8)) > PKVersion)
- return FlateErr;
- if ((p[8] | (p[9] << 8)) != PKMethod)
- return FlateErr;
- k += p[26] | (p[27] << 8);
- k += p[28] | (p[29] << 8);
- if (k > n)
- return FlateErr;
- return k;
+ int k = 30;
+
+ if (k > n)
+ return FlateErr;
+ if (!check32le(p, PKHeadID))
+ return FlateErr;
+ if ((p[4] | (p[5] << 8)) > PKVersion)
+ return FlateErr;
+ if ((p[8] | (p[9] << 8)) != PKMethod)
+ return FlateErr;
+ k += p[26] | (p[27] << 8);
+ k += p[28] | (p[29] << 8);
+ if (k > n)
+ return FlateErr;
+ return k;
}
int inflate_pkzip_footer(uchar *p, int n, uint sum, uint len, uint zlen) {
- int k = PKDirSize + 22;
-
- if (k > n)
- return FlateErr;
- if (check32le(p, PKDataID)) {
- p += 16;
- k += 16;
- if (k > n)
- return FlateErr;
- }
- if (!check32le(p, PKDirID))
- return FlateErr;
- if (!check32le(p+16, sum))
- return FlateErr;
- if (!check32le(p+20, zlen))
- return FlateErr;
- if (!check32le(p+24, len))
- return FlateErr;
- return k;
+ int k = PKDirSize + 22;
+
+ if (k > n)
+ return FlateErr;
+ if (check32le(p, PKDataID)) {
+ p += 16;
+ k += 16;
+ if (k > n)
+ return FlateErr;
+ }
+ if (!check32le(p, PKDirID))
+ return FlateErr;
+ if (!check32le(p+16, sum))
+ return FlateErr;
+ if (!check32le(p+20, zlen))
+ return FlateErr;
+ if (!check32le(p+24, len))
+ return FlateErr;
+ return k;
}
static uint extralen;
static int dummyheader(uchar *p, int n) {
- return 0;
+ return 0;
}
static int dummyfooter(uchar *p, int n, uint sum, uint len, uint zlen) {
- return 0;
+ return 0;
}
static uint dummysum(uchar *p, int n, uint sum) {
- return 0;
+ return 0;
}
/* compress, using FlateStream interface */
int compress_stream(FILE *in, FILE *out) {
- FlateStream s;
- int k, n;
- enum {Nin = 1<<15, Nout = 1<<15};
-
- s.in = malloc(Nin);
- s.out = malloc(Nout);
- s.nin = 0;
- s.nout = Nout;
- s.err = 0;
- s.state = 0;
-
- k = header(s.out, s.nout);
- if (k == FlateErr) {
- s.err = "header error.";
- n = FlateErr;
- } else {
- headerlen = s.nout = k;
- n = FlateOut;
- }
- for (;; n = deflate(&s))
- switch (n) {
- case FlateOk:
- k = footer(s.out, s.nout, sum, nin, nout - headerlen);
- if (k == FlateErr) {
- s.err = "footer error.";
- n = FlateErr;
- } else if (k != fwrite(s.out, 1, k, out)) {
- s.err = "write error.";
- n = FlateErr;
- } else {
- footerlen = k;
- nout += k;
- }
- case FlateErr:
- free(s.in);
- free(s.out);
- err = s.err;
- return n;
- case FlateIn:
- s.nin = fread(s.in, 1, Nin, in);
- nin += s.nin;
- sum = checksum(s.in, s.nin, sum);
- break;
- case FlateOut:
- k = fwrite(s.out, 1, s.nout, out);
- if (k != s.nout)
- s.err = "write error.";
- nout += k;
- s.nout = Nout;
- break;
- }
+ FlateStream s;
+ int k, n;
+ enum {Nin = 1<<15, Nout = 1<<15};
+
+ s.in = malloc(Nin);
+ s.out = malloc(Nout);
+ s.nin = 0;
+ s.nout = Nout;
+ s.err = 0;
+ s.state = 0;
+
+ k = header(s.out, s.nout);
+ if (k == FlateErr) {
+ s.err = "header error.";
+ n = FlateErr;
+ } else {
+ headerlen = s.nout = k;
+ n = FlateOut;
+ }
+ for (;; n = deflate(&s))
+ switch (n) {
+ case FlateOk:
+ k = footer(s.out, s.nout, sum, nin, nout - headerlen);
+ if (k == FlateErr) {
+ s.err = "footer error.";
+ n = FlateErr;
+ } else if (k != fwrite(s.out, 1, k, out)) {
+ s.err = "write error.";
+ n = FlateErr;
+ } else {
+ footerlen = k;
+ nout += k;
+ }
+ case FlateErr:
+ free(s.in);
+ free(s.out);
+ err = s.err;
+ return n;
+ case FlateIn:
+ s.nin = fread(s.in, 1, Nin, in);
+ nin += s.nin;
+ sum = checksum(s.in, s.nin, sum);
+ break;
+ case FlateOut:
+ k = fwrite(s.out, 1, s.nout, out);
+ if (k != s.nout)
+ s.err = "write error.";
+ nout += k;
+ s.nout = Nout;
+ break;
+ }
}
/* decompress, using FlateStream interface */
int decompress_stream(FILE *in, FILE *out) {
- FlateStream s;
- uchar *begin;
- int k, n;
- enum {Nin = 1<<15, Nout = 1<<15};
-
- s.in = begin = malloc(Nin);
- s.out = malloc(Nout);
- s.nout = Nout;
- s.err = 0;
- s.state = 0;
-
- s.nin = fread(s.in, 1, Nin, in);
- nin += s.nin;
- k = header(s.in, s.nin);
- if (k == FlateErr) {
- s.err = "header error.";
- n = FlateErr;
- } else {
- headerlen = k;
- s.nin -= k;
- s.in += k;
- n = inflate(&s);
- }
- for (;; n = inflate(&s))
- switch (n) {
- case FlateOk:
- memmove(begin, s.in, s.nin);
- k = fread(begin, 1, Nin-s.nin, in);
- nin += k;
- s.nin += k;
- k = footer(begin, s.nin, sum, nout, nin - s.nin - headerlen);
- if (k == FlateErr) {
- s.err = "footer error.";
- n = FlateErr;
- } else {
- footerlen = k;
- extralen = s.nin - k;
- }
- case FlateErr:
- free(begin);
- free(s.out);
- err = s.err;
- return n;
- case FlateIn:
- s.in = begin;
- s.nin = fread(s.in, 1, Nin, in);
- nin += s.nin;
- break;
- case FlateOut:
- k = fwrite(s.out, 1, s.nout, out);
- if (k != s.nout)
- s.err = "write error.";
- sum = checksum(s.out, k, sum);
- nout += k;
- s.nout = Nout;
- break;
- }
+ FlateStream s;
+ uchar *begin;
+ int k, n;
+ enum {Nin = 1<<15, Nout = 1<<15};
+
+ s.in = begin = malloc(Nin);
+ s.out = malloc(Nout);
+ s.nout = Nout;
+ s.err = 0;
+ s.state = 0;
+
+ s.nin = fread(s.in, 1, Nin, in);
+ nin += s.nin;
+ k = header(s.in, s.nin);
+ if (k == FlateErr) {
+ s.err = "header error.";
+ n = FlateErr;
+ } else {
+ headerlen = k;
+ s.nin -= k;
+ s.in += k;
+ n = inflate(&s);
+ }
+ for (;; n = inflate(&s))
+ switch (n) {
+ case FlateOk:
+ memmove(begin, s.in, s.nin);
+ k = fread(begin, 1, Nin-s.nin, in);
+ nin += k;
+ s.nin += k;
+ k = footer(begin, s.nin, sum, nout, nin - s.nin - headerlen);
+ if (k == FlateErr) {
+ s.err = "footer error.";
+ n = FlateErr;
+ } else {
+ footerlen = k;
+ extralen = s.nin - k;
+ }
+ case FlateErr:
+ free(begin);
+ free(s.out);
+ err = s.err;
+ return n;
+ case FlateIn:
+ s.in = begin;
+ s.nin = fread(s.in, 1, Nin, in);
+ nin += s.nin;
+ break;
+ case FlateOut:
+ k = fwrite(s.out, 1, s.nout, out);
+ if (k != s.nout)
+ s.err = "write error.";
+ sum = checksum(s.out, k, sum);
+ nout += k;
+ s.nout = Nout;
+ break;
+ }
}
static int old_main(int argc, char *argv[]) {
- char comp = 'c';
- char fmt = 'r';
- char verbose = 'q';
- int (*call)(FILE *, FILE*);
- int n, i;
-
- for (i = 1; i < argc; i++) {
- if (argv[i][0] == '-' && argv[i][1] && argv[i][2] == 0)
- switch (argv[i][1]) {
- case 'q':
- case 'v':
- verbose = argv[i][1];
- continue;
- case 'c':
- case 'd':
- comp = argv[i][1];
- continue;
- case 'r':
- case 'g':
- case 'z':
- case 'p':
- fmt = argv[i][1];
- continue;
- }
- fprintf(stderr, "usage: %s [-q|-v] [-c|-d] [-r|-g|-z|-p]\n\n"
- "deflate stream compression\n"
- " -q quiet (default)\n"
- " -v verbose\n"
- " -c compress (default)\n"
- " -d decompress\n"
- " -r raw (default)\n"
- " -g gzip\n"
- " -z zlib\n"
- " -p pkzip\n", argv[0]);
- return -1;
- }
- call = comp == 'c' ? compress_stream : decompress_stream;
- switch (fmt) {
- case 'r':
- header = dummyheader;
- footer = dummyfooter;
- checksum = dummysum;
- n = call(stdin, stdout);
- break;
- case 'g':
- if (comp == 'c') {
- header = deflate_gzip_header;
- footer = deflate_gzip_footer;
- } else {
- header = inflate_gzip_header;
- footer = inflate_gzip_footer;
- }
- checksum = crc32;
- crc32init();
- n = call(stdin, stdout);
- break;
- case 'z':
- if (comp == 'c') {
- header = deflate_zlib_header;
- footer = deflate_zlib_footer;
- } else {
- header = inflate_zlib_header;
- footer = inflate_zlib_footer;
- }
- checksum = adler32;
- n = call(stdin, stdout);
- break;
- case 'p':
- if (comp == 'c') {
- header = deflate_pkzip_header;
- footer = deflate_pkzip_footer;
- } else {
- header = inflate_pkzip_header;
- footer = inflate_pkzip_footer;
- }
- checksum = crc32;
- crc32init();
- n = call(stdin, stdout);
- break;
- default:
- err = "uninplemented.";
- n = FlateErr;
- break;
- }
- if (verbose == 'v')
- fprintf(stderr, "in:%d out:%d checksum: 0x%08x (header:%d data:%d footer:%d extra input:%s)\n",
- nin, nout, sum, headerlen, (comp == 'c' ? nout : nin) - headerlen - footerlen - extralen,
- footerlen, extralen ? "yes" : "no");
- if (n != FlateOk)
- fprintf(stderr, "error: %s\n", err);
- return n;
+ char comp = 'c';
+ char fmt = 'r';
+ char verbose = 'q';
+ int (*call)(FILE *, FILE*);
+ int n, i;
+
+ for (i = 1; i < argc; i++) {
+ if (argv[i][0] == '-' && argv[i][1] && argv[i][2] == 0)
+ switch (argv[i][1]) {
+ case 'q':
+ case 'v':
+ verbose = argv[i][1];
+ continue;
+ case 'c':
+ case 'd':
+ comp = argv[i][1];
+ continue;
+ case 'r':
+ case 'g':
+ case 'z':
+ case 'p':
+ fmt = argv[i][1];
+ continue;
+ }
+ fprintf(stderr, "usage: %s [-q|-v] [-c|-d] [-r|-g|-z|-p]\n\n"
+ "deflate stream compression\n"
+ " -q quiet (default)\n"
+ " -v verbose\n"
+ " -c compress (default)\n"
+ " -d decompress\n"
+ " -r raw (default)\n"
+ " -g gzip\n"
+ " -z zlib\n"
+ " -p pkzip\n", argv[0]);
+ return -1;
+ }
+ call = comp == 'c' ? compress_stream : decompress_stream;
+ switch (fmt) {
+ case 'r':
+ header = dummyheader;
+ footer = dummyfooter;
+ checksum = dummysum;
+ n = call(stdin, stdout);
+ break;
+ case 'g':
+ if (comp == 'c') {
+ header = deflate_gzip_header;
+ footer = deflate_gzip_footer;
+ } else {
+ header = inflate_gzip_header;
+ footer = inflate_gzip_footer;
+ }
+ checksum = crc32;
+ crc32init();
+ n = call(stdin, stdout);
+ break;
+ case 'z':
+ if (comp == 'c') {
+ header = deflate_zlib_header;
+ footer = deflate_zlib_footer;
+ } else {
+ header = inflate_zlib_header;
+ footer = inflate_zlib_footer;
+ }
+ checksum = adler32;
+ n = call(stdin, stdout);
+ break;
+ case 'p':
+ if (comp == 'c') {
+ header = deflate_pkzip_header;
+ footer = deflate_pkzip_footer;
+ } else {
+ header = inflate_pkzip_header;
+ footer = inflate_pkzip_footer;
+ }
+ checksum = crc32;
+ crc32init();
+ n = call(stdin, stdout);
+ break;
+ default:
+ err = "uninplemented.";
+ n = FlateErr;
+ break;
+ }
+ if (verbose == 'v')
+ fprintf(stderr, "in:%d out:%d checksum: 0x%08x (header:%d data:%d footer:%d extra input:%s)\n",
+ nin, nout, sum, headerlen, (comp == 'c' ? nout : nin) - headerlen - footerlen - extralen,
+ footerlen, extralen ? "yes" : "no");
+ if (n != FlateOk)
+ fprintf(stderr, "error: %s\n", err);
+ return n;
}
// Total hack
for (i=0; toys.argv[i]; i++);
old_main(i, toys.argv);
}
-
-