Commit 4f3865fb authored by Richard Purdie's avatar Richard Purdie Committed by Linus Torvalds

[PATCH] zlib_inflate: Upgrade library code to a recent version

Upgrade the zlib_inflate implementation in the kernel from a patched
version 1.1.3/4 to a patched 1.2.3.

The code in the kernel is about seven years old and I noticed that the
external zlib library's inflate performance was significantly faster (~50%)
than the code in the kernel on ARM (and faster again on x86_32).

For comparison the newer deflate code is 20% slower on ARM and 50% slower
on x86_32 but gives an approx 1% compression ratio improvement.  I don't
consider this to be an improvement for kernel use so have no plans to
change the zlib_deflate code.

Various changes have been made to the zlib code in the kernel, the most
significant being the extra functions/flush option used by ppp_deflate.
This update reimplements the features PPP needs to ensure it continues to
work.

This code has been tested on ARM under both JFFS2 (with zlib compression
enabled) and ppp_deflate and on x86_32.  JFFS2 sees an approx.  10% real
world file read speed improvement.

This patch also removes ZLIB_VERSION as it no longer has a correct value.
We don't need version checks anyway as the kernel's module handling will
take care of that for us.  This removal is also more in keeping with the
zlib author's wishes (http://www.zlib.net/zlib_faq.html#faq24) and I've
added something to the zlib.h header to note its a modified version.
Signed-off-by: default avatarRichard Purdie <rpurdie@rpsys.net>
Acked-by: default avatarJoern Engel <joern@wh.fh-wedel.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 4f1bcaf0
...@@ -29,8 +29,8 @@ OBJCOPYFLAGS := contents,alloc,load,readonly,data ...@@ -29,8 +29,8 @@ OBJCOPYFLAGS := contents,alloc,load,readonly,data
OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000 OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000
OBJCOPY_MIB_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment OBJCOPY_MIB_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment
zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c zlib := inffast.c inflate.c inftrees.c
zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h zlibheader := inffast.h inffixed.h inflate.h inftrees.h infutil.h
zliblinuxheader := zlib.h zconf.h zutil.h zliblinuxheader := zlib.h zconf.h zutil.h
$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
CFLAGS_kbd.o := -Idrivers/char CFLAGS_kbd.o := -Idrivers/char
CFLAGS_vreset.o := -Iarch/ppc/boot/include CFLAGS_vreset.o := -Iarch/ppc/boot/include
zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c zlib := inffast.c inflate.c inftrees.c
lib-y += $(zlib:.c=.o) div64.o lib-y += $(zlib:.c=.o) div64.o
lib-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o lib-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for some libs needed by zImage. # Makefile for some libs needed by zImage.
# #
zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c zlib := inffast.c inflate.c inftrees.c
lib-y += $(zlib:.c=.o) zmem.o lib-y += $(zlib:.c=.o) zmem.o
......
...@@ -33,6 +33,18 @@ ...@@ -33,6 +33,18 @@
*/ */
#ifndef MAX_WBITS #ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */ # define MAX_WBITS 15 /* 32K LZ77 window */
#endif
/* default windowBits for decompression. MAX_WBITS is for compression only */
#ifndef DEF_WBITS
# define DEF_WBITS MAX_WBITS
#endif
/* default memLevel */
#if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
#else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif #endif
/* Type declarations */ /* Type declarations */
......
This diff is collapsed.
...@@ -23,18 +23,6 @@ typedef unsigned long ulg; ...@@ -23,18 +23,6 @@ typedef unsigned long ulg;
/* common constants */ /* common constants */
#ifndef DEF_WBITS
# define DEF_WBITS MAX_WBITS
#endif
/* default windowBits for decompression. MAX_WBITS is for compression only */
#if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
#else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif
/* default memLevel */
#define STORED_BLOCK 0 #define STORED_BLOCK 0
#define STATIC_TREES 1 #define STATIC_TREES 1
#define DYN_TREES 2 #define DYN_TREES 2
......
...@@ -164,34 +164,17 @@ static const config configuration_table[10] = { ...@@ -164,34 +164,17 @@ static const config configuration_table[10] = {
memset((char *)s->head, 0, (unsigned)(s->hash_size-1)*sizeof(*s->head)); memset((char *)s->head, 0, (unsigned)(s->hash_size-1)*sizeof(*s->head));
/* ========================================================================= */ /* ========================================================================= */
int zlib_deflateInit_( int zlib_deflateInit2(
z_streamp strm,
int level,
const char *version,
int stream_size
)
{
return zlib_deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS,
DEF_MEM_LEVEL,
Z_DEFAULT_STRATEGY, version, stream_size);
/* To do: ignore strm->next_in if we use it as window */
}
/* ========================================================================= */
int zlib_deflateInit2_(
z_streamp strm, z_streamp strm,
int level, int level,
int method, int method,
int windowBits, int windowBits,
int memLevel, int memLevel,
int strategy, int strategy
const char *version,
int stream_size
) )
{ {
deflate_state *s; deflate_state *s;
int noheader = 0; int noheader = 0;
static char* my_version = ZLIB_VERSION;
deflate_workspace *mem; deflate_workspace *mem;
ush *overlay; ush *overlay;
...@@ -199,10 +182,6 @@ int zlib_deflateInit2_( ...@@ -199,10 +182,6 @@ int zlib_deflateInit2_(
* output size for (length,distance) codes is <= 24 bits. * output size for (length,distance) codes is <= 24 bits.
*/ */
if (version == NULL || version[0] != my_version[0] ||
stream_size != sizeof(z_stream)) {
return Z_VERSION_ERROR;
}
if (strm == NULL) return Z_STREAM_ERROR; if (strm == NULL) return Z_STREAM_ERROR;
strm->msg = NULL; strm->msg = NULL;
......
...@@ -12,8 +12,7 @@ ...@@ -12,8 +12,7 @@
EXPORT_SYMBOL(zlib_deflate_workspacesize); EXPORT_SYMBOL(zlib_deflate_workspacesize);
EXPORT_SYMBOL(zlib_deflate); EXPORT_SYMBOL(zlib_deflate);
EXPORT_SYMBOL(zlib_deflateInit_); EXPORT_SYMBOL(zlib_deflateInit2);
EXPORT_SYMBOL(zlib_deflateInit2_);
EXPORT_SYMBOL(zlib_deflateEnd); EXPORT_SYMBOL(zlib_deflateEnd);
EXPORT_SYMBOL(zlib_deflateReset); EXPORT_SYMBOL(zlib_deflateReset);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -15,5 +15,5 @@ ...@@ -15,5 +15,5 @@
obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate.o obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate.o
zlib_inflate-objs := infblock.o infcodes.o inffast.o inflate.o \ zlib_inflate-objs := inffast.o inflate.o \
inflate_sync.o inftrees.o infutil.o inflate_syms.o inftrees.o inflate_syms.o
This diff is collapsed.
/* infblock.h -- header to use infblock.c
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
#ifndef _INFBLOCK_H
#define _INFBLOCK_H
struct inflate_blocks_state;
typedef struct inflate_blocks_state inflate_blocks_statef;
extern inflate_blocks_statef * zlib_inflate_blocks_new (
z_streamp z,
check_func c, /* check function */
uInt w); /* window size */
extern int zlib_inflate_blocks (
inflate_blocks_statef *,
z_streamp ,
int); /* initial return code */
extern void zlib_inflate_blocks_reset (
inflate_blocks_statef *,
z_streamp ,
uLong *); /* check value on output */
extern int zlib_inflate_blocks_free (
inflate_blocks_statef *,
z_streamp);
#if 0
extern void zlib_inflate_set_dictionary (
inflate_blocks_statef *s,
const Byte *d, /* dictionary */
uInt n); /* dictionary length */
#endif /* 0 */
#if 0
extern int zlib_inflate_blocks_sync_point (
inflate_blocks_statef *s);
#endif /* 0 */
#endif /* _INFBLOCK_H */
/* infcodes.c -- process literals and length/distance pairs
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include <linux/zutil.h>
#include "inftrees.h"
#include "infblock.h"
#include "infcodes.h"
#include "infutil.h"
#include "inffast.h"
/* simplify the use of the inflate_huft type with some defines */
#define exop word.what.Exop
#define bits word.what.Bits
inflate_codes_statef *zlib_inflate_codes_new(
uInt bl,
uInt bd,
inflate_huft *tl,
inflate_huft *td, /* need separate declaration for Borland C++ */
z_streamp z
)
{
inflate_codes_statef *c;
c = &WS(z)->working_state;
{
c->mode = START;
c->lbits = (Byte)bl;
c->dbits = (Byte)bd;
c->ltree = tl;
c->dtree = td;
}
return c;
}
int zlib_inflate_codes(
inflate_blocks_statef *s,
z_streamp z,
int r
)
{
uInt j; /* temporary storage */
inflate_huft *t; /* temporary pointer */
uInt e; /* extra bits or operation */
uLong b; /* bit buffer */
uInt k; /* bits in bit buffer */
Byte *p; /* input data pointer */
uInt n; /* bytes available there */
Byte *q; /* output window write pointer */
uInt m; /* bytes to end of window or read pointer */
Byte *f; /* pointer to copy strings from */
inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
/* copy input/output information to locals (UPDATE macro restores) */
LOAD
/* process input and output based on current state */
while (1) switch (c->mode)
{ /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
case START: /* x: set up for LEN */
#ifndef SLOW
if (m >= 258 && n >= 10)
{
UPDATE
r = zlib_inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
LOAD
if (r != Z_OK)
{
c->mode = r == Z_STREAM_END ? WASH : BADCODE;
break;
}
}
#endif /* !SLOW */
c->sub.code.need = c->lbits;
c->sub.code.tree = c->ltree;
c->mode = LEN;
case LEN: /* i: get length/literal/eob next */
j = c->sub.code.need;
NEEDBITS(j)
t = c->sub.code.tree + ((uInt)b & zlib_inflate_mask[j]);
DUMPBITS(t->bits)
e = (uInt)(t->exop);
if (e == 0) /* literal */
{
c->sub.lit = t->base;
c->mode = LIT;
break;
}
if (e & 16) /* length */
{
c->sub.copy.get = e & 15;
c->len = t->base;
c->mode = LENEXT;
break;
}
if ((e & 64) == 0) /* next table */
{
c->sub.code.need = e;
c->sub.code.tree = t + t->base;
break;
}
if (e & 32) /* end of block */
{
c->mode = WASH;
break;
}
c->mode = BADCODE; /* invalid code */
z->msg = (char*)"invalid literal/length code";
r = Z_DATA_ERROR;
LEAVE
case LENEXT: /* i: getting length extra (have base) */
j = c->sub.copy.get;
NEEDBITS(j)
c->len += (uInt)b & zlib_inflate_mask[j];
DUMPBITS(j)
c->sub.code.need = c->dbits;
c->sub.code.tree = c->dtree;
c->mode = DIST;
case DIST: /* i: get distance next */
j = c->sub.code.need;
NEEDBITS(j)
t = c->sub.code.tree + ((uInt)b & zlib_inflate_mask[j]);
DUMPBITS(t->bits)
e = (uInt)(t->exop);
if (e & 16) /* distance */
{
c->sub.copy.get = e & 15;
c->sub.copy.dist = t->base;
c->mode = DISTEXT;
break;
}
if ((e & 64) == 0) /* next table */
{
c->sub.code.need = e;
c->sub.code.tree = t + t->base;
break;
}
c->mode = BADCODE; /* invalid code */
z->msg = (char*)"invalid distance code";
r = Z_DATA_ERROR;
LEAVE
case DISTEXT: /* i: getting distance extra */
j = c->sub.copy.get;
NEEDBITS(j)
c->sub.copy.dist += (uInt)b & zlib_inflate_mask[j];
DUMPBITS(j)
c->mode = COPY;
case COPY: /* o: copying bytes in window, waiting for space */
f = q - c->sub.copy.dist;
while (f < s->window) /* modulo window size-"while" instead */
f += s->end - s->window; /* of "if" handles invalid distances */
while (c->len)
{
NEEDOUT
OUTBYTE(*f++)
if (f == s->end)
f = s->window;
c->len--;
}
c->mode = START;
break;
case LIT: /* o: got literal, waiting for output space */
NEEDOUT
OUTBYTE(c->sub.lit)
c->mode = START;
break;
case WASH: /* o: got eob, possibly more output */
if (k > 7) /* return unused byte, if any */
{
k -= 8;
n++;
p--; /* can always return one */
}
FLUSH
if (s->read != s->write)
LEAVE
c->mode = END;
case END:
r = Z_STREAM_END;
LEAVE
case BADCODE: /* x: got error */
r = Z_DATA_ERROR;
LEAVE
default:
r = Z_STREAM_ERROR;
LEAVE
}
#ifdef NEED_DUMMY_RETURN
return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
#endif
}
void zlib_inflate_codes_free(
inflate_codes_statef *c,
z_streamp z
)
{
}
/* infcodes.h -- header to use infcodes.c
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
#ifndef _INFCODES_H
#define _INFCODES_H
#include "infblock.h"
struct inflate_codes_state;
typedef struct inflate_codes_state inflate_codes_statef;
extern inflate_codes_statef *zlib_inflate_codes_new (
uInt, uInt,
inflate_huft *, inflate_huft *,
z_streamp );
extern int zlib_inflate_codes (
inflate_blocks_statef *,
z_streamp ,
int);
extern void zlib_inflate_codes_free (
inflate_codes_statef *,
z_streamp );
#endif /* _INFCODES_H */
This diff is collapsed.
/* inffast.h -- header to use inffast.c /* inffast.h -- header to use inffast.c
* Copyright (C) 1995-1998 Mark Adler * Copyright (C) 1995-2003 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
/* WARNING: this file should *not* be used by applications. It is /* WARNING: this file should *not* be used by applications. It is
...@@ -8,10 +8,4 @@ ...@@ -8,10 +8,4 @@
subject to change. Applications should only use zlib.h. subject to change. Applications should only use zlib.h.
*/ */
extern int zlib_inflate_fast ( void inflate_fast (z_streamp strm, unsigned start);
uInt,
uInt,
inflate_huft *,
inflate_huft *,
inflate_blocks_statef *,
z_streamp );
/* inffixed.h -- table for decoding fixed codes
* Generated automatically by makefixed().
*/
/* WARNING: this file should *not* be used by applications. It
is part of the implementation of the compression library and
is subject to change. Applications should only use zlib.h.
*/
static const code lenfix[512] = {
{96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
{0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
{0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
{0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
{0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
{21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
{0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
{0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
{18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
{0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
{0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
{0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
{20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
{0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
{0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
{16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
{0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
{0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
{0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
{0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
{0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
{0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
{0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
{17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
{0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
{0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
{0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
{19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
{0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
{0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
{16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
{0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
{0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
{0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
{0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
{20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
{0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
{0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
{17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
{0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
{0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
{0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
{20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
{0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
{0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
{0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
{16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
{0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
{0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
{0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
{0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
{0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
{0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
{0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
{16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
{0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
{0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
{0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
{19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
{0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
{0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
{16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
{0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
{0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
{0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
{0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
{64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
{0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
{0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
{18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
{0,9,255}
};
static const code distfix[32] = {
{16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
{21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
{18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
{19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
{16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
{22,5,193},{64,5,0}
};
This diff is collapsed.
/* inflate.h -- internal inflate state definition
* Copyright (C) 1995-2004 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* Possible inflate modes between inflate() calls */
typedef enum {
HEAD, /* i: waiting for magic header */
FLAGS, /* i: waiting for method and flags (gzip) */
TIME, /* i: waiting for modification time (gzip) */
OS, /* i: waiting for extra flags and operating system (gzip) */
EXLEN, /* i: waiting for extra length (gzip) */
EXTRA, /* i: waiting for extra bytes (gzip) */
NAME, /* i: waiting for end of file name (gzip) */
COMMENT, /* i: waiting for end of comment (gzip) */
HCRC, /* i: waiting for header crc (gzip) */
DICTID, /* i: waiting for dictionary check value */
DICT, /* waiting for inflateSetDictionary() call */
TYPE, /* i: waiting for type bits, including last-flag bit */
TYPEDO, /* i: same, but skip check to exit inflate on new block */
STORED, /* i: waiting for stored size (length and complement) */
COPY, /* i/o: waiting for input or output to copy stored block */
TABLE, /* i: waiting for dynamic block table lengths */
LENLENS, /* i: waiting for code length code lengths */
CODELENS, /* i: waiting for length/lit and distance code lengths */
LEN, /* i: waiting for length/lit code */
LENEXT, /* i: waiting for length extra bits */
DIST, /* i: waiting for distance code */
DISTEXT, /* i: waiting for distance extra bits */
MATCH, /* o: waiting for output space to copy string */
LIT, /* o: waiting for output space to write literal */
CHECK, /* i: waiting for 32-bit check value */
LENGTH, /* i: waiting for 32-bit length (gzip) */
DONE, /* finished check, done -- remain here until reset */
BAD, /* got a data error -- remain here until reset */
MEM, /* got an inflate() memory error -- remain here until reset */
SYNC /* looking for synchronization bytes to restart inflate() */
} inflate_mode;
/*
State transitions between above modes -
(most modes can go to the BAD or MEM mode -- not shown for clarity)
Process header:
HEAD -> (gzip) or (zlib)
(gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
NAME -> COMMENT -> HCRC -> TYPE
(zlib) -> DICTID or TYPE
DICTID -> DICT -> TYPE
Read deflate blocks:
TYPE -> STORED or TABLE or LEN or CHECK
STORED -> COPY -> TYPE
TABLE -> LENLENS -> CODELENS -> LEN
Read deflate codes:
LEN -> LENEXT or LIT or TYPE
LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
LIT -> LEN
Process trailer:
CHECK -> LENGTH -> DONE
*/
/* state maintained between inflate() calls. Approximately 7K bytes. */
struct inflate_state {
inflate_mode mode; /* current inflate mode */
int last; /* true if processing last block */
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
int havedict; /* true if dictionary provided */
int flags; /* gzip header method and flags (0 if zlib) */
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
unsigned long check; /* protected copy of check value */
unsigned long total; /* protected copy of output count */
/* gz_headerp head; */ /* where to save gzip header information */
/* sliding window */
unsigned wbits; /* log base 2 of requested window size */
unsigned wsize; /* window size or zero if not using window */
unsigned whave; /* valid bytes in the window */
unsigned write; /* window write index */
unsigned char *window; /* allocated sliding window, if needed */
/* bit accumulator */
unsigned long hold; /* input bit accumulator */
unsigned bits; /* number of bits in "in" */
/* for string and stored block copying */
unsigned length; /* literal or length of data to copy */
unsigned offset; /* distance back to copy string from */
/* for table and code decoding */
unsigned extra; /* extra bits needed */
/* fixed and dynamic code tables */
code const *lencode; /* starting table for length/literal codes */
code const *distcode; /* starting table for distance codes */
unsigned lenbits; /* index bits for lencode */
unsigned distbits; /* index bits for distcode */
/* dynamic table building */
unsigned ncode; /* number of code length code lengths */
unsigned nlen; /* number of length code lengths */
unsigned ndist; /* number of distance code lengths */
unsigned have; /* number of code lengths in lens[] */
code *next; /* next available space in codes[] */
unsigned short lens[320]; /* temporary storage for code lengths */
unsigned short work[288]; /* work area for code table building */
code codes[ENOUGH]; /* space for code tables */
};
...@@ -12,8 +12,7 @@ ...@@ -12,8 +12,7 @@
EXPORT_SYMBOL(zlib_inflate_workspacesize); EXPORT_SYMBOL(zlib_inflate_workspacesize);
EXPORT_SYMBOL(zlib_inflate); EXPORT_SYMBOL(zlib_inflate);
EXPORT_SYMBOL(zlib_inflateInit_); EXPORT_SYMBOL(zlib_inflateInit2);
EXPORT_SYMBOL(zlib_inflateInit2_);
EXPORT_SYMBOL(zlib_inflateEnd); EXPORT_SYMBOL(zlib_inflateEnd);
EXPORT_SYMBOL(zlib_inflateReset); EXPORT_SYMBOL(zlib_inflateReset);
EXPORT_SYMBOL(zlib_inflateIncomp); EXPORT_SYMBOL(zlib_inflateIncomp);
......
/* inflate.c -- zlib interface to inflate modules
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include <linux/zutil.h>
#include "infblock.h"
#include "infutil.h"
#if 0
int zlib_inflateSync(
z_streamp z
)
{
uInt n; /* number of bytes to look at */
Byte *p; /* pointer to bytes */
uInt m; /* number of marker bytes found in a row */
uLong r, w; /* temporaries to save total_in and total_out */
/* set up */
if (z == NULL || z->state == NULL)
return Z_STREAM_ERROR;
if (z->state->mode != I_BAD)
{
z->state->mode = I_BAD;
z->state->sub.marker = 0;
}
if ((n = z->avail_in) == 0)
return Z_BUF_ERROR;
p = z->next_in;
m = z->state->sub.marker;
/* search */
while (n && m < 4)
{
static const Byte mark[4] = {0, 0, 0xff, 0xff};
if (*p == mark[m])
m++;
else if (*p)
m = 0;
else
m = 4 - m;
p++, n--;
}
/* restore */
z->total_in += p - z->next_in;
z->next_in = p;
z->avail_in = n;
z->state->sub.marker = m;
/* return no joy or set up to restart on a new block */
if (m != 4)
return Z_DATA_ERROR;
r = z->total_in; w = z->total_out;
zlib_inflateReset(z);
z->total_in = r; z->total_out = w;
z->state->mode = BLOCKS;
return Z_OK;
}
#endif /* 0 */
/* Returns true if inflate is currently at the end of a block generated
* by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
* implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
* but removes the length bytes of the resulting empty stored block. When
* decompressing, PPP checks that at the end of input packet, inflate is
* waiting for these length bytes.
*/
#if 0
int zlib_inflateSyncPoint(
z_streamp z
)
{
if (z == NULL || z->state == NULL || z->state->blocks == NULL)
return Z_STREAM_ERROR;
return zlib_inflate_blocks_sync_point(z->state->blocks);
}
#endif /* 0 */
/*
* This subroutine adds the data at next_in/avail_in to the output history
* without performing any output. The output buffer must be "caught up";
* i.e. no pending output (hence s->read equals s->write), and the state must
* be BLOCKS (i.e. we should be willing to see the start of a series of
* BLOCKS). On exit, the output will also be caught up, and the checksum
* will have been updated if need be.
*/
static int zlib_inflate_addhistory(inflate_blocks_statef *s,
z_stream *z)
{
uLong b; /* bit buffer */ /* NOT USED HERE */
uInt k; /* bits in bit buffer */ /* NOT USED HERE */
uInt t; /* temporary storage */
Byte *p; /* input data pointer */
uInt n; /* bytes available there */
Byte *q; /* output window write pointer */
uInt m; /* bytes to end of window or read pointer */
if (s->read != s->write)
return Z_STREAM_ERROR;
if (s->mode != TYPE)
return Z_DATA_ERROR;
/* we're ready to rock */
LOAD
/* while there is input ready, copy to output buffer, moving
* pointers as needed.
*/
while (n) {
t = n; /* how many to do */
/* is there room until end of buffer? */
if (t > m) t = m;
/* update check information */
if (s->checkfn != NULL)
s->check = (*s->checkfn)(s->check, q, t);
memcpy(q, p, t);
q += t;
p += t;
n -= t;
z->total_out += t;
s->read = q; /* drag read pointer forward */
/* WWRAP */ /* expand WWRAP macro by hand to handle s->read */
if (q == s->end) {
s->read = q = s->window;
m = WAVAIL;
}
}
UPDATE
return Z_OK;
}
/*
* This subroutine adds the data at next_in/avail_in to the output history
* without performing any output. The output buffer must be "caught up";
* i.e. no pending output (hence s->read equals s->write), and the state must
* be BLOCKS (i.e. we should be willing to see the start of a series of
* BLOCKS). On exit, the output will also be caught up, and the checksum
* will have been updated if need be.
*/
int zlib_inflateIncomp(
z_stream *z
)
{
if (z->state->mode != BLOCKS)
return Z_DATA_ERROR;
return zlib_inflate_addhistory(z->state->blocks, z);
}
This diff is collapsed.
/* inftrees.h -- header to use inftrees.c /* inftrees.h -- header to use inftrees.c
* Copyright (C) 1995-1998 Mark Adler * Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
/* WARNING: this file should *not* be used by applications. It is /* WARNING: this file should *not* be used by applications. It is
...@@ -8,57 +8,48 @@ ...@@ -8,57 +8,48 @@
subject to change. Applications should only use zlib.h. subject to change. Applications should only use zlib.h.
*/ */
/* Huffman code lookup table entry--this entry is four bytes for machines /* Structure for decoding tables. Each entry provides either the
that have 16-bit pointers (e.g. PC's in the small or medium model). */ information needed to do the operation requested by the code that
indexed that table entry, or it provides a pointer to another
#ifndef _INFTREES_H table that indexes more bits of the code. op indicates whether
#define _INFTREES_H the entry is a pointer to another table, a literal, a length or
distance, an end-of-block, or an invalid code. For a table
typedef struct inflate_huft_s inflate_huft; pointer, the low four bits of op is the number of index bits of
that table. For a length or distance, the low four bits of op
struct inflate_huft_s { is the number of extra bits to get after the code. bits is
union { the number of bits in this code or part of the code to drop off
struct { of the bit buffer. val is the actual byte to output in the case
Byte Exop; /* number of extra bits or operation */ of a literal, the base length or distance, or the offset from
Byte Bits; /* number of bits in this code or subcode */ the current table to the next table. Each entry is four bytes. */
} what; typedef struct {
uInt pad; /* pad structure to a power of 2 (4 bytes for */ unsigned char op; /* operation, extra bits, table bits */
} word; /* 16-bit, 8 bytes for 32-bit int's) */ unsigned char bits; /* bits in this part of the code */
uInt base; /* literal, length base, distance base, unsigned short val; /* offset in table or code value */
or table offset */ } code;
};
/* op values as set by inflate_table():
00000000 - literal
0000tttt - table link, tttt != 0 is the number of table index bits
0001eeee - length or distance, eeee is the number of extra bits
01100000 - end of block
01000000 - invalid code
*/
/* Maximum size of dynamic tree. The maximum found in a long but non- /* Maximum size of dynamic tree. The maximum found in a long but non-
exhaustive search was 1004 huft structures (850 for length/literals exhaustive search was 1444 code structures (852 for length/literals
and 154 for distances, the latter actually the result of an and 592 for distances, the latter actually the result of an
exhaustive search). The actual maximum is not known, but the exhaustive search). The true maximum is not known, but the value
value below is more than safe. */ below is more than safe. */
#define MANY 1440 #define ENOUGH 2048
#define MAXD 592
extern int zlib_inflate_trees_bits (
uInt *, /* 19 code lengths */ /* Type of code to build for inftable() */
uInt *, /* bits tree desired/actual depth */ typedef enum {
inflate_huft **, /* bits tree result */ CODES,
inflate_huft *, /* space for trees */ LENS,
z_streamp); /* for messages */ DISTS
} codetype;
extern int zlib_inflate_trees_dynamic (
uInt, /* number of literal/length codes */ extern int zlib_inflate_table (codetype type, unsigned short *lens,
uInt, /* number of distance codes */ unsigned codes, code **table,
uInt *, /* that many (total) code lengths */ unsigned *bits, unsigned short *work);
uInt *, /* literal desired/actual bit depth */
uInt *, /* distance desired/actual bit depth */
inflate_huft **, /* literal/length tree result */
inflate_huft **, /* distance tree result */
inflate_huft *, /* space for trees */
z_streamp); /* for messages */
extern int zlib_inflate_trees_fixed (
uInt *, /* literal desired/actual bit depth */
uInt *, /* distance desired/actual bit depth */
inflate_huft **, /* literal/length tree result */
inflate_huft **, /* distance tree result */
inflate_huft *, /* space for trees */
z_streamp); /* for memory allocation */
#endif /* _INFTREES_H */
/* inflate_util.c -- data and routines common to blocks and codes
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include <linux/zutil.h>
#include "infblock.h"
#include "inftrees.h"
#include "infcodes.h"
#include "infutil.h"
struct inflate_codes_state;
/* And'ing with mask[n] masks the lower n bits */
uInt zlib_inflate_mask[17] = {
0x0000,
0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
};
/* copy as much as possible from the sliding window to the output area */
int zlib_inflate_flush(
inflate_blocks_statef *s,
z_streamp z,
int r
)
{
uInt n;
Byte *p;
Byte *q;
/* local copies of source and destination pointers */
p = z->next_out;
q = s->read;
/* compute number of bytes to copy as far as end of window */
n = (uInt)((q <= s->write ? s->write : s->end) - q);
if (n > z->avail_out) n = z->avail_out;
if (n && r == Z_BUF_ERROR) r = Z_OK;
/* update counters */
z->avail_out -= n;
z->total_out += n;
/* update check information */
if (s->checkfn != NULL)
z->adler = s->check = (*s->checkfn)(s->check, q, n);
/* copy as far as end of window */
memcpy(p, q, n);
p += n;
q += n;
/* see if more to copy at beginning of window */
if (q == s->end)
{
/* wrap pointers */
q = s->window;
if (s->write == s->end)
s->write = s->window;
/* compute bytes to copy */
n = (uInt)(s->write - q);
if (n > z->avail_out) n = z->avail_out;
if (n && r == Z_BUF_ERROR) r = Z_OK;
/* update counters */
z->avail_out -= n;
z->total_out += n;
/* update check information */
if (s->checkfn != NULL)
z->adler = s->check = (*s->checkfn)(s->check, q, n);
/* copy */
memcpy(p, q, n);
p += n;
q += n;
}
/* update pointers */
z->next_out = p;
s->read = q;
/* done */
return r;
}
...@@ -11,184 +11,12 @@ ...@@ -11,184 +11,12 @@
#ifndef _INFUTIL_H #ifndef _INFUTIL_H
#define _INFUTIL_H #define _INFUTIL_H
#include <linux/zconf.h> #include <linux/zlib.h>
#include "inftrees.h"
#include "infcodes.h"
typedef enum {
TYPE, /* get type bits (3, including end bit) */
LENS, /* get lengths for stored */
STORED, /* processing stored block */
TABLE, /* get table lengths */
BTREE, /* get bit lengths tree for a dynamic block */
DTREE, /* get length, distance trees for a dynamic block */
CODES, /* processing fixed or dynamic block */
DRY, /* output remaining window bytes */
B_DONE, /* finished last block, done */
B_BAD} /* got a data error--stuck here */
inflate_block_mode;
/* inflate blocks semi-private state */
struct inflate_blocks_state {
/* mode */
inflate_block_mode mode; /* current inflate_block mode */
/* mode dependent information */
union {
uInt left; /* if STORED, bytes left to copy */
struct {
uInt table; /* table lengths (14 bits) */
uInt index; /* index into blens (or border) */
uInt *blens; /* bit lengths of codes */
uInt bb; /* bit length tree depth */
inflate_huft *tb; /* bit length decoding tree */
} trees; /* if DTREE, decoding info for trees */
struct {
inflate_codes_statef
*codes;
} decode; /* if CODES, current state */
} sub; /* submode */
uInt last; /* true if this block is the last block */
/* mode independent information */
uInt bitk; /* bits in bit buffer */
uLong bitb; /* bit buffer */
inflate_huft *hufts; /* single malloc for tree space */
Byte *window; /* sliding window */
Byte *end; /* one byte after sliding window */
Byte *read; /* window read pointer */
Byte *write; /* window write pointer */
check_func checkfn; /* check function */
uLong check; /* check on output */
};
/* defines for inflate input/output */
/* update pointers and return */
#define UPDBITS {s->bitb=b;s->bitk=k;}
#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
#define UPDOUT {s->write=q;}
#define UPDATE {UPDBITS UPDIN UPDOUT}
#define LEAVE {UPDATE return zlib_inflate_flush(s,z,r);}
/* get bytes and bits */
#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
#define NEXTBYTE (n--,*p++)
#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
#define DUMPBITS(j) {b>>=(j);k-=(j);}
/* output bytes */
#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
#define FLUSH {UPDOUT r=zlib_inflate_flush(s,z,r); LOADOUT}
#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
/* load local pointers */
#define LOAD {LOADIN LOADOUT}
/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
extern uInt zlib_inflate_mask[17];
/* copy as much as possible from the sliding window to the output area */
extern int zlib_inflate_flush (
inflate_blocks_statef *,
z_streamp ,
int);
/* inflate private state */
typedef enum {
METHOD, /* waiting for method byte */
FLAG, /* waiting for flag byte */
DICT4, /* four dictionary check bytes to go */
DICT3, /* three dictionary check bytes to go */
DICT2, /* two dictionary check bytes to go */
DICT1, /* one dictionary check byte to go */
DICT0, /* waiting for inflateSetDictionary */
BLOCKS, /* decompressing blocks */
CHECK4, /* four check bytes to go */
CHECK3, /* three check bytes to go */
CHECK2, /* two check bytes to go */
CHECK1, /* one check byte to go */
I_DONE, /* finished check, done */
I_BAD} /* got an error--stay here */
inflate_mode;
struct internal_state {
/* mode */
inflate_mode mode; /* current inflate mode */
/* mode dependent information */
union {
uInt method; /* if FLAGS, method byte */
struct {
uLong was; /* computed check value */
uLong need; /* stream check value */
} check; /* if CHECK, check values to compare */
uInt marker; /* if BAD, inflateSync's marker bytes count */
} sub; /* submode */
/* mode independent information */
int nowrap; /* flag for no wrapper */
uInt wbits; /* log2(window size) (8..15, defaults to 15) */
inflate_blocks_statef
*blocks; /* current inflate_blocks state */
};
/* inflate codes private state */
typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
START, /* x: set up for LEN */
LEN, /* i: get length/literal/eob next */
LENEXT, /* i: getting length extra (have base) */
DIST, /* i: get distance next */
DISTEXT, /* i: getting distance extra */
COPY, /* o: copying bytes in window, waiting for space */
LIT, /* o: got literal, waiting for output space */
WASH, /* o: got eob, possibly still output waiting */
END, /* x: got eob and all data flushed */
BADCODE} /* x: got error */
inflate_codes_mode;
struct inflate_codes_state {
/* mode */
inflate_codes_mode mode; /* current inflate_codes mode */
/* mode dependent information */
uInt len;
union {
struct {
inflate_huft *tree; /* pointer into tree */
uInt need; /* bits needed */
} code; /* if LEN or DIST, where in tree */
uInt lit; /* if LIT, literal */
struct {
uInt get; /* bits to get for extra */
uInt dist; /* distance back to copy from */
} copy; /* if EXT or COPY, where and how much */
} sub; /* submode */
/* mode independent information */
Byte lbits; /* ltree bits decoded per branch */
Byte dbits; /* dtree bits decoder per branch */
inflate_huft *ltree; /* literal/length/eob tree */
inflate_huft *dtree; /* distance tree */
};
/* memory allocation for inflation */ /* memory allocation for inflation */
struct inflate_workspace { struct inflate_workspace {
inflate_codes_statef working_state; struct inflate_state inflate_state;
struct inflate_blocks_state working_blocks_state;
struct internal_state internal_state;
unsigned int tree_work_area_1[19];
unsigned int tree_work_area_2[288];
unsigned working_blens[258 + 0x1f + 0x1f];
inflate_huft working_hufts[MANY];
unsigned char working_window[1 << MAX_WBITS]; unsigned char working_window[1 << MAX_WBITS];
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment